Decrypt user password in ASP.Net SqlMembershipProvider

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>
comments powered by Disqus