English
preview
Знакомство с языком MQL5 (Часть 36): Освоение API и функции WebRequest в языке MQL5 (X)

Знакомство с языком MQL5 (Часть 36): Освоение API и функции WebRequest в языке MQL5 (X)

MetaTrader 5Интеграция |
67 0
Israel Pelumi Abioye
Israel Pelumi Abioye

Введение

И снова приветствуем вас в Части 36 серии "Знакомство с языком MQL5"! В Части 31 этой серии мы обсудили, как взаимодействовать с внешними платформами, такими, как Binance, но это взаимодействие было прямым и не предполагало передачи какой-либо конфиденциальной информации. В этой статье мы рассмотрим вопросы безопасности при подключении к API. Мы рассмотрим ключевые темы, включая подписи, HMAC (Hash-based Message Authentication Code) и хеширование SHA256, которые используются для аутентификации запросов, подтверждения их целостности и предотвращения подделки. При выполнении критически важных API-вызовов, таких, как размещение ордеров или управление сделками, эти меры безопасности крайне важны. 

Важно отметить, что в этой статье будут рассмотрены только теория и базовые составляющие. Конфиденциальная информация пока не будет отправляться в реальных запросах. В следующей статье мы объединим эти концепции, чтобы безопасно подключаться к серверу. К концу этого раздела у вас сформируется прочное базовое понимание того, как при совместном использовании HMAC, SHA256 и подписи создают основу для безопасных API-вызовов в языке MQL5.

 

Что такое подпись?

В API подпись работает как специальная печать, которая добавляется к каждому запросу. С помощью этой печати сервер может проверить две вещи: действительно ли запрос отправлен вами, и что до его поступления в нем ничего не было изменено. Иными словами, подпись сообщает серверу: "этому запросу можно доверять". Без нее кто угодно сможет выдавать себя за вас, что особенно опасно при выполнении чувствительных операций, таких, как размещение ордеров или совершение сделок.

Подписи играют ключевую роль в проверке запросов. Серверы должны проверять подлинность запроса. Это достигается с помощью таких криптографических методов, как HMAC-SHA256, которые создают подпись на основе данных запроса и секретного ключа. Эта подпись отправляется вместе с запросом на сервер, где выполняется то же самое вычисление. Совпадение результатов подтверждает подлинность запроса. Чтобы это было проще понять, представьте подписанное письмо. Получатель может быть уверен, что рукописное письмо с вашей подписью внизу действительно написали вы. Если кто-то попытается подделать письмо без вашей подписи, получатель сразу поймет, что оно не подлинное. Аналогичным образом, в API подпись гарантирует, что ваш запрос будет распознан как исходящий от вас, и что никто не изменил его во время передачи.


Что такое HMAC-SHA256

Прежде чем обсуждать HMAC, важно понять, что означает MAC. MAC расшифровывается как Message Authentication Code. MAC – это небольшой фрагмент данных, который создается на основе сообщения и секретного ключа. Его основная задача – одновременно показать, что сообщение действительно исходит от предполагаемого отправителя, и что оно не было изменено. После получения сообщения сервер использует тот же секретный ключ, чтобы заново вычислить MAC. Сообщение считается подлинным, если результаты совпадают. Существует несколько разновидностей MAC. Некоторые создаются с использованием хеш-функций, другие – с использованием блочных шифров. Независимо от типа, все они служат одной и той же цели: аутентификации сообщений и проверке их целостности. Среди них HMAC – один из самых популярных и надежных методов.

Он используется для создания подписи, которая подтверждает, что API-запрос является подлинным и не был изменен. При отправке чувствительных запросов, таких как размещение ордеров, такие платформы как Binance часто используют этот метод. В этой статье мы не будем углубляться во все внутренние математические детали HMAC-SHA256. Вместо этого мы сосредоточимся только на тех компонентах, которые нужно понять, чтобы правильно создавать и подписывать API-запросы в языке MQL5. Здесь практическое понимание важнее, чем глубокое освоение криптографии. Основные компоненты этого механизма – метод аутентификации сообщений и алгоритм хеширования SHA256. В итоге получается подпись, то есть значение фиксированной длины. Затем, после того как эта подпись добавлена к URL запроса, для отправки используется функция WebRequest.

