Sfondo (È possibile saltare questo paragrafo)SHA1Managed.ComputeHash Di tanto in tanto diverso su server diversi
ho una grande quantità di dati (circa 3 MB) che devono essere tenuti aggiornati su diverse centinaia di macchine. Alcune macchine eseguono C# e alcune eseguono Java. I dati potrebbero cambiare in qualsiasi momento e devono essere propagati ai clienti in pochi minuti. I dati vengono consegnati in formato Json da 4 server con carico bilanciato. Questi 4 server eseguono ASP.NET 4.0 con Mvc 3 e C# 4.0.
Il codice che viene eseguito sui 4 server ha un algoritmo di hash che blocca la risposta Json e quindi converte l'hash in una stringa. Questo hash è dato al cliente. Quindi, ogni pochi minuti, i client eseguono il ping del server con l'hash e se l'hash non è aggiornato viene restituito il nuovo oggetto Json. Se l'hash è ancora attuale, viene restituito un 304 con un corpo empie.
Occasionalmente gli hash generati dalle 4 caselle sono incoerenti tra le caselle, il che significa che i client scaricano costantemente i dati (ogni richiesta potrebbe colpire un server diverso).
pezzo di codice presentato
Qui è il codice che viene utilizzato per generare l'hash.
internal static HashAlgorithm Hasher { get; set; }
...
Hasher = new SHA1Managed();
...
Convert.ToBase64String(Hasher.ComputeHash(Encoding.ASCII.GetBytes(jsonString)));
per cercare di eseguire il debug del problema ho diviso fuori in questo modo:
Prehash = PreHashBuilder.ToString();
ASCIIBytes = Encoding.ASCII.GetBytes(Prehash);
HashedBytes = Hasher.ComputeHash(ASCIIBytes);
Hash = Convert.ToBase64String(HashedBytes);
Ho poi aggiunto un percorso che sputa fuori i valori sopra indicati e utilizzati Beyond Compare per confrontare le differenze.
array byte vengono convertiti in un formato di stringa per l'uso BeyondCompare utilizzando:
private static string GetString(byte[] bytes)
{
StringBuilder sb = new StringBuilder();
foreach (byte b in bytes)
{
sb.Append(b);
}
return sb.ToString();
}
Come si può vedere la matrice di byte viene visualizzato letteralmente come una sequenza di byte. Non è "convertito".
Il problema
ho scoperto che i valori Prehash e ASCIIBytes erano gli stessi, ma i valori HashedBytes erano diverse - il che significa che l'hash è stato anche diverso.
Ho riavviato IIS WebSites sulle 4 caselle del server più volte e, quando avevano diversi hash, ha confrontato i valori in BeyondCompare. In everycase era il valore "HashedBytes" che era diverso (i risultati di SHA1Managed.ComputeHash (...))
La questione
Che cosa sto facendo di sbagliato? L'input per la funzione ComputeHash è identico. È dipendente dalla macchina SHA1? Ciò non accade poiché metà del tempo in cui le 4 macchine hanno lo stesso hash.
Ho cercato StackOverFlow e Bing ma non sono riuscito a trovare nessun altro con questo problema. La cosa più vicina che ho trovato sono persone con problemi di codifica, ma penso di aver dimostrato che la codifica non è un problema.
uscita
speravo di non scaricare tutto qui a causa di quanto tempo è, ma qui è uno snipet della discarica mi sto paragonando:
Hash: o1ZxBaVuU6OhE6De96wJXUvmz3M =
HashedBytes: 163861135165110831631611916022224717299375230207115
ASCIIBytes: 115116971031014699111109477911410010111483101114118105991014711510111411810599101461151189959115105103110117112951151011141181059910111410110210111410111099101115959897991071011101001111141001011141151011141181059910195 1185095117114108611041161161125847471051159897991071011101004610910211598101115116971031014699111109477911410010111483101114118105991014711510111411810599101461151189947118505911510510311011711295115101114118105991011141011021011141011109910111595989799107101110100112971211091011101161151161111141011151011141 .... Prehash: ...
Quando metto a confronto le due pagine su diversi server i byte ASCII sono identiche, ma i HashedBytes non lo sono. Il metodo di dumping che utilizzo per i byte non esegue conversioni, semplicemente scarica ogni byte in sequenza. Potrei delimitare i byte con un '.' Credo.
Follow Up ho fatto il cambiamento b.ToString (CultureInfo.InvariantCulture) e hanno fatto il HashAlgorithm una variabile locale invece di una proprietà statica. Sto aspettando che il codice venga distribuito ai server.
Invece di scaricare una stringa e controllarla (che il tuo strumento potrebbe ignorare alcune differenze), scarica i byte e guarda come si confrontano. – CrazyCasta
I 'HashedBytes' sono esattamente gli stessi? –
@ Mike No, sta dicendo che sono diversi. – CrazyCasta