2009-06-27 10 views
6

Estoy buscando un contenedor C# a una biblioteca nativa MD5 o SHA1 para mejorar el rendimiento del cálculo hash.C# cálculo de hash rápido

Anteriormente cambié SharpZipLib a zlib y obtuve más de 2 aumentos de rendimiento. (De acuerdo, debe tener cuidado de que tenga el zlib.so o el zlib.dll correcto según el sistema operativo y el hardware, pero vale la pena).

¿Valdrá la pena para MD5 o SHA1 o ambos .NET y Mono ya cuentan con una implementación nativa?

(Editado) También: en caso de que tenga que apegarme al MD5CryptoServiceProvider, ¿hay alguna forma de calcular un hash de un archivo mientras lo estoy leyendo? Quiero decir, enviar bytes en fragmentos, pero aún calcular el hash completo?

+1

Tenga en cuenta que MD5 es un algoritmo hash crackeado, y ya no se considera seguro. También se han encontrado colisiones con SHA1, y aunque no son tan severas como MD5, se consideraron roturas significativas. Si necesita un algoritmo de hash seguro, debe optar por las variantes de SHA2 (256/512). – jrista

+0

@pablo, ¿estás seguro de que hashing y no IO access es tu cuello de botella ... –

+0

También puede ser IO, tienes razón, pero después de mi experiencia con zlib, estaba pensando si cambiar la implementación de MD5 aceleraría las cosas. – pablo

Respuesta

3

La clase SHA1CryptoServiceProvider usa la implementación subyacente de Windows API. Sin embargo, SHA1Managed es bastante rápido.

EDITAR: Sí, es posible calcular el hash paso a paso. Los métodos TransformBlock y TransformFinalBlock hacen esto.

+0

bastante rápido puede significar muchas cosas ... resulta bastante rápido significa 3 veces más lento ... aún 30MB por 300ms es mucho más rápido –

0

Solo utilizaría las clases SHA1 y MD5CryptoServiceProvider de BCL. Los que se envían con el marco son bastante rápidos.

+0

Gracias. Eso es lo que estoy usando en este momento, solo me pregunto si hay una manera de hacerlo más rápido. Estoy procesando archivos completos. – pablo

16

MD5 y SHA1 dependen de implementaciones nativas, sin embargo, es posible que una solución C++ + introp sea un poco más rápida, ya que podría reducir un poco el número de llamadas a método y optimizar la implementación nativa.

Tenga en cuenta que Native (SHA1CryptoServiceProvider) puede ser 3 veces más rápido que el administrado (SHA1Managed).

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Diagnostics; 
using System.Security.Cryptography; 

namespace ConsoleApplication22 { 



    class Program { 

     static void Profile(string description, int iterations, Action func) { 

      // clean up 
      GC.Collect(); 
      GC.WaitForPendingFinalizers(); 
      GC.Collect(); 

      // warm up 
      func(); 

      var watch = Stopwatch.StartNew(); 
      for (int i = 0; i < iterations; i++) { 
       func(); 
      } 
      watch.Stop(); 
      Console.Write(description); 
      Console.WriteLine(" Time Elapsed {0} ms", watch.ElapsedMilliseconds); 
     } 

     static void Main() { 
      SHA1Managed managed = new SHA1Managed(); 
      SHA1CryptoServiceProvider unmanaged = new SHA1CryptoServiceProvider(); 

      Random rnd = new Random(); 

      var buffer = new byte[100000]; 
      rnd.NextBytes(buffer); 

      Profile("managed", 1000,() => { 
       managed.ComputeHash(buffer, 0, buffer.Length); 
      }); 

      Profile("unmanaged", 1000,() => 
      { 
       unmanaged.ComputeHash(buffer, 0, buffer.Length); 
      }); 

      Console.ReadKey(); 
     } 
    } 
} 
 
managed Time Elapsed 891 ms 
unmanaged Time Elapsed 336 ms 

También hay que tener en cuenta a menos que mi cálculo es incorrecto, la aplicación no administrada es hashing 100 MB de datos en unos 300 milisegundos, esto sería muy raramente ser un cuello de botella.

+0

Sin embargo, una solución de interoperabilidad requeriría clasificación, lo que podría mitigar cualquier otra ganancia que de otro modo se podría lograr. Sólo algo para tener en cuenta. – jrista

+0

Según tengo entendido, el SHA1CryptoServiceProvider requiere una ordenación de todos modos, está usando llamadas externas –

+0

Tiene sentido. – pablo

0

Dependiendo de su aplicación de hashing, MD5 podría no ser aplicable. MD5 solo es útil para la corrección de errores, ya no es viable como una verificación contra la alteración de archivos maliciosos.

http://en.wikipedia.org/wiki/Md5#Vulnerability

El cuento es, las colisiones MD5 son fáciles de generar cambiando 16 bytes en un archivo.