Hoy vamos a hablar sobre una manera sencilla y efectiva de proteger tu código en MetaTrader 4. Sabemos que hay diversos métodos para hacerlo, pero muchos resultan demasiado simples o complicados, lo que puede ser un dolor de cabeza si solo tienes un puñado de clientes. Así que, aquí te traigo un esquema de verificación de contraseñas que aprovecha el motor de seguridad integrado de MT4, proporcionando cifrado DES/ECB sin necesidad de recompilar tu código cada vez que tengas un nuevo cliente.
He trabajado en varias iniciativas de tarjetas inteligentes en Canadá, donde me familiaricé con diferentes esquemas de seguridad utilizados por instituciones financieras. La primera pregunta que debes hacerte es: "¿Qué está en juego?" Si la respuesta es "millones de dólares", este esquema de seguridad no es para ti. Pero si lo que arriesgas es "un mes o dos de codificación si alguien gasta un año tratando de hackear mi esquema de seguridad", entonces esta solución es perfecta para ti. La clave DES única utilizada en este esquema de cifrado proporcionará una seguridad más que adecuada para tu código y no requerirá recompilación para nuevos clientes.
Te dejaré dos archivos fuente para tu comodidad. El primero, Password_Check, es lo que debes añadir a tu indicador o asesor experto. Verificará la contraseña ingresada por el usuario en el parámetro de entrada "Password". Si la contraseña es incorrecta (o si el usuario está desconectado), mostrará un mensaje amigable, eliminará el asesor (si es que está corriendo) y devolverá un estado INIT_FAILED.
El segundo archivo, Password_Generate, se utiliza para ingresar el nombre y el número de cuenta del cliente que deseas proteger. Se generará una contraseña que podrás proporcionar a tus clientes. ¡Obviamente, no querrás incluir este código en tu producto final! :)
¡Así que empecemos!
Definiendo el Parámetro de Entrada
Primero, necesitamos definir un string de entrada en tu indicador o Asesor Experto:
//--- parámetros de entrada extern string Password;
Verificación de Contraseña en la Función init()
A continuación, añadimos código en la función init() para verificar la contraseña y mostrar un mensaje si la contraseña es incorrecta, si el usuario está desconectado o si simplemente no ingresó una contraseña.
//+------------------------------------------------------------------+ //| Función de inicialización del experto //+------------------------------------------------------------------+ int init() { string client = NULL; // Asegúrate de que el cliente esté en línea para obtener su nombre y número de cuenta if(IsConnected()) client = AccountInfoString(ACCOUNT_NAME) + " / " + DoubleToStr(AccountInfoInteger(ACCOUNT_LOGIN), 0); // Verificar la contraseña del cliente if(!Password_Check(client)) { if(StringLen(Password) != 0) MessageBox("No se puede verificar el cliente y el número de cuenta!" + (IsConnected() ? " Por favor verifica que tienes la contraseña correcta." : " Necesitas estar en línea para la verificación."), (IsConnected() ? "¡Contraseña inválida!" : "¡Desconectado!"), MB_OK | MB_ICONSTOP); else MessageBox("Software no registrado. Por favor contacta al proveedor del software para obtener tu contraseña de activación personal." + (StringLen(client) == 0 ? "" : " Tu información de registro es: '"+client+"'", "No registrado", MB_OK | MB_ICONSTOP); // Contraseña inválida o usuario desconectado. Eliminar el experto y salir con error ExpertRemove(); return(INIT_FAILED); } // Todo bien... return(INIT_SUCCEEDED); }
Codificando el Nombre del Cliente
Ahora viene lo interesante... Necesitamos codificar el nombre del cliente y el número de cuenta con nuestra clave DES, codificar el resultado en BASE64 y compararlo con la contraseña ingresada. Si coincide, ¡tienes un cliente feliz! Si no, entonces tienes un hacker intentando romper tu clave DES. Dado que el asesor experto se eliminará cada vez que se ingrese una contraseña incorrecta, ¡probablemente tendrás tiempo de retirarte a Bora Bora antes de que tengan éxito!
//+------------------------------------------------------------------+ //| Validar la contraseña del cliente //+------------------------------------------------------------------+ bool Password_Check(string client) { string MasterKey; uchar dst[], src[], key[]; // Define tu clave de cifrado aquí. Debe tener 7 caracteres para cifrado DES/ECB // Haz que tu contraseña sea difícil de adivinar. Tu apellido no es una buena idea! // Algo como "wLdU&$z" sería bueno. Por ahora, usaremos una simple... MasterKey = "NotDemo"; // Convertir MasterKey a array de caracteres StringToCharArray(MasterKey, key); // Asegúrate de que el string del cliente no sea nulo if(StringLen(client) == 0) return(false); // Cifrar el cliente usando la clave DES StringToCharArray(client, src); CryptEncode(CRYPT_DES, src, key, dst); // Limpiar clave y codificar a BASE64 ArrayInitialize(key, 0x00); CryptEncode(CRYPT_BASE64, dst, key, src); // Comparar contraseña y devolver resultado return(CharArrayToString(src) == Password); }
Generando la Contraseña para el Cliente
Eso es todo. Ahora puedes validar el nombre del cliente (tomado del nombre de cuenta del cliente en MetaTrader 4) junto con el número de cuenta (también tomado de MetaTrader 4).
Si tu política de licencias permite múltiples cuentas para un solo cliente, solo necesitas eliminar el número de cuenta de la cadena 'client', así:
// Asegúrate de que el cliente esté en línea para obtener el nombre del cliente if(IsConnected()) client = AccountInfoString(ACCOUNT_NAME);
Por supuesto, puedes hacer una mezcla entre "Nombre del Bróker", "Nombre de la Cuenta" y "Inicio de Sesión" como mejor te parezca. Solo recuerda que cuanto más largo sea la variable 'client', más larga será la contraseña cifrada.
Ahora, echemos un vistazo al código de Password_Generate. Lo que queremos hacer es lo mismo que Password_Check, pero en lugar de ingresar una contraseña en el EA, queremos ingresar el nombre del cliente (o una combinación de Nombre del Bróker, Nombre de la Cuenta y Inicio de Sesión que elijas) para ser cifrado y luego mostrar la contraseña generada. Esto es lo que le darás a tus clientes cuando compren tu increíble indicador y/o Asesor Experto.
De nuevo, en tu función init() agregarás el siguiente código.
//+------------------------------------------------------------------+ //| Función de inicialización del experto //+------------------------------------------------------------------+ int init() { string Password = NULL; // Asegúrate de que la entrada del Cliente no esté vacía if(StringLen(Client) != 0) { // Generar una contraseña para el cliente Password = Password_Generate(Client); // Imprimir la contraseña generada (facilita copiar y pegar) Print("Cliente: '"+Client+"' Contraseña: "+Password); // Mostrar la contraseña generada para el cliente MessageBox("Contraseña generada para el cliente / cuenta '"+Client+"' es: "+Password, "Generador de Contraseña", MB_OK | MB_ICONINFORMATION); } else MessageBox("¡Debes especificar un cliente / número de cuenta!", "Generador de Contraseña", MB_OK | MB_ICONSTOP); // Todo bien. Eliminar el experto. ExpertRemove(); return(INIT_SUCCEEDED); }
Modificación de Password_Check()
Ahora hacemos una ligera modificación a nuestra función Password_Check() para devolver un string de la contraseña codificada. Recuerda usar la misma contraseña en ambas funciones, Password_Check() y Password_Generate(). ¡Puedes imaginar lo que sucederá si no lo haces!
//+------------------------------------------------------------------+ //| Cifrar la información del cliente y devolver la contraseña //+------------------------------------------------------------------+ string Password_Generate(string client) { string MasterKey; uchar dst[], src[], key[]; // Define tu clave de cifrado aquí. Debe tener 7 caracteres para cifrado DES/ECB // ¡DEBE SER LA MISMA CONTRASEÑA QUE DEFINISTE EN LA FUNCIÓN "Password_Check()"! // Haz que tu contraseña sea difícil de adivinar. Tu apellido no es una buena idea! // Algo como "wLdU&$z" sería bueno. Por ahora, usaremos una simple... MasterKey = "NotDemo"; // Convertir MasterKey a array de caracteres StringToCharArray(MasterKey, key); // Cifrar el cliente usando la clave DES StringToCharArray(client, src); CryptEncode(CRYPT_DES, src, key, dst); // Limpiar clave y codificar a BASE64 ArrayInitialize(key, 0x00); CryptEncode(CRYPT_BASE64, dst, key, src); // Devolver contraseña cifrada return(CharArrayToString(src)); }
Y eso es todo. Ingresas la información proporcionada por tu cliente y le envías la contraseña por email o el medio que elijas. Por supuesto, la belleza de esto es que puedes hacerlo desde tu sala en Bora Bora.
Como mencioné antes, este esquema de seguridad no requiere que recompiles tu código para cada nuevo cliente ni que codifiques un host de validación del lado del servidor, mientras proporciona una seguridad bastante buena para el arduo trabajo que realizaste creando ese increíble indicador o Asesor Experto.
¡Saludos!
- Claude.
Publicaciones relacionadas
- Señales de Trading con MQL5: Patrones de Estrellas y MFI
- Señales de Trading con Patrón Hammer/Hanging Man y Estocástico en MetaTrader 5
- Crea tu Asesor Experto con MQL5: Señales de Trading Basadas en Dark Cloud Cover y Piercing Line
- MQL5 Wizard: Crea un Asesor Experto con Señales de Bullish Harami y Bearish Harami + CCI
- MQL5 Wizard: Crea EAs con Señales de Trading basadas en Dark Cloud Cover y Piercing Line