Question

we previously use a C#.net 2.0 to create a web app.

Users password were hashed and stored in database using the following code.

private const string encryptionKey = "AE09F72B007CAAB5";

HMACSHA1 hash = new HMACSHA1();
hash.Key = HexToByte(encryptionKey);
encodedPassword = Convert.ToBase64String(
    hash.ComputeHash(Encoding.Unicode.GetBytes(password)));

now we intend to migrate to php.

so we face a problem for users when they want to back in.

what php equivalent of the method should be used so that the hash values in the database would work?

eg password to encode is pa55w0rd the hash value gotten is oK9NOVhpTkxLoLfvh1430SFb5gw=

Thank you.

Was it helpful?

Solution

In your C# app you generate the byte[] arrays in two different ways with a little bit different results. Your PHP script needs to emulate them exactly.

hash.Key = HexToByte(encryptionKey)
You pass in a 16 characters long string and get an array of 8 bytes, just like hash.Key = new byte[]{0xAE, 0x09, 0xF7, 0x2B, 0x00, 0x7C, 0xAA, 0xB5 }; but
string password = "pa55w0rd";
byte[] b = Encoding.Unicode.GetBytes(password)
returns an array with 16 elements because of the Encoding.Unicode, like byte[] b = { 0x112, 0x0, 0x97, 0x0, 0x53, 0x0, 0x53, 0x0, 0x119, 0x0, 0x48, 0x0, 0x114, 0x0,0x100, 0x0 }
In your php script you can change the encoding of $password to utf-16le with $data = mb_convert_encoding($password, 'UTF16-LE') to achieve a similar result. hash_hmac() being unaware of any encoding will treat the string a 16 byte single-byte encoded string, just like hash.ComputeHash(byte[]) in .net does.

<?php
$password = "pa55w0rd";
$key = HexToBytes("AE09F72B007CAAB5"); // 8 bytes, hex

// $to must be 'UTF-16LE' // $from depends on the "source" of $password $data = mb_convert_encoding($password, 'UTF-16LE', 'ASCII');

// I've saved this script as an ascii file -> the string literal is ASCII encoded // therefore php's strlen() returns 8 for $password and 16 for $data // this may differ in your case, e.g. if the contents of $password comes from a // http-request where the data is utf-8 encoded. Adjust the $from parameter for // mb_convert_encoding() accordingly echo 'Debug: |data|=', strlen($data), ' |password|=', strlen($password), "\n";

$h = HexToBytes(hash_hmac('sha1', $data, $key)); echo 'hmac-sha1: ', base64_encode($h);

function HexToBytes($s) { // there has to be a more elegant way... return join('', array_map('chr', array_map('hexdec', str_split($s, 2)))); }

prints
Debug: |data|=16 |password|=8
hmac-sha1: oK9NOVhpTkxLoLfvh1430SFb5gw=

OTHER TIPS

Using a .Net version of PHP (Phalanger) or using a .Net webservice to encode/decode isn't an option?

Try something like:

<?php
 $key = "AE09F72B007CAAB5";
 echo base64_encode(hash_hmac("sha1", "test", $key, true));
?>

In C# the default formatting of the hash is in HEX (AE09F72B007CAAB5 is a hex number).PHP defaults to Base64 formatting. Solving your problem is a matter of converting the base64 string to hex in php

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top