Этот криптографический алгоритм хеширования принимает входные данные произвольной длины и выдает результат фиксированной длины – 256 бит. Какими бы ни были входные данные, размер результата остается одинаковым. Результат детерминирован, что гарантирует повторяемый и предсказуемый выход для одних и тех же входных данных, даже если внешне он кажется случайным. Эффект лавины – одна из важных особенностей SHA256. Изменение даже одного символа во входных данных приведет к совершенно другому хешу. Поэтому SHA256 особенно полезен для выявления изменений в данных. Однако SHA256 сам по себе не может определить, кто именно отправил данные. Сообщение может хешировать кто угодно. Именно здесь и вступает в дело HMAC.

HMAC расширяет SHA256, добавляя в процесс хеширования секретный ключ. Этот секретный ключ известен только вам и серверу, например, Binance и вашей программе для MetaTrader 5. Когда сообщение и секретный ключ объединяются и хешируются с помощью SHA256, создается подпись, которую может получить только тот, у кого есть правильный секретный ключ. Это означает, что злоумышленник не сможет создать действительную подпись без секретного ключа, даже если он видит передаваемое сообщение. В нашем случае нет необходимости углубляться в детали того, как работают внутренние процедуры хеширования. Самое важное здесь следующее: если использовать одно и то же сообщение и один и тот же секретный ключ, вы всегда получите одну и ту же подпись; при малейшем изменении в них подпись будет отличаться.

На практике подписываемое "сообщение" обычно представляет собой строку запроса, составленную из элементов запроса, таких как временная метка. Эта строка и ваш секретный API-ключ передаются в процесс HMAC-SHA256. В результате создается подпись. Созданная подпись добавляется к URL запроса как дополнительный параметр. После получения запроса сервер заново вычисляет подпись, используя тот же криптографический метод и копию вашего секретного ключа. Запрос будет одобрен, если заново вычисленная подпись совпадет с той, которую вы отправили; в противном случае он будет отклонен. Хотя эта процедура основана на сложных криптографических принципах, для обычной работы с API из кода MQL5 эти подробности не нужны. Эта статья не углубляется в такие базовые механизмы, как паддинг (padding), размеры блоков или раунды хеширования; вместо этого она сосредоточена на том, что нужно для эффективного создания подписей и понимания их назначения.

Такой целенаправленный подход гарантирует, что вы сможете уверенно перейти к следующей части серии, где мы уже будем подписывать реальные API-запросы с помощью HMAC-SHA256 и безопасно отправлять их через функцию WebRequest языка MQL5. Для создания подписи для API Binance нужны два основных компонента. Первый – это временная метка, которая указывает точное время отправки запроса и постоянно меняется. Второй – это ваш секретный ключ, который Binance предоставляет вам, и который вы всегда должны держать в секрете. Даже если все остальные параметры остаются неизменными, временная метка гарантирует, что каждый запрос будет уникальным.

Когда вы отправляете запрос, Binance не получает ваш секретный ключ. Вместо этого ваша система генерирует подпись с помощью HMAC-SHA256, используя этот секретный ключ и данные запроса, включая временную метку. После этого запрос отправляется в Binance с прикрепленной подписью. Платформа Binance использует имеющуюся у нее копию вашего секретного ключа, чтобы выполнить тот же самый расчет на своей стороне. Запрос будет одобрен, если вычисленная платформой подпись совпадет с той, которую вы отправили.

Figure 1. HMAC

Эта процедура гарантирует, что запрос не был изменен при передаче по сети. Проверка не пройдет даже при незначительном изменении параметров запроса, что приведет к совершенно другой подписи. Это критически важно для безопасности, особенно при выполнении чувствительных задач, таких как размещение ордеров.

Figure 2. Minor Modification

Еще один важный вопрос – почему запрос никогда не содержит сам секретный ключ. Если бы его отправляли по сети, он мог бы быть перехвачен. При использовании криптографической подписи отправляется только вычисленная подпись; сам секретный ключ надежно хранится на вашем компьютере. Таким образом, перехват запроса не даст злоумышленнику достаточно информации, чтобы подделать подлинные запросы или восстановить секретный ключ.

Аналогия:

Представьте, что вы доставляете важное письмо надежному другу в городе, полном почтальонов. Вам нужно, чтобы ваш друг знал, что письмо действительно пришло от вас, и что никто не изменил его содержимое. Для этого у вас есть секретная восковая печать, которую можете воспроизвести только вы и ваш друг. Подобно секретному ключу, эта печать всегда находится у вас и не может быть воспроизведена никем другим. Теперь представьте, что на каждом отправленном вами письме указано точное время, когда оно было написано. Эта временная метка крайне важна, поскольку письма будут различаться, даже если вы отправите одно и то же сообщение дважды, из-за разного времени отправки. Без временной метки кто-то мог бы попытаться обмануть вашего друга, повторно отправив старое письмо. Подобно отпечатку пальца для конкретного момента, временная метка делает каждое письмо уникальным.

Перед отправкой вы ставите на письмо временную метку и свою секретную восковую печать. Такое сочетание придает письму уникальную отметку, подтверждающую его подлинность. Подобно подписи HMAC-SHA256, эта отметка привязана именно к данному сообщению в данный момент, поскольку создается на основе вашей секретной восковой печати и времени. Ваш знакомый проверяет отметку на письме, используя копию вашей восковой печати. Чтобы убедиться, что письмо актуально, он также смотрит на временную метку. Если отметка верна, а время выглядит логично, ваш знакомый поймет, что письмо подлинное и не было изменено. В противном случае он сразу его отклонит.

Прелесть этой системы в том, что секретная восковая печать никогда не покидает ваш стол. С письмом отправляется только отметка, то есть подпись. Даже если хитрый почтальон увидит письмо и отметку, он не сможет ни подделать вашу печать, ни сфальсифицировать новое письмо. Ваша секретная печать и временная метка работают вместе, чтобы каждое письмо оставалось защищенным, подлинным и уникальным. При отправке запросов к API Binance для создания подписи используются секретный ключ и временная метка. Временная метка предотвращает повторное использование одного и того же запроса, а секретный ключ служит для подтверждения того, что он исходит от вас. Затем Binance проверяет подлинность и целостность запроса, сверяя подпись и временную метку.

 

Создание API-подписей в языке MQL5

Именно при создании API-подписей с помощью HMAC SHA256 в языке MQL5 вся ранее изученная теория начинает складываться в практическую картину. Цель теперь проста: создать подпись, которая покажет внешнему сервису, например, API биржи, что запрос действительно исходит от вас и не был изменен при передаче. Этот процесс полностью выполняется на вашем локальном компьютере, в коде MQL5, до отправки запроса через функцию WebRequest.

Прежде всего, важно точно понимать, что именно мы подписываем. Большинство API, в том числе у Binance, не генерируют подпись на основе случайных данных. Вместо этого параметры запроса представляются строкой, которая и используется для ее генерации. В эту строку часто входят такие значения, как временная метка, информация об ордере, количество или другие параметры, требуемые эндпоинтом. Поскольку временная метка постоянно меняется, она имеет очень большое значение. Это гарантирует, что каждый запрос будет уникальным, даже если все остальные параметры остаются неизменными. Если действительный запрос сохранить без временной метки и затем воспроизвести позже, возникает серьезная угроза безопасности.

Когда эта строка параметров готова, следующим шагом она объединяется с вашим секретным ключом. Поставщик API предоставляет вам секретный ключ, который никогда не следует никому передавать и отправлять по сети. Этот секретный ключ используется в языке MQL5 только как входные данные для процедуры HMAC SHA256. Сам ключ никогда не покидает ваш компьютер. Вместо этого он выступает как невидимый компонент, влияющий на итоговый результат. Идентичная подпись для одного и того же сообщения может быть создана только тем, кто знает этот секретный ключ.

В языке MQL5 к сообщению и секретному ключу применяется специальная процедура хеширования. Главное здесь – результат, поэтому о сложных вычислениях можно не беспокоиться. Результатом будет строка фиксированной длины, которая выглядит случайной, но при этом полностью детерминирована. Именно эта строка и является вашей подписью. Если снова подписать то же самое сообщение тем же секретным ключом, вы получите ту же подпись. Подпись будет совершенно другой, если использовать другой ключ или изменить хотя бы один символ.

