Login

Designing Code

An insider's view into the dark world of marketing and how to design code with the right side of your brain.

PHP5 - Recreating .NET's membership password hash algorithm

Premise:

 

I'm writing a php app that runs alongside ASP .NET site. I want to utilize the existing users and roles tables in the MSSQL server and can, except for one thing- matching the hashed passwords in the database. I found a blog that shows how .NET does the hashing (with salt) so I can try to recreate it in PHP.

A developer on Twitter sent me this link which shows the .NET membership procedure for developing the hashes for passwords. 
private static HashAlgorithm passwordHasher = HashAlgorithm.Create("SHA1"); 
 
private bool ValidateUser(string username, string password) 
var user = GlobalApplication.Database.Users.FirstOrDefault(u => u.UserName == username); 
if (user == null) return false; 

byte[] saltBytes = Convert.FromBase64String(user.Membership.PasswordSalt); 
byte[] passwordBytes = Encoding.UTF8.GetBytes(password); 
byte[] bytesToHash = new byte[saltBytes.Length + passwordBytes.Length]; 
saltBytes.CopyTo(bytesToHash, 0); 
passwordBytes.CopyTo(bytesToHash, saltBytes.Length); 
byte[] hash = passwordHasher.ComputeHash(bytesToHash); 
string base64Hash = Convert.ToBase64String(hash); 
return user.Membership.Password == base64Hash;
}

This was very useful is seeing what is done in C# and clues me into the procedures needed to replicate it in PHP
I've gleemed over search results that SHA1 is the hash algorithm used (and PHP has implementations of this). 

However a couple of hurdles I've run into:
  1. converting the UTF-8 password into bytes in PHP comes back as a string of 1's and 0's and the salt unpacks as true binary (returning +7ª\ætR<_9deji|Ï)
  2. not sure the "copyTo()" method is easily replaced by straight out concatenation 

Thoughts?

my PHP code version of above:
----

$hash_password = "bgT8AutbQgtlec0VNhhtmAXdXxvI0V/96Vj48KRz26E=";
$salt = "KzeqXOZ0UjwYOWRlaml8zw==";

$password = "church";

$salt = base64_decode($salt); //convert salt back to it's binary state

$passwordBytes = bstr2bin(utf8_encode($password)); //convert password to utf8 then binary

echo "$salt"; //prints "+7ª\ætR<9deji|Ï"
echo "$passwordBytes"; //prints 11000110110100001110101011100100110001101101000

$bytesToHash = $salt . $passwordBytes; //combine the 2 binary objs
$hash = sha1($bytesToHash, true); //sha1 hash it
$hashedpassword = base64_encode($hash); //base64 encode it into a string

echo "$hashedpassword
$hash_password";
function bstr2bin($input)
// Binary representation of a binary-string
{
  if (!is_string($input)) return null; // Sanity check
  // Unpack as a hexadecimal string
  $value = unpack('H*', $input);
  // Output binary representation
  return base_convert($value[1], 16, 2);
}
function bin2bstr($input)
// Convert a binary expression (e.g., "100111") into a binary-string
{
  if (!is_string($input)) return null; // Sanity check
  // Pack into a string
  return pack('H*', base_convert($input, 2, 16));
}
---
last "echo" prints:
2mOfuA7gRcDEYNJF9fjN83em+Jw=
bgT8AutbQgtlec0VNhhtmAXdXxvI0V/96Vj48KRz26E=

 

Posted by kcbruce at 2009-11-12 4:53pm | Permanent Link | Comments(1)

Share |

Home  • NeutralGood Blog  • Tech Blog  • Portfolio  • Resume  • Scripts  • Photos  • Contact
Phone: (240) 415-8721
http://www.kevinbruce.com · Site Modified Jul 09, 2014 · ©2014 Kevin Bruce | Designer of Web & Print
Follow me on LinkedIn Profile   Facebook   Twitter