Created
August 22, 2012 19:08
-
-
Save benlesh/3428461 to your computer and use it in GitHub Desktop.
A password hashing utility for .NET and a functional test console application for it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// A hashing utility. | |
/// </summary> | |
public static class Hasher | |
{ | |
/// <summary> | |
/// Gets an HMAC SHA512 hash for some text. | |
/// </summary> | |
/// <param name="text">The text to hash</param> | |
/// <param name="salt">The salt to use in hashing.</param> | |
/// <param name="key">The key to use to hash the text.</param> | |
/// <returns>The hash.</returns> | |
public static byte[] GetHash(string text, byte[] salt, byte[] key) | |
{ | |
using (var sha512 = new HMACSHA512(key)) | |
{ | |
var buffer = GetBytesToHash(text, salt); | |
return sha512.ComputeHash(buffer); | |
} | |
} | |
/// <summary> | |
/// Does the work of combining the text and the salt into | |
/// a single byte array. | |
/// </summary> | |
/// <param name="text">The text to be hashed at some point.</param> | |
/// <param name="salt">The bytes to salt it with.</param> | |
/// <returns>The combined byte array.</returns> | |
private static byte[] GetBytesToHash(string text, byte[] salt) | |
{ | |
var buffer = new byte[text.Length + salt.Length]; | |
var passwordBytes = Encoding.UTF8.GetBytes(text); | |
passwordBytes.CopyTo(buffer, 0); | |
Array.ConstrainedCopy(salt, 0, buffer, passwordBytes.Length, salt.Length); | |
return buffer; | |
} | |
/// <summary> | |
/// Generates a key from text input. | |
/// </summary> | |
/// <param name="text">The text to generate the key from.</param> | |
/// <param name="salt">The salt to use to generate a key.</param> | |
/// <param name="iterations">The number of iterations to use to stretch the key.</param> | |
/// <param name="length">The number of bytes in length the key should be.</param> | |
/// <returns>A key byte array.</returns> | |
public static byte[] GetKey(string text, byte[] salt, int iterations, int length) | |
{ | |
using (var pbkdf2 = new Rfc2898DeriveBytes(text, salt, iterations)) | |
{ | |
return pbkdf2.GetBytes(length); | |
} | |
} | |
/// <summary> | |
/// Gets a random salt of a specified length. | |
/// </summary> | |
/// <param name="length">The length of the salt to get.</param> | |
/// <returns>A random array of bytes.</returns> | |
public static byte[] GetSalt(int length) | |
{ | |
using (var rng = new RNGCryptoServiceProvider()) | |
{ | |
var salt = new byte[length]; | |
rng.GetBytes(salt); | |
return salt; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
byte[] salt = null; | |
var sw = new Stopwatch(); | |
while (true) | |
{ | |
// get some text to hash. | |
Console.WriteLine("Enter some text to hash:"); | |
var text = Console.ReadLine(); | |
// start timing the process (for reference purposes) | |
sw.Restart(); | |
if (salt == null) | |
{ | |
// get a 512 byte salt. | |
salt = Hasher.GetSalt(512); | |
} | |
// get a 512 byte key based off of the password and the salt | |
// stretch by iterating 2000 times to slow down the hashing process. | |
var key = Hasher.GetKey(text, salt, 2000, 512); | |
// finally, generate the hash. | |
var hash = Hasher.GetHash(text, salt, key); | |
// let's check how long that took. | |
var ms = sw.ElapsedMilliseconds; | |
// display the information. | |
Console.WriteLine("Salt: {0}", Convert.ToBase64String(salt)); | |
Console.WriteLine("Hash: {0}", Convert.ToBase64String(hash)); | |
Console.WriteLine("Hash Length: {0}", hash.Length); | |
Console.WriteLine("Time: {0}", ms); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment