Amazon ec2 API version 2 with c # encoding

I am having a problem with the hash encoding for signing version 2 of the ec2 API.

Pay attention to my version 1. Signing hashing works fine, but it depreciates, and I will need to upgrade to version 2. So, firstly, here is the code that works ...

Options

- this is just a dictionary, I just need to sort the parameters by key and add each pair of values ​​without separators, and then the hash of this line against my key. (again, note that this works great)

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

Now, with version 2 there are some changes, here is the doco from the API Developer's Guide ...

  • Create the canonical query string that you will need later in this procedure:

but. Sort UTF-8 query string components by parameter name with natural byte order. Parameters can be obtained from a GET URI or from a POST body (when the Content-Type is application / x-www-form-urlencoded).

b. The URL encodes the name and parameter values ​​in accordance with the following rules:

β€’ Do not encode the URLs of any of the unreserved characters defined in RFC 3986. These undeserved characters are: AZ, az, 0-9, hyphen (-), underscore (_), period (.), And tilde (~).
β€’ Percentage encodes all other characters with% XY, where X and Y are hexadecimal characters 0-9 and upper case AF.
β€’ Percentage encodes extended UTF-8 characters in the form% XY% ZA ....
β€’ Percentage encodes a whitespace as% 20 (and not +, as general coding schemes do).

Note
Currently, all AWS parameter names use unreserved characters, so you do not need to encode them. However, you can include code to handle parameter names that use reserved characters for possible future use.

from. Separate the names of the encoded parameters from their encoded values ​​with an equal sign (=) (ASCII character 61), even if the parameter value is empty.

e. Separate name-value pairs with ampersand (s) (ASCII code 38).

  1. Create a signature line according to the following pseudogram ("\ n" is an ASCII new line). StringToSign = HTTPVerb + "\ n" + ValueOfHostHeaderInLowercase + "\ n" + HTTPRequestURI + "\ n" +
    CanonicalizedQueryString The HTTPRequestURI component is a component of the absolute HTTP URI path to, but not including, the query string. If HTTPRequestURI is empty, use a forward slash (/).
  2. Compute the HMAC compliant with RFC 2104, the string you just created, the secret access key as the key, and SHA256 or SHA1 as the hash algorithm. For more information, go to http://www.rfc.net/rfc2104.html .
  3. Convert the resulting value to base64.
  4. Use the resulting value as the value of the signature request parameter.

So, I have a....

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

for completeness, here is the implementation of IComparer ....

  internal class CanonicalizedDictCompare : IComparer<string> { #region IComparer<string> Members public int Compare(string x, string y) { return string.CompareOrdinal(x, y); } #endregion } 

As far as I can tell, I have done everything I need to do for this hash, but I keep getting an error message from the server, telling me that my signature is incorrect. Help...

+6
c # amazon amazon-ec2 hash
source share
1 answer

Well, I get it .... UrlEncoding in the HttpUtility class does not match the Amazon coding scheme .... grrr (in particular, the hexadecimal value after% in the .NET program has lowercase letters, not uppercase)

b. The URL encodes the name and parameter values ​​in accordance with the following rules:

  • Do not encode the URL of any of the unconditional characters that RFC 3986 defines. These undeserved characters are AZ, az, 0-9, hyphen (-), underscore (_), period (.), And tilde (~).
  • Percent encodes all other characters with% XY, where X and Y are hexadecimal characters 0-9 and uppercase AF .

  • Percentage of encoded extension of UTF-8 characters in the form of% XY% ZA ....

  • Percentage of character space encoding as% 20 (and not +, as general encoding schemes).

So, after writing a quick method that encodes this circuit, it works great.

+7
source share

All Articles