views:

747

answers:

5

I'm rewriting a PHP web site in ASP.NET MVC. I'd like to maintain the same user base but the passwords are hashed using the PHP crypt() function. I need the same function in .Net so that I can hash a password on login and check it against the hashed password in the user database.

crypt in this case is using the CRYPT_MD5 implementation - the hashes all start with $1$

I've tried Phalanger but it doesn't have an MD5 implementation of the crypt function.

Does anyone know of one in .Net? The C# example of crypt() on CodeProject uses DES, not MD5.

I've tried the following code in C#, with different permutations of salt+password, password+salt and salt with and without $1$ prefix and $ suffix. None gives same result as PHP:

static void Main(string[] args)
{
    const string salt = "somesalt";
    const string password = "fubar";
    const string plaintextString = password + salt;
    byte[] plaintext = GetBytes(plaintextString);
    var md5 = MD5.Create("MD5");
    byte[] hash = md5.ComputeHash(plaintext);
    string s = System.Convert.ToBase64String(hash);
    Console.WriteLine("Hash of " + password + " is " + s);
    Console.ReadKey();
}

private static byte[] GetBytes(string s)
{
    var result = new byte[s.Length];
    for (int i = 0; i < s.Length; i++)
        result[i] = (byte)s[i];
    return result;
}
+2  A: 

There are a few .NET methods for md5 hashing, System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(password, format) is the easiest to use, even though it's a mouthful. Just pass "md5" through as the format.

Depending on how PHP is doing this, it may be as simple as chopping the $1$ off the beginning of the hash when you import it. It may be more complex. If you can post an example password/hash, I'll see if I can come up with some C# that generates the same hash from that password for you.

MrKurt
I've tried MD5 hashing in .Net, but it results in a different hash from what I'm seeing using PHP crypt()
Mike Scott
+1  A: 

Have you taken a look at the .NET MD5 class? $1$ is part of a 12 character salt.

chriscena
+1  A: 

These look promising, at least.

unix md5crypt for CRYPT_MD5 with $1$ salts.

(A C# implementation of Unix crypt() for DES)

Jonathan Lonowski
A: 

I am currently working on exactly the same issue. The solution I came up with was to call the php function directly via an extern call:

[DllImport( "php5ts.dll", EntryPoint = "crypt", CharSet = CharSet.Ansi )]
private static extern string crypt( string str, string salt );

This works well for php version 5.2.10 when running the local WebDev server, IIS5 and IIS6 but if you use II7 the ASP.Net worker process crashes with an unhandled exception. (I will update my answer as soon as I find a resolution)

We are also including a password type flag to allow us to use the .Net MD5 implementation for all new users and seamlessly convert existing users over as they update their details.

Update: The issue with referencing php5ts.dll directly from IIS7 seems to most likely be down to using 64 bit windows, so this solution might work on a 32 bit Windows 7 or Server 2008 installation, however I am unable to verify this. As it turned out our existing site was using DES so we were able to use the crypt implementation from CodeProject, thanks for the reference Mike.

bstoney
A: 

The only solution I found was to call a trivial PHP script that simply performs a hash of the input string and returns it :-(

Mike Scott