1. 前言
今天做一个三方接口,接口文档描述签名采用MD5,但是实际测试过程中,始终校验不通过,经过和三方沟通,才知道采用的是HMAC-MD5。由于Delphi7没有对HMAC的支持,则采用XE版本来支持。本次使用Delphi XE 10.3.3、Delphi 7来实现。
HMAC 散列消息认证码 (Hash-based Message Authentication Code),它是一种基于加密哈希函数和共享密钥的消息认证协议。它是一种给消息加上数字签名的方法,这个签名是根据消息内容和一个共享密钥生成的,只有知道密钥的人才能生成或验证这个签名。
HMAC - https://baike.baidu.com/item/hmac/7307543
在线验证 https://www.btool.cn/hmac-generator
2. Delphi XE 10.3.3 实现动态库
2.1 工程文件 hmactool.dpr
library hmactool;
{
HMAC 散列消息认证码 (Hash-based Message Authentication Code)
它是一种基于加密哈希函数和共享密钥的消息认证协议。
它是一种给消息加上数字签名的方法,这个签名是根据消息内容和一个共享密钥生成的,只有知道密钥的人才能生成或验证这个签名。
HMAC - https://baike.baidu.com/item/hmac/7307543
在线验证 https://www.btool.cn/hmac-generator
}
uses
Winapi.Windows,
System.SysUtils,
System.Classes,
InterfaceDll in 'InterfaceDll.pas';
{$R *.res}
exports
dll_hmac_md5,
dll_hmac_sha1,
dll_hmac_sha2;
procedure DLLHandler(Reason: integer);
var
buf: array[0..1023] of char;
begin
case Reason of
DLL_PROCESS_DETACH: //释放DLL时
begin
end;
DLL_Process_Attach: //加载DLL时
begin
end;
DLL_Thread_Attach: //主进程创建一个新线程时
begin
end;
DLL_Thread_Detach: //主进程结束一个线程时
begin
end;
end;
end;
begin
DLLProc := @DLLHandler;
DLLHandler(DLL_Process_Attach);
end.
2.2 接口文件 InterfaceDll.pas
unit InterfaceDll;
interface
uses
System.SysUtils, System.Hash;
var
ErrInfo: WideString;
function dll_hmac_md5(sIn, sKey: PWideChar; var sOut: PWideChar): Byte; stdcall;
function dll_hmac_sha1(sIn, sKey: PWideChar; var sOut: PWideChar): Byte; stdcall;
function dll_hmac_sha2(iType: Byte; sIn, sKey: PWideChar; var sOut: PWideChar): Byte; stdcall;
implementation
function dll_hmac_md5(sIn, sKey: PWideChar; var sOut: PWideChar): Byte; stdcall;
var
Key, Data: WideString;
Hash: THashMD5;
HMAC: WideString;
begin
Data := Trim(sIn);
Key:= Trim(sKey);
Hash := THashMD5.Create;
HMAC := Hash.GetHMAC(Data, Key);
sOut:= PWideChar(HMAC);
result:= 0;
end;
function dll_hmac_sha1(sIn, sKey: PWideChar; var sOut: PWideChar): Byte; stdcall;
var
Key, Data: WideString;
Hash: THashSHA1;
HMAC: WideString;
begin
Data := Trim(sIn);
Key:= Trim(sKey);
Hash := THashSHA1.Create;
HMAC := Hash.GetHMAC(Data, Key);
sOut:= PWideChar(HMAC);
result:= 0;
end;
function dll_hmac_sha2(iType: Byte; sIn, sKey: PWideChar; var sOut: PWideChar): Byte; stdcall;
var
Key, Data: WideString;
Hash: THashSHA2;
HMAC: WideString;
begin
Data := Trim(sIn);
Key:= Trim(sKey);
Hash := THashSHA2.Create(THashSHA2.TSHA2Version(iType));
HMAC := Hash.GetHMAC(Data, Key, THashSHA2.TSHA2Version(iType));
sOut:= PWideChar(HMAC);
result:= 0;
end;
end.
3. Delphi 7 实现Demo
3.1 工程文件 D7Demo.dpr
program D7Demo;
uses
Forms,
uDemo in 'uDemo.pas' {FrmMain};
{$R *.res}
begin
Application.Initialize;
Application.CreateForm(TFrmMain, FrmMain);
Application.Run;
end.
3.2 窗体代码 uDemo.pas
unit uDemo;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls;
const
dllname= 'hmactool.dll';
type
TFrmMain = class(TForm)
redt1: TRichEdit;
btn1: TButton;
edt1: TEdit;
edt2: TEdit;
lbl1: TLabel;
lbl2: TLabel;
lbl3: TLabel;
btn2: TButton;
grp1: TGroupBox;
btn3: TButton;
rb1: TRadioButton;
rb2: TRadioButton;
rb3: TRadioButton;
rb4: TRadioButton;
rb5: TRadioButton;
rb6: TRadioButton;
procedure btn1Click(Sender: TObject);
procedure btn2Click(Sender: TObject);
procedure btn3Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
function dll_hmac_md5(pIn, pKey: PWideChar; var pOut: PWideChar): Byte; stdcall; external dllname;
function dll_hmac_sha1(sIn, sKey: PWideChar; var sOut: PWideChar): Byte; stdcall; external dllname;
function dll_hmac_sha2(iType: Byte; sIn, sKey: PWideChar; var sOut: PWideChar): Byte; stdcall; external dllname;
var
FrmMain: TFrmMain;
implementation
{$R *.dfm}
procedure TFrmMain.btn1Click(Sender: TObject);
var
sIn, sKey, sOut: WideString;
pOut: PWideChar;
iRet: Byte;
begin
sIn:= StringReplace(Trim(redt1.Lines.Text),#13#10,'',[rfReplaceAll,rfIgnoreCase]);
sKey:= Trim(edt2.Text);
iRet:= dll_hmac_md5(PWideChar(sIn), PWideChar(sKey), pOut);
if (iRet= 0) then
begin
edt1.Text:= UTF8Decode(pOut);
end;
end;
procedure TFrmMain.btn2Click(Sender: TObject);
var
sIn, sKey, sOut: WideString;
pOut: PWideChar;
iRet: Byte;
begin
sIn:= StringReplace(Trim(redt1.Lines.Text),#13#10,'',[rfReplaceAll,rfIgnoreCase]);
sKey:= Trim(edt2.Text);
iRet:= dll_hmac_sha1(PWideChar(sIn), PWideChar(sKey), pOut);
if (iRet= 0) then
begin
edt1.Text:= UTF8Decode(pOut);
end;
end;
procedure TFrmMain.btn3Click(Sender: TObject);
var
sIn, sKey, sOut: WideString;
pOut: PWideChar;
iType, iRet: Byte;
begin
if rb1.Checked then
iType:= 0
else if rb2.Checked then
iType:= 1
else if rb3.Checked then
iType:= 2
else if rb4.Checked then
iType:= 3
else if rb5.Checked then
iType:= 4
else if rb6.Checked then
iType:= 5;
sIn:= StringReplace(Trim(redt1.Lines.Text),#13#10,'',[rfReplaceAll,rfIgnoreCase]);
sKey:= Trim(edt2.Text);
iRet:= dll_hmac_sha2(iType, PWideChar(sIn), PWideChar(sKey), pOut);
if (iRet= 0) then
begin
edt1.Text:= UTF8Decode(pOut);
end;
end;
end.
4. 最终效果
测试了MD5、SHA1、SHA224、SHA256、SHA384、SHA512、SHA512-224、SHA512-256都可行,以下就贴出其中三个效果图吧,其他就不贴了。




1744

被折叠的 条评论
为什么被折叠?



