2012-09-18 60 views
2

我正在嘗試使用使用OAuth 1.0a並需要HMAC-SHA1簽名的第三方服務。我用C#編寫了一個工作版本,並嘗試將其移至Delphi XE2。我立即發現有問題,服務器拒絕了我的電話,說我的「簽名無效」。這是我生成簽名方法:Indy HMAC-SHA1生成意想不到的值

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

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'); 

所以我的問題是這樣的:我使用的HMAC-SHA1不正確?如果是這樣,我應該採取什麼措施來解決它?如果不是,那麼Indy中的HMAC-SHA1的實現是不正確的?如果是這樣,是否有一個易於使用(最好是免費)單位,可以正確處理?還是在這裏有其他的完全錯誤?

+0

在加密中,鍵不是'strings',它們應該是'binary'值(因爲字符串編碼可能不同)。當在這裏查看C#代碼http://msdn.microsoft.com/en-us/library/windowsazure/hh674475.aspx時,'key'應該被解釋爲Base64字符串('Convert.FromBase64String'調用)將它們轉換爲字節。 'signatureBase'作爲ASCII字符串(就像Stijn所回答的那樣)使用字節。 –

回答

5

看起來像普遍的Unicode字符串誤解。自Delphi 2009以來,string映射到UnicodeString,使用UTF-16編碼,而不再使用AnsiString。所以,

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

可能只會複製字符串的前半部分,每個字符2個字節。使用UTF8Encode先將密鑰轉換爲UTF8,然後將其複製到keyBytes中。

+0

謝謝,它現在生成正確的簽名。 – nick

+0

@Stijn你確定它是UTF-8而不是普通的舊ASCII嗎? –

+0

http://oauth.net/core/1.0a/#rfc.section.5.1 –