image

This blog post is the result of a thread on Twitter which starts here: https://twitter.com/crumpled_jeavon/status/880522105795870720 and works its way into confusion. Suffice to say I can’t answer these questions in 140 chars so here’s re-cap in the form of Q and A about Machine Keys and Umbraco.  Please note that I am not an expert in hashing algorithms, some of these answers are based on my own research. Hope this clears things up!

How is the password hashed?

It is hashed in the same way that the ASP.NET Universal membership provider (DefaultMembershipProvider) and SqlMembershipProvider hashes passwords which by default uses the HMACSHA256 algorithm.

Jeffrey Schoemaker has been discussing updating Umbraco’s default password hashing to use an even stronger hash algorithm and I’ve recently updated a new task on the issue tracker to research this but it really comes down to the fact that Microsoft does not offer the best stronger hashing method in it’s standard .NET Framework so we’ll see where we end up.

Is the Machine Key used for password hashing?

Yes, In 7.6.0+ it is by default because useLegacyEncoding is false by default in this release. Previous to 7.6.0 the useLegacyEncoding value was true by default purely to preserve some backwards compatibility settings for other products but you’ve been able to set it to true from 7.0.0 (IIRC). Since those products support the more secure password formats, this is now false by default and should be kept as false for new installs. By default the hashing algorithm uses HMACSHA256 which uses the ASP.NET Machine Key to perform part of it’s hashing function. This algorithm is configurable but you really shouldn’t change this to be a lesser strength hashing algorithm.

The HMAC part of this algorithm means it’s derived from a keyed algorithm and the machine key is used to create this key by default. There doesn’t seem to be any documentation or reference to this online that I can find but trying to look through the crypto source code (which isn’t nice to look at) it seems that the default key gets set based on some logic in the RSACryptoServiceProvider class which reads some info from the machine key.

Do machine keys change between environments?

If you explicitly generate and set your own machine key in your web.config then the answer is No.

If you don’t explicitly generate and set your own machine key than you will get an auto-generated machine key. The simple answer for this is: In most cases No, an auto-generated machine key will not change between environments.

To understand when it will change between environments is a little more complicated and comes down to a combination of IIS user, IIS website virtual path (i.e. if you are running a site in a virtual directory), and a combination of a few settings set at the machine config level: “IsolateApps” and “IsolateByAppId”.  Unless a server administrator specifically changes these settings than chances are you won’t be affected by different auto-generated machine keys for your site. If you are really keen, here’s a series all about this topic and other cryptographic changes in .NET 4.5:

  • Part 1 – see the “A brief digression: auto-generated machine keys” for info on auto-generating keys
  • Part 2 – in-depth info about the machine key and hashing changes
  • Part 3 – interesting info especially with regards to  PBKDF2 in .NET Framework

Can I change my machine key?

No.

However, I realize In some cases you might need to change it or move from an auto-generated machine key to an explicit machine key. If that is the case there will be a lot of manual work you’ll need to do. If you simply just change the machine key or add an explicit one when you previously didn’t have one than your members/users will not be able to log in! A few ideas that could use to try to work around this issue (NOTE: I’ve never tried any of these, these are just ideas I thought up)

  • Create a new password column in the database which will store the newly hashed password based on the new machine key
  • Create another website on the same server that doesn’t have a machine key and use that as a REST API (which you’ll also need to auth) to validate existing/old passwords and then re-hash the submitted password on the existing site and store that in the new password column
  • Set a new machine key and then send an email out to all users explaining they’ll need to reset their password. The token/link in the email that you’d use to validate the user can be generated based on their existing hashed password. You’d also have to add in some logic to your login screen to manually reset the password which would re-send this email
  • You could try to figure out the currently auto-generated machine key and use that to attempt to validate the old password format
  • If you are just changing to another explicitly defined machine key, you could try to use the old machine key stored somewhere else to validate the old password format

Can I change from useLegacyEncoding ‘true’ to ‘false’?

Not easily.

This will require a bit of extra work just like the above question but it’s not quite as tricky as changing a Machine Key. When you have useLegacyEncoding=’true’ , the machine key is not used, so you could do something like:

  • Create a new password column in the database which will store the newly hashed password based on the new machine key
  • When a user logs in you can check if they have the new password format or not.
    • If not, then you can validate the password based on the old format then re-hash with the new format and store it and delete the old stored hash password.
    • If so, then you can validate the password based on the new format
  • To do this would probably require inheriting from the current Umbraco membership provider and implementing this logic yourself

Do I need to generate and store a custom Machine Key if I am planning on Load Balancing?

Yes.

This is also mentioned in the Umbraco docs for load balancing

Do I need to generate and install a Machine Key before I run the Umbraco installer?

Yes.

This is because during the Umbraco installation it will hash and store the password for the admin account and if you then add a Machine Key after the fact, you will no longer be able to log in.

Can Umbraco generate a custom Machine Key on install for me?

Yes!

but it doesn’t do that right now. I created that functionality in a PR but we decided to remove the machine key generation part when it was accepted. We have decided to bring it back though so that will be part of an upcoming Umbraco release, whether that is the 7.6.x series or 7.7 series is still being decided.

Do Machine Key’s exist in ASP.NET Core?

No.

Well sort of but not really. I haven’t been able to research too much into this but when speaking to a couple MS Dev’s about this a couple years ago the answer was that the way machine key’s work will be different. If keys need to be shared between apps in ASP.NET Core the data protection APIs need to be used and these keys would then be stored in the registry or the Cloud (i.e. Azure Key Vault), here’s a SO article on this.

 

Clear as mud?! ;)