Подпись создается, а затем добавляется к запросу, обычно как дополнительный параметр URL. Когда запрос поступает на сервер, тот использует сохраненную копию вашего секретного ключа и переданные параметры, чтобы выполнить тот же расчет подписи. Совпадающая подпись показывает серверу, что данные не были изменены при передаче по сети, и что запрос был отправлен владельцем авторизованного ключа. В языке MQL5 для создания подписей и хешей используется функция CryptEncode . Она может генерировать хеши, такие как SHA256, или подписи на основе HMAC и является одним из встроенных криптографических инструментов платформы. По сути, CryptEncode принимает входные данные, преобразует их с помощью криптографического метода, при необходимости добавляет ключ и выдает двоичное значение. Затем мы используем это двоичное значение как подпись или хеш.

Преобразование сообщения и секретного ключа в байтовые данные

Первый этап создания подписи – преобразование сообщения и секретного ключа в формат данных, подходящий для криптографических операций. Обычные текстовые строки в языке MQL5 не используются напрямую в операциях хеширования и HMAC. Вместо этого такие операции работают с необработанными байтовыми данными. Это означает, что прежде чем начнется какая-либо криптографическая обработка, человекочитаемое сообщение и секретный ключ нужно преобразовать в низкоуровневое представление. Обычно в качестве преобразуемого сообщения выступают данные, которые нужно защитить, например, строка запроса, составленная из параметров запроса. Чтобы каждый запрос был уникальным, такая строка часто содержит временную метку. Секретный ключ – это закрытое значение, которое предоставляет вам поставщик API. Чтобы один и тот же ввод стабильно давал одну и ту же подпись и на вашей стороне, и на стороне сервера, оба значения нужно обрабатывать аккуратно и преобразовывать единообразно.

В этой процедуре используется стандартная текстовая кодировка, которая преобразует каждый символ сообщения и секретного ключа в соответствующее байтовое значение. Для этого часто используется UTF-8, поскольку эта кодировка широко поддерживается и гарантирует, что данные будут единообразно интерпретироваться во многих системах. На этом этапе получаются две последовательности байтов: одна для сообщения, другая для секретного ключа. Поскольку криптографические методы зависят от точных последовательностей байтов, такое преобразование имеет решающее значение. Даже небольшое отличие в кодировке или представлении даст на выходе совершенно другую подпись. Контролируемо и предсказуемо преобразуя и сообщение, и секретный ключ в байтовую форму, мы обеспечиваем точность последующей криптографической обработки и возможность для сервера воспроизвести ту же подпись для проверки.

Когда этот шаг завершен, сообщение и секретный ключ уже представлены в правильном формате для использования в процедуре HMAC SHA256. Все последующие операции работают с этими байтовыми представлениями, что позволяет создать безопасную подпись, ни разу не раскрывая секретный ключ.

Пример:
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---

   string message = "71772777";
   string key = "ABCDER2y8VAzqopxzLVEhVYABCDEV2AxIYLueComud3aSEez8Z8fvgHPZTXABCDE";

   uchar uMsg[], uKey[];

   StringToCharArray(message, uMsg, 0, StringLen(message), CP_UTF8);
   StringToCharArray(key, uKey, 0, StringLen(key), CP_UTF8);
  }

Пояснение:

Первый этап – задать сообщение и секретный ключ в читаемом виде. Сообщение представляет данные, которые нужно подписать; на практике при работе с API зачастую это временная метка или набор параметров запроса. Секретный ключ – это закрытое значение, предоставленное платформой, которое должно быть известно только вашей системе и серверу. Пока оба значения доступны только в виде обычного текста, что удобно для человека, но не подходит для криптографических операций.

Следующий этап – подготовить хранилища, способные хранить необработанные байтовые данные. Поскольку текст является абстрактным представлением, криптографические методы не работают с ним напрямую. Им нужны байты. Поэтому создаются специальные байтовые контейнеры для хранения секретного ключа и преобразованного сообщения. В процессе преобразования эти изначально пустые контейнеры будут постепенно заполняться. Затем сообщение преобразуется из текста в его байтовое представление. Единообразие обеспечивается использованием кодировки UTF-8 для этого преобразования. Благодаря UTF-8 одни и те же символы всегда будут преобразовываться в одну и ту же последовательность байтов. Это имеет решающее значение, поскольку даже незначительное различие в байтах может дать на выходе совершенно другую подпись.

