Wednesday, December 12, 2007

Interop with Membership Provider

I have a situation where I have been using the Membership provider and wish to migrate to a custom format for the re-work i am doing on OpenID. There is no great reason for not using their structure other than it has a bunch of stuff I really don't need nor will be implementing.

My issue was that the user passwords are SHA-1 hashed and i wanted to simply migrate that data and provide the same implementation so that I don't have hassles checking password or creating new password.

The code below will do that (except for encrypted passwords).

using System;
using System.Text;
using System.Security.Cryptography;

public enum PasswordFormats
{
Clear,
Hashed
}

public static class MembershipManager
{
public static bool IsMatch(string pass, string salt, string encodedPassword)
{
string newencoded = EncodePassword(pass, salt);
return newencoded.Equals(encodedPassword);
}

public static string EncodePassword(string pass, string salt)
{
return EncodePassword(pass, PasswordFormats.Hashed ,salt);
}

public static string EncodePassword(string pass, PasswordFormats format, string salt)
{
if (format == PasswordFormats.Clear)
return pass;

byte[] bIn = Encoding.Unicode.GetBytes(pass);
byte[] bSalt = Convert.FromBase64String(salt);
byte[] bAll = new byte[bSalt.Length + bIn.Length];
byte[] bRet = null;

Buffer.BlockCopy(bSalt, 0, bAll, 0, bSalt.Length);
Buffer.BlockCopy(bIn, 0, bAll, bSalt.Length, bIn.Length);
HashAlgorithm s = HashAlgorithm.Create("SHA1");
bRet = s.ComputeHash(bAll);

return Convert.ToBase64String(bRet);
}

public static string GenerateSalt()
{
byte[] buf = new byte[16];
(new RNGCryptoServiceProvider()).GetBytes(buf);
return Convert.ToBase64String(buf);
}
}

No comments: