zoukankan      html  css  js  c++  java
  • 【Delphi】HMACMD5算法(三):实现

     //******************************************************************************
    //基于MD5算法的Hash MAC:实现
    //******************************************************************************
    //作者:Cai
    //日期:2011-10-25
    //******************************************************************************
    
    unit HMAC_MD5Class;
    
    
    interface
    uses
        MD5Class;
    
    type
    
    THMAC_MD5Context = record
        MD5Context: TMD5Context;
        Key : TBytes_64;
        InPad : TBytes_64;
        OutPad : TBytes_64;
    end;
    
    THMAC_MD5Class = Class
    protected
        FHash: TMD5Class;
    public
        constructor Create(); virtual;
        destructor Destroy; override;
        //=========基于MD5的Hash MAC算法:实现==========
        procedure HMAC_MD5Init(var Context: THMAC_MD5Context; sKey: string);
        procedure HMAC_MD5Update(var Context: THMAC_MD5Context; pInBuffer: PByte; iInBufLen: UINT4);
        procedure HMAC_MD5Final(var Digest: TMD5Digest; var Context: THMAC_MD5Context);
    end;
    
    
    implementation
    
    { THMAC_MD5Class }
    
    constructor THMAC_MD5Class.Create;
    begin
        FHash:=TMD5Class.Create;
    end;
    
    destructor THMAC_MD5Class.Destroy;
    begin
        FHash.Destroy;
        inherited;
    end;
    
    (*引用百科:
    HMAC引擎提供HMAC运算步骤:
      (1) 在密钥K后面添加0来创建一个字长为B的字符串。(例如,如果K的字长是20
      字节,B=64字节,则K后会加入44个零字节0x00, 鉴别密钥的长度可以是小于等
    于数据块字长的任何正整数值。应用程序中使用的密钥长度若是比B大,则首先
    用使用散列函数H作用于它,然后用H输出的L长度字符串作为在HMAC中实际使用
    的密钥。一般情况下,推荐的最小密钥K长度是L个字节。)
      (2) 将上一步生成的B字长的字符串与ipad做异或运算。
      (3) 将数据流text填充至第二步的结果字符串中。
      (4) 用H作用于第三步生成的数据流。
      (5) 将第一步生成的B字长字符串与opad做异或运算。
      (6) 再将第四步的结果填充进第五步的结果中。
      (7) 用H作用于第六步生成的数据流,输出最终结果
    *)
    //基于MD5的HMAC算法 (Hash-MAC算法)
    procedure THMAC_MD5Class.HMAC_MD5Init(var Context: THMAC_MD5Context;
    sKey: string);
    var
        TmpContext: TMD5Context;
         I, iKeyLen: UINT4;
        TmpKey: TMD5Digest;
    begin
        FillChar(Context, SizeOf(THMAC_MD5Context), 0);
        iKeyLen := Length(sKey);
        // if key is longer than 64 bytes reset it to key=MD5(key)
        if (iKeyLen > 64) then
        begin
            FHash.MD5Init(TmpContext);
            FHash.MD5Update(TmpContext, PByte(PChar(sKey)), iKeyLen);
            FHash.MD5Final(TmpKey, TmpContext);
            Move(TmpKey, Context.Key, 16);//SizeOf(TmpKey));
            iKeyLen := SizeOf(TBytes_16); //16
        end
        else
        begin
            Move(PChar(sKey)^, Context.Key, iKeyLen);
        end;  
    
        (* start out by storing key in pads *)
    
        FillChar(Context.InPad , SizeOf(Context.InPad) , 0);
    
        FillChar(Context.OutPad, SizeOf(Context.OutPad), 0);
        for i:=0 to iKeyLen-1 do
        begin
            Context.InPad[i] := Context.key[i];
            Context.OutPad[i] := Context.key[i];
        end;
        (* XOR key with ipad and opad values *)
        for i:=0 to 64-1 do
        begin
            Context.InPad[i] := Context.InPad[i] xor $36;
            Context.OutPad[i] := Context.OutPad[i] xor $5C;
        end;
        // perform inner MD5
        // init context for 1st * pass
        FHash.MD5Init(Context.MD5Context);
        //start with inner pad
        FHash.MD5Update(Context.MD5Context, @Context.InPad, 64);
    end;
    
    procedure THMAC_MD5Class.HMAC_MD5Update(var Context: THMAC_MD5Context;
        pInBuffer: PByte; iInBufLen: UINT4);
    begin
        //then text of datagram
        FHash.MD5Update(Context.MD5Context, pInBuffer, iInBufLen);
    end;
    
    procedure THMAC_MD5Class.HMAC_MD5Final(var Digest: TMD5Digest;
        var Context: THMAC_MD5Context);
    begin
        //finish up 1st pass
        FHash.MD5Final(Digest, Context.MD5Context);
        // perform outer MD5
        //init context for 2nd * pass
        FHash.MD5Init(Context.MD5Context);
        //start with outer pad
        FHash.MD5Update(Context.MD5Context, @Context.OutPad, 64);
        //then results of 1st * hash
        FHash.MD5Update(Context.MD5Context, @Digest, 16);
        //finish up 2nd pass
        FHash.MD5Final(Digest, Context.MD5Context);
    end;
    
    end.
  • 相关阅读:
    【转载】分析商品日均销量(DMS)对促销商品选择的意义
    日志备份和差异备份还原中的常见问题示例(转自&邹建)
    SQL Server 2000中的完整备份、差异备份操作
    数据库差异备份与增量备份的不同之处
    差异备份和还原操作方法(转)
    SQL备份(全)
    Microsoft SQL2000 错误代码 (@@error)
    图解SQL的inner join(join)、left join、right join、full outer join、union、union all的区别
    arm-none-linux-gnueabi-gcc command not found
    关于ST-Link的internal command error问题的解决方法
  • 原文地址:https://www.cnblogs.com/caibirdy1985/p/4232964.html
Copyright © 2011-2022 走看看