Затем той же процедуре преобразования подвергается и секретный ключ. Символы ключа преобразуются в байты и сохраняются в отдельном контейнере. Секретный ключ еще никому не передавался и по-прежнему остается конфиденциальным. Он лишь приведен к виду, который понятен криптографическим функциям. Когда оба преобразования завершены, в системе хранятся байтовые массивы сообщения и секретного ключа. Подписание и хеширование еще не выполнялись. Этот шаг нужен только для подготовки. Это гарантирует, что на следующем этапе процедура HMAC SHA256 сможет сгенерировать подлинную и проверяемую подпись, поскольку данные уже представлены в правильном формате.

Аналогия:

Предположим, что секретный ключ и сообщение – это две рукописные записки. В одной записке содержится информация, которую вы хотите передать, например, временная метка или детали запроса. На другой записке указан уникальный код, который известен только вам и получателю. Пока обе записки написаны обычным почерком: человек их читает без труда, но для машинной проверки безопасности они ненадежны. Следующий шаг – подготовить два пустых конверта. Эти конверты – всего лишь контейнеры, в которые записки будут помещены в машиночитаемом формате; для отправки по почте они пока не предназначены. Конверты пока пусты и ждут заполнения. Теперь представьте, что вы берете сообщение из первой рукописной записки и переводите каждое слово в строгий стандартный язык, о котором вы договорились с получателем.

Это похоже на превращение рукописного текста в машинописный с использованием определенного алфавита, в котором каждая буква выглядит одинаково. Это гарантирует, что сообщение всегда будет пониматься одинаково и без двусмысленности. Затем вы выполняете ту же процедуру с секретным ключом. Вы переписываете его на том же стандартизированном языке, удобном для машин, и помещаете в отдельный конверт, но он остается конфиденциальным и никогда не покидает ваш стол. Смысл здесь только в том, чтобы подготовиться к следующему шагу; этот конверт никуда не передается. Теперь у вас есть два конверта: в одном – преобразованный секретный ключ, в другом – преобразованное сообщение. Оба лишь подготовлены к тому, чтобы на следующем этапе использоваться для создания надежной подписи; пока ничего не запечатано и не защищено.

Подготовка внутреннего и внешнего паддинг-блоков для подписи

На этом этапе задача состоит в том, чтобы преобразовать секретный ключ в две особые рабочие формы, которые будут использоваться для безопасного объединения ключа и сообщения. Эти две формы часто называют внешним паддинг-блоком и внутренним паддинг-блоком. Они никуда не отправляются и не выбираются произвольно. Они существуют только в рамках процесса подписания. Этот процесс можно сравнить с изготовлением двух разных печатей на основе одного и того же мастер-ключа. Хотя обе печати происходят из одного и того же секрета, они слегка модифицируются, чтобы выполнять разные функции в процессе проверки. Процесс начинается с одной печати и заканчивается другой. Использование двух отдельных паддинг-блоков вместо одного добавляет дополнительный уровень защиты, и подпись становится намного труднее подделать.

Здесь решающее значение имеет фиксированный размер. HMAC использует блоки определенной длины; в случае SHA256 эта длина составляет 64 байта. Эта техника обеспечивает единообразие и безопасность: ключ подгоняется под этот точный размер, а затем обрабатывается двумя разными способами. Процедура всегда следует предсказуемой структуре, независимо от того, насколько длинным или коротким был исходный секретный ключ.

Пример:
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---

   string message = "71772777";
   string key = "ABCDER2y8VAzqopxzLVEhVYABCDEV2AxIYLueComud3aSEez8Z8fvgHPZTXABCDE";

   uchar uMsg[], uKey[];

   StringToCharArray(message, uMsg, 0, StringLen(message), CP_UTF8);
   StringToCharArray(key, uKey, 0, StringLen(key), CP_UTF8);



   int blockSize = 64;

   uchar ipad[], opad[];
   ArrayResize(ipad, blockSize);
   ArrayResize(opad, blockSize);

   for(int i = 0; i < blockSize; i++)
     {
      ipad[i] = uKey[i] ^ 0x36;
      opad[i] = uKey[i] ^ 0x5C;
     }

  }

Пояснение:

