Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   DXE7+Indy: HMAC SHA256 - Encoding (https://www.delphipraxis.net/190563-dxe7-indy-hmac-sha256-encoding.html)

KaiW 16. Okt 2016 12:01

DXE7+Indy: HMAC SHA256 - Encoding
 
Hallo zusammen,

das eigentliche Kernproblem: Ich möchte die PHP-Funktionen hash_hmac und base64_encode in Delphi abbilden um das Datum '1234567890' mit dem Schlüssel 'ABCDEFG' zu signieren und das Ergebnis anschließend base64 kodieren.

In PHP sieht das ganze folgendermaßen aus:
Code:
echo base64_encode(hash_hmac('sha256', '1234567890', 'ABCDEFG', TRUE));
Ausgabe: aRGlc3RY1pKmKX0hvorkVKNcPigiJX2rksqXzlAeCLg=

Ich habe die Indy-Klasse TIdHMACSHA256 auserkoren, dies für mich zu tun:

Delphi-Quellcode:
uses
  IdHash, IdHashSHA, IdHMACSHA1, IdSSLOpenSSL, IdGlobal, IdCoderMIME;

function GenerateSignature(const AKey, AData: string): string;
var
   AHMAC: TIdBytes;
begin
     IdSSLOpenSSL.LoadOpenSSLLibrary;

     With TIdHMACSHA256.Create do
      try
         Key:= ToBytes(AKey, IndyTextEncoding_UTF16LE);
         AHMAC:= HashValue(ToBytes(AData, IndyTextEncoding_UTF16LE));
         Result:= TIdEncoderMIME.EncodeBytes(AHMAC);
      finally
         Free;
      end;
end;
Rückgabewert: H3eBWh0jKF0WZIK+NcYdwXRQAWrMrNLfOM3/mBU0XpU=

Auffällig ist, dass der Rückgabewert bei
Delphi-Quellcode:
Memo.Lines.Text:= GenerateSignature('1234567890', 'ABCDEFG');
nicht mit dem über PHP ermittelten Wert übereinstimmt.
Meine Kernfrage lautet also: Warum ist das so und wie bekomme ich den gleichen Wert, den ich über die PHP-Funktionen erhalte?

Mein bisheriger Ansatz:
Ich vermute ein Problem mit den Zeichensätzen.
Ich habe verstanden, dass der Datentyp "string" bei Delphi XE7 dem Typ "UnicodeString" entspricht. UnicodeString arbeitet intern mit 2 Byte großen Zeichen (also 16bit) und ist UTF16 kodiert. http://docwiki.embarcadero.com/RADSt...Types_(Delphi).

Die Indy-Funktion "ToBytes" erwartet einen UnicodeString, sowie eine Zeichensatzangabe. Wird keine angegeben, wird ASCII verwendet, was ja zu Datenverlust führen könnte/wird. Also gebe ich UTF16 an. Da bei UTF16 zwischen BE (Big-Endian) und LE(Little-Endian) gewählt werden muss, habe ich mich für UTF16LE entschieden, da einerseits in einigen Artikeln im Netz LE als von "aktuellen Maschinen" verwendet bezeichnet wurde und andererseits Delphi's eigene Encodings "Unicode" und "BigEndianUnicode" heißen, was impliziert, dass Unicode (also LE) der Standard ist. Ich hatte hier auch bereits mit anderen Zeichensätzen experimentiert, jedoch ohne Erfolg.

Da
Delphi-Quellcode:
TIdEncoderMIME.EncodeBytes(AHMAC);
bei Übergabe der IdBytes als Parameter zunächst alles in einen Stream schreibt und diesen dann mit Charset 8bit wieder ausliest, vermute ich hier ebenfalls eine Fehlerquelle. Daher habe ich stattdessen auch

Delphi-Quellcode:
Result:= BytesToString(AHMAC, IndyTextEncoding_UTF16LE);
Result:= TIdEncoderMIME.EncodeString(Result, IndyTextEncoding_UTF16LE);
probiert. Leider ebenfalls ohne Erfolg.

Für jedwede Hilfe bin ich dankbar.

Kai

KaiW 18. Okt 2016 12:09

AW: DXE7+Indy: HMAC SHA256 - Encoding
 
Hallo,

hier die Lösung für alle, die ein ähnliches Problem haben:

Delphi-Quellcode:
function GenerateSignature(const AData, AKey: string): string;
var
   AHMAC: TIdBytes;
begin
     IdSSLOpenSSL.LoadOpenSSLLibrary;

     IF NOT TIdHashSHA256.IsAvailable
      THEN Raise Exception.Create('SHA-256 hashing is not available!');

     With TIdHMACSHA256.Create do
      try
         Key:= IndyTextEncoding_UTF8.GetBytes(AKey);
         AHMAC:= HashValue(IndyTextEncoding_UTF8.GetBytes(AData));
      finally
         Free;
      end;

     Result:= TIdEncoderMIME.EncodeBytes(AHMAC);
end;
Es muß also definitiv UTF8 verwendet werden, um ein gleiches Ergebnis zu erzielen.

Für weitere Informationen zum Thema Amazon MWS Signatur mit Delphi und Indy, siehe auch den folgenden Thread in Englisch:
http://stackoverflow.com/questions/4...d-indy-classes


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:20 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz