A estrutura .NET é fornecida com 6 algoritmos de hash diferentes:
- MD5: 16 bytes (tempo para o 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 uma dessas funções executa de maneira diferente; MD5 sendo o mais rápido e RIPEMD sendo o mais lento.
O MD5 tem a vantagem de se encaixar no tipo Guid incorporado; e é a base do tipo 3 UUID . O hash SHA-1 é a base do UUID do tipo 5. O que os torna realmente fáceis de usar para identificação.
No entanto, o MD5 é vulnerável a ataques de colisão , o SHA-1 também é vulnerável, mas em menor grau.
Sob quais condições devo usar qual algoritmo de hash?
Perguntas particulares que estou realmente curioso para ver respondidas são:
MD5 não é confiável? Em situações normais, quando você usa o algoritmo MD5 sem intenção maliciosa e nenhum terceiro tem intenção maliciosa, você esperaria QUALQUER colisão (ou seja, dois bytes arbitrários [] produzindo o mesmo hash)
Quanto melhor o RIPEMD do que o SHA1? (se melhor) é 5 vezes mais lento para calcular, mas o tamanho do hash é o mesmo que o SHA1.
Quais são as chances de obter colisões não-maliciosas ao misturar nomes de arquivos (ou outras seqüências curtas)? (Por exemplo, 2 nomes de arquivos aleatórios com o mesmo hash MD5) (com MD5 / SHA1 / SHA2xx) Em geral, quais são as chances de colisões não maliciosas?
Esta é a referência que eu usei:
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();
}