Necesito acceder a los servicios de Amazon REST como una pregunta anterior en "HMAC-SHA256 in Delphi". Dado que este tiene que estar en D2010 Estoy tratando de utilizar la última libeay32.dll para pasar los vectores de prueba en el RFC 4231:Delphi - No se puede obtener HMAC-SHA256 para pasar los vectores de prueba RFC 4231
http://tools.ietf.org/html/rfc4231
¿alguien tiene un método que pasa estas pruebas en Delphi que utilizan esta biblioteca ? El código publicado por shunty en la publicación a la que me he referido pasa los primeros dos vectores de prueba y el quinto, pero falla en el tercero y el cuarto. Esos vectores tienen más de 64 bytes y dado que todas las URL que debo firmar para Amazon tienen más de 64 bytes, esto es un problema. No he podido averiguar si estoy haciendo algo mal. La prueba OpenSSL está en hmactest.c, pero solo verifica EVP_md5 y los vectores de prueba no son todos iguales que en RFC. Necesito que esto funcione con SHA256 para que pueda verificar contra los vectores de prueba en el RFC. Estoy usando las siguientes constantes para las pruebas constantes (ahora actualizado para futuros espectadores para arreglar mis copiar y pegar errores mencionados en los comentarios a continuación):
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';
No sé cómo este código por shunty se verá pegado porque se ve terrible aquí (soy un principiante de stackoverflow). Solía RAND_seed en lugar de RAND_load_file como lo hizo, pero por lo demás es lo mismo:
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;
El código que utilizo para la prueba es el siguiente. Este método particular es para la prueba 3 que falla. El resultado es bb861233f283aef2ef7aea09785245c9f3c62720c9d04e0c232789f27a586e44, pero debe ser igual al valor hexadecimal constante para 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;
¿Alguna idea? Estoy a punto de darse por vencido y acaba de crear una aplicación .NET utilizando la biblioteca que proporcionan ...
En mi defensa, se usó el UTF8.GetBytes porque eso era lo que requería la parte interna de la aplicación en particular en la que estábamos trabajando, nunca interactuamos con nada fuera de la aplicación. Y hay un descargo de responsabilidad en la parte inferior de la publicación que indica que no lo había usado contra los datos de referencia. Y hemos mejorado en los últimos dos años :-) – shunty
Interesante. En un momento tuve un GetHMAC sobrecargado que tomaba TBytes como parámetros. Sin embargo, no estoy seguro si estaba usando las pruebas codificadas Hex del RFC en ese momento. Probablemente no funcionó debido a algunos problemas Unicode. Nunca antes tuve que lidiar con esto directamente así. Para Amazon, debe tomar un URI, convertirlo con HMAC SHA1 o SHA256, luego convertirlo a Base64, luego codificarlo con URL, luego agregar la firma al URI original. En Delphi es como caminar de un tanque de tiburones a otro y a otro de nuevo. El código que usa la biblioteca .NET de Amazon es tan simple en comparación. –
@shunty - Gracias por la publicación original.Parece mi comentario de que dijiste que no lo habías probado en comparación con los datos de referencia que se descartaron en algún momento de la edición. Eso estuvo bien porque tu descargo de responsabilidad es lo que me hizo encontrar el RFC y tratar de que funcionen sus pruebas con codificación hexadecimal. –