Support for new ASP.NET password storage practices
At present, the EPiServer pattern can be used against hashes generated by the ASP.NET membership provider. However, this is what's referred to as the SqlMembershipProvider which has now been somewhat deprecated by newer implementations.

It all gets a bit confusing, but in short there is a new pattern for MVC apps and another for web forms apps. I'd really like to write something up on the strength improvements (for one of them, anyway) and be able to do a back-to-back comparison of old and new.
Here's how they work:

For a new ASP.NET MVC4 app using the Visual Studio 2012 template, the SimpleMembershipProvider is used. This is also used in what Microsoft refers to as "ASP.NET WebPages" which have been around for a while now.

The hashing approach is explained here:

From the comments in the code: "PBKDF2 with HMAC-SHA1, 128-bit salt, 256-bit subkey, 1000 iterations."

The implementation of the hashing is here:

In simple terms:
1. Generate the 128 bit salt and 256 bit subkey from the password using the Rfc2898DeriveBytes class with 1,000 iterations (implements PBKDF2):
2. Create a byte array containing the salt then the subkey.
3. Base64 encode it all then store it in a single DB field.

This gives us "passwords" as follows (password, plain text):

AG8nVMgXdmjX+LVQUjrhNz1QFOt+S/wudjeeOSPyz/+cuXYtY12TrQqQ9SV2HnO0mA== password
AKmqIP8aQ3HepENus1wOKkHUG73OPFuVqhVOxzr4Ar6kMdMeOhA3tTEmeQ61gd+iWw== password
AB2OiyAI8LPgCHwk4VXxsaheWk7Ka/Yq2XGFX3FwlH/GUWKdTZFp0oKPWfOHNgRmpg== Password!
AHzkkhFXHZUCDzryniFjI3/LF4viZG0IY9PYMVlsakpkScnFZDWXRm7iTVBLAooHYA== Password!

For a new Web Forms app using the Visual Studio 2012 template, the DefaultMembershipProvider is used. It's pretty much the same deal hashing wise as with the old SqlMembershipProvider (and therefore the EPiServer pattern) but uses a SHA256 hash by default instead of SHA1 (although can be configured to use SHA1). Here's the process:

1. Generates a 128 bit salt.
2. Hash the password with SHA256.
3. Add the hash to the salt then Base64 encode it.
4. Base64 encode the salt.
5. Store both encoded values into separate DB fields.

This gives us "passwords" as follows (password, salt, plain text):

cfrhyZf2CHjZ/pI7TNUJXcxMqKy0nsmR6e9qY+mCmNk= JAtBUUstKzWYVJhxMfG3bQ== password
jYkIDI2hGqEZ4T7mlv7aqXqOQNiw13Nbq08UXkjZPIk= dXPGsSyHJ4FEmkfRsuGFsg== password
Hzxoixo/8Bx9AQfQ+b3DjSMAB09gSCYNa7Woxz4ar34= C9Zj7TZRWIBhhK3qlcrkEA== Password!
fEnbqvFsutQS1tONeCybK/HyfmSl+tDPKBOuyW/clQA= mdi0z0NpxSC6igdRGqm/Fw== Password!

All of this supersedes the SqlMembershipProvider which was ultimately just a single iteration of SHA1.

Caveat: this is from briefly browsing through mostly decompiled source code and I've not actually recreated the process myself. Originally, I'd been advised that the DefaultMembershipProvider implemented 1,000 iterations of SHA256 but evidence seems to be to the contrary. Hopefully this is easy enough to validate if you're able to put together a pattern for it. I'm happy to validate against a complete sample data set if you want a beta tester.

Messages In This Thread
Support for new ASP.NET password storage practices - by troyhunt - 11-14-2012, 10:17 AM