Il framework .NET viene fornito con 6 diversi algoritmi di hashing:
- MD5: 16 byte (tempo di hash 500 MB: 1462 ms)
- SHA-1: 20 byte (1644 ms)
- SHA256: 32 byte (5618 ms)
- SHA384: 48 byte (3839 ms)
- SHA512: 64 byte (3820 ms)
- RIPEMD: 20 byte (7066 ms)
Ognuna di queste funzioni svolge in modo diverso; MD5 è il più veloce e RIPEMD il più lento.
MD5 ha il vantaggio di adattarsi al tipo Guid incorporato; ed è la base dell'UUID di tipo 3 . L'hash SHA-1 è la base dell'UUID di tipo 5.Il che li rende davvero facili da usare per l'identificazione.
MD5 è tuttavia vulnerabile agli attacchi di collisione , SHA-1 è anche vulnerabile ma in misura minore.
In quali condizioni dovrei usare quale algoritmo di hashing?
Le domande particolari a cui sono davvero curioso di vedere la risposta sono:
MD5 non è affidabile? In situazioni normali quando si utilizza l'algoritmo MD5 senza intenzioni dannose e nessuna terza parte ha intenzioni dannose ci si aspetterebbe QUALSIASI collisione (ovvero due byte arbitrari [] che producono lo stesso hash)
Quanto è meglio RIPEMD di SHA1? (se è meglio) è 5 volte più lento da calcolare ma la dimensione dell'hash è la stessa di SHA1.
Quali sono le probabilità di ottenere collisioni non dannose quando si esegue l'hashing di nomi di file (o altre stringhe brevi)? (Ad esempio 2 nomi di file casuali con lo stesso hash MD5) (con MD5 / SHA1 / SHA2xx) In generale, quali sono le probabilità di collisioni non dannose?
Questo è il benchmark che ho usato:
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();
}