Ho riscontrato un problema con la codifica dell'hash per la firma della versione 2 dell'ec2 API.Codifica della firma della versione 2 di Amazon ec2 API con C#
Nota mia versione 1 Firma hashing funziona bene, ma questo sono ammortizzati e che ho bisogno di passare alla versione 2. Quindi, in primo luogo qui è il codice che funziona ...
parametri è solo un dizionario, quello che ho è sufficiente ordinare i parametri per chiave e aggiungere ogni coppia di valori senza delimitatori, quindi eseguire l'hash della stringa con la mia chiave. (Ancora una volta, notare che questo funziona bene)
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;
}
Ora, con la versione 2 ci sono alcuni cambiamenti, qui è la doco dalla guida sviluppatori API ...
- Creare la stringa di query che si Canonicalized necessario più avanti in questa procedura:
a. Ordinare i componenti della stringa di query UTF-8 in base al nome del parametro con l'ordinamento di byte naturale. I parametri possono provenire dall'URI GET o dal corpo POST (quando Content-Type è application/x-www-form-urlencoded).
b. L'URL codifica il nome e i valori dei parametri in base alle seguenti regole:
• Non codificare URL per nessuno dei caratteri non prenotati definiti da RFC 3986. Questi caratteri non riservati sono A-Z, a-z, 0-9, trattino (-), trattino basso (_), punto (.), e tilde (~).
• La percentuale codifica tutti gli altri caratteri con% XY, dove X e Y sono caratteri esadecimali 0-9 e maiuscolo A-F.
• La percentuale codifica caratteri UTF-8 estesi nella forma% XY% ZA ....
• La percentuale codifica il carattere dello spazio come% 20 (e non +, come fanno gli schemi di codifica comuni ).
Nota
Attualmente tutti i nomi dei parametri del servizio AWS utilizzano caratteri non prenotati, pertanto non è necessario codificarli per . Tuttavia, è possibile includere il codice per gestire i nomi dei parametri che utilizzano caratteri riservati, per un possibile utilizzo futuro.
c. Separare i nomi dei parametri codificati dai loro valori codificati con il segno di uguale (=) (carattere ASCII 61), anche se il valore del parametro è vuoto.
d. Separare le coppie nome-valore con una e commerciale (&) (codice ASCII 38).
- Creare la stringa da firmare in base alla seguente pseudo-grammatica ("\ n" rappresenta una riga nuova ASCII ). StringToSign = HTTPVerb + "\ n" + ValueOfHostHeaderInLowercase + "\ n" + HTTPRequestURI + "\ n" +
CanonicalizedQueryString Il componente HTTPRequestURI è il componente percorso assoluto HTTP del URI fino a, ma non tra cui, la stringa di query. Se HTTPRequestURI è vuoto, utilizzare una barra (/). - Calcolare un HMAC conforme a RFC 2104 con la stringa appena creata, la chiave di accesso segreto come chiave e SHA256 o SHA1 come algoritmo di hash. Per ulteriori informazioni, andare a http://www.rfc.net/rfc2104.html.
- Convertire il valore risultante in base64.
- Utilizzare il valore risultante come valore del parametro di richiesta Firma.
Quindi quello che ho è ....
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;
}
per completezza qui è l'implementazione IComparer ....
internal class CanonicalizedDictCompare : IComparer<string>
{
#region IComparer<string> Members
public int Compare(string x, string y)
{
return string.CompareOrdinal(x, y);
}
#endregion
}
Per quanto mi riguarda posso dire che ho fatto tutto Ho bisogno di fare questo hash, ma continuo a ricevere un errore dal server che mi dice che la mia firma non è corretta. Aiuto ...
La classe nell'esempio precedente avrebbe: utilizzando System.Security.Cryptography; Inoltre, per la descrizione di Amazon su come eseguire questa operazione (meno il calcolo dell'hash), vedere http://docs.amazonwebservices.com/AWSECommerceService/latest/DG/index.html?rest-signature.html – adinas