Delphi HMAC算法

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都可行,以下就贴出其中三个效果图吧,其他就不贴了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值