【问题标题】:Indy HMAC-SHA1 generating unexpected valuesIndy HMAC-SHA1 生成意外值
【发布时间】:2012-09-18 19:56:16
【问题描述】:

我正在尝试使用使用 OAuth 1.0a 并且需要 HMAC-SHA1 进行签名的第 3 方服务。我用 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;

我看不出有什么不对劲的地方,所以我从我的 C# 测试中获取了 signatureBasekey

签名库: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');

所以我的问题是:我是否错误地使用了 HMAC-SHA1?如果是这样,我应该采取哪些步骤来修复它?如果不是,那么在 Indy 中 HMAC-SHA1 的实现是否不正确?如果是这样,是否有一个易于使用(最好是免费的)单元可以正确处理它?还是这里有其他完全错误的地方?

【问题讨论】:

  • 在加密中,密钥不是strings,它们应该是binary 值(因为字符串编码可能会有所不同)。在查看msdn.microsoft.com/en-us/library/windowsazure/hh674475.aspx 此处的 C# 代码时,key 应被解释为 Base64 字符串(Convert.FromBase64String 调用)以将它们转换为字节。 signatureBase 作为 ASCII 字符串(正如 Stijn 回答的那样),其中使用了字节。

标签: delphi delphi-xe2 indy hmacsha1


【解决方案1】:

看起来像是常见的 Unicode 字符串误解。自 Delphi 2009 以来,string 映射到使用 UTF-16 编码的 UnicodeString,不再映射到 AnsiString。所以,

Move(key[1],keyBytes[0],Length(key));

可能只会复制字符串的前半部分,每个字符 2 个字节。使用UTF8Encode先将密钥转换为UTF8,然后将其复制到keyBytes中。

【讨论】:

  • @Stijn 你确定它是 UTF-8 而不是普通的旧 ASCII?
  • 啊,我明白你的意思了,因为密钥是用% 编码的 URL,所以你不会有任何高于 #127 的东西,所以是的,普通的 AnsiString 应该没问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-04
  • 2014-10-01
相关资源
最近更新 更多