Первое, что мы делаем на этом этапе, – задаем размер блока для процедуры хеширования SHA-256. Данные в SHA-256 обрабатываются блоками фиксированного размера (64 байта). Именно этот размер блока определяет длину внутреннего паддинг-блока (ipad) и внешнего паддинг-блока (opad), используемых в HMAC. Указывая размер блока, мы гарантируем, что оба паддинг-блока будут иметь правильную длину для вычисления HMAC. Затем внутренний и внешний паддинг-блоки сохраняются в двух массивах: ipad и opad. Эти массивы приводятся к размеру блока 64 байта. В каждом элементе массива будет храниться один байт, полученный из секретного ключа и измененный так, чтобы подготовить его к операции хеширования.

На этом этапе каждый байт секретного ключа обрабатывается по отдельности в цикле. Чтобы подготовить каждый байт для внутреннего и внешнего паддинг-блоков, его комбинируют с фиксированной константой. Это гарантирует, что ключ будет должным образом модифицирован для процедуры хеширования, но его исходное значение при этом не изменится. По сути, на этом этапе ключ подготавливается к процессу хеширования: каждый его байт изменяется единообразным и предсказуемым образом. Чтобы отделить внутренний паддинг-блок от внешнего, используются две разные константы. Это различие имеет решающее значение, поскольку внутренний и внешний паддинг-блоки используются на разных этапах хеширования, которые вместе формируют безопасную подпись.

К концу этого этапа у нас будут два подготовленных паддинг-блока. Один – для внутренней части, другой – для внешней. Оба основаны на секретном ключе, но слегка изменены, чтобы подготовить их к хешированию. Сначала объединяются сообщение и внутренний паддинг-блок, после чего результат хешируется. Затем, объединив полученный хеш с внешним паддинг-блоком, создается итоговая подпись. Это гарантирует, что подпись будет уникально связана с вашим ключом и не сможет быть изменена.

Аналогия:

Предположим, вы используете защищенную почтовую систему для отправки особенно важного документа. В этой системе действует жесткое правило: прежде чем документ будет обработан, его нужно запечатать в конверт строго заданного размера. Размер блока 64 – это и есть фиксированный размер такого конверта. Прежде чем продолжить, все нужно подготовить так, чтобы оно точно соответствовало этому размеру, независимо от того, насколько длинным или коротким является сообщение. Теперь представьте секретный ключ как уникальное доказательство того, что документ действительно исходит от вас. Прежде чем запечатать документ, вы должны использовать это доказательство, чтобы создать два разных защитных слоя. Этими двумя слоями являются внутренний паддинг-блок и внешний паддинг-блок.

Их можно сравнить с двумя специально изготовленными защитными файлами для бумаг, в которые сообщение помещается на разных этапах проверки. Каждый такой канцелярский файл тщательно подгоняется в точности под нужный размер, потому что по размеру файл должен совпадать с конвертом. Далее следует этап настройки. Для каждой позиции в этих файлах часть секретного ключа комбинируется с заранее заданным шаблоном. Шаблон внешнего файла отличается от шаблона внутреннего файла. Эта процедура смешивания аналогична использованию двух отличительных паттернов штамповки для тиснения вашего отличительного печати на обеих рукавах. Поскольку шаблоны заданы заранее, а сама печать остается конфиденциальной, итоговый результат смогут воспроизвести только вы и получатель.

Генерация подписи

На этом этапе создается сама подпись с использованием внутренних и внешних паддинг-блоков, подготовленных ранее. Внутренний хеш и внешний хеш – это два основных этапа хеширования в этой процедуре. Сначала сообщение, которое нужно подписать, объединяется с внутренним паддинг-блоком, а затем эти данные хешируются. В результате этого первого хеширования мы получаем внутренний хеш. Затем объединяются внешний паддинг-блок и внутренний хеш. Затем повторное хеширование этой новой комбинации дает итоговый хеш. Это итоговое значение, выступающее в роли надежной подписи, уникально представляет исходное сообщение и секретный ключ.

Наконец, сгенерированный хеш преобразуется из последовательности байтов в читаемый формат, обычно шестнадцатеричный, подобно тому как секретный код переводится в письменное сообщение. Именно это значение и используется как подпись API-запроса. Сервер использует его, чтобы проверить, что сообщение действительно исходит от владельца секретного ключа, и что при передаче оно не было изменено. На этом этапе создается готовая к использованию надежная "цифровая печать", потому что сообщение и ключ связываются воедино.

Пример:

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---

   string message = "71772777";
   string key = "ABCDER2y8VAzqopxzLVEhVYABCDEV2AxIYLueComud3aSEez8Z8fvgHPZTXABCDE";

   uchar uMsg[], uKey[];

   StringToCharArray(message, uMsg, 0, StringLen(message), CP_UTF8);
   StringToCharArray(key, uKey, 0, StringLen(key), CP_UTF8);



   int blockSize = 64;

   uchar ipad[], opad[];
   ArrayResize(ipad, blockSize);
   ArrayResize(opad, blockSize);

   for(int i = 0; i < blockSize; i++)
     {
      ipad[i] = uKey[i] ^ 0x36;
      opad[i] = uKey[i] ^ 0x5C;
     }


   uchar innerData[], innerHash[];
   ArrayCopy(innerData, ipad);
   ArrayCopy(innerData, uMsg, blockSize);
   CryptEncode(CRYPT_HASH_SHA256, innerData, uKey, innerHash);


   uchar outerData[], finalHash[];
   ArrayCopy(outerData, opad);
   ArrayCopy(outerData, innerHash, blockSize);
   CryptEncode(CRYPT_HASH_SHA256, outerData, uKey, finalHash);

   string signature = "";
   for(int i = 0; i < ArraySize(finalHash); i++)
      signature += StringFormat("%02x", finalHash[i]);

   Print(signature);

  }

Пояснение:

Внутренние данные и результат внутреннего хеша хранятся в двух массивах, созданных в первом разделе. Внутренний паддинг-блок (iPad) и сообщение, которое нужно подписать, объединяются, образуя внутренние данные. Сообщение добавляется сразу после того, как внутренний паддинг-блок будет скопирован в новый массив с помощью метода ArrayCopy. Это гарантирует, что сообщение будет идти после внутреннего паддинг-блока в правильном порядке байтов для входных данных внутреннего хеша. Поскольку даже один неверный байт даст на выходе совершенно другой хеш, правильный порядок имеет решающее значение. Когда внутренние данные готовы, программа использует функцию CryptEncode, алгоритм SHA256 и секретный ключ для вычисления внутреннего хеша. Этот внутренний хеш служит надежным отпечатком, полученным на основе комбинации сообщения и внутреннего паддинг-блока, и связан с вашим секретным ключом. Это первый уровень хеширования HMAC-SHA256, и он гарантирует, что итоговая подпись будет зависеть и от сообщения, и от вашего секретного ключа.

Следующий этап – подготовка внешних данных. Эта процедура похожа на подготовку внутренних данных: создается массив, и с помощью ArrayCopy в него копируется внешний паддинг-блок (opad). Затем в тот же массив после внешнего паддинг-блока добавляется внутренний хеш. Входные данные для итогового вычисления хеша состоят из внешнего паддинг-блока и внутреннего хеша. И здесь снова: для корректной работы HMAC нужно точно соблюдать последовательность. После подготовки внешних данных функция CryptEncode с алгоритмом SHA256 и секретным ключом применяется еще раз, и в результате создается итоговый хеш. Итоговый хеш и есть подпись HMAC-SHA256. Это специальный массив байтов фиксированной длины, который безопасно хранит секретный ключ и сообщение. Затем сервер сможет использовать тот же процесс, чтобы подтвердить, что сообщение создано тем, кто знает секретный ключ, и что оно не было изменено.

Нельзя просто отправить итоговый хеш через интернет напрямую; это все равно что переслать набор необработанных материалов. Чтобы сделать результат пригодным к использованию, программа создает пустой контейнер signature. Каждый байт хеша преобразуется в фрагмент из двух шестнадцатеричных символов, после чего помещается в этот контейнер. После того как этот процесс повторен для каждого байта, безопасная подпись оказывается представлена одной аккуратной шестнадцатеричной строкой, которую можно добавить к API-запросу. Наконец, программа выводит шестнадцатеричную подпись. Теперь эту подпись можно включать в API-запросы, и это будет гарантировать подлинность запроса. Ваш секретный ключ никогда не должен покидать компьютер, поскольку только тот, у кого есть правильный секретный ключ, может создать совпадающую подпись. Поскольку по подписи нельзя восстановить секретный ключ, это обеспечивает безопасность даже в случае перехвата сетевого трафика.

Аналогия:

Представьте эту процедуру так, будто вы передаете другу запертый сундук с сокровищами и уникальной печатью. Первый шаг – подготовить внутреннюю часть сундука. После того как вы кладете внутрь сообщение, вы запираете сундук с помощью особого механизма, который можно задействовать только вашим секретным ключом. Сообщение и внутренний паддинг-блок объединяются, связывая содержимое с вашим секретом так, чтобы результат нельзя было подделать, – подобно тому, как создается внутренний хеш. После этого вы закрепляете сундук, формируя особый рисунок замка на основе сообщения и внутреннего паддинг-блока. Этот рисунок замка и представляет внутренний хеш. Подобно сложному замку, даже незначительное изменение в сообщении или в паддинг-блоке даст другой рисунок, и тайно вмешаться в содержимое сундука уже не получится.

После того как установлен внутренний замок, подготавливается внешняя часть сундука. Затем вы добавляете крышку, которая тоже создается на основе вашего секретного ключа как дополнительный уровень защиты, и помещаете под нее внутренний замок. Подобно созданию внешних данных, эта двухслойная стратегия гарантирует, что никто не сможет воспроизвести замок без секретного ключа, даже если увидит внутреннюю часть. Последний этап – запечатать внешний замок, то есть вычислить внешний хеш. В результате получается подпись – отличительный знак, который подтверждает, что сундук действительно отправлен вами и что его содержимое не было изменено. Вы можете безопасно передать эту подпись своему другу. После того как сундук будет получен, ваш друг сможет проверить замки при помощи своей копии вашего секретного ключа. Если все совпадает, он сможет быть уверен, что сундук подлинный и не был изменен.

Наконец, вы преобразуете рисунок замка в формат, удобный для всех, например, в уникальный код на ярлыке, поскольку напрямую читать такую строку из букв и цифр трудно. Это и есть шестнадцатеричная строка подписи. Вы включаете этот код в свой API-запрос. Аналогичным образом, как ваш друг проверяет печать на сундуке, чтобы убедиться, что он действительно отправлен вами, сервер будет проверять подлинность, сравнивая этот код со своим собственным вычислением.

 

Заключение

Эта статья показала, как создать  API-подпись в языке MQL5. Вы узнали , как использовать внутренний и внешний паддинг-блоки, преобразовывать сообщения и секретные ключи в хешированные значения и создавать подпись, которая позволяет корректно проверять запросы, не раскрывая конфиденциальную информацию. Мы также увидели, зачем нужны временные метки и секретные ключи: чтобы каждый запрос был уникальным и защищенным от изменений. В следующей статье мы применим все это на практике: создадим подпись и с ее помощью запросим у Binance конфиденциальные данные.


Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/20938

Прикрепленные файлы |
Особенности написания Пользовательских Индикаторов Особенности написания Пользовательских Индикаторов
Написание пользовательских индикаторов в торговой системе MetaTrader 4
Создание самооптимизирующихся советников на MQL5 (Часть 8): Анализ нескольких стратегий Создание самооптимизирующихся советников на MQL5 (Часть 8): Анализ нескольких стратегий
Как лучше всего объединить несколько стратегий для создания мощной ансамблевой стратегии? Мы рассмотрим, как объединить три различные стратегии в нашем торговом приложении. Трейдеры часто используют специализированные стратегии для открытия и закрытия позиций, и мы хотим узнать, могут ли машины выполнять эту задачу лучше. В начале нашего обсуждения мы ознакомимся с возможностями тестера стратегий и принципами объектно-ориентированного программирования, которые нам понадобятся для решения этой задачи.
Особенности написания экспертов Особенности написания экспертов
Написание и тестирование экспертов в торговой системе MetaTrader 4.
Алгоритм Стрекозы — Dragonfly Algorithm (DA) Алгоритм Стрекозы — Dragonfly Algorithm (DA)
В данной статье рассмотрим алгоритм стрекозы (Dragonfly Algorithm, DA), вдохновлённый коллективным поведением стрекоз в природе — их способностью координировать полёт в стае, избегая столкновений, следуя за добычей и уклоняясь от хищников. Разберём, как пять простых поведенческих правил и адаптивный механизм перехода от исследования к эксплуатации реализуются на MQL5, и проверим алгоритм на нашем тестовом стенде.