Tag Archives: NET

Encrypting (Hashing) Passwords for your Website

In my previous blog entry which explains how to implement a custom MembershipProvider on an ASP.Net MVC web site, I mentioned the BCrypt library in passing. Today I’d like to dig into the library a little more and show you how and why you should consider using it.

Before we get into that though, what is what is ‘hashing’ and how is it different to ‘encryption’?

Encryption is part of a two way process in which data is encoded, but must be decryptable afterwards. For password storage, this decryption step is unnecessary and is actually a security vulnerability if someone gets hold of your keys.

In contrast, hashing is a one way transformation that is very hard to reverse. So to store passwords, a site would simply hash them before saving them to a database. Then when a user logs in, the password they supply is also hashed and compared to the hashed value in the database. If they typed in the same password the hashes will match and the authentication passes.

The advantage of this, is that the web site doesn’t need to decrypt a password at any point. All it ever does is hash them which is great for security.

There are various hashing algorithms out there, and many of them are wonderfully optimised and very fast. A typical example is SHA. An optimal hasher sounds great doesn’t it?

… well it isn’t. In fact it’s a weakness with the power of modern cpus and cloud computing resources. It means that its very possible and remarkably cheap to brute force SHA with a dictionary attack, simply because it is so fast.

This is where BCrypt comes in. It is intentionally slow, so should someone try to brute force it, its simply not viable. Whereas a hacker can generate 100s of millions of SHA hashes a second, they can’t with BCrypt, and as technology marches on, you can just increase the work factor on BCrypt to keep ahead of processors.

There are a few BCrypt.Net implementations floating around, and the one I’ve used I pulled down with nuget. To use it is as simple as:

private static readonly int BCRYPT_WORK_FACTOR = 10;
string hashedPassword = BCrypt.Net.BCrypt.HashPassword(account.HashedPassword, BCRYPT_WORK_FACTOR);
bool matched = BCrypt.Net.BCrypt.Verify(password, match.HashedPassword))

Every increment in work factor doubles the type the hash takes. Some of the .net implemtations struggle to get past 31 due to a bug, but you shouldn’t need a value anything like that high for a few years at least!

A Retry Helper Class with Exponential Backoff

Just a small snippet here. It’s sometimes useful to have some retry logic when talking to web services etc. This little helper class does just that whilst implementing exponential backoff:

	public class RetryHelper<T>
	{
		private static readonly ILog log = LogManager.GetLogger(typeof(RetryHelper<T>));
		
		public T Value { get; protected set; }

		/// <summary>
		/// Performs an operations returning a type of T. Should the operation throw an exception, it will be 
		/// retried after the retry interval. The backoff is exponentional on each retry.
		/// e.g. string res = RetryHelper{string}( () => myFunc(myParam1, myParam2), 5, 500).Value;
		/// </summary>
		/// <typeparam name="T">Return type of function to add retry semantics to.</typeparam>
		/// <param name="func">The function delegate.</param>
		/// <param name="maxAttempts">Number of times to retry the operation.</param>
		/// <param name="baseMillisecondsInterval">The interval of the first retry, will double upon each attempt.</param>
		public RetryHelper(Func<T> func, int maxAttempts = 5, int baseMillisecondsInterval = 500)
		{
			int retryInterval = baseMillisecondsInterval;

			for (int attempt = 1; attempt <= maxAttempts; ++attempt)
			{
				try
				{
					Value = func();
					return;
				}
				catch (Exception ex)
				{
					log.ErrorFormat("Failure executing operation (Attempt={0}) : {1}", attempt, ex.Message);
				}

				System.Threading.Thread.Sleep(retryInterval);

				retryInterval *= 2;
			}

			throw new ApplicationException(string.Format("Exhausted retries (Attempts={0})", maxAttempts));
		}
	}

This code is dependent on log4net, but you can of course remove that.

To use it, all you need to do is:

string MyFunc(int i, string s)
{
	...
}

...

string res = new RetryHelper<string>( 
	() => MyFunc(myParam1, myParam2)).Value;

It’s worth noting that exponential backoff for network code often randomises the retry interval to prevent packet collisions. This example doesn’t, but there is nothing stop you from doing that.