2009-07-23 29 views
6

Tôi đang gặp sự cố với mã hóa hàm băm cho Chữ ký phiên bản 2 của API ec2.Mã hóa chữ ký của Amazon ec2 API phiên bản 2 với C#

Lưu ý tôi Phiên bản 1 Chữ ký băm hoạt động tốt, nhưng điều này được khấu hao và tôi sẽ cần phải chuyển sang phiên bản 2. Vì vậy, trước hết ở đây là mã mà hoạt động ...

thông số chỉ là một cuốn từ điển, những gì tôi phải làm là chỉ cần sắp xếp các tham số theo khóa và nối thêm mỗi cặp giá trị không có dấu phân tách, sau đó băm chuỗi đó vào khóa của tôi. (Một lần nữa, lưu ý làm việc này tốt)

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; 
} 

Giờ đây, với phiên bản 2 có một số thay đổi, đây là doco từ hướng dẫn các nhà phát triển API ...

  1. Tạo chuỗi truy vấn canonicalized mà bạn cần sau này trong thủ tục này:

a. Sắp xếp thành phần chuỗi truy vấn UTF-8 theo tên tham số với thứ tự byte tự nhiên. Các tham số có thể đến từ GET URI hoặc từ nội dung POST (khi Content-Type là ứng dụng/x-www-form-urlencoded).

b. URL mã hóa tên và giá trị thông số theo các quy tắc sau:

• Không mã hóa URL bất kỳ ký tự không được đặt trước nào mà RFC 3986 xác định. Các ký tự không được đặt trước này là A-Z, a-z, 0-9, dấu gạch ngang (-), dấu gạch dưới (_), dấu chấm (.), và dấu ngã (~).
• Phần trăm mã hóa tất cả các ký tự khác với% XY, trong đó X và Y là các ký tự hex 0-9 và chữ hoa A-F.
• Phần trăm mã hóa các ký tự UTF-8 mở rộng dưới dạng% XY% ZA ....
• Phần trăm mã hóa ký tự khoảng 20% ​​(và không +, như các lược đồ mã hóa phổ biến ).

Lưu ý
Hiện tại tất cả tên thông số dịch vụ AWS sử dụng ký tự không được đặt trước, vì vậy bạn không cần cần mã hóa chúng. Tuy nhiên, bạn có thể muốn bao gồm mã để xử lý thông số tên sử dụng các ký tự dành riêng, để sử dụng trong tương lai có thể.

c. Phân tách các tên tham số được mã hóa từ các giá trị được mã hóa của chúng bằng dấu bằng (=) (ký tự ASCII 61), ngay cả khi giá trị tham số trống.

d. Tách các cặp tên-giá trị bằng dấu và (&) (mã ASCII 38).

  1. Tạo chuỗi ký theo đúng ngữ pháp giả sau ("\ n" đại diện cho dòng ASCII mới). StringToSign = HTTPVerb + "\ n" + ValueOfHostHeaderInLowercase + "\ n" + HTTPRequestURI + "\ n" +
    CanonicalizedQueryString Thành phần HTTPRequestURI là HTTP thành phần đường dẫn tuyệt đối của URI đến, nhưng không phải bao gồm, chuỗi truy vấn. Nếu HTTPRequestURI trống, sử dụng dấu gạch chéo (/).
  2. Tính HMAC tuân thủ RFC 2104 với chuỗi bạn vừa tạo, Khóa truy cập bí mật làm khóa và SHA256 hoặc SHA1 làm thuật toán băm. Để biết thêm thông tin, hãy truy cập http://www.rfc.net/rfc2104.html.
  3. Chuyển đổi giá trị kết quả thành base64.
  4. Sử dụng giá trị kết quả làm giá trị của thông số Yêu cầu ký tự.

Vì vậy, những gì tôi có là ....

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; 
} 

cho đầy đủ ở đây là việc thực hiện IComparer ....

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

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

    #endregion 
    } 

Theo như tôi có thể nói tôi đã làm tất cả mọi thứ Tôi cần phải làm cho băm này, nhưng tôi tiếp tục nhận được một lỗi từ máy chủ nói với tôi rằng chữ ký của tôi là không chính xác. Trợ giúp ...

+1

Lớp trong ví dụ trên sẽ có: bằng System.Security.Cryptography; Ngoài ra, đối với mô tả của Amazon về cách thực hiện điều này (trừ tính toán băm), hãy xem http://docs.amazonwebservices.com/AWSECommerceService/latest/DG/index.html?rest-signature.html – adinas

Trả lời

7

Ok, tôi đã tìm ra .... UrlEncoding trong lớp HttpUtility không phù hợp với lược đồ mã hóa Amazon .... grrr (cụ thể giá trị hex sau% trong tiện ích .NET. là chữ thường, không viết hoa)

b. URL mã hóa các tên tham số và giá trị theo các quy tắc sau:

  • Đừng URL mã hóa bất kỳ nhân vật ưa thổ lộ rằng RFC 3986 định nghĩa. Các ký tự không được đặt trước là các dấu A-Z, a-z, 0-9, dấu gạch ngang (-), gạch dưới (_), dấu chấm (.) Và dấu ngã (~).
  • Phần trăm mã hóa tất cả các ký tự khác với% XY, trong đó X và Y là hex ký tự 0-9 và chữ hoa A-F.

  • Percent mã hóa mở rộng UTF-8 ký tự dưới dạng% XY% ZA ....

  • Percent mã hóa không gian nhân vật như% 20 (chứ không phải +, như chương trình mã hóa thường làm).

Vì vậy, sau khi viết một phương pháp nhanh chóng mã hóa cho lược đồ này, nó hoạt động tốt.

+0

Chúc mừng cho điều này. Giúp tôi làm cho nó hoạt động. Tuy nhiên tôi thấy tôi vẫn cần phải mã hóa (ít nhất) dấu gạch nối. thực hiện tìm kiếm từ khóa bằng dấu gạch nối trong đó đã gây ra lỗi "Chữ ký không hợp lệ". Tôi chưa thử nghiệm các ký tự đặc biệt khác .. – Dermot

+0

Bạn có thể chia sẻ mã cho phương pháp này không? Tôi thực sự đánh giá cao nó. –

+0

@AlirezaNoori tiếc là tôi không có quyền truy cập vào nó nữa. Tôi đã chuyển từ công ty mà tôi đã làm điều này. Nếu tôi nhớ lại mặc dù, nó không phải là quá khó khăn để làm điều này, nếu bạn sử dụng phản xạ hoặc IL/Spy bạn có thể có một cái nhìn như thế nào của nó được thực hiện trong lớp HttpUtility và chỉ đơn giản là chữ hoa chữ thập hex. –

Các vấn đề liên quan