Платформа .NET поставляется с 6 различными алгоритмами хеширования:
- MD5: 16 байт (время хеширования 500 МБ: 1462 мс)
- SHA-1: 20 байтов (1644 мс)
- SHA256: 32 байта (5618 мс)
- SHA384: 48 байтов (3839 мс)
- SHA512: 64 байта (3820 мс)
- RIPEMD: 20 байт (7066 мс)
Каждая из этих функций выполняется по-разному; MD5 - самый быстрый, а RIPEMD - самый медленный.
Преимущество MD5 в том, что он подходит для встроенного типа Guid; и это основа UUID типа 3 . Хеш SHA-1 является основой UUID типа 5. Что делает их действительно простыми в использовании для идентификации.
Однако MD5 уязвим для коллизионных атак , SHA-1 также уязвим, но в меньшей степени.
При каких условиях я должен использовать какой алгоритм хеширования?
Мне действительно любопытно получить ответы на следующие конкретные вопросы:
Разве нельзя верить MD5? В обычных ситуациях, когда вы используете алгоритм MD5 без злонамеренного намерения, и никакая третья сторона не имеет злонамеренного намерения, вы ожидаете ЛЮБЫХ коллизий (то есть два произвольных байта [] производят один и тот же хэш)
Насколько RIPEMD лучше SHA1? (если он лучше) его вычисление в 5 раз медленнее, но размер хэша такой же, как у SHA1.
Каковы шансы получить незащищенные коллизии при хешировании имен файлов (или других коротких строк)? (Например, 2 случайных имени файла с одинаковым хешем MD5) (с MD5 / SHA1 / SHA2xx) В общем, каковы шансы на отсутствие вредоносных коллизий?
Это тест, который я использовал:
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();
}