【发布时间】:2014-08-21 21:41:21
【问题描述】:
我将下面的代码与 Crypto API 一起使用,但我没有得到基于对其他 API 和库的测试所期望的结果。
我正在使用密钥“key”,数据为“message”
例如,使用 Indy 的 TidHMACSHA1,我得到 2088df74d5f2146b48146caf4965377e9d0be3a4
我使用在线生成器(例如http://www.freeformatter.com/hmac-generator.html)得到了相同的结果。
使用我编写的代码(见下文),我得到 4a52c3c0abc0a06049d1ab648bb4057e3ff5f359
代码如下,我使用的是 JEDI wcrypt2.pas 标头
function Hashhmacsha1(const Key, Value: AnsiString): AnsiString;
var
hCryptProvider: HCRYPTPROV;
hHash: HCRYPTHASH;
hKey: HCRYPTKEY;
bHash: array[0..$7F] of Byte;
dwHashLen: dWord;
i: Integer;
hHmacHash: HCRYPTHASH;
bHmacHash: array[0..$7F] of Byte;
dwHmacHashLen: dWord;
hmac_info : Wcrypt2.HMAC_INFO;
begin
dwHashLen := 32;
dwHmacHashLen := 32;
{get context for crypt default provider}
if CryptAcquireContext(@hCryptProvider, nil, nil, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT or CRYPT_MACHINE_KEYSET) then
begin
{create hash-object }
if CryptCreateHash(hCryptProvider, CALG_SHA1, 0, 0, @hHash) then
begin
{get hash from password}
if CryptHashData(hHash, @Key[1], Length(Key), 0) then
begin
// hHash is now a hash of the provided key, (SHA1)
// Now we derive a key for it
if CryptDeriveKey(hCryptProvider, CALG_RC4, hHash, 0, @hKey) then
begin
//hkey now holds our key. So we have do the whole thing over again
//ZeroMemory( hmac_info, SizeOf(hmac_info) );
hmac_info.HashAlgid := CALG_SHA1;
if CryptCreateHash(hCryptProvider, CALG_HMAC, hKey, 0, @hHmacHash) then
begin
{get hash from password}
if CryptSetHashParam( hHmacHash, HP_HMAC_INFO, @hmac_info, 0) then
begin
if CryptHashData(hHmacHash, @Value[1], Length(Value), 0) then
begin
if CryptGetHashParam(hHmacHash, HP_HASHVAL, @bHmacHash[0], @dwHmacHashLen, 0) then
begin
for i := 0 to dwHmacHashLen-1 do
Result := Result + IntToHex(bHmacHash[i], 2);
end
else
WriteLn( 'CryptGetHashParam ERROR --> ' + SysErrorMessage(GetLastError)) ;
end
else
WriteLn( 'CryptHashData ERROR --> ' + SysErrorMessage(GetLastError)) ;
{destroy hash-object}
CryptDestroyHash(hHmacHash);
CryptDestroyKey(hKey);
end
else
WriteLn( 'CryptSetHashParam ERROR --> ' + SysErrorMessage(GetLastError)) ;
end
else
WriteLn( 'CryptCreateHash ERROR --> ' + SysErrorMessage(GetLastError)) ;
end
else
WriteLn( 'CryptDeriveKey ERROR --> ' + SysErrorMessage(GetLastError)) ;
end;
{destroy hash-object}
CryptDestroyHash(hHash);
end;
{release the context for crypt default provider}
CryptReleaseContext(hCryptProvider, 0);
end;
Result := AnsiLowerCase(Result);
end;
我显然做错了什么,但我不知道是什么??
【问题讨论】:
-
看到这样的问题,我首先想到的是“因为Unicode问题”。但看起来你正在使用 AnsiStrings,所以这实际上并不是问题的根源......
-
是的,我考虑到了这一点,这就是我使用 AnsiStrings 的原因——所以我有一个比较有效的比较。好像没用!!
-
我不确定这是否会有所帮助,但所有散列算法都适用于二进制数据。在您的情况下,您为它提供了一个以空字符结尾的字符串(Delphi 字符串是以空字符结尾的字符串)。这可能意味着它在计算哈希时也会在字符串末尾使用那个 nul 字符。因此,您可能想使用 ansi 字符数组作为输入值,而不是默认的 Delphi ansi 字符串。
-
@SilverWarior 感谢您的建议,但我已经发现这不是问题所在。我正在发布一个有效的答案,有点过......
-
您应该停止将字符串缓冲区视为二进制。将 Unicode 字符串转换为 utf8 字节并对其进行哈希处理。
标签: delphi delphi-xe5 cryptoapi hmacsha1