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

aw 2013-05-30 01:40:47
请教如何在delpih中使用HMAC-SHA1算法?
...全文
1624 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
x_kun 2013-09-27
  • 打赏
  • 举报
回复
unit Unit1; interface uses 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. 结果返回不对啊,和真实值不一样
  • 打赏
  • 举报
回复
那就让C++编写一个实现HMAC-SHA1算法,编译为dll, 然后delphi7去调用。 HMAC-SHA1的使用场合: 淘宝网api:MD5或HMAC-SHA1算法。 拍拍网api:HMAC-SHA1算法. 亚马逊api:HMAC-SHA256算法。
fullhappy 2013-08-01
  • 打赏
  • 举报
回复
delpih中使用HMAC-SHA1算法,我用Delphi7,自带不行,我就将Indy10里面的改成了Delphi7下的,但是最后所得的计算结果值不对,乱码来着。怪异
centerall 2013-07-19
  • 打赏
  • 举报
回复
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;
orxor 2013-06-18
  • 打赏
  • 举报
回复
看一下 RFC 2316
  • 打赏
  • 举报
回复
unit Unit3; interface uses 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); begin end; //Base64编码 function TForm3.Base64Encode(const Input: TBytes): string; begin Result := TIdEncoderMIME.EncodeBytes(Input); end; end.
  • 打赏
  • 举报
回复
下面是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; 希望能给后面新入手的朋友一点帮助。
  • 打赏
  • 举报
回复
OAuth的精髓 DM5是无密钥的加密算法,输入明文,得到密码 如果黑客截获URL值,里面包含网店的id、密码、spid等值, 就可以利用这些值构造另外一个URL, 再用DM5算法得到sign值,这样网店的接口也对黑客开放了。 所以MD5加密签权方法,让黑客有机会进入网店后台乱搞,比如修改价格、修改商品等 黑客可以用木马等程序,截获API的URL 而OAuth方法,是采用hmac-sha1算法,加密时必须OAuthKey(密钥值), 这个值是商家系统在平台注册商家系统时留在平台里的,把明文加密成sign值时, 必需要提供OAuthKey值才可以加密成密码。 而在URL只是包含网店的key、密码、商家ID,没有AuthKey, 那么黑客截获了URL,因为没有包含AuthKey值(在商家系统和平台才有), 那么就不能生成Sign值,所以就无法随意访问网店信息,这样就安全了。
  • 打赏
  • 举报
回复
byte[] hash = mac.doFinal(mk.getBytes(charset)); //5 明码转化为byte数组,mac计算得到byte数组 这句就是核心,根据byte[]值,得到byte[]
ysai 2013-06-13
  • 打赏
  • 举报
回复
这是indy组件中的单元,要安装indy,我用的是最新版本的
  • 打赏
  • 举报
回复
下面这段是拍拍网的中关于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 源名码=源明码
  • 打赏
  • 举报
回复
Indy在delphi7版本中,也是有的。 最新是指xe4 版本吗?
  • 打赏
  • 举报
回复
现在很多平台的api访问,都从MD5的签权算法,改为了HMac-Sha1算法了, 但delphi7下不支持HMac-Sha1算法。 怎么让delphi7下,可以调用Hmac-sha1算法, 没有可以直接调用的dll方式
  • 打赏
  • 举报
回复
引用 2 楼 ysai 的回复:
uses IdHMACSHA1; var bs: TBytes; begin with TIdHMACSHA1.Create do try Key := ToBytes(HashKey); bs := HashValue(ToBytes(BaseString)); finally Free; end; end;
这个是在delphi2010中,有的吗。delphi7下提示找不到IdHMACSHA1.dcu
ysai 2013-06-05
  • 打赏
  • 举报
回复
uses IdHMACSHA1; var bs: TBytes; begin with TIdHMACSHA1.Create do try Key := ToBytes(HashKey); bs := HashValue(ToBytes(BaseString)); finally Free; end; end;
orxor 2013-06-05
  • 打赏
  • 举报
回复
哈哈 搞YY的吧

16,748

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 语言基础/算法/系统设计
社区管理员
  • 语言基础/算法/系统设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