348 lines
12 KiB
MQL5
348 lines
12 KiB
MQL5
//+------------------------------------------------------------------+
| |||
//| Encrypt.mqh |
| |||
//| Copyright 2026, MetaQuotes Ltd. |
| |||
//| https://www.mql5.com |
| |||
//+------------------------------------------------------------------+
| |||
#property copyright "Copyright 2026, MetaQuotes Ltd."
| |||
#property link "https://www.mql5.com"
| |||
#property strict
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| |
| |||
//+------------------------------------------------------------------+
| |||
#include "..\\Basic.mqh"
| |||
#include "..\\RandomSimple.mqh"
| |||
| |||
/*
| |||
2026.03.26 17:37:44.570 Test (EURUSD,H1) CRYPT_BASE64 = 0
| |||
2026.03.26 17:37:44.570 Test (EURUSD,H1) CRYPT_AES128 = 1
| |||
2026.03.26 17:37:44.570 Test (EURUSD,H1) CRYPT_AES256 = 2
| |||
2026.03.26 17:37:44.570 Test (EURUSD,H1) CRYPT_DES = 3
| |||
2026.03.26 17:37:44.570 Test (EURUSD,H1) CRYPT_HASH_SHA1 = 4
| |||
2026.03.26 17:37:44.570 Test (EURUSD,H1) CRYPT_HASH_SHA256 = 5
| |||
2026.03.26 17:37:44.570 Test (EURUSD,H1) CRYPT_HASH_MD5 = 6
| |||
2026.03.26 17:37:44.570 Test (EURUSD,H1) CRYPT_ARCH_ZIP = 7
| |||
*/
| |||
| |||
//---
| |||
const uint8_t g_mqlarticles_entryptor_key_len[3] =
| |||
{
| |||
16, // CRYPT_AES128
| |||
32, // CRYPT_AES256
| |||
7 // CRYPT_DES
| |||
};
| |||
| |||
//---
| |||
const bool g_mqlarticles_entryptor_is_encrypther[8] =
| |||
{
| |||
false,
| |||
true,
| |||
true,
| |||
true,
| |||
false,
| |||
false,
| |||
false,
| |||
false
| |||
};
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| |
| |||
//+------------------------------------------------------------------+
| |||
typedef uchar(*FuncGenerateRandomUchar)(void* ptr, uchar start, uchar stop);
| |||
uchar RandomSimpleGenerateRandomUchar(void* ptr, uchar start, uchar stop) { return (uchar)((CRandomSimple*)ptr).RandomShort(start, stop); }
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| |
| |||
//+------------------------------------------------------------------+
| |||
class CEncryptor : public CLoggerBase
| |||
{
| |||
private:
| |||
string m_key;
| |||
public:
| |||
CEncryptor(void) {}
| |||
~CEncryptor(void) {}
| |||
| |||
//---
| |||
void Key(const string& key) { m_key = key; }
| |||
__forceinline string Key() const { return m_key; }
| |||
| |||
//---
| |||
bool SetAleatoryKey(ENUM_CRYPT_METHOD method, FuncGenerateRandomUchar f_generate_char, void* ptr = NULL, uchar chart_start = 32, uchar chart_stop = 255);
| |||
| |||
//---
| |||
bool EncryptFile(const string& file_name, bool common_flag, ENUM_CRYPT_METHOD method, bool delete_prev_file, string ext_encrypt = "");
| |||
bool DecryptFile(const string& file_name, bool common_flag, ENUM_CRYPT_METHOD method, bool delete_prev_file, string ext_decrypt = "");
| |||
| |||
//---
| |||
bool EncryptText(const string& initial_text, ENUM_CRYPT_METHOD method, string& encrypted_text);
| |||
bool DecryptText(const string& encrypted_text, ENUM_CRYPT_METHOD method, string& decrypted_text);
| |||
};
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| |
| |||
//+------------------------------------------------------------------+
| |||
bool CEncryptor::SetAleatoryKey(ENUM_CRYPT_METHOD method, FuncGenerateRandomUchar f_generate_char, void* ptr = NULL, uchar chart_start = 32, uchar chart_stop = 255)
| |||
{
| |||
//---
| |||
if(!g_mqlarticles_entryptor_is_encrypther[method])
| |||
{
| |||
LogError(StringFormat("El metodo de encrypt = %s, no es de encryptacion de archivos", EnumToString(method)), FUNCION_ACTUAL);
| |||
return false;
| |||
}
| |||
| |||
| |||
//---
| |||
const uint8_t clen = g_mqlarticles_entryptor_key_len[method - 1];
| |||
m_key.Truncate(clen);
| |||
for(int i = 0; i < clen; i++)
| |||
{
| |||
m_key.SetChar(i, f_generate_char(ptr, chart_start, chart_stop));
| |||
}
| |||
| |||
//---
| |||
return true;
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| |
| |||
//+------------------------------------------------------------------+
| |||
bool CEncryptor::EncryptFile(const string& file_name, bool common_flag, ENUM_CRYPT_METHOD method, bool delete_prev_file, string ext_encrypt = "")
| |||
{
| |||
//---
| |||
if(!g_mqlarticles_entryptor_is_encrypther[method])
| |||
{
| |||
LogError(StringFormat("El metodo de encrypt = %s, no es de encryptacion de archivos", EnumToString(method)), FUNCION_ACTUAL);
| |||
return false;
| |||
}
| |||
| |||
//---
| |||
const uint8_t clen = g_mqlarticles_entryptor_key_len[method - 1];
| |||
if(m_key.Length() != clen)
| |||
{
| |||
LogError(StringFormat("La clave debe de tener un len de %u chars, con el metodo = %s", clen, EnumToString(method)), FUNCION_ACTUAL);
| |||
return false;
| |||
}
| |||
| |||
//---
| |||
::ResetLastError();
| |||
const int common_file_flag = (common_flag ? FILE_COMMON : 0);
| |||
int fh = FileOpen(file_name, FILE_BIN | FILE_READ | common_file_flag);
| |||
if(fh == INVALID_HANDLE)
| |||
{
| |||
LogError(StringFormat("Fallo al abrir el archivo = %s, ultimo error =%d", file_name, ::GetLastError()), FUNCION_ACTUAL);
| |||
return false;
| |||
}
| |||
| |||
//---
| |||
uchar data[];
| |||
FileReadArray(fh, data);
| |||
FileClose(fh);
| |||
| |||
//---
| |||
uchar key_chars[];
| |||
StringToCharArray(m_key, key_chars, 0, clen);
| |||
| |||
//--- Encryptamos
| |||
uchar res[];
| |||
::ResetLastError();
| |||
if(CryptEncode(method, data, key_chars, res) == 0)
| |||
{
| |||
LogError(StringFormat("Fallo al encriptar el archivo %s a AES256, ultimo error = %d", file_name, ::GetLastError()), FUNCION_ACTUAL);
| |||
return false;
| |||
}
| |||
| |||
//--- Creamos el archivo 2 (o sobreescribimos si ext = "")
| |||
::ResetLastError();
| |||
fh = FileOpen((file_name + ext_encrypt), FILE_BIN | FILE_WRITE | common_file_flag);
| |||
if(fh == INVALID_HANDLE)
| |||
{
| |||
LogError(StringFormat("Fallo al abrir el archivo = %s, ultimo error =%d", (file_name + ext_encrypt), ::GetLastError()), FUNCION_ACTUAL);
| |||
return false;
| |||
}
| |||
FileWriteArray(fh, res);
| |||
FileClose(fh);
| |||
| |||
//--- Ahora si eliminamso el archivo previo si es que se pide
| |||
::ResetLastError();
| |||
if(delete_prev_file && !FileDelete(file_name, common_file_flag))
| |||
{
| |||
LogWarning(StringFormat("Fallo al eliminar el archivo = %s, ultimo error = %d", file_name, ::GetLastError()), FUNCION_ACTUAL);
| |||
}
| |||
| |||
//---
| |||
return true;
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| |
| |||
//+------------------------------------------------------------------+
| |||
bool CEncryptor::DecryptFile(const string& file_name, bool common_flag, ENUM_CRYPT_METHOD method, bool delete_prev_file, string ext_decrypt = "")
| |||
{
| |||
//---
| |||
if(!g_mqlarticles_entryptor_is_encrypther[method])
| |||
{
| |||
LogError(StringFormat("El metodo = %s, no es de encryptacion de archivos", EnumToString(method)), FUNCION_ACTUAL);
| |||
return false;
| |||
}
| |||
| |||
//---
| |||
const uint8_t clen = g_mqlarticles_entryptor_key_len[method - 1];
| |||
if(m_key.Length() != clen)
| |||
{
| |||
LogError(StringFormat("La clave debe de tener un len de %u chars, con el metodo = %s", clen, EnumToString(method)), FUNCION_ACTUAL);
| |||
return false;
| |||
}
| |||
| |||
//---
| |||
::ResetLastError();
| |||
const int common_file_flag = (common_flag ? FILE_COMMON : 0);
| |||
int fh = FileOpen(file_name, FILE_BIN | FILE_READ | common_file_flag);
| |||
if(fh == INVALID_HANDLE)
| |||
{
| |||
LogError(StringFormat("Fallo al abrir el archivo = %s, ultimo error = %d", file_name, ::GetLastError()), FUNCION_ACTUAL);
| |||
return false;
| |||
}
| |||
| |||
//---
| |||
uchar data[];
| |||
FileReadArray(fh, data);
| |||
FileClose(fh);
| |||
| |||
//---
| |||
uchar key_chars[];
| |||
StringToCharArray(m_key, key_chars, 0, clen);
| |||
| |||
//--- Desencryptamos
| |||
uchar res[];
| |||
::ResetLastError();
| |||
if(CryptDecode(method, data, key_chars, res) == 0)
| |||
{
| |||
LogError(StringFormat("Fallo al desencriptar el archivo %s, ultimo error = %d", file_name, ::GetLastError()), FUNCION_ACTUAL);
| |||
return false;
| |||
}
| |||
| |||
//--- Creamos el archivo destino (o sobreescribimos si ext = "")
| |||
::ResetLastError();
| |||
fh = FileOpen((file_name + ext_decrypt), FILE_BIN | FILE_WRITE | common_file_flag);
| |||
if(fh == INVALID_HANDLE)
| |||
{
| |||
LogError(StringFormat("Fallo al abrir el archivo = %s, ultimo error = %d", (file_name + ext_decrypt), ::GetLastError()), FUNCION_ACTUAL);
| |||
return false;
| |||
}
| |||
FileWriteArray(fh, res);
| |||
FileClose(fh);
| |||
| |||
//--- Ahora si eliminamos el archivo previo si es que se pide
| |||
::ResetLastError();
| |||
if(delete_prev_file && !FileDelete(file_name, common_file_flag))
| |||
{
| |||
LogWarning(StringFormat("Fallo al eliminar el archivo = %s, ultimo error = %d", file_name, ::GetLastError()), FUNCION_ACTUAL);
| |||
}
| |||
| |||
//---
| |||
return true;
| |||
}
| |||
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| |
| |||
//+------------------------------------------------------------------+
| |||
bool CEncryptor::EncryptText(const string& initial_text, ENUM_CRYPT_METHOD method, string& encrypted_text)
| |||
{
| |||
//---
| |||
if(!g_mqlarticles_entryptor_is_encrypther[method])
| |||
{
| |||
LogError(StringFormat("El metodo = %s no es de encryptacion", EnumToString(method)), FUNCION_ACTUAL);
| |||
return false;
| |||
}
| |||
| |||
//---
| |||
const uint8_t clen = g_mqlarticles_entryptor_key_len[method - 1];
| |||
if(m_key.Length() != clen)
| |||
{
| |||
LogError(StringFormat("La clave debe de tener un len de %u chars, con el metodo = %s", clen, EnumToString(method)), FUNCION_ACTUAL);
| |||
return false;
| |||
}
| |||
| |||
//--- Convertimos el texto a uchar
| |||
uchar data[];
| |||
StringToCharArray(initial_text, data, 0, StringLen(initial_text));
| |||
| |||
//---
| |||
uchar key_chars[];
| |||
StringToCharArray(m_key, key_chars, 0, clen);
| |||
| |||
//--- Encryptamos
| |||
uchar res[];
| |||
::ResetLastError();
| |||
if(CryptEncode(method, data, key_chars, res) == 0)
| |||
{
| |||
LogError(StringFormat("Fallo al encriptar el texto, ultimo error = %d", ::GetLastError()), FUNCION_ACTUAL);
| |||
return false;
| |||
}
| |||
| |||
//--- Convertimos el resultado a BASE64 para poder guardarlo como string
| |||
uchar base64[];
| |||
::ResetLastError();
| |||
if(CryptEncode(CRYPT_BASE64, res, key_chars, base64) == 0)
| |||
{
| |||
LogError(StringFormat("Fallo al convertir a BASE64, ultimo error = %d", ::GetLastError()), FUNCION_ACTUAL);
| |||
return false;
| |||
}
| |||
| |||
//---
| |||
encrypted_text = CharArrayToString(base64);
| |||
return true;
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| |
| |||
//+------------------------------------------------------------------+
| |||
bool CEncryptor::DecryptText(const string& encrypted_text, ENUM_CRYPT_METHOD method, string& decrypted_text)
| |||
{
| |||
//---
| |||
if(!g_mqlarticles_entryptor_is_encrypther[method])
| |||
{
| |||
LogError(StringFormat("El metodo = %s no es de encryptacion", EnumToString(method)), FUNCION_ACTUAL);
| |||
return false;
| |||
}
| |||
| |||
//---
| |||
const uint8_t clen = g_mqlarticles_entryptor_key_len[method - 1];
| |||
if(m_key.Length() != clen)
| |||
{
| |||
LogError(StringFormat("La clave debe de tener un len de %u chars, con el metodo = %s", clen, EnumToString(method)), FUNCION_ACTUAL);
| |||
return false;
| |||
}
| |||
| |||
//--- Convertimos el string BASE64 a uchar
| |||
uchar base64[];
| |||
StringToCharArray(encrypted_text, base64, 0, StringLen(encrypted_text));
| |||
| |||
//---
| |||
uchar key_chars[];
| |||
StringToCharArray(m_key, key_chars, 0, clen);
| |||
| |||
//--- Decodificamos BASE64 primero
| |||
uchar data[];
| |||
::ResetLastError();
| |||
if(CryptDecode(CRYPT_BASE64, base64, key_chars, data) == 0)
| |||
{
| |||
LogError(StringFormat("Fallo al decodificar BASE64, ultimo error = %d", ::GetLastError()), FUNCION_ACTUAL);
| |||
return false;
| |||
}
| |||
| |||
//--- Desencryptamos
| |||
uchar res[];
| |||
::ResetLastError();
| |||
if(CryptDecode(method, data, key_chars, res) == 0)
| |||
{
| |||
LogError(StringFormat("Fallo al desencriptar el texto, ultimo error = %d", ::GetLastError()), FUNCION_ACTUAL);
| |||
return false;
| |||
}
| |||
| |||
//---
| |||
decrypted_text = CharArrayToString(res);
| |||
return true;
| |||
}
| |||
//+------------------------------------------------------------------+
|