Platforma .NET jest dostarczana z 6 różnymi algorytmami mieszania:
- MD5: 16 bajtów (czas do skrótu 500 MB: 1462 ms)
- SHA-1: 20 bajtów (1644 ms)
- SHA256: 32 bajty (5618 ms)
- SHA384: 48 bajtów (3839 ms)
- SHA512: 64 bajty (3820 ms)
- RIPEMD: 20 bajtów (7066 ms)
Każda z tych funkcji działa inaczej; MD5 jest najszybszy, a RIPEMD najwolniejszy.
MD5 ma tę zaletę, że pasuje do wbudowanego typu Guid; i stanowi podstawę UUID typu 3 . Skrót SHA-1 jest podstawą UUID typu 5. Co sprawia, że są naprawdę łatwe w użyciu do identyfikacji.
MD5 jest jednak podatny na ataki kolizyjne , SHA-1 jest również podatny, ale w mniejszym stopniu.
W jakich warunkach powinienem używać algorytmu haszującego?
Konkretne pytania, na które jestem bardzo ciekawa, mają odpowiedzi:
Czy MD5 nie jest godne zaufania? W normalnych sytuacjach, gdy używasz algorytmu MD5 bez złośliwych zamiarów i żadna osoba trzecia nie ma żadnych złośliwych zamiarów, możesz spodziewać się ŻADNYCH kolizji (czyli dwóch dowolnych bajtów [] tworzących ten sam hash)
O ile lepszy jest RIPEMD niż SHA1? (jeśli jest lepszy) jego obliczenie jest 5 razy wolniejsze, ale rozmiar skrótu jest taki sam jak SHA1.
Jakie są szanse na niezłośliwe kolizje podczas haszowania nazw plików (lub innych krótkich ciągów znaków)? (Np. 2 losowe nazwy plików z tym samym hashem MD5) (z MD5 / SHA1 / SHA2xx) Jakie są ogólne szanse na niezłośliwe kolizje?
Oto wzorzec, którego użyłem:
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();
}