2009-07-23 83 views
6

我有問題編碼ec2 API版本2簽名的散列。亞馬遜ec2 API版本2的簽名編碼與c#

注意我的第1版簽名哈希工作正常,但是這是貶值,我將需要移動到2。所以首先在這裏的說法是,工作代碼...

參數僅僅是一本字典,我所要做的只是按鍵對參數進行排序並將每個值對添加爲無定界符,然後將該字符串與我的密鑰進行散列。 (再次,注意,這正常工作)現在

private string GetVersion1Sig() 
{ 
    string sig = string.Join(string.Empty, parameters.OrderBy(vp => vp.Key).Select(p => string.Format("{0}{1}", p.Key, p.Value)).ToArray()); 
    UTF8Encoding encoding = new UTF8Encoding(); 
    HMACSHA256 signature = new HMACSHA256(encoding.GetBytes(_secretAccessKey)); 
    byte[] hash = signature.ComputeHash(encoding.GetBytes(sig)); 
    string result = Convert.ToBase64String(hash); 
    return result; 
} 

,與第2版有一些變化,這裏是從API開發人員指南的DOCO ...

  1. 創建規範化查詢字符串,你需要稍後在此過程中:

a。按照自然字節順序通過參數名稱對UTF-8查詢字符串組件進行排序。 參數可以來自GET URI或來自POST主體(當Content-Type 是application/x-www-form-urlencoded時)。

b。根據以下規則對參數名稱和值進行URL編碼:

•不要URL編碼RFC 3986定義的任何未預留字符。 ( - ),下劃線(_),句號(。), 和代字號(〜)。這些非保留字符是A-Z,a-z,0-9,連字符( - ),
•使用%XY對所有其他字符進行百分比編碼,其中X和Y是十六進制字符0-9和 大寫字母A-F。
•以%XY%ZA的形式百分比編碼擴展的UTF-8字符....
•將空格字符百分比編碼爲%20(而不是+,如常見編碼方案 一樣)。

注意
當前所有AWS服務參數名稱都使用非保留字符,因此您不需要 對它們進行編碼。但是,您可能希望包含代碼來處理使用保留字符的參數 名稱,以備將來使用。

c。即使參數值爲空,也可以使用等號(=) (ASCII字符61)將編碼參數名與其編碼值分開。

d。用&符號分隔名稱 - 值對(&)(ASCII代碼38)。

  1. 根據以下僞文法創建​​要簽名的字符串(「\ n」代表 ASCII換行符)。 StringToSign = HTTPVerb + 「\ n」 個+ ValueOfHostHeaderInLowercase + 「\ n」 個+ HTTPRequestURI + 「\ n」 個+
    CanonicalizedQueryString 的HTTPRequestURI組件是URI的HTTP絕對路徑組件達,但不 包括查詢字符串。如果HTTPRequestURI爲空,請使用正斜槓(/)。
  2. 使用剛剛創建的字符串計算符合RFC 2104的HMAC,將祕密訪問密鑰 作爲密鑰,將SHA256或SHA1作爲哈希算法。 欲瞭解更多信息,請登錄http://www.rfc.net/rfc2104.html
  3. 將結果值轉換爲base64。
  4. 使用結果值作爲簽名請求參數的值。

所以我有什麼是....

private string GetSignature() 
{ 
    StringBuilder sb = new StringBuilder(); 
    sb.Append("GET\n"); 
    sb.Append("ec2.amazonaws.com\n"); 
    sb.Append("/\n"); 
    sb.Append(string.Join("&", parameters.OrderBy(vp => vp.Key, new CanonicalizedDictCompare()).Select(p => string.Format("{0}={1}", HttpUtility.UrlEncode(p.Key), HttpUtility.UrlEncode(p.Value))).ToArray())); 
    UTF8Encoding encoding = new UTF8Encoding(); 
    HMACSHA256 signature = new HMACSHA256(encoding.GetBytes(_secretAccessKey)); 
    byte[] hash = signature.ComputeHash(encoding.GetBytes(sb.ToString())); 
    string result = Convert.ToBase64String(hash); 
    return result; 
} 

的完整性這裏是IComparer實現....

internal class CanonicalizedDictCompare : IComparer<string> 
    { 
    #region IComparer<string> Members 

    public int Compare(string x, string y) 
    { 
     return string.CompareOrdinal(x, y); 
    } 

    #endregion 
    } 

至於我可以告訴我所做的一切我需要做這個散列,但我一直從服務器收到一個錯誤,告訴我我的簽名不正確。幫助...

+1

以上示例中的類將具有: 使用System.Security.Cryptography; 此外,亞馬遜的描述如何做到這一點(減去計算散列),請參閱http://docs.amazonwebservices.com/AWSECommerceService/latest/DG/index.html?rest-signature.html – adinas 2009-09-13 11:57:21

回答

7

好吧,我想通了...... HttpUtility類中的UrlEncoding不符合亞馬遜編碼方案.... grrr(特別是.NET工具中的%之後的十六進制值小寫,不是大寫)

b。 URL按照以下規則進行編碼的參數名稱和值:

  • 不要URL編碼任何 毫無保留的字符RFC 3986 定義。這些未保留的字符 是A-Z,a-z,0-9,連字符( - ), 下劃線(_),句點(。)和 代字號(〜)。
  • 百分比編碼所有其他字符 用%XY,其中X和Y是十六進制 0-9和大寫字母A-F

  • 百分比編碼擴展UTF-8的形式%XY%ZA 字符....

  • 百分比編碼的空間 字符爲%20(而不是+,作爲 共同編碼方案一樣)。

因此,編寫一個快速的方法編碼到這個方案後,它工作正常。

+0

乾杯。幫助我得到它的工作。但是我發現我仍然需要編碼(至少)連字符。用連字符進行關鍵字搜索會導致「無效簽名」錯誤。我還沒有測試過其他特殊字符。 – Dermot 2012-02-17 07:26:05

+0

請問你能分享一下這個方法的代碼嗎?我真的很感激它。 – 2013-09-12 21:00:42

+0

@AlirezaNoori很遺憾,我無法再訪問它了。我已經從我做這件事的公司轉移了下來。如果我回想一下,這樣做並不困難,如果你使用反射器或IL/Spy,你可以看看它在HttpUtility類中的完成方式,並簡單地用大寫字母表示十六進制字符。 – 2013-09-12 21:56:18