Antecedentes (Puede omitir esta sección)SHA1Managed.ComputeHash diferente de vez en cuando en diferentes servidores
tengo una gran cantidad de datos (alrededor de 3 MB) que debe mantenerse al tanto de varios cientos de máquinas. Algunas de las máquinas ejecutan C# y algunas ejecutan Java. Los datos podrían cambiar en cualquier momento y deben ser propocionados a los clientes en cuestión de minutos. Los datos se entregan en formato Json desde 4 servidores con equilibrio de carga. Estos 4 servidores ejecutan ASP.NET 4.0 con Mvc 3 y C# 4.0.
El código que se ejecuta en los 4 servidores tiene un algoritmo hash que mezcla la respuesta Json y luego convierte el hash en una cadena. Este hash se le da al cliente. Luego, cada pocos minutos, los clientes hacen ping al servidor con el hash y si el hash está desactualizado, se devuelve el nuevo objeto Json. Si el hash sigue siendo actual, se devuelve un 304 con un cuerpo emptry.
De vez en cuando los hashes generados por los 4 cuadros son inconsistentes en todos los cuadros, lo que significa que los clientes están constantemente descargando los datos (cada solicitud podría afectar a un servidor diferente).
Código snipet
Este es el código que se utiliza para generar el hash.
internal static HashAlgorithm Hasher { get; set; }
...
Hasher = new SHA1Managed();
...
Convert.ToBase64String(Hasher.ComputeHash(Encoding.ASCII.GetBytes(jsonString)));
para tratar de depurar el problema Me dividir a cabo de esta manera:
Prehash = PreHashBuilder.ToString();
ASCIIBytes = Encoding.ASCII.GetBytes(Prehash);
HashedBytes = Hasher.ComputeHash(ASCIIBytes);
Hash = Convert.ToBase64String(HashedBytes);
Luego añade un recorrido que escupe los valores anteriores y que no tiene comparación utilizaron para comparar las diferencias.
matrices de bytes se convierten a un formato de cadena para su uso mediante el uso de BeyondCompare:
private static string GetString(byte[] bytes)
{
StringBuilder sb = new StringBuilder();
foreach (byte b in bytes)
{
sb.Append(b);
}
return sb.ToString();
}
Como se puede ver el conjunto de bytes se muestra literalmente como una secuencia de bytes. No es 'convertido'.
El problema
he descubierto que los valores pre-hash y ASCIIBytes eran los mismos, pero los valores HashedBytes eran diferentes - que significaba que el Hash también era diferente.
He reiniciado IIS WebSites en los 4 cuadros de servidor varias veces y, cuando tenían diferentes valores hash, comparé los valores en BeyondCompare. En everycase que era el valor "HashedBytes" que era diferente (los resultados de SHA1Managed.ComputeHash (...))
La pregunta
¿Qué estoy haciendo mal? La entrada a la función ComputeHash es idéntica. ¿Es SHA1Managed Machine dependiente? Eso no ocurre porque la mitad del tiempo las 4 máquinas tienen el mismo hash.
He buscado StackOverFlow y Bing pero no he podido encontrar a nadie más con este problema. Lo más cercano que pude encontrar fue a personas con problemas con su codificación, pero creo que he demostrado que la codificación no es un problema.
salida
Tenía la esperanza de no volcar todo aquí debido a lo largo que es, pero aquí es una snipet del vertedero estoy comparando:
Hash: o1ZxBaVuU6OhE6De96wJXUvmz3M =
HashedBytes: 163861135165110831631611916022224717299375230207115
ASCIIBytes: 115116971031014699111109477911410010111483101114118105991014711510111411810599101461151189959115105103110117112951151011141181059910111410110210111410111099101115959897991071011101001111141001011141151011141181059910195 1185095117114108611041161161125847471051159897991071011101004610910211598101115116971031014699111109477911410010111483101114118105991014711510111411810599101461151189947118505911510510311011711295115101114118105991011141011021011141011109910111595989799107101110100112971211091011101161151161111141011151011141 .... pre-hash: ...
Cuando comparo las dos páginas de los diferentes servidores los bytes ASCII son idénticos, pero los HashedBytes no lo son. El método de volcado que uso para los bytes no genera conversiones, simplemente vacía cada byte en secuencia. Podría delimitar los bytes con un '.' Supongo.
Seguimiento he hecho el cambio b.ToString (CultureInfo.InvariantCulture) haciendo de él la HashAlgorithm una variable local en lugar de una propiedad estática. Estoy esperando que el código se despliegue en los servidores.
En lugar de volcar una cadena y verificarla (que su herramienta puede ignorar para ciertas diferencias) volcar los bytes y ver cómo se comparan. – CrazyCasta
¿Son los 'HashedBytes' exactamente iguales? –
@Mike No, él dice que son diferentes. – CrazyCasta