Skip to content

Instantly share code, notes, and snippets.

@akamsteeg
Last active November 30, 2023 18:09
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save akamsteeg/fe04d4b4909fae23d2b8 to your computer and use it in GitHub Desktop.
Save akamsteeg/fe04d4b4909fae23d2b8 to your computer and use it in GitHub Desktop.
Speed of different hashing algorithms
using System;
using System.Security.Cryptography;
using System.Diagnostics;
using System.Text;
// Compile in the VS Developer Command Prompt with: csc /warnaserror+ /optimize+ hasingspeed.cs
// This is just a demonstration. :)
// Sample output:
// Time to calculate one hash:
// - MD5: 0.152 sec.
// - SHA1: 0.006 sec.
// - SHA256: 0.006 sec.
// - SHA384: 0.007 sec.
// - SHA512: 0.006 sec.
// - RipeMD160: 0.024 sec.
// - PBKDF2_1000: 0.023 sec.
// - PBKDF2_10000: 0.044 sec.
// - PBKDF2_20000: 0.089 sec.
// - PBKDF2_40000: 0.177 sec.
// - PBKDF2_80000: 0.341 sec.
// - PBKDF2_120000: 0.549 sec.
//
// Hashes per second:
// - MD5: 185,185.2 hashes/sec.
// - SHA1: 1,250,000.0 hashes/sec.
// - SHA256: 833,333.3 hashes/sec.
// - SHA384: 714,285.7 hashes/sec.
// - SHA512: 714,285.7 hashes/sec.
// - RipeMD160: 1,250,000.0 hashes/sec.
// - PBKDF2_1000: 217.0 hashes/sec.
// - PBKDF2_10000: 21.5 hashes/sec.
// - PBKDF2_20000: 11.0 hashes/sec.
// - PBKDF2_40000: 5.4 hashes/sec.
// - PBKDF2_80000: 2.6 hashes/sec.
// - PBKDF2_120000: 1.8 hashes/sec.
// Alex Kamsteeg (http://atlex.nl/)
internal class Program
{
public static void Main(string[] args)
{
byte[] hash = BytesToHash(16);
byte[] password = Encoding.UTF8.GetBytes("e7K7ZB$z");
const int maxHashes = 5000;
HashFormat[] formatsToTest = new[]
{
HashFormat.MD5,
HashFormat.SHA1,
HashFormat.SHA256,
HashFormat.SHA384,
HashFormat.SHA512,
HashFormat.RipeMD160,
HashFormat.PBKDF2_1000,
HashFormat.PBKDF2_10000,
HashFormat.PBKDF2_20000,
HashFormat.PBKDF2_40000,
HashFormat.PBKDF2_80000,
HashFormat.PBKDF2_120000,
};
Stopwatch sw = new Stopwatch();
Console.WriteLine("Time to calculate one hash:");
for(int f = 0; f < formatsToTest.Length; f++)
{
Console.Write("- {0}: ", formatsToTest[f]);
sw.Restart();
HashBytes(hash, password, formatsToTest[f]);
sw.Stop();
Console.WriteLine("{0:N3} sec.", sw.ElapsedMilliseconds/1000.0);
}
Console.WriteLine();
Console.WriteLine("Hashes per second:");
for(int f = 0; f < formatsToTest.Length; f++)
{
Console.Write("- {0}: ", formatsToTest[f]);
sw.Restart();
for (int i = 0; i < maxHashes; i++)
HashBytes(hash, password, formatsToTest[f]);
sw.Stop();
Console.WriteLine("{0:N1} hashes/sec.", maxHashes/(sw.ElapsedMilliseconds/1000.0));
}
}
private static byte[] BytesToHash(int numberOfBytes)
{
byte[] bytesToHash = new byte[numberOfBytes];
new RNGCryptoServiceProvider().GetNonZeroBytes(bytesToHash);
return bytesToHash;
}
private static byte[] HashBytes(byte[] hash, byte[] password, HashFormat format)
{
byte[] result = null;
switch (format)
{
case HashFormat.PBKDF2_1000:
case HashFormat.PBKDF2_10000:
case HashFormat.PBKDF2_20000:
case HashFormat.PBKDF2_40000:
case HashFormat.PBKDF2_80000:
case HashFormat.PBKDF2_120000:
{
int iterations = Convert.ToInt32(format.ToString().Split('_')[1]);
var pbkdf2 = new Rfc2898DeriveBytes(password, hash, iterations);
result = pbkdf2.GetBytes(20);
break;
}
case HashFormat.RipeMD160:
case HashFormat.SHA512:
case HashFormat.SHA384:
case HashFormat.SHA256:
case HashFormat.SHA1:
case HashFormat.MD5:
{
// Create a buffer of buffer.Length * 2 and fill it to
// make sure we're hashing salted (just like PBKDF2)
var saltAndPassword = new byte[hash.Length + password.Length];
Buffer.BlockCopy(hash, 0, saltAndPassword, 0, hash.Length);
Buffer.BlockCopy(password, 0, saltAndPassword, hash.Length, password.Length);
HashAlgorithm algorithm = null;
if (format == HashFormat.RipeMD160)
algorithm = new RIPEMD160Managed();
else if (format == HashFormat.SHA512)
algorithm = new SHA512Managed();
else if (format == HashFormat.SHA384)
algorithm = new SHA384Managed();
else if (format == HashFormat.SHA256)
algorithm = new SHA256Managed();
else if (format == HashFormat.SHA1)
algorithm = new SHA1Managed();
else if (format == HashFormat.MD5)
algorithm = MD5.Create();
//Console.WriteLine(algorithm.GetType().Name);
using (algorithm)
{
result = algorithm.ComputeHash(saltAndPassword);
}
break;
}
default:
throw new InvalidOperationException();
}
return result;
}
}
internal enum HashFormat
{
MD5,
SHA1,
SHA256,
SHA384,
SHA512,
RipeMD160,
PBKDF2_1000,
PBKDF2_10000,
PBKDF2_20000,
PBKDF2_40000,
PBKDF2_80000,
PBKDF2_120000,
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment