我需要为 Amazon Web 服务 API 生成 HMAC-SHA256 签名。旧的 DCPcrypt 库具有 sha256 例程,但不进行 HMAC 签名。有人知道我可以使用的免费哈希库吗?
9 回答
Delphi 安装了 Indy,Indy 有一个TIdHMACSHA256
类:
uses
IdGlobal, IdHashSHA, IdHMAC, IdHMACSHA1, IdSSLOpenSSL;
function CalculateHMACSHA256(const value, salt: String): String;
var
hmac: TIdHMACSHA256;
hash: TIdBytes;
begin
LoadOpenSSLLibrary;
if not TIdHashSHA256.IsAvailable then
raise Exception.Create('SHA256 hashing is not available!');
hmac := TIdHMACSHA256.Create;
try
hmac.Key := IndyTextEncoding_UTF8.GetBytes(salt);
hash := hmac.HashValue(IndyTextEncoding_UTF8.GetBytes(value));
Result := ToHex(hash);
finally
hmac.Free;
end;
end;
经过一番搜索后,我找到了 OpenStreamSec - 看起来它在几年前就被废弃了,但仍在 D2007 中编译。
http://sourceforge.net/projects/openstrsecii/
为 Amazon 生成 HMAC-256 非常简单:
StrToMime64(HMACString(haSHA256, SecretKey, 32, DataToHash));
我最喜欢的答案 - 我会使用 OpenSSL 库、HMAC 函数。通过采用和改编 M Ferrante http://www.disi.unige.it/person/FerranteM/delphiopenssl/
的工作,我已经成功地在 Delphi 中使用了 OpenSSL 库。
对于其他 OpenSSL 签名等,请参阅此链接
在 D2010 中是这样的(libeay32 是取自网站的单位,针对 unicode/D2010 稍作修改):
uses libeay32;
const
LIBEAY_DLL_NAME = 'libeay32.dll';
EVP_MAX_MD_SIZE = 64;
function EVP_sha256: pEVP_MD; cdecl; external LIBEAY_DLL_NAME;
function HMAC(evp: pEVP_MD; key: PByte; key_len: integer;
data: PByte; data_len: integer;
md: PByte; var md_len: integer): PByte; cdecl; external LIBEAY_DLL_NAME;
function GetHMAC(const AKey, AData: string): TBytes;
var
key, data: TBytes;
md_len: integer;
res: PByte;
begin
OpenSSL_add_all_algorithms;
// Seed the pseudo-random number generator
// This should be something a little more "random"!
RAND_load_file('c:\windows\paint.exe', 512);
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
begin
SetLength(result, md_len);
end;
end;
然后用关键短语和数据字符串调用它。结果是一个 TBytes,可以根据需要转换为 Base64,例如使用 JclMime 或简单的 HexToString 类型函数。
对于旧版本的 Delphi,您必须将 PBytes 更改为 PChars 或类似的东西。
免责声明:我没有参考数据来测试它,但它似乎工作正常!
你看过这个SO问题的答案吗?
关于 Jacob 的回答:OpenStrSecII 是 StreamSec Tools 2.1 的一个分支,它是在商业严肃许可下出售的,今天(2012 年 2 月 8 日)支持 Delphi Win32,包括 Delphi XE2。StreamSec Tools 4.0 也支持 Win64。
在网上搜索时我也发现了这个,在Delphi10下编译正确:
result:= (TNetEncoding.Base64.EncodeBytesToString(THashSHA2.GetHMACAsBytes(TEncoding.UTF8.GetBytes(StringToSign),TNetEncoding.Base64.DecodeStringToBytes(Key))));
尽管我在正在进行的过程中确实遇到了麻烦-不确定它是否与此功能有关..
该GetHMAC
函数在类中也可用THashSHA2
,在模块中System.Hash
。
我不确定这是从哪个版本的 Delphi 中可用的。它肯定在 Delphi 10 Seattle 及以后。
使用最新版本的 Delphi,一切都变得简单多了……
uses system.hash;
var s, sst:string;
bt:TBytes;
HMAC 256:
s:=THashSHA2.GetHMAC(DATA, KEY, SHA256);
base64 HMAC 256:
bt:= THashSHA2.GetHMACAsBytes(DATA, KEY, SHA256);
sst:= TNetEncoding.Base64.EncodeBytesToString(bt);