请教如何在delpih中使用HMAC-SHA1算法?

解决方案 »

  1.   

    uses IdHMACSHA1;var
      bs: TBytes;
    begin
      with TIdHMACSHA1.Create do
      try
        Key := ToBytes(HashKey);
        bs := HashValue(ToBytes(BaseString));
      finally
        Free;
      end;
    end;
      

  2.   

    这个是在delphi2010中,有的吗。delphi7下提示找不到IdHMACSHA1.dcu
      

  3.   

    现在很多平台的api访问,都从MD5的签权算法,改为了HMac-Sha1算法了,
    但delphi7下不支持HMac-Sha1算法。
    怎么让delphi7下,可以调用Hmac-sha1算法,
    没有可以直接调用的dll方式
      

  4.   

    这是indy组件中的单元,要安装indy,我用的是最新版本的
      

  5.   

    Indy在delphi7版本中,也是有的。
    最新是指xe4 版本吗?
      

  6.   

    下面这段是拍拍网的中关于hmac-sha1算法签名的demo中的一个函数:
      /*
         * 生成签名
         * @param method HTTP请求方法 "get" / "post" //参数1:请求方式的字符串值
         * @param url_path CGI名字,                 //参数2:api的相对URL的字符串值
         * @param params URL请求参数                   //参数3:由request的请求名和值,构成的hashmap数据类型值
         * @param secret 密钥                          //参数4:用户网站的appkey的字符串值
         * @return 签名值                               //返回值,对请求值进行hmac-sha1加密算法的计算返回值。
         * @throws OpensnsException 不支持指定编码以及不支持指定的加密方法时抛出异常。
         */
        private String makeSign(String method, String url_path, HashMap<String, String> params, String secret) throws OpenApiException {
            String sig = "";
            try {
                Mac mac = Mac.getInstance("HmacSHA1");            //1 得到一个是hmacsha1的mac对象
                SecretKeySpec secretKey = new SecretKeySpec(secret.getBytes(charset), mac.getAlgorithm()); //2 创建secretKey对象
                mac.init(secretKey);                              //3 用secretkey对象,初始化mac对象。
                String mk = makeSource(method, url_path, params); //4 输入method、url_path,parms参数,得到源名码
                System.out.println(mk);
                byte[] hash = mac.doFinal(mk.getBytes(charset)); //5 用mac对源名码加密,得到byte数组
                sig = new String(Base64Coder.encode(hash));      //6 encode编码,然后转化为string输出值
                // sig = encodeUrl(sig);
            } catch (Exception e) {
                throw new OpenApiException(OpenApiException.MAKE_SIGNATURE_ERROR, e);
            }
            return sig;
        }就是输入post/get 的string值、相对api的url string值、hashmap方式的request值、appkey的string值,经过hmac算法,得到计算的密码值。
    zck(25594165)  18:04:19
    源名码=源明码
      

  7.   

                byte[] hash = mac.doFinal(mk.getBytes(charset)); //5 明码转化为byte数组,mac计算得到byte数组
    这句就是核心,根据byte[]值,得到byte[] 
      

  8.   

    下面是Delphi2010实现的源码仅供参考。Uses IdHashMessageDigest, HTTPApp, IdHMACSHA1, IdCoderMIME, DateUtils; //这些文件。 procedure TForm1.Button5Click(Sender: TObject);var  sHttpMethod: AnsiString;  sRequestURL: AnsiString;  sRequestParameter: AnsiString;  sAppSecret: AnsiString;  sSignatureBaseString: AnsiString;  sMD5: TIdHashMessageDigest5;begin  sMD5 := TIdHashMessageDigest5.Create;   sAppSecret := '4b50186d12987f405b17bc38c9b99b0a&';  //密钥   sHttpMethod := 'GET';  sRequestURL := 'http://open.t.qq.com/cgi-bin/request_token';  sRequestParameter := 'oauth_callback=null&oauth_consumer_key=8*******9&oauth_nonce=';  sRequestParameter := sRequestParameter + sMD5.HashStringAsHex(IntToStr(Random(10000)), nil);  //随机32位数  sRequestParameter := sRequestParameter + '&oauth_signature_method=HMAC-SHA1&oauth_timestamp=';  sRequestParameter := sRequestParameter + FloatToStr(DateTimeToUnix(Now()-1/3)); //时间戳  sRequestParameter := sRequestParameter + '&oauth_version=1.0';   sSignatureBaseString := HTTPEncode(sHttpMethod) + '&' + HTTPEncode(sRequestURL) + '&' + HTTPEncode(sRequestParameter);  Memo1.Text := Base64Encode(EncryptHMACSha1(sSignatureBaseString, sAppSecret));  sMD5.Free;end; 两个函数 Base64Encode,EncryptHMACSha1;//HMACSha1算法function TForm1.EncryptHMACSha1(Input,AKey:AnsiString): TBytes;var  Key: TBytes;begin  with TIdHMACSHA1.Create do  try    Key := BytesOf(AKey);    Result := HashValue(BytesOf(Input));  finally    Free;  end;end; //Base64编码function TForm1.Base64Encode(const Input: TBytes): string;begin  Result := TIdEncoderMIME.EncodeBytes(Input);end;希望能给后面新入手的朋友一点帮助。
      

  9.   

    unit Unit3;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, Buttons,
      IdHashMessageDigest, HTTPApp, IdHMACSHA1, IdCoderMIME, DateUtils;type
      TForm3 = class(TForm)
        BitBtn1: TBitBtn;
        Memo1: TMemo;
        procedure BitBtn1Click(Sender: TObject);
        procedure Memo1Change(Sender: TObject);  private
        { Private declarations }
        function Base64Encode(const Input: TBytes): string;
        function EncryptHMACSha1(Input,AKey:AnsiString): TBytes;
      public
        { Public declarations }
      end;var
      Form3: TForm3;implementation{$R *.dfm}procedure TForm3.BitBtn1Click(Sender: TObject);var  sHttpMethod: AnsiString;  sRequestURL: AnsiString;  sRequestParameter: AnsiString;  sAppSecret: AnsiString;  sSignatureBaseString: AnsiString;  sMD5: TIdHashMessageDigest5;begin  sMD5 := TIdHashMessageDigest5.Create;  sAppSecret := '4b50186d12987f405b17bc38c9b99b0a&';  //密钥  sHttpMethod := 'GET';  sRequestURL := 'http://open.t.qq.com/cgi-bin/request_token';  sRequestParameter := 'oauth_callback=null&oauth_consumer_key=8*******9&oauth_nonce=';  sRequestParameter := sRequestParameter + sMD5.HashStringAsHex(IntToStr(Random(10000)), nil);  //随机32位数  sRequestParameter := sRequestParameter + '&oauth_signature_method=HMAC-SHA1&oauth_timestamp=';  sRequestParameter := sRequestParameter + FloatToStr(DateTimeToUnix(Now()-1/3)); //时间戳  sRequestParameter := sRequestParameter + '&oauth_version=1.0';  sSignatureBaseString := HTTPEncode(sHttpMethod) + '&' + HTTPEncode(sRequestURL) + '&' + HTTPEncode(sRequestParameter);  Memo1.Text := Base64Encode(EncryptHMACSha1(sSignatureBaseString, sAppSecret));  sMD5.Free;end;//两个函数 Base64Encode,EncryptHMACSha1;
     //HMACSha1算法
    function TForm3.EncryptHMACSha1(Input,AKey:AnsiString): TBytes;
    var Key: TBytes;
    begin  with TIdHMACSHA1.Create do
      try
         Key := BytesOf(AKey);
         Result := HashValue(BytesOf(Input));   finally
         Free;
      end;end;procedure TForm3.Memo1Change(Sender: TObject);
    beginend;//Base64编码function TForm3.Base64Encode(const Input: TBytes): string;
    begin  Result := TIdEncoderMIME.EncodeBytes(Input);
    end;
    end.
      

  10.   

    看一下 RFC 2316
      

  11.   

    Delphi XE4下该如何编写呢?为了编译通过,修改TBytes为TIdBytes,但是结果就不ok了。
    // Base64编码
    function Base64Encode(const Input: TIdBytes): string;
    begin
      Result := TIdEncoderMIME.EncodeBytes(Input);
    end;// HMACSha1算法
    function EncryptHMACSha1(Input, AKey: string): TIdBytes;
    var
      Key: TIdBytes;
    begin
      with TIdHMACSHA1.Create do
        try
          Key := TIdBytes(AKey);
          Result := HashValue(TIdBytes(Input));
        finally
          Free;
        end;
    end;
      

  12.   

    delpih中使用HMAC-SHA1算法,我用Delphi7,自带不行,我就将Indy10里面的改成了Delphi7下的,但是最后所得的计算结果值不对,乱码来着。怪异
      

  13.   

     那就让C++编写一个实现HMAC-SHA1算法,编译为dll,
     然后delphi7去调用。
     HMAC-SHA1的使用场合:
      淘宝网api:MD5或HMAC-SHA1算法。
      拍拍网api:HMAC-SHA1算法.
      亚马逊api:HMAC-SHA256算法。
      

  14.   

    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, IdHashMessageDigest, HTTPApp, IdHMACSHA1, IdCoderMIME, DateUtils,
      StdCtrls, Types, IdGlobal, CnSHA1, EncdDecd, IdBaseComponent, IdComponent,
      IdTCPConnection, IdTCPClient, IdHTTP;type
      TBytes = array of Byte;
      TForm1 = class(TForm)    btnOk: TButton;
        Memo1: TMemo;
        Label1: TLabel;
        Label2: TLabel;
        Memo2: TMemo;
        IdHTTP1: TIdHTTP;
        Memo3: TMemo;
        Button1: TButton;
        procedure btnOkClick(Sender: TObject);
        procedure Button1Click(Sender: TObject);
      private
        function EncryptHMACSha1(Input, AKey: AnsiString): TIdBytes;
        function Base64Encode(const Input: TIdBytes): string;
       //url编码
        function URLEncode(const S: string; const InQueryString: Boolean): string;
        function URLDecode(const S: string): string;
        function HTMLEncode(const AStr: string): string;
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.dfm}procedure TForm1.btnOkClick(Sender: TObject);
    var
      sHttpMethod: AnsiString;
      sRequestURL: AnsiString;
      sRequestParameter: AnsiString;
      sAppSecret: AnsiString;
      sSignatureBaseString: AnsiString;
      sMD5: TIdHashMessageDigest5;
    begin  sMD5 := TIdHashMessageDigest5.Create;
      //sAppSecret := '4b50186d12987f405b17bc38c9b99b0a&';  //密钥
      sAppSecret := 'test';
      sHttpMethod := 'Post';  sRequestURL := 'http://apis.youhuiin.com/api2';  sRequestParameter := 'nonce=';
      sRequestParameter := sRequestParameter + IntToStr(Random(10000)); //随机32位数    sMD5.HashStringAsHex(IntToStr(Random(10000)), nil)
      sRequestParameter := sRequestParameter + '&from=erp';
      sRequestParameter := sRequestParameter + '&ts=';
      sRequestParameter := sRequestParameter + FloatToStr(DateTimeToUnix(Now() - 1 / 3)); //时间戳
      Memo2.Text := sRequestParameter;
     // sRequestParameter := sRequestParameter + '&oauth_version=1.0';
     // sSignatureBaseString := HTTPEncode(sHttpMethod) + '&' + HTTPEncode(sRequestURL) + '&' + HTTPEncode(sRequestParameter);
      sSignatureBaseString := HTTPEncode(sHttpMethod) + '&' + HTTPEncode(sRequestURL) + '&' + HTTPEncode(sRequestParameter);
      sSignatureBaseString :=HTTPEncode(sRequestParameter);
      //sSignatureBaseString :='100&erp&12345678';  sSignatureBaseString:=HTTPEncode('nonce=100&from=erp&ts=12345678');
      //indy10  Memo1.Text := URLEncode(Base64Encode(EncryptHMACSha1(sSignatureBaseString, sAppSecret)), true);
      sMD5.Free;  //添加CnSHA1.pas
     // Memo1.Text :=URLEncode(EncodeString(CnSHA1.SHA1Print(CnSHA1.SHA1StringA(sSignatureBaseString))),false);
    end;
    //HMACSha1算法function TForm1.EncryptHMACSha1(Input, AKey: AnsiString): TIdBytes;
    var
      Key: TIdBytes;
    begin
      with TIdHMACSHA1.Create do
      try
        Key := ToBytes(AKey);
        Result := HashValue(ToBytes(Input));
      finally
        Free;
      end;
    end;//Base64编码function TForm1.Base64Encode(const Input: TIdBytes): string;
    begin
      Result := TIdEncoderMIME.EncodeBytes(Input);
    end;function TForm1.URLDecode(const S: string): string;
    var
      Idx: Integer; // loops thru chars in string
      Hex: string; // string of hex characters
      Code: Integer; // hex character code (-1 on error)
    begin
      // Intialise result and string index
      Result := '';
      Idx := 1;
      // Loop thru string decoding each character
      while Idx <= Length(S) do
      begin
        case S[Idx] of
          '%':
            begin
            // % should be followed by two hex digits - exception otherwise
              if Idx <= Length(S) - 2 then
              begin
              // there are sufficient digits - try to decode hex digits
                Hex := S[Idx + 1] + S[Idx + 2];
                Code := SysUtils.StrToIntDef('$' + Hex, -1);
                Inc(Idx, 2);
              end
              else
              // insufficient digits - error
                Code := -1;
            // check for error and raise exception if found
              if Code = -1 then
                raise SysUtils.EConvertError.Create(
                  'Invalid hex digit in URL'
                  );
            // decoded OK - add character to result
              Result := Result + Chr(Code);
            end;
          '+':
            // + is decoded as a space
            Result := Result + ' '
        else
            // All other characters pass thru unchanged
          Result := Result + S[Idx];
        end;
        Inc(Idx);
      end;
    end;
    function TForm1.URLEncode(const S: string; const InQueryString: Boolean): string;
    var
      Idx: Integer; // loops thru characters in string
    begin
      Result := '';
      for Idx := 1 to Length(S) do
      begin
        case S[Idx] of
          'A'..'Z', 'a'..'z', '0'..'9', '-', '_', '.':
            Result := Result + S[Idx];
          ' ':
            if InQueryString then
              Result := Result + '+'
            else
              Result := Result + '%20';
        else
          Result := Result + '%' + SysUtils.IntToHex(Ord(S[Idx]), 2);
        end;
      end;
    end;procedure TForm1.Button1Click(Sender: TObject);
    var
      postcmd: TStringList;
      sPostUrl: string;
    begin
      sPostUrl := 'http://apis.youhuiin.com/api2/order/prepareship?nonce=100&from=erp&ts=12345678&sign=LuW3%2f7AHkkA0WInXC73DDp85818%3d';
      postcmd := TStringList.Create; // 组合参数列表
      postcmd.Add('orderno=113092265023');
      postcmd.Add('updatetime=2013-09-24 12:05:37');
      postcmd.Add('memo=12333');
      postcmd.Add('storeid=1');
      IdHTTP1.Request.ContentType := 'application/json';
      IdHTTP1.Request.AcceptCharSet:='gb2312';
      Memo3.Text :=UTF8Decode(IdHTTP1.Post(sPostUrl, postcmd)); // 以post的方式发送到服务器
    end;function TForm1.HTMLEncode(const AStr: string): string;
    const
      NoConversion = ['A'..'Z', 'a'..'z', '*', '.', '_', '-', '0'..'9', '!', '''', '(', ')']; //不需要进行转换的字符。
    var
      Sp, Rp: PChar;
    begin
      SetLength(Result, Length(AStr) * 3);
      Sp := PChar(AStr);
      Rp := PChar(Result);
      while Sp^ <> #0 do
      begin
        if Sp^ in NoConversion then
          Rp^ := Sp^
        else
          if Sp^ = '   ' then
            Rp^ := '+'
          else
          begin
            FormatBuf(Rp^, 3, '%%%.2x', 6, [Ord(Sp^)]);
            Inc(Rp, 2);
          end;
        Inc(Rp);
        Inc(Sp);
      end;
      SetLength(Result, Rp - PChar(Result));
    end;
    end.结果返回不对啊,和真实值不一样