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