Tengo un problema con la codificación del hash para la versión 2 Firma de la API ec2.Amazon ec2 API versión 2 codificación de firma con C#
Nota mi versión 1 de la firma hash funciona bien, pero esto es amortizado y que tendrá que mover a la versión 2. Así que en primer lugar, aquí es el código que funciona ...
parámetros es sólo un diccionario, lo que lo que tengo que hacer es simplemente ordenar los parámetros por clave y anexar cada par de valores sin ningún delimetro, luego ajustar esa cadena contra mi clave. (De nuevo, tenga en cuenta que esto funciona muy bien)
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;
}
Ahora, con la versión 2 hay algunos cambios, aquí está el mana de la guía de desarrolladores de la API ...
- Crear la cadena de consulta que forma canónica necesitará más adelante en este procedimiento:
a. Ordene los componentes de cadena de consulta UTF-8 por nombre de parámetro con ordenamiento natural de bytes. Los parámetros pueden provenir del URI GET o del cuerpo POST (cuando Content-Type es application/x-www-form-urlencoded).
b. La URL codifica el nombre del parámetro y los valores de acuerdo con las siguientes reglas:
• No codifique URL de ninguno de los caracteres no reservados que RFC 3986 define. Estos caracteres no reservados son A-Z, a-z, 0-9, guión (-), guión bajo (_), punto (.), y tilde (~).
• El porcentaje codifica todos los demás caracteres con% XY, donde X e Y son caracteres hexadecimales 0-9 y mayúsculas A-F.
• Porcentaje codifica caracteres UTF-8 extendidos en el formato% XY% ZA ....
• El porcentaje codifica el carácter de espacio como% 20 (y no +, como lo hacen los esquemas de codificación comunes do).
Nota
Actualmente, todos los nombres de los parámetros de servicio AWS utilizar caracteres no reservados, por lo que no necesita codificarlos. Sin embargo, es posible que desee incluir código para manejar los nombres de los parámetros que usan caracteres reservados, para un posible uso futuro.
c. Separe los nombres de los parámetros codificados de sus valores codificados con el signo igual (=) (carácter ASCII 61), incluso si el valor del parámetro está vacío.
d. Separe los pares nombre-valor con un signo de y comercial (&) (código ASCII 38).
- Cree la cadena para firmar de acuerdo con la siguiente pseudo-gramática (la "\ n" representa una nueva línea ASCII ). StringToSign = HTTPVerb + "\ n" + ValueOfHostHeaderInLowercase + "\ n" + HTTPRequestURI + "\ n" +
CanonicalizedQueryString El componente HTTPRequestURI es el componente ruta absoluta HTTP de la URI hasta, pero no incluyendo, la cadena de consulta. Si HTTPRequestURI está vacío, use una barra inclinada (/). - Calcule un HMAC compatible con RFC 2104 con la cadena que acaba de crear, su clave secreta de acceso como clave, y SHA256 o SHA1 como el algoritmo hash. Para obtener más información, vaya al http://www.rfc.net/rfc2104.html.
- Convierta el valor resultante a base64.
- Utilice el valor resultante como el valor del parámetro de solicitud de Firma.
Así que lo que tengo es ....
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;
}
esté completo aquí es la implementación IComparer ....
internal class CanonicalizedDictCompare : IComparer<string>
{
#region IComparer<string> Members
public int Compare(string x, string y)
{
return string.CompareOrdinal(x, y);
}
#endregion
}
Por lo que yo puedo decir que he hecho todo lo Tengo que hacer este hash, pero recibo un error del servidor que me dice que mi firma es incorrecta. Ayuda ...
La clase en el ejemplo anterior tendría: usando System.Security.Cryptography; Además, para la descripción de Amazon de cómo hacer esto (menos el cálculo del hash), consulte http://docs.amazonwebservices.com/AWSECommerceService/latest/DG/index.html?rest-signature.html – adinas