nic*_*ick 2 delphi indy hmacsha1 delphi-xe2
我正在尝试使用使用OAuth 1.0a的第三方服务,并且需要使用HMAC-SHA1进行签名.我在C#中编写了一个工作版本,并尝试将其移至Delphi XE2.我立刻发现了一些错误,服务器拒绝我的电话说我的"签名无效".这是我生成签名的方法:
function TOAuth1.GenerateSignature(signatureBase, key : string) : string;
var
hmacSha1 : TIdHMACSHA1;
keyBytes, textBytes, hashedBytes : TBytes;
begin
if(AnsiCompareText(fSignMethod,'PLAINTEXT') = 0) then
begin
Result := key;
end
else if(AnsiCompareText(fSignMethod,'HMAC-SHA1') = 0) then
begin
hmacSha1 := TIdHMACSHA1.Create;
SetLength(keyBytes,Length(key));
Move(key[1],keyBytes[0],Length(key));
hmacSha1.Key := keyBytes;
SetLength(textBytes,Length(signatureBase));
Move(signatureBase[1],textBytes[0],Length(signatureBase));
hashedBytes := hmacSha1.HashValue(textBytes);
Result := EncodeBase64(hashedBytes,Length(hashedBytes));
keyBytes := nil;
textBytes := nil;
hashedBytes := nil;
hmacSha1.Free;
hmacSha1 := nil;
end;
end;
Run Code Online (Sandbox Code Playgroud)
我不能发现任何疑似错误的我,所以我抓住一个signatureBase,并key从我的C#测试
signatureBase: POST&https%3A%2F%2Fapi.twitter.com%2Foauth%2Frequest_token&oauth_callback%3Dhttp%253A%252F%252Flocalhost%252Fsign-in-with-twitter%252F%26oauth_consumer_key%3DcChZNFj6T5R0TigYB9yd1w%26oauth_nonce%3Dea9ec8429b68d6b77cd5600adbbb0456%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1318467427%26oauth_version%3D1.0
键: L8qq9PZyRg6ieKGEKhZolGC0vJWLw8iEJ88DRdyOg&
在C#中使用这些值,我获得了签名F1Li3tvehgcraF8DMJ7OyxO4w9Y=,这是Twitter给我的预期价值.然而,在Delphi中,我获得了签名/kov410nJhE6PTlk0R8bjP7JQq4=
在Delphi中,我调用了我的函数:
signature := self.GenerateSignature('POST&https%3A%2F%2Fapi.twitter.com%2Foauth%2Frequest_token&oauth_callback%3Dhttp%253A%252F%252Flocalhost%252Fsign-in-with-twitter%252F%26oauth_consumer_key%3DcChZNFj6T5R0TigYB9yd1w%26oauth_nonce%3Dea9ec8429b68d6b77cd5600adbbb0456%26oauth_signature_method'+'%3DHMAC-SHA1%26oauth_timestamp%3D1318467427%26oauth_version%3D1.0','L8qq9PZyRg6ieKGEKhZolGC0vJWLw8iEJ88DRdyOg&');
assert(AnsiCompareStr(signature,'F1Li3tvehgcraF8DMJ7OyxO4w9Y=') = 0,'Signature generated is invalid');
Run Code Online (Sandbox Code Playgroud)
所以我的问题是:我是否正确使用HMAC-SHA1?如果是这样,我应该采取什么措施来解决它?如果没有,那么Indy中的HMAC-SHA1的实现是否做错了?如果是这样,是否有一个易于使用(最好是免费)的单位,可以正确处理它?或者这里有其他错误吗?
看起来像常见的Unicode字符串误解.自Delphi 2009以来,string映射到UnicodeString,用UTF-16编码,而不再是AnsiString.所以,
Move(key[1],keyBytes[0],Length(key));
Run Code Online (Sandbox Code Playgroud)
可能只复制字符串的前半部分,每个字符2个字节.用于UTF8Encode首先将密钥转换为UTF8,并将其复制到keyBytes.