Ho bisogno di accedere ai servizi Amazon REST come una domanda precedente a "HMAC-SHA256 in Delphi" richiesto. Dal momento che questo deve essere in D2010 sto cercando di utilizzare l'ultima libeay32.dll di passare i vettori di test nella RFC 4231:Delphi - Impossibile ottenere HMAC-SHA256 per passare i vettori di prova RFC 4231
http://tools.ietf.org/html/rfc4231
Qualcuno ha un metodo che passa questi test in Delphi che utilizzano questa libreria ? Il codice pubblicato da shunty nel post a cui ho fatto riferimento passa i primi due vettori di test e anche il quinto, ma fallisce nel terzo e nel quarto. Questi vettori sono oltre 64 byte e poiché tutti gli URL che devo firmare per Amazon sono superiori a 64 byte, questo è un problema. Non sono stato in grado di capire se sto facendo qualcosa di sbagliato. Il test OpenSSL è in hmactest.c, ma controlla solo EVP_md5 ei vettori di test non sono tutti uguali a quelli della RFC. Ho bisogno di questo per lavorare con SHA256 in modo da poter verificare i vettori di prova nella RFC. Sto utilizzando le seguenti costanti per le prove (costanti ora aggiornato per gli spettatori futuri per correggere i miei errori di copia e incolla menzionati nei commenti qui sotto):
const
LIBEAY_DLL_NAME = 'libeay32.dll';
EVP_MAX_MD_SIZE = 64;
//RFC 4231 Test case 1
TEST1_KEY: string = '0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b';
TEST1_DATA: string = '4869205468657265';
TEST1_DIGEST: string = 'b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7';
//RFC 4231 Test case 2
TEST2_KEY = '4a656665';
TEST2_DATA = '7768617420646f2079612077616e7420666f72206e6f7468696e673f';
TEST2_DIGEST = '5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843';
//RFC 4231 Test case 3
TEST3_KEY = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
TEST3_DATA = 'dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd';
TEST3_DIGEST = '773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe';
//RFC 4231 Test case 4
TEST4_KEY = '0102030405060708090a0b0c0d0e0f10111213141516171819';
TEST4_DATA = 'cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd';
TEST4_DIGEST = '82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b';
//RFC 4231 Test case 5
TEST5_KEY = '0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c';
TEST5_DATA = '546573742057697468205472756e636174696f6e';
TEST5_DIGEST = 'a3b6167473100ee06e0c796c2955552b';
non so come questo codice shunty guarderà incollato perché sembra terribile qui (sono un novizio dello stackoverflow). Ho usato rand_seed piuttosto che RAND_load_file come ha fatto, ma per il resto è la stessa:
function TForm1.GetHMAC(const AKey, AData: string): TBytes;
var
key, data: TBytes;
md_len: integer;
res: PByte;
buf: PInteger;
rand_val: Integer;
begin
OpenSSL_add_all_algorithms;
Randomize;
rand_val := Random(100);
GetMem(buf, rand_val);
try
RAND_seed(buf, rand_val);
key := TEncoding.UTF8.GetBytes(AKey);
data := TEncoding.UTF8.GetBytes(AData);
md_len := EVP_MAX_MD_SIZE;
SetLength(Result, md_len);
res := HMAC(EVP_sha256, @key[0], Length(key), @data[0], Length(data), @result[0], md_len);
if (res <> nil) then
SetLength(Result, md_len);
finally
FreeMem(buf);
end;
end;
Il codice che uso per test di simile a questo. Questo particolare metodo è per il test 3 che fallisce. Il risultato è bb861233f283aef2ef7aea09785245c9f3c62720c9d04e0c232789f27a586e44, ma dovrebbe essere uguale al valore esadecimale costante per TEST3_DIGEST:
procedure TForm1.btnTestCase3Click(Sender: TObject);
var
LBytesDigest: TBytes;
LHashString: string;
LHexDigest: string;
begin
LBytesDigest := GetHMAC(HexToStr(TEST3_KEY), HexToStr(TEST3_DATA));
LHexDigest := LowerCase(BytesToHex(LBytesDigest));
if LHexDigest = TEST3_DIGEST then begin
Memo1.Lines.Add('SUCCESS: Matches test case');
Memo1.Lines.Add(LHexDigest);
end else begin
Memo1.Lines.Add('ERROR: Does not match test case');
Memo1.Lines.Add('Result: ' + LHexDigest);
Memo1.Lines.Add('Test Case: ' + TEST3_DIGEST);
end;
end;
Tutte le idee? Sto per mollare e basta creare una app .NET usando la libreria che forniscono ...
In mia difesa, è stato utilizzato UTF8.GetBytes perché era quello che richiedevano gli interni della particolare app su cui stavamo lavorando: non abbiamo mai interagito con nessun elemento esterno all'app. E c'è un disclaimer in fondo al post che afferma che non l'ho usato contro i dati di riferimento. E siamo migliorati negli ultimi due anni :-) – shunty
Interessante. A un certo punto ho avuto un GetHMAC sovraccarico che ha preso TByte come parametri. Non sono sicuro se stavo usando i test codificati Hex dal RFC al momento, però. Probabilmente non ha funzionato a causa di alcuni problemi Unicode. Non ho mai dovuto affrontarlo direttamente come prima. Per Amazon devi prendere un URI, convertirlo con HMAC SHA1 o SHA256, quindi convertirlo in Base64, quindi codificare l'URL, quindi aggiungere la firma all'URI originale. In Delphi è come camminare da un carro di squali in un altro e di nuovo in un altro. Il codice utilizzato dalla libreria .NET di Amazon è così semplice al confronto. –
@shunty - Grazie per il post originale.Sembra che il mio commento abbia affermato che non era stato testato su nessun dato di riferimento che è stato eliminato a un certo punto del montaggio. Questo andava bene perché il tuo disclaimer è ciò che mi ha fatto trovare la RFC e provare a far funzionare i loro test con codifica esadecimale. –