El marco .NET se entrega con 6 algoritmos de hashing diferentes:
- MD5: 16 bytes (Tiempo de hash 500MB: 1462 ms)
- SHA-1: 20 bytes (1644 ms)
- SHA256: 32 bytes (5618 ms)
- SHA384: 48 bytes (3839 ms)
- SHA512: 64 bytes (3820 ms)
- RIPEMD: 20 bytes (7066 ms)
Cada una de estas funciones se realiza de manera diferente; MD5 es el más rápido y RIPEMD es el más lento.
MD5 tiene la ventaja de que cabe en el tipo Guid incorporado; y es la base del UUID tipo 3 . El hash SHA-1 es la base del UUID tipo 5. Lo que los hace realmente fáciles de usar para la identificación.
MD5, sin embargo, es vulnerable a los ataques de colisión , SHA-1 también es vulnerable, pero en menor grado.
¿En qué condiciones debo usar qué algoritmo de hash?
Las preguntas particulares que realmente tengo curiosidad por ver respondidas son:
¿No se puede confiar en MD5? En situaciones normales, cuando utiliza el algoritmo MD5 sin intención maliciosa y ningún tercero tiene ninguna intención maliciosa, esperaría CUALQUIER colisión (es decir, dos bytes arbitrarios [] que producen el mismo hash)
¿Cuánto mejor es RIPEMD que SHA1? (si es mejor) es 5 veces más lento de calcular, pero el tamaño de hash es el mismo que SHA1.
¿Cuáles son las probabilidades de obtener colisiones no maliciosas al codificar nombres de archivos (u otras cadenas cortas)? (Por ejemplo, 2 nombres de archivo aleatorios con el mismo hash MD5) (con MD5 / SHA1 / SHA2xx) En general, ¿cuáles son las probabilidades de colisiones no maliciosas?
Este es el punto de referencia que utilicé:
static void TimeAction(string description, int iterations, Action func) {
var watch = new Stopwatch();
watch.Start();
for (int i = 0; i < iterations; i++) {
func();
}
watch.Stop();
Console.Write(description);
Console.WriteLine(" Time Elapsed {0} ms", watch.ElapsedMilliseconds);
}
static byte[] GetRandomBytes(int count) {
var bytes = new byte[count];
(new Random()).NextBytes(bytes);
return bytes;
}
static void Main(string[] args) {
var md5 = new MD5CryptoServiceProvider();
var sha1 = new SHA1CryptoServiceProvider();
var sha256 = new SHA256CryptoServiceProvider();
var sha384 = new SHA384CryptoServiceProvider();
var sha512 = new SHA512CryptoServiceProvider();
var ripemd160 = new RIPEMD160Managed();
var source = GetRandomBytes(1000 * 1024);
var algorithms = new Dictionary<string,HashAlgorithm>();
algorithms["md5"] = md5;
algorithms["sha1"] = sha1;
algorithms["sha256"] = sha256;
algorithms["sha384"] = sha384;
algorithms["sha512"] = sha512;
algorithms["ripemd160"] = ripemd160;
foreach (var pair in algorithms) {
Console.WriteLine("Hash Length for {0} is {1}",
pair.Key,
pair.Value.ComputeHash(source).Length);
}
foreach (var pair in algorithms) {
TimeAction(pair.Key + " calculation", 500, () =>
{
pair.Value.ComputeHash(source);
});
}
Console.ReadKey();
}