2009-11-11 12 views
5

Estoy escribiendo una rutina C# que crea hashes a partir de archivos jpg. Si paso en una matriz de bytes a mi objeto SHA512, entonces obtengo el comportamiento esperado, sin embargo, si paso en una secuencia de memoria, los dos archivos siempre tienen el mismo valor.¿Por qué estos dos archivos tienen el mismo valor cuando uso MemoryStream?

Ejemplo 1:

 SHA512 mySHA512 = SHA512.Create(); 

     Image img1 = Image.FromFile(@"d:\img1.jpg"); 
     Image img2 = Image.FromFile(@"d:\img2.jpg"); 
     MemoryStream ms1 = new MemoryStream(); 
     MemoryStream ms2 = new MemoryStream(); 

     img1.Save(ms1, ImageFormat.Jpeg); 
     byte[] buf1 = ms1.GetBuffer(); 
     byte[] hash1 = mySHA512.ComputeHash(buf1); 

     img2.Save(ms2, ImageFormat.Jpeg); 
     byte[] buf2 = ms2.GetBuffer(); 
     byte[] hash2 = mySHA512.ComputeHash(buf2); 

     if (Convert.ToBase64String(hash1) == Convert.ToBase64String(hash2)) 
      MessageBox.Show("Hashed the same"); 
     else 
      MessageBox.Show("Different hashes"); 

que produce "Diferentes hashes". Pero una de las sobrecargas del método ComputeHash toma un objeto de flujo y prefiero usarlo. Cuando lo hago:

 SHA512 mySHA512 = SHA512.Create(); 

     Image img1 = Image.FromFile(@"d:\img1.jpg"); 
     Image img2 = Image.FromFile(@"d:\img2.jpg"); 
     MemoryStream ms1 = new MemoryStream(); 
     MemoryStream ms2 = new MemoryStream(); 

     img1.Save(ms1, ImageFormat.Jpeg); 
     byte[] hash1 = mySHA512.ComputeHash(ms1); 

     img2.Save(ms2, ImageFormat.Jpeg); 
     byte[] hash2 = mySHA512.ComputeHash(ms2); 

     if (Convert.ToBase64String(hash1) == Convert.ToBase64String(hash2)) 
      MessageBox.Show("Hashed the same"); 
     else 
      MessageBox.Show("Different hashes"); 

Eso produce "Hashed lo mismo".

¿Qué está pasando aquí que me falta?

+0

No son copias de la imagen _same_, ¿o sí? –

+0

¿Qué sucede si buscas el comienzo de la transmisión después de la llamada .Save? p.ej. ms1.Seek (0, SeekOrigin.Begin); – Joe

+0

En este caso, podría usar 'mySHA512.ComputeHash.ComputeHash (ms1.GetBuffer(), 0, (int) ms1.Length)'. Evita copias innecesarias – CodesInChaos

Respuesta

14

No está rebobinando sus MemoryStreams, por lo que el hash se calcula a partir de una secuencia de bytes vacía. Utilice

ms1.Position = 0; 
ms2.Position = 0; 

después de llamar Save.

Una nota adicional: no use GetBuffer de esta manera. Use ToArray, que le proporcionará una matriz de bytes del mismo tamaño que la longitud de la secuencia: GetBuffer devuelve el almacenamiento intermedio sin procesar, que (normalmente) tendrá algo de relleno, que no querría usar accidentalmente. Puede usar GetBuffer si luego se asegura de que solo usa la parte relevante de él, por supuesto, esto evita crear una nueva copia de los datos.

+0

Gracias por el consejo, ¡eso funciona! –

Cuestiones relacionadas