2011-08-24 14 views
5

Sto cercando di ottenere rapidamente una libreria client netta buggy per un servizio di terze parti che sto usando per lavorare. La libreria originale (che funziona) è scritta in Ruby, ma la loro libreria equivalente per DotNet produce output di hash diversi alla libreria Ruby.HMC SHA1 hash - C# produce output hash diversi da Ruby

Il codice di crittografia Ruby è la seguente:

def self.encrypt_string(input_string) 
    raise Recurly::ConfigurationError.new("Recurly gem not configured") unless Recurly.private_key.present? 
    digest_key = ::Digest::SHA1.digest(Recurly.private_key) 
    sha1_hash = ::OpenSSL::Digest::Digest.new("sha1") 
    ::OpenSSL::HMAC.hexdigest(sha1_hash, digest_key, input_string.to_s) 
end 

L'(presumibilmente) codice equivalente C# è:

private static string ComputePrivateHash(string dataToProtect) 
{ 
    if(String.IsNullOrEmpty(Configuration.RecurlySection.Current.PrivateKey)) 
     throw new RecurlyException("A Private Key must be configured to use the Recurly Transparent Post API."); 

    byte[] salt_binary = SHA1.Create().ComputeHash(Encoding.ASCII.GetBytes(dataToProtect)); 
    string salt_hex = BitConverter.ToString(salt_binary).Replace("-", "").ToLower(); 
    string salt = salt_hex.Substring(0, 20); 

    HMACSHA1 hmac_sha1 = new HMACSHA1(Encoding.ASCII.GetBytes(Configuration.RecurlySection.Current.PrivateKey)); 
    hmac_sha1.Initialize(); 

    byte[] private_key_binary = Encoding.ASCII.GetBytes(salt); 
    byte[] passkey_binary = hmac_sha1.ComputeHash(private_key_binary, 0, private_key_binary.Length); 

    return BitConverter.ToString(passkey_binary).Replace("-", "").ToLower(); 
} 

L'uscita hash effettiva differisce però, dato lo stesso ingresso e la chiave privata. Cosa c'è di sbagliato nel metodo C# che causa la produzione dell'hash errato?

EDIT
Questo è il modo ho avrei scritto il codice, anche se produce ancora l'uscita sbagliata:

private static string ComputePrivateHash(string dataToProtect) 
{ 
    if(String.IsNullOrEmpty(Configuration.RecurlySection.Current.PrivateKey)) 
     throw new RecurlyException("A Private Key must be configured to use the Recurly Transparent Post API."); 

    var privateKey = Configuration.RecurlySection.Current.PrivateKey; 
    var hashedData = SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(dataToProtect)); 
    var hmac = new HMACSHA1(Encoding.UTF8.GetBytes(privateKey)); 
    var hash = hmac.ComputeHash(hashedData); 
    return BitConverter.ToString(hash).Replace("-", "").ToLower(); 
} 

risposta corretta

Grazie alla risposta di Henning in basso , Sono stato in grado di determinare che il codice corretto è:

var privateKey = Configuration.RecurlySection.Current.PrivateKey; 
var hashedKey = SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(privateKey)); 
var hmac = new HMACSHA1(hashedKey); 
var hash = hmac.ComputeHash(Encoding.ASCII.GetBytes(dataToProtect)); 
return BitConverter.ToString(hash).Replace("-", "").ToLower(); 
+0

Forse http://stackoverflow.com/questions/3393790/how-to-do-it-in-ruby-on-rails può aiutare? –

+1

Si potrebbe pensare, ma no :( –

+0

Cosa avete fatto per risolvere il problema da soli? Il minimo che ci si potrebbe aspettare sarebbe che si indagasse se gli input binari della primitiva HMAC sono uguali o no. facendo cose strane con la codifica esadecimale e l'estrazione della sottostringa che non sembra essere presente nel tuo codice Ruby. Quindi sei sicuro che la versione di Ruby stia facendo tutto questo dietro alle tue spalle? –

risposta

4

Se ho capito il codice, sembra che il codice Ruby stia eseguendo l'hashing della chiave prima di inviarlo a HMAC (che non deve essere crittografato, dato che HMAC avrà una chiave lunga se necessario) e feed la chiave con hash di HMAC insieme al messaggio originale.

D'altra parte, il codice C# calcola un HMAC con la chiave originale e hash del messaggio. (Inspiegabilmente, le variabili in cui si memorizza il messaggio di hash sono chiamati salt e private_key_binary, se il contenuto non è né un sale né una chiave ...)

Non riesco a immaginare che le # librerie Ruby e C sarebbero trattare HMAC in modo diverso che questa è la cosa giusta da fare.

+0

Eccellente, hai ragione, non stavo interpretando quello che stavo leggendo correttamente. Grazie per avermi parlato di questo; Ho aggiornato la mia domanda per includere la risposta corretta. –