- Как стать провайдером сигналов - Торговые сигналы и копирование сделок
- Миграция - Виртуальный хостинг для круглосуточной работы
- Сервисы
Всем доброго дня.
Самое базовое - нужно применить шифрование, везде где важные данные нужно применять криптографию. Такие данные должны шифроваться.
Номер счета в исходнике лучше вообще не хранить - следует хранить только проверочный отпечаток.
++ Оптимально это HMAC-SHA-256 , так как он использует дополнительный секретный ключ и значительно усложняет перебор.
++ MQL5 штатно поддерживает SHA-256 и AES-256 через через CryptEncode() . Номер текущего счёта получается через AccountInfoInteger(ACCOUNT_LOGIN) , а сервер - через AccountInfoString(ACCOUNT_SERVER) .
//+------------------------------------------------------------------+ //| Преобразование строки в UTF-8 без завершающего нуля | //+------------------------------------------------------------------+ bool StringToUtf8Bytes(const string text, uchar &result[]) { int copied = StringToCharArray( text, result, 0, WHOLE_ARRAY, CP_UTF8 ); if(copied <= 0) return false; // StringToCharArray при WHOLE_ARRAY добавляет завершающий 0. ArrayResize(result, copied - 1); return true; } //+------------------------------------------------------------------+ //| SHA-256 | //+------------------------------------------------------------------+ bool Sha256Bytes(const uchar &data[], uchar &digest[]) { uchar empty_key[]; ResetLastError(); int written = CryptEncode( CRYPT_HASH_SHA256, data, empty_key, digest ); if(written != 32) { PrintFormat( "Ошибка SHA-256. Код: %d, записано байт: %d", GetLastError(), written ); return false; } ArrayResize(digest, 32); return true; } //+------------------------------------------------------------------+ //| HMAC-SHA-256 | //+------------------------------------------------------------------+ bool HmacSha256( const string secret, const string message, uchar &mac[] ) { const int BLOCK_SIZE = 64; uchar key[]; uchar message_bytes[]; if(!StringToUtf8Bytes(secret, key)) return false; if(!StringToUtf8Bytes(message, message_bytes)) return false; // Если ключ длиннее блока SHA-256, сначала хешируем его. if(ArraySize(key) > BLOCK_SIZE) { uchar shortened_key[]; if(!Sha256Bytes(key, shortened_key)) return false; ArrayResize(key, ArraySize(shortened_key)); ArrayCopy(key, shortened_key); } // Ключ, дополненный нулями до 64 байт. uchar padded_key[]; ArrayResize(padded_key, BLOCK_SIZE); ArrayInitialize(padded_key, 0); if(ArraySize(key) > 0) ArrayCopy(padded_key, key, 0, 0, ArraySize(key)); uchar inner_data[]; uchar outer_data[]; ArrayResize( inner_data, BLOCK_SIZE + ArraySize(message_bytes) ); // inner pad = key XOR 0x36 for(int i = 0; i < BLOCK_SIZE; i++) inner_data[i] = (uchar)(padded_key[i] ^ 0x36); if(ArraySize(message_bytes) > 0) { ArrayCopy( inner_data, message_bytes, BLOCK_SIZE, 0, ArraySize(message_bytes) ); } uchar inner_hash[]; if(!Sha256Bytes(inner_data, inner_hash)) return false; ArrayResize( outer_data, BLOCK_SIZE + ArraySize(inner_hash) ); // outer pad = key XOR 0x5C for(int i = 0; i < BLOCK_SIZE; i++) outer_data[i] = (uchar)(padded_key[i] ^ 0x5C); ArrayCopy( outer_data, inner_hash, BLOCK_SIZE, 0, ArraySize(inner_hash) ); return Sha256Bytes(outer_data, mac); } //+------------------------------------------------------------------+ //| Байты в HEX | //+------------------------------------------------------------------+ string BytesToHex(const uchar &data[]) { string result = ""; for(int i = 0; i < ArraySize(data); i++) result += StringFormat("%.2X", data[i]); return result; }
Формирование идентификатора лицензии
string GetCurrentLicensePayload() { long login = AccountInfoInteger(ACCOUNT_LOGIN); string server = AccountInfoString(ACCOUNT_SERVER); return StringFormat( "%I64d|%s|MY_EA_V1", login, server ); }
Проверка при запуске советника
const string LICENSE_MAC = "ВСТАВЬТЕ_СЮДА_64_СИМВОЛА_HEX"; // Сгенерируй случайную строку минимум из 32 байт. // Не используй пароль вроде "12345" или название советника. string GetLicenseSecret() { return "D7A9F4C8216E53B0" "19C8A42F6D03E7B5" "A8E176C94B2D50F3" "63AF9082C1E74D5B"; } bool IsAccountLicensed() { string payload = GetCurrentLicensePayload(); uchar mac[]; if(!HmacSha256(GetLicenseSecret(), payload, mac)) return false; string calculated_mac = BytesToHex(mac); return calculated_mac == LICENSE_MAC; } int OnInit() { if(!IsAccountLicensed()) { PrintFormat( "Советник не лицензирован для счета %I64d, сервер %s", AccountInfoInteger(ACCOUNT_LOGIN), AccountInfoString(ACCOUNT_SERVER) ); return INIT_FAILED; } return INIT_SUCCEEDED; }
Скрипт для генерации LICENSE_MAC - этот код запускается только у разработчика. Его не нужно передавать пользователю.
#property script_show_inputs input long LicenseAccount = 12345678; input string LicenseServer = "Broker-Live"; void OnStart() { string payload = StringFormat( "%I64d|%s|MY_EA_V1", LicenseAccount, LicenseServer ); uchar mac[]; if(!HmacSha256(GetLicenseSecret(), payload, mac)) { Print("Не удалось создать лицензионный HMAC"); return; } Print("Payload: ", payload); Print("LICENSE_MAC = \"", BytesToHex(mac), "\";"); }
Скопированный результат вставляется в пользовательскую версию советника:
const string LICENSE_MAC = "5F601A32B2D6A35C3685D61EBB5BE6D4D422B58BA21A89CE0AB4AC37D271D743";
Самое базовое - нужно применить шифрование, везде где важные данные нужно применять криптографию. Такие данные должны шифроваться.
Номер счета в исходнике лучше вообще не хранить - следует хранить только проверочный отпечаток.
++ Оптимально это HMAC-SHA-256 , так как он использует дополнительный секретный ключ и значительно усложняет перебор.
++ MQL5 штатно поддерживает SHA-256 и AES-256 через через CryptEncode() . Номер текущего счёта получается через AccountInfoInteger(ACCOUNT_LOGIN) , а сервер - через AccountInfoString(ACCOUNT_SERVER) .
Формирование идентификатора лицензии
Проверка при запуске советника
Скрипт для генерации LICENSE_MAC - этот код запускается только у разработчика. Его не нужно передавать пользователю.
Скопированный результат вставляется в пользовательскую версию советника:
Самое базовое - нужно применить шифрование, везде где важные данные нужно применять криптографию. Такие данные должны шифроваться.
Номер счета в исходнике лучше вообще не хранить - следует хранить только проверочный отпечаток.
++ Оптимально это HMAC-SHA-256 , так как он использует дополнительный секретный ключ и значительно усложняет перебор.
++ MQL5 штатно поддерживает SHA-256 и AES-256 через через CryptEncode() . Номер текущего счёта получается через AccountInfoInteger(ACCOUNT_LOGIN) , а сервер - через AccountInfoString(ACCOUNT_SERVER) .
Формирование идентификатора лицензии
Проверка при запуске советника
Скрипт для генерации LICENSE_MAC - этот код запускается только у разработчика. Его не нужно передавать пользователю.
Скопированный результат вставляется в пользовательскую версию советника:
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования