English 日本語
preview
Implementierung des kryptografischen SHA-256-Algorithmus von Grund auf in MQL5

Implementierung des kryptografischen SHA-256-Algorithmus von Grund auf in MQL5

MetaTrader 5Beispiele | 4 Juni 2025, 07:39
55 5
Abdulkudus Okatengwu Kadir
Abdulkudus Okatengwu Kadir

Die Fortschritte in MQL5 ermöglichen eine effiziente Implementierung kryptografischer Algorithmen ohne Lösungen von Drittanbietern, was die Sicherheit, Optimierung und Stabilität erhöht. Zu den Vorteilen einer nutzerdefinierten Implementierung gehören aufgabenspezifische Anpassungen, die Beseitigung von Schwachstellen und eine einheitliche Leistung in verschiedenen Umgebungen. Kryptografie ist heute ein integraler Bestandteil von APIs, Transaktionsüberprüfung und Datenintegrität, sodass die Entwickler diese Algorithmen genau verstehen müssen. Die Konvergenz von Kryptographie und Handelssystemen ist ein obligatorischer Aspekt der modernen Plattformentwicklung geworden.


Herausforderungen bei der Kompatibilität von API-Signaturen

Der Hauptgrund für die nutzerdefinierte SHA-256-Implementierung liegt in der grundlegenden Inkompatibilität zwischen den nativen Hashing-Funktionen von MQL5 und den Anforderungen für den Austausch von Kryptowährungen. Diese Inkompatibilität äußert sich in mehreren kritischen Aspekten, die sich direkt auf die Handelsgeschäfte auswirken.

Wenn Handelsplattformen API-Aufrufe an Kryptowährungsbörsen wie Binance oder Bybit tätigen, müssen sie kryptografische Signaturen erzeugen, die den Erwartungen der Börse perfekt entsprechen. Diese Signaturen dienen als Authentizitätsnachweis für jede Anfrage und stellen sicher, dass Aufträge und andere sensible Vorgänge von autorisierten Quellen stammen. Die in MQL5 integrierten kryptographischen Funktionen erzeugen jedoch oft Signaturen, die sich von denen unterscheiden, die von Standardimplementierungen in anderen Programmiersprachen erzeugt werden.

Diese Fehlanpassung der Signaturen tritt auf, weil Kryptowährungsbörsen in der Regel Signaturen erwarten, die nach bestimmten Standards erstellt werden, die oft auf Implementierungen in Sprachen wie Python oder JavaScript basieren. Die nativen Funktionen von MQL5 sind zwar für allgemeine Zwecke geeignet, können aber bestimmte Aspekte des Hashing-Prozesses anders handhaben, wie z. B.:

  1. Byte-Reihenfolge bei der Eingabeverarbeitung.
  2. Padding-Implementierungen.
  3. Handhabung der Zeichenkodierung.
  4. Speicherdarstellung von Zwischenwerten.
  5. Behandlung von Sonderzeichen in der Eingabezeichenfolge.

Diese Unterschiede führen in produktiven Umgebungen zu mehreren schwerwiegenden betrieblichen Problemen:

Erstens werden API-Anfragen von Vermittlungsstellen abgelehnt, weil die Signaturen nicht mit den erwarteten Werten übereinstimmen. Diese Ablehnung erfolgt auf der Authentifizierungsebene, bevor die eigentliche Handelslogik überhaupt ausgeführt wird. Stellen Sie sich ein Szenario vor, in dem ein Handelsalgorithmus eine profitable Gelegenheit erkennt und versucht, einen Auftrag zu erteilen. Ist die Signatur ungültig, lehnt die Börse den Antrag sofort ab, sodass das System die Handelsmöglichkeit vollständig verpasst.

Zweitens treten Authentifizierungsfehler immer wieder bei verschiedenen Arten von API-Aufrufen auf. Selbst einfache Vorgänge wie die Abfrage von Kontoständen oder die Überprüfung des Auftragsstatus werden unmöglich, da die Börse die Authentizität der Anfrage nicht überprüfen kann. Dies führt zu einem systemischen Problem, das sich auf alle Aspekte der Funktionsweise des Handelssystems auswirkt.

Drittens wird die Auftragsvergabe besonders problematisch. Beim Versuch, Aufträge zu erteilen, verhindern ungültige Signaturen die Ausführung von Handelsgeschäften, was zu Problemen führen kann:

  • Verpasste Einstiegspunkte für geplante Abschlüsse.
  • Unfähigkeit, Positionen bei Bedarf zu verlassen.
  • Fehlgeschlagene Risikomanagementmaßnahmen.
  • Unvollständige Ausführung von Handelsstrategien.

Viertens: Die Überprüfung von Nachrichten wird unzuverlässig. Viele Börsen verwenden die Hash-basierte Verifizierung für verschiedene Arten von Nachrichten und Benachrichtigungen. Inkonsistente Hash-Ausgaben bedeuten, dass das Handelssystem diese Nachrichten nicht zuverlässig überprüfen kann, wodurch möglicherweise wichtige Aktualisierungen verpasst werden oder auf ungeprüfte Informationen zurückgegriffen wird.

Die Auswirkungen dieser Kompatibilitätsprobleme gehen über die unmittelbaren technischen Probleme hinaus. Sie wirken sich auf subtile, aber bedeutsame Weise auf den gesamten Handelsbetrieb aus:

  • Handelsstrategien können nicht zuverlässig ausgeführt werden.
  • Risikomanagementsysteme können nicht wie vorgesehen funktionieren.
  • Systemüberwachung und -protokollierung werden weniger zuverlässig.
  • Integration mit Börsen-APIs erfordert ständige Umgehungslösungen.

Nehmen wir zum Beispiel einen typischen API-Aufruf an eine Kryptowährungsbörse. Dieselben Eingabedaten können zu völlig unterschiedlichen Signaturen führen:

Mit der integrierten Funktion von MQL5:

void OnStart()
{
   // The text to hash
   string text = "Hello";
   string key_text = "key";   
   
   // Method 1: Using HashCalculate() - Returns uchar array
   uchar data[];
   uchar key[];
   uchar result[];
   StringToCharArray(text, data);
   StringToCharArray(key_text, key);
  
  int res =  CryptEncode(CRYPT_HASH_SHA256, data, key, result);
  
  Print(ArrayToHex(result));
}

/*Result
 D9D3734CD05564A131946ECF9E240E0319CA2F5BA321BD9F87D634A24A29EF4D
*/

Verwendung der Standardimplementierung:


import hashlib
import hmac

text = "Hello" #message
key = "key"  #password

hash_object = hmac.new(bytes(key, 'utf-8'), text.encode('utf-8'), hashlib.sha256)
hex_dig = hash_object.hexdigest()

hex_dig

##output >>> "c70b9f4d665bd62974afc83582de810e72a41a58db82c538a9d734c9266d321e"

Unstimmigkeiten bei der Signaturerstellung können dazu führen, dass gültige Handelssignale und Strategien fehlschlagen. Unterschiedliche Börsen haben möglicherweise einzigartige Signaturanforderungen, die eine flexible, anpassbare Implementierung erfordern.

Nutzerdefinierte SHA-256-Implementierungen bieten Entwicklern die Möglichkeit, die Kontrolle zu übernehmen:

    Anpassen an die spezifischen Anforderungen der Börse.
    Anpassung an sich entwickelnde Normen.
    Beseitigung von Problemen im Zusammenhang mit Signaturen.
    Gewährleistung der Konsistenz des gesamten Handelssystems.

Diese Kontrolle ist entscheidend für den Hochfrequenzhandel und komplexe Strategien, bei denen Zuverlässigkeit und Geschwindigkeit von größter Bedeutung sind. Kundenspezifische Implementierungen sind zwar eine Herausforderung, verbessern aber die Zuverlässigkeit und die Integration in produktive Handelssysteme.

Unterschied in der Implementierung von HMAC und SHA-256

  • Python verwendet die hmac-Bibliothek, die HMAC (Hash-based Message Authentication Code) durchführt. Dabei handelt es sich nicht nur um ein Hashing des Textes mit dem Schlüssel, sondern um einen kombinierten Prozess:
    1. Der Schlüssel wird auf die gewünschte Größe ergänzt (oder zugeschnitten).
    2. Es werden zwei Hashing-Schritte durchgeführt: zuerst mit dem Schlüssel und der Nachricht, dann mit dem Schlüssel und dem Zwischenergebnis.
  • MQL5 führt in diesem Code nur eine SHA-256-Berechnung über CryptEncode() ohne vollständige HMAC-Implementierung durch. Dies ist ein normales Text-Hashing mit einem Schlüssel, nicht HMAC.

Schlussfolgerung: Python verwendet HMAC, während MQL5 nur SHA-256 verwendet, was bereits unterschiedliche Ergebnisse garantiert.


Optimierung der Leistung: Ein Tiefgang

Bei der Implementierung von SHA-256 in einer Handelsumgebung ist die Leistungsoptimierung von entscheidender Bedeutung, da jede Millisekunde das Handelsergebnis beeinflussen kann. Eine nutzerdefinierte Implementierung bietet mehrere Möglichkeiten zur Optimierung, die mit den integrierten Funktionen nicht möglich wären.

Handelssysteme weisen bei ihren kryptografischen Operationen häufig bestimmte Muster auf. So enthalten Auftragssignaturen in der Regel ähnliche Komponenten wie Zeitstempel, Symbole und Mengenangaben. Wenn wir diese Muster verstehen, können wir unsere SHA-256-Implementierung speziell für handelsbezogene Datenstrukturen optimieren.

Betrachten Sie, wie die Auftragserteilung in einem typischen Handelsszenario funktioniert. Für jeden Auftrag sind mehrere Informationen erforderlich: das Handelspaar, die Auftragsart, die Menge, der Preis und der Zeitstempel. Bei Standardimplementierungen würden diese Daten jedes Mal als völlig neue Eingabe verarbeitet werden. Wir können diesen Prozess jedoch optimieren, indem wir erkennen, dass viele Komponenten konstant bleiben oder vorhersehbaren Mustern folgen.

Schauen wir uns an, wie diese Optimierung in der Praxis funktioniert. Bei der Erzeugung von Signaturen für Aufträge bleibt die Datenstruktur weitgehend konsistent:

baseEndpoint/symbol=BTCUSDT&side=BUY&type=LIMIT&quantity=0.1&price=50000&timestamp=1234567890

In dieser Zeichenfolge ändern sich in der Regel nur einige wenige Elemente zwischen den Bestellungen: Menge, Preis und Zeitstempel. Indem wir unsere Implementierung so strukturieren, dass diese partiellen Änderungen effizient gehandhabt werden, können wir die Leistung erheblich verbessern. Dies könnte bedeuten:

Die Speicherverwaltung ist besonders wichtig in der MQL5-Umgebung, die ihre eigenen spezifischen Einschränkungen und Merkmale hat. Die MetaTrader-Plattform arbeitet mit begrenzten Ressourcen, und eine ineffiziente Speichernutzung kann die Leistung des gesamten Handelssystems beeinträchtigen. Eine nutzerdefinierte Implementierung ermöglicht uns, die Speicherzuweisung und -freigabe genau auf die Bedürfnisse unserer Handelsoperationen abzustimmen.

Wir können ausgeklügelte Caching-Strategien implementieren, die die zeitliche Lokalität von Handelsoperationen berücksichtigen. So können beispielsweise bei Hochfrequenzhandelssitzungen bestimmte Handelspaare oder Auftragsarten wiederholt verwendet werden. Durch das Zwischenspeichern der Hash-Zwischenstände für diese allgemeinen Muster können wir den Rechenaufwand für nachfolgende Operationen verringern.


Zukunftssicher machen: Langfristige Rentabilität sicherstellen

Die Landschaft der Kryptowährungen ist besonders dynamisch, da die Börsen ihre Anforderungen und Sicherheitsprotokolle häufig aktualisieren. Eine nutzerdefinierte SHA-256-Implementierung bietet die nötige Flexibilität, um sich an diese Änderungen anzupassen und gleichzeitig die Zuverlässigkeit des Systems zu gewährleisten.

Überlegen Sie, wie die Börsen ihre Signaturanforderungen im Laufe der Zeit ändern könnten. Sie könnten:

  • Die Reihenfolge der Parameter in der Signaturzeichenfolge ändern.
  • Neue Pflichtfelder in der Signatur hinzufügen.
  • Ändern, wie bestimmte Zeichen oder Sonderfälle behandelt werden.
  • Neue Sicherheitsmaßnahmen implementieren, die sich auf die Art und Weise auswirken, wie Signaturen erzeugt werden.

Mit einer nutzerdefinierten Implementierung wird die Anpassung an diese Änderungen zum Kinderspiel. Wir behalten die vollständige Kontrolle über jeden Aspekt des Hashing-Prozesses, von der anfänglichen Datenvorverarbeitung bis zur endgültigen Formatierung der Ausgabe. Diese Steuerung ermöglicht es uns, schnell auf neue Anforderungen zu reagieren, ohne auf Updates der in MQL5 integrierten Funktionen warten zu müssen.

Wenn zum Beispiel eine Börse beschließt, die Behandlung von Unicode-Zeichen in Signaturen zu ändern, können wir unsere Implementierung sofort aktualisieren, um den neuen Anforderungen gerecht zu werden. Dieses Maß an Anpassungsfähigkeit ist von entscheidender Bedeutung, wenn man es mit mehreren Börsen zu tun hat, von denen jede möglicherweise unterschiedliche Anforderungen hat.

Die Unabhängigkeit von den integrierten Funktionen von MQL5 ist ein weiterer wichtiger Vorteil. Im Zuge der Weiterentwicklung und Aktualisierung der MetaTrader-Plattform können sich die integrierten Funktionen geringfügig ändern, was sich auf die Signaturerstellung auswirken kann. Eine nutzerdefinierte Implementierung bleibt über verschiedene MetaTrader-Versionen hinweg stabil und gewährleistet ein konsistentes Verhalten unabhängig von Plattform-Updates.

Der Aspekt der Zukunftssicherheit geht über die reinen Signaturanforderungen hinaus. Kryptowährungsbörsen könnten neue Sicherheitsfunktionen oder Authentifizierungsmethoden einführen, die auf SHA-256 aufbauen. Eine nutzerdefinierte Implementierung ermöglicht uns:

  • Erweiterung der grundlegenden SHA-256-Funktionalität zur Unterstützung neuer Sicherheitsmerkmale.
  • Modifizierung der Implementierung für neue Authentifizierungsverfahren.
  • Reibungslose Integration zusätzlicher kryptografischer Operationen.
  • Aufrechterhaltung der Abwärtskompatibilität bei gleichzeitiger Hinzufügung neuer Funktionen.

Darüber hinaus bietet eine nutzerdefinierte Implementierung eine Grundlage für die Implementierung anderer kryptografischer Funktionen, die in Zukunft erforderlich werden könnten. Die für SHA-256 entwickelte Codestruktur und Optimierungstechniken können als Vorlage für die Implementierung anderer Hash-Funktionen oder kryptografischer Operationen dienen.

Stellen Sie sich ein Szenario vor, in dem ein Austausch eine neue Anforderung für doppeltes Hashing einführt oder SHA-256 mit einem anderen Algorithmus kombiniert. Bei einer nutzerdefinierten Implementierung wird das Hinzufügen dieser Funktionen zu einer Frage der Erweiterung des vorhandenen Codes, anstatt zu versuchen, die Einschränkungen der integrierten Funktionen zu umgehen.

Diese Erweiterbarkeit ist besonders wertvoll in der sich schnell entwickelnden Handelslandschaft für Kryptowährungen. Neue Handelsmuster, Sicherheitsanforderungen und technologische Fortschritte können schnell auftauchen, und eine flexible, anpassbare Implementierung ermöglicht es den Handelssystemen, sich an den Markt anzupassen und sich mit ihm weiterzuentwickeln.

Die Kombination aus Leistungsoptimierung und Zukunftssicherheit macht eine nutzerdefinierte SHA-256-Implementierung von unschätzbarem Wert für ernsthafte Kryptowährungshandelsoperationen. Sie bietet die Kontrolle, Flexibilität und Effizienz, die erforderlich sind, um in einem sich schnell verändernden Markt Wettbewerbsvorteile zu erzielen und gleichzeitig die langfristige Lebensfähigkeit bei sich ändernden Anforderungen zu gewährleisten.


Verstehen des SHA-256-Algorithmus

SHA-256 steht für Secure Hash Algorithm 256-bit, eine kryptografische Hash-Funktion, die eine beliebige Eingabe annimmt und eine Ausgabe mit fester Größe von 256 Bit (32 Byte) abbildet. Er gehört zur SHA-2-Familie von Algorithmen und folgt einer sehr systematischen und genau definierten Reihe von Schritten in seinem Prozess - eine Eigenschaft, die sowohl Sicherheit als auch Determinismus ausgleicht.

MQL5-Implementierung

Schauen wir uns die einzelnen Komponenten im Detail an. Die vollständige Implementierung ist im letzten Abschnitt als Referenz verfügbar. In dieser Implementierung werden wir zwei Klassen haben, ähnlich wie in der Python-Implementierung, wo die Klassen HMAC und SHA256 verwendet werden:

Hier ist die Struktur der SHA256- und HMAC-Klasse.

class CSha256Class
  {
private:

   uint              total_message[];
   uint              paddedMessage[64];
   void              Initialize_H();//This function initializes the values of h0-h7
   uint              RawMessage[];//Keeps track of the raw message sent in
public:
   //hash values from h0 - h7
   uint              h0;
   uint              h1;
   uint              h2;
   uint              h3;
   uint              h4;
   uint              h5;
   uint              h6;
   uint              h7;

   uint              K[64];
   uint              W[64];

                     CSha256Class(void);
                    ~CSha256Class() {};

   void              PreProcessMessage(uint &message[], int messageLength);
   void              CreateMessageSchedule();
   void              Compression();
   void              UpdateHash(uint &message[], int message_len);
   void              GetDigest(uint &digest[]);
   string            GetHex();
  };
class HMacSha256
  {
private:

public:
   uint              k_ipad[64];
   uint              k_opad[64];
   uint              K[];
   string            hexval;
                     HMacSha256(string key, string message);
                    ~HMacSha256() {};
   CSha256Class      myshaclass;
   void              ProcessKey(string key);
  };



Eine Schritt-für-Schritt-Anleitung für die Implementierung dieser Klassen

Dieses Modul implementiert den HMAC-Algorithmus, wie in RFC 2104 beschrieben.

Schritt 1:
Erstellen einer Funktion zur Verarbeitung des Schlüssels. 

void HMacSha256::ProcessKey(string key)
  {
   int keyLength = StringLen(key);//stores the length of the key

   if(keyLength>64)
     {
      uchar keyCharacters[];

      StringToCharArray(key, keyCharacters);
      uint KeyCharuint[];
      ArrayResize(KeyCharuint, keyLength);

      //Converts the keys to their characters
      for(int i=0;i<keyLength;i++)
         KeyCharuint[i] = (uint)keyCharacters[i];

      //Time to hash the 
      CSha256Class keyhasher;
      keyhasher.UpdateHash(KeyCharuint, keyLength);

      uint digestValue[];
      keyhasher.GetDigest(digestValue);
      ArrayResize(K, 64);

      for(int i=0;i<ArraySize(digestValue);i++)
         K[i] = digestValue[i];

      for(int i=ArraySize(digestValue);i<64;i++)
         K[i] = 0x00;

     }
   else
     {
      uchar keyCharacters[];

      StringToCharArray(key, keyCharacters);
      ArrayResize(K, 64);

      for(int i=0;i<keyLength;i++)
         K[i] = (uint)keyCharacters[i];

      for(int i=keyLength;i<64;i++)
         K[i] = 0x00;
     }
  }

Diese Implementierung berücksichtigt die Länge des Schlüssels, wenn sie größer als 64 ist, wird er zuerst mit unserer CSha256Class gehasht.

Schritt 2:
Vollständige Implementierung von HMAC.

HMacSha256::HMacSha256(string key,string message)
  {
//process key and add zeros to complete n bytes of 64
   ProcessKey(key);

   for(int i=0;i<64;i++)
     {
      uint keyval = K[i];
      k_ipad[i] = 0x36 ^ keyval;
      k_opad[i] = 0x5c ^ keyval;
     }

//text chars
   uchar messageCharacters[];
   StringToCharArray(message, messageCharacters);
   int innerPaddingLength = 64+StringLen(message);

   uint innerPadding[];
   ArrayResize(innerPadding, innerPaddingLength);
        
   for(int i=0;i<64;i++)
      innerPadding[i] = k_ipad[i];

   int msg_counts = 0;
   for(int i=64;i<innerPaddingLength;i++)
     {
      innerPadding[i] = (uint)messageCharacters[msg_counts];
      msg_counts +=1;
     }

//send inner padding for hashing
   CSha256Class innerpaddHasher;
   innerpaddHasher.UpdateHash(innerPadding, ArraySize(innerPadding));


   uint ipad_digest_result[];
   innerpaddHasher.GetDigest(ipad_digest_result);

//   merge digest with outer padding
   uint outerpadding[];
   int outerpaddSize = 64 + ArraySize(ipad_digest_result);

   ArrayResize(outerpadding, outerpaddSize);
   for(int i=0;i<64;i++)
      outerpadding[i] = k_opad[i];

   int inner_counts = 0;
   for(int i=64;i<outerpaddSize;i++)
     {
      outerpadding[i] = ipad_digest_result[inner_counts];
      inner_counts+=1;
     }

   CSha256Class outerpaddHash;
   outerpaddHash.UpdateHash(outerpadding, ArraySize(outerpadding));
   hexval = outerpaddHash.GetHex();
  }

Weitere Funktionen sind im beigefügten vollständigen Code verfügbar.

Die Schlüsselkomponente dieser Implementierung ist die Hash-Funktion, die von der CSHa256Class gehandhabt wird.

Die Hashing-Funktion umfasst mehrere Schritte zur Bearbeitung des Textes.

Schritt 1: Vorverarbeitung der Werte.

Wir müssen sicherstellen, dass die gesamten Daten ein Vielfaches von 512 Bit sind, also wenden wir einige Auffüllungsoperationen an.

  1. Konvertiere die Nachricht in ihre binäre Form.
  2. Füge 1 am Ende an.
  3. Füge Nullen als Füllung hinzu, bis die Datenlänge 448 Bit erreicht (das sind 512 - 64 Bit). Dadurch wird sichergestellt, dass in dem 512-Bit-Block genau 64 Bits verbleiben. Mit anderen Worten: Wir polstern die Nachricht so auf, dass sie kongruent zu 448 modulo 512 ist.
  4. 64 Bits an das Ende anhängen, wobei die 64 Bits eine Big-Endian-Ganzzahl sind, die die Länge der ursprünglichen Eingabe in binärer Form darstellt.

Schritt 2: Initialisierung der Hash-Werte.

Schritt 3: Initialisierung von runden Konstanten.

Schritt 4: Teile die gesamten Nachrichtenbits in 512 Bits pro Block auf und führe die folgende Operation iterativ an jedem Block durch.

   int chunks_count = (int)MathFloor(ArraySize(total_message)/64.0);
   int copied = 0;

   for(int i=0; i<chunks_count; i++)
     {
      uint newChunk[];
      ArrayResize(newChunk, 64);
      ArrayInitialize(newChunk, 0);  // Initialize chunk array

      for(int j=0; j<64; j++)
        {
         newChunk[j] = total_message[copied];
         copied += 1;
        }

      PreProcessMessage(newChunk, ArraySize(newChunk));
      CreateMessageSchedule();
      Compression();
     }

Schritt 5: Vorverarbeitung der Nachricht durch Kopieren des Chunk-Arrays in ein neues Array, in dem jeder Eintrag ein 32-Bit-Wort ist.

void CSha256Class::PreProcessMessage(uint &message[],int messageLength)
  {
   ArrayInitialize(paddedMessage, 0);
   for(int i=0; i < messageLength; i++)
      paddedMessage[i] = message[i];
  }
Schritt 6: Erstelle den Nachrichtenplan für diesen Chunk.
void CSha256Class::CreateMessageSchedule()
  {
   ArrayInitialize(W, 0);

   int counts = 0;
   for(int i=0; i<ArraySize(paddedMessage); i+=4)
     {
      //32 bits is equivalent to 4 bytes from message
      uint byte1 = paddedMessage[i];
      uint byte2 = paddedMessage[i+1];
      uint byte3 = paddedMessage[i+2];
      uint byte4 = paddedMessage[i+3];

      uint combined = ((byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4);
      W[counts] = combined & 0xFFFFFFFF;

      counts += 1;
     }
   for(int i=counts; i<64; i++)
      W[i] = 0x00000000;
//preserve previous counts

   int prev_counts = counts;
   int left_count = 64-counts;
   for(int i=counts; i<64; i++)
     {
      uint s0 = (RightRotate(W[i-15], 7)) ^ (RightRotate(W[i-15],18)) ^ (W[i-15] >> 3);
      uint s1 = (RightRotate(W[i-2], 17)) ^ (RightRotate(W[i-2],19)) ^ (W[i-2] >> 10);

      W[i] = (W[i-16] + s0 + W[i-7] + s1) & 0xFFFFFFFF;
     }
  }

Schritt 7:  Lege die Kompressionsschlaufe an.

void CSha256Class::Compression(void)
  {
   uint a = h0;
   uint b = h1;
   uint c = h2;
   uint d = h3;
   uint e = h4;
   uint f = h5;
   uint g = h6;
   uint h = h7;

   for(int i=0; i<64; i++)
     {
      uint S1 = (RightRotate(e, 6) ^ RightRotate(e,11) ^ RightRotate(e,25)) & 0xFFFFFFFF;
      uint ch = ((e & f) ^ ((~e) & g))& 0xFFFFFFFF;
      uint temp1 = (h + S1 + ch + K[i] + W[i]) & 0xFFFFFFFF;
      uint S0 = (RightRotate(a, 2) ^ RightRotate(a, 13) ^ RightRotate(a, 22)) & 0xFFFFFFFF;
      uint maj = ((a & b) ^ (a & c) ^ (b & c)) & 0xFFFFFFFF;
      uint temp2 = (S0 + maj) & 0xFFFFFFFF;
      h = g & 0xFFFFFFFF;
      g = f & 0xFFFFFFFF;
      f = e & 0xFFFFFFFF;
      e = (d + temp1) & 0xFFFFFFFF;
      d = c & 0xFFFFFFFF;
      c = b & 0xFFFFFFFF;
      b = a & 0xFFFFFFFF;
      a = (temp1 + temp2)&0xFFFFFFFF;
     }

   h0 = h0 + a;
   h1 = h1 + b;
   h2 = h2 + c;
   h3 = h3 + d;
   h4 = h4 + e;
   h5 = h5 + f;
   h6 = h6 + g;
   h7 = h7 + h;

  }

Nach Abschluss der Komprimierungsschleife aktualisieren wir die endgültigen Hash-Werte, indem wir die geänderten Arbeitsvariablen zu den ursprünglichen Hash-Werten hinzufügen. 
Dieser Additionsvorgang wird nach der Verarbeitung jedes 512-Bit-Blocks der Nachricht durchgeführt, und die aktualisierten Hash-Werte bilden den Ausgangspunkt für die Verarbeitung des nächsten Blocks. Durch diesen Verkettungsmechanismus wird sichergestellt, dass der Hash-Wert jedes Blocks von allen vorherigen Blöcken abhängt, sodass der endgültige Hash-Wert von der gesamten Nachricht abhängt.


Wie man diese Klasse verwendet

Um API-Signaturen für Binance oder Bybit zu generieren, erstellen Sie eine HMAC-Instanz (Hash-based Message Authentication Code), ähnlich der Implementierung von Python.

void OnStart()
{
   // The text to hash
   string text = "Hello";
   string key_text = "key";   
     
  HMacSha256 sha256(key_text, text);
  Print(sha256.hexval);
}

>>> C70B9F4D665BD62974AFC83582DE810E72A41A58DB82C538A9D734C9266D321E

Wenn Sie die von beiden Implementierungen erzeugten Signaturen vergleichen, werden Sie feststellen, dass sie identische Ergebnisse liefern.


Schlussfolgerung

Händler, die mit Kryptowährungen handeln, sehen sich oft mit Problemen bei der Kompatibilität von API-Signaturen, der Leistungsoptimierung und der Zukunftssicherheit konfrontiert, wenn sie integrierte kryptografische Funktionen in Handelssystemen wie MetaTrader 5 verwenden. Dieser Artikel zeigt Händlern, wie sie SHA-256 von Grund auf in MQL5 implementieren, um diese Probleme zu überwinden.

Zusammenfassend lässt sich sagen, dass die Erstellung einer nutzerdefinierten SHA-256-Implementierung Händlern Kompatibilität mit Börsen, verbesserte Leistung und Flexibilität bei der Anpassung an künftige Änderungen bietet, was sie zu einer wesentlichen Strategie für sichere und effiziente Kryptowährungshandelsoperationen macht.

Denken Sie daran, die Implementierung regelmäßig anhand von Standard-Testvektoren zu testen und die Signaturen mit Ihren Zielbörsen zu validieren, bevor Sie sie in der Produktion einsetzen. Da Kryptowährungsbörsen ihre Sicherheitsanforderungen weiterentwickeln, wird sich diese flexible, nutzerdefinierte Implementierung für eine schnelle Anpassung und Wartung als unschätzbar erweisen.

Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/16357

Beigefügte Dateien |
Sha256Algorithm.mqh (18.56 KB)
Sha256TestFile.mq5 (0.89 KB)
Letzte Kommentare | Zur Diskussion im Händlerforum (5)
Sergey Zhilinskiy
Sergey Zhilinskiy | 27 Feb. 2025 in 10:15

Wenn key_text mehr als 64 Zeichen hat, dann berechnet HMacSha256 falsch. Was sollte in diesem Fall korrigiert werden?

Abdulkudus Okatengwu Kadir
Abdulkudus Okatengwu Kadir | 27 Feb. 2025 in 14:08
Sergey Zhilinskiy #:

Wenn key_text mehr als 64 Zeichen hat, dann berechnet HMacSha256 falsch. Was sollte in diesem Fall korrigiert werden?

Meine aktuelle Implementierung passt sich an Schlüssel mit mehr als 64 Zeichen Länge an. Haben Sie ein bestimmtes Schlüssel-/Nachrichtenpaar, bei dem es nicht funktioniert hat?

Sergey Zhilinskiy
Sergey Zhilinskiy | 27 Feb. 2025 in 15:32
Abdulkudus Okatengwu Kadir #:

Meine derzeitige Implementierung passt sich an Schlüssel mit mehr als 64 Zeichen Länge an. Haben Sie ein bestimmtes Schlüssel-Meldungs-Paar, bei dem es nicht funktioniert hat?

string text = "Hallo";

string key_text = "1234567890123456789012345678901234567890123456789012345678901234";

https://www.devglan.com/online-tools/hmac-sha256-online -> 7558a77ff19ed6cb4777355e4bbc4772759a8130e1bb0913ba62b88411fdbaf8

Testskript -> 2025.02.27 22:28:43.792 Sha256TestFile (EURUSD,M5) 6d8ee9dc1d16261fd986fafb97d919584aa206ca76706fb3deccc63ab2b7f6b

if string key_text = "123456789012345678901234567890123456789012345678901234567890123" - OK
Abdulkudus Okatengwu Kadir
Abdulkudus Okatengwu Kadir | 28 Feb. 2025 in 11:39
Sergey Zhilinskiy #:

string text = "Hallo";

string key_text = "1234567890123456789012345678901234567890123456789012345678901234";

https://www.devglan.com/online-tools/hmac-sha256-online -> 7558a77ff19ed6cb4777355e4bbc4772759a8130e1bb0913ba62b88411fdbaf8

Testskript -> 2025.02.27 22:28:43.792 Sha256TestFile (EURUSD,M5) 6d8ee9dc1d16261fd986fafb97d919584aa206ca76706fb3deccc63ab2b7f6b

if string key_text = "123456789012345678901234567890123456789012345678901234567890123" - OK

Ich habe es gerade auf meinem Terminal ausprobiert und das gleiche Ergebnis wie mit dem Online-Hash-Tool erhalten:

2025.02.28 12:37:16.468 hashin_example_code (EURUSD,M5) 7558A77FF19ED6CB4777355E4BBC4772759A8130E1BB0913BA62B88411FDBAF8

unter Verwendung des folgenden Codes:
void Hash()
{
   // Der zu hashende Text
   string text = "Hello";
   string key_text = "1234567890123456789012345678901234567890123456789012345678901234";
   HMacSha256 myhash(key_text, text);
   Print(myhash.hexval);
}
Vielleicht möchten Sie Ihren Code mit anderen teilen.

Sergey Zhilinskiy
Sergey Zhilinskiy | 1 März 2025 in 02:50

Ja, es funktioniert korrekt mit dem Original Sha256Algorithm.mqh. Ich habe einige Änderungen vorgenommen, vielleicht hat es deshalb nicht funktioniert?

 string CSha256Class::GetHex( void )
  {
   string result  = "" ;
 /*
 result += UintToHex(h0);
 result += UintToHex(h1);
 result += UintToHex(h2);
 result += UintToHex(h3);
 result += UintToHex(h4);
 result += UintToHex(h5);
 result += UintToHex(h6);
 result += UintToHex(h7);
*/ 
   result += StringFormat ( "%.2x" ,h0);
   result += StringFormat ( "%.2x" ,h1);
   result += StringFormat ( "%.2x" ,h2);
   result += StringFormat ( "%.2x" ,h3);
   result += StringFormat ( "%.2x" ,h4);
   result += StringFormat ( "%.2x" ,h5);
   result += StringFormat ( "%.2x" ,h6);
   result += StringFormat ( "%.2x" ,h7);

   return (result);
  }

Tut mir leid, Sie zu stören!

Neudefinition der Indikatoren von MQL5 und dem MetaTrader 5 Neudefinition der Indikatoren von MQL5 und dem MetaTrader 5
Ein innovativer Ansatz zur Erfassung von Indikatorinformationen in MQL5 ermöglicht eine flexiblere und rationalisierte Datenanalyse, indem Entwickler nutzerdefinierte Eingaben an Indikatoren für sofortige Berechnungen weitergeben können. Dieser Ansatz ist besonders nützlich für den algorithmischen Handel, da er eine bessere Kontrolle über die von den Indikatoren verarbeiteten Informationen ermöglicht und über die traditionellen Beschränkungen hinausgeht.
Integrieren Sie Ihr eigenes LLM in einen EA (Teil 5): Handelsstrategie mit LLMs(IV) entwickeln und testen - Test der Handelsstrategie Integrieren Sie Ihr eigenes LLM in einen EA (Teil 5): Handelsstrategie mit LLMs(IV) entwickeln und testen - Test der Handelsstrategie
Angesichts der rasanten Entwicklung der künstlichen Intelligenz sind Sprachmodelle (language models, LLMs) heute ein wichtiger Bestandteil der künstlichen Intelligenz, sodass wir darüber nachdenken sollten, wie wir leistungsstarke LLMs in unseren algorithmischen Handel integrieren können. Für die meisten Menschen ist es schwierig, diese leistungsstarken Modelle auf ihre Bedürfnisse abzustimmen, sie lokal einzusetzen und sie dann auf den algorithmischen Handel anzuwenden. In dieser Artikelserie werden wir Schritt für Schritt vorgehen, um dieses Ziel zu erreichen.
Selbstoptimierende Expert Advisor in MQL5 (Teil 4): Dynamische Positionsgrößen Selbstoptimierende Expert Advisor in MQL5 (Teil 4): Dynamische Positionsgrößen
Der erfolgreiche Einsatz des algorithmischen Handels erfordert kontinuierliches, interdisziplinäres Lernen. Die unendlichen Möglichkeiten können jedoch jahrelange Bemühungen verschlingen, ohne greifbare Ergebnisse zu liefern. Um dieses Problem zu lösen, schlagen wir einen Rahmen vor, der die Komplexität schrittweise einführt und es den Händlern ermöglicht, ihre Strategien iterativ zu verfeinern, anstatt sich für unbestimmte Zeit auf ungewisse Ergebnisse festzulegen.
Meistern der Log-Einträge (Teil 4): Speichern der Protokolle in Dateien Meistern der Log-Einträge (Teil 4): Speichern der Protokolle in Dateien
In diesem Artikel zeige ich Ihnen die grundlegenden Dateioperationen und wie Sie einen flexiblen Handler zur Anpassung konfigurieren. Wir werden die Klasse CLogifyHandlerFile aktualisieren, um Protokolle direkt in die Datei zu schreiben. Wir werden einen Leistungstest durchführen, indem wir eine Strategie für EURUSD eine Woche lang simulieren und bei jedem Tick Protokolle erstellen, mit einer Gesamtzeit von 5 Minuten und 11 Sekunden. Das Ergebnis wird in einem zukünftigen Artikel verglichen, in dem wir ein Caching-System zur Verbesserung der Leistung implementieren werden.