gpt4 book ai didi

Delphi - 无法让 HMAC-SHA256 通过 RFC 4231 测试向量

转载 作者:行者123 更新时间:2023-12-03 15:10:29 30 4
gpt4 key购买 nike

我需要访问 Amazon REST 服务,就像之前在“HMAC-SHA256 in Delphi”中提出的问题一样。由于这必须在 D2010 中,我尝试使用最新的 libeay32.dll 来通过 RFC 4231 中的测试向量:

https://www.rfc-editor.org/rfc/rfc4231

有人有一种方法可以使用这个库在 Delphi 中通过这些测试吗?我提到的帖子中 shunty 发布的代码通过了前两个测试向量以及第五个测试向量,但在第三个和第四个测试向量中失败了。这些向量超过 64 个字节,并且由于我需要为 Amazon 签名的所有 url 都超过 64 个字节,这是一个问题。我一直无法弄清楚我是否做错了什么。 OpenSSL 测试位于 hmactest.c 中,但它仅检查 EVP_md5 并且测试向量与 RFC 中的不完全相同。我需要它与 SHA256 一起使用,以便我可以根据 RFC 中的测试向量进行验证。我使用以下常量进行测试(常量现已更新,以供将来的查看者修复下面评论中提到的复制和粘贴错误):

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';

我不知道 shunty 的这段代码粘贴进去后会是什么样子,因为它在这里看起来很糟糕(我是一个 stackoverflow 新手)。我像他一样使用 RAND_seed 而不是 RAND_load_file,但其他方面是相同的:

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;

我用来测试的代码如下所示。此特定方法适用于失败的测试 3。结果是 bb861233f283aef2ef7aea09785245c9f3c62720c9d04e0c232789f27a586e44,但它应该等于 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;

有什么想法吗?我即将放弃,只是使用他们提供的库创建一个 .NET 应用程序...

最佳答案

您正在使用 D2009+(从您使用 TEncoding 可以看出),这意味着您正在处理 UnicodeString,但您没有在逻辑中考虑 Unicode 。 RFC 不对字符进行操作,而是对字节进行操作。您的测试数据包含十六进制编码的字符串。当您将它们解码为 (Unicode)String 值时,许多结果字符超出了 ASCII 字符范围,这意味着它们必须先由 Ansi 代码页解释,然后才能将其转换为 UTF- 8 正确(无论如何你不应该在这种情况下使用)。

您需要更改实现以将十六进制字符串直接解码为 TBytes (您可以使用 Classes.HexToBin() ),因此正确的字节值是保留并传递给 HMAC,并完全摆脱 TEncoding.UTF8.GetBytes():

function TForm1.GetHMAC(const AKey, AData: TBytes): TBytes; 
var
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);
md_len := EVP_MAX_MD_SIZE;
SetLength(Result, md_len);
res := HMAC(EVP_sha256, Pointer(AKey), Length(AKey), Pointer(AData), Length(AData), @Result[0], md_len);
if (res <> nil) then
SetLength(Result, md_len);
finally
FreeMem(buf);
end;
end;

function HexToBytes(const S: String): TBytes;
begin
SetLength(Result, Length(S) div 2);
SetLength(Result, HexToBin(PChar(S), Pointer(Result), Length(Result)));
en;

procedure TForm1.btnTestCase3Click(Sender: TObject);
var
LBytesDigest: TBytes;
LHashString: string;
LHexDigest: string;
begin
LBytesDigest := GetHMAC(HexToBytes(TEST3_KEY), HexToBytes(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;

关于Delphi - 无法让 HMAC-SHA256 通过 RFC 4231 测试向量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9985787/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com