In this post I will discuss decoding of encrypted passwords in ASP.Net SqlMembershipProvider table. This
discussion will help answer to questions as follows:
- How to decrypt passwords stored database created by SqlMembershipProvider?
- How to decrypt passwords in DNN (Dotnetnuke)?
- How to extend a memebership provider object?
- And more questions related to ASP.Net membership provoider using Sql database...
If you are using Microsoft provider SqlMembershipProvider in DNN or any other ASP.Net application,
look in the database and you will find a table aspnet_Membership. This is where
passwords are stored. Depending on how you configured your membership provider, these passwords
may already be in clear text. This behavior is controlled by an attribute in definition of
membership provider in config file of your application.
passwordFormat="Encrypted"
There is PasswordFormat field in the database table as well. That means handling
of password values depends very heavily of this value. If your passwords are encrypted, then
the value of this field is set to 2.
Algorithm for encrypt and decrypt of password
Next you need to know what algorithm and key is used to encrypt and decrypt the password. Default
implementation of Membership provider picks up these values from machineKey
settings from your config file. So in your config file under system.web you
will notice an entry like:
<machineKey validationKey="AD3642D1C078D34C05741E5A63514C784......."
decryptionKey="F18D8F1FA9F986B26B9F0C8CB4067CAC45E25F4BD6........"
decryption="3DES" validation="SHA1" />
This is where your algorithm and keys are defined. And this is what default implementation of
SqlMembershipProvider uses.
How to decrypt password?
MembershipProvider class has DecryptPassword and EncryptPassword methods that
are used by SqlMembershipProvider. When I started researching this topic, I found suggestions on
creating a new class that inherits from MembershipProvider class and then call DecryptPassword
method to do the job. Well I did try that approach and it did not work. I always ended up with following
exception.
Unable to validate data.
at System.Web.Configuration.MachineKeySection.EncryptOrDecryptData
(Boolean fEncrypt, Byte[] buf, Byte[] modifier, Int32 start, Int32 length,
Boolean useValidationSymAlgo, Boolean useLegacyMode, IVType ivType, Boolean signData)
at System.Web.Security.MembershipAdapter.EncryptOrDecryptData(Boolean encrypt,
Byte[] buffer, Boolean useLegacyMode)
at System.Web.Security.MembershipProvider.DecryptPassword(Byte[] encodedPassword)
at MembershipPasswordRecover.NetFourMembershipProvider.GetPassword(String encPwd) in
at MembershipPasswordRecover.Program.Main(String[] args) in
After looking through the code in reflector, I saw that Microsoft providers decrypts in two steps.
The encrypted password is actually a Base64 conversion of encrypted data. So first it converts it
back from Base64 and then calls DecryptPassword method. I just did the easiest thing. Copied the code
from Microsoft implementation, removed all the checks it was doing and then used it. Following
class is an example of a class derived form SqlMembershipProvider with a method that just
returns me password in clear text for a given encrypted password.
namespace MembershipPasswordRecover
{
public class NetFourMembershipProvider : SqlMembershipProvider
{
public string GetClearTextPassword(string encryptedPwd)
{
byte[] encodedPassword = Convert.FromBase64String(encryptedPwd);
byte[] bytes = this.DecryptPassword(encodedPassword);
if (bytes == null)
{
return null;
}
return Encoding.Unicode.GetString(bytes, 0x10, bytes.Length - 0x10);
}
}
}
static void Main(string[] args)
{
var passwordManager = new NetFourMembershipProvider();
var clearPWd = passwordManager.GetClearTextPassword("encryptedpasswordhere");
Console.WriteLine(clearPWd);
}
Configuration of your recovery application
If you are putting this password decryption code in a separate application, then you have to
ensure the following things.
- Create machineKey section in your configuration file under system.web section.
It does not matter if you are creating a web application or console application, you always
have a application configuration file you can create this entry.
- You do not have to add an entry for SqlMembershipProvider in configuration file for recovery
of the password. But it is good idea to that you copy the same settings from web application into
your password decryption application as well.
Here is how app.config file looks in my sample console application. You can
see that I do not need a web application to include system.web section in my console
application.
<?xml version="1.0"?>
<configuration>
<system.web>
<machineKey validationKey="AD3642D1C078D34C05741E5A63514C784......."
decryptionKey="F18D8F1FA9F986B26B9F0C8CB4067CAC45E25F4BD......"
decryption="3DES" validation="SHA1" />
<membership defaultProvider="AspNetSqlMembershipProvider" userIsOnlineTimeWindow="15">
<providers>
<clear />
<add name="AspNetSqlMembershipProvider"
type="System.Web.Security.SqlMembershipProvider"
connectionStringName="SiteSqlServer" enablePasswordRetrieval="true"
enablePasswordReset="true" requiresQuestionAndAnswer="false"
minRequiredPasswordLength="7" minRequiredNonalphanumericCharacters="0"
requiresUniqueEmail="false"
passwordFormat="Encrypted"
applicationName="DotNetNuke"
description="Stores and retrieves ......." />
</providers>
</membership>
</system.web>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup>
</configuration>