2

I'm trying to replicate some C# code in PHP5 and am having some difficulties.

The C# code is as following, and it is important to note that it cannot be changed:

string s = strToHash;
UnicodeEncoding encoding = new UnicodeEncoding();
byte[] bytes = encoding.GetBytes(s);
SHA1Managed managed = new SHA1Managed();     
bytes = encoding.GetBytes(Convert.ToBase64String(managed.ComputeHash(bytes)) + "Space");
return Convert.ToBase64String(managed.ComputeHash(bytes));

The PHP code I've written to replicate this is as follows:

utfString = mb_convert_encoding($strToHash,"UTF-16");
hashTag = sha1($utfString,true); 
base64Tag = base64_encode($hashTag); 
encodedBase64Tag = mb_convert_encoding($base64Tag."Space","UTF-16");
base64EncodedAgain = base64_encode($encodedBase64Tag);

echo $base64EncodedAgain

However, the two outputs don't match up. I believe this is because the SHA1 method in PHP works on ASCII encoded strings, not the encoding actually used by the passed in string.

I would like to get this to work, and I can't achieve it by altering the c# code (although no-doubt that would be the easiest fix).

Please can any advise on some ideas?


OK, I have altered the code following Artefacto's advice, and it still isn't working as expected.

The PHP Code now looks like this:

$utfString = "\xFF\xFE".mb_convert_encoding($strToHash,"UTF-16LE");
$hashTag = sha1($utfString,true);       
$base64Tag = base64_encode($hashTag);   
$encodedBase64Tag = "\xFF\xFE".mb_convert_encoding($base64Tag."Space","UTF-16LE");  
$hashedAgain = sha1($encodedBase64Tag,true);
$base64EncodedAgain = base64_encode($hashedAgain);

echo $base64EncodedAgain."<Br/>";

And the outputed value of this method is:

1/Y5MCzI8vDJqc456YIicpwoyy0=

However, from the C# code, the value is this:

VPf7BhT1ksAfWbzeJw35g+bVKwY=

Sk93
  • 3,676
  • 3
  • 37
  • 67

3 Answers3

2

Well, try this code:

$utfString = mb_convert_encoding($strToHash,"UTF-16");
$hashTag = sha1($utfString,true); 
$base64Tag = base64_encode($hashTag); 
$encodedBase64Tag = mb_convert_encoding($base64Tag."Space","UTF-16");
$base64EncodedAgain = base64_encode(sha1($encodedBase64Tag, true));

echo $base64EncodedAgain

Because you miss one sha1 call.

Update

Now this code should work:

$utfString = mb_convert_encoding($strToHash,"UTF-16LE");
$hashTag = sha1($utfString,true);       
$base64Tag = base64_encode($hashTag);   
$encodedBase64Tag = mb_convert_encoding($base64Tag."Space","UTF-16LE");  
$hashedAgain = sha1($encodedBase64Tag,true);
$base64EncodedAgain = base64_encode($hashedAgain);
echo $base64EncodedAgain . "<br />";
Paya
  • 5,124
  • 4
  • 45
  • 71
2

The docs for the no-arg constructor of UnicodeEncoding say this:

This constructor creates an instance that uses the little endian byte order, provides a Unicode byte order mark, and does not throw an exception when an invalid encoding is detected.

Now, mb_convert_encoding assumes "UTF-16" as "UTF-16BE" (big-endian). It also does not provide a BOM. Therefore, you must do instead:

$utfString = "\xFF\xFE" . mb_convert_encoding($strToHash,"UTF-16LE");
/* ...*/
$encodedBase64Tag = "\xFF\xFE" . mb_convert_encoding($base64Tag."Space","UTF-16LE");

As Paja pointed out, you're also missing a call to sha1.

Community
  • 1
  • 1
Artefacto
  • 96,375
  • 17
  • 202
  • 225
  • I tried this, but as shown in my edited comment now, the results are still very different. Have I done something wrong? – Sk93 Aug 19 '10 at 14:47
  • @Sk93 It doesn't help. Post the UTF-16 data that `encoding.GetBytes` (in the two occasions). – Artefacto Aug 19 '10 at 15:23
0
  1. This code should work...

    $utfString = mb_convert_encoding($strToHash,"UTF-16LE");
    $hashTag = sha1($utfString,true);
    $base64Tag = base64_encode($hashTag);
    echo $base64Tag;
    
Guimel G
  • 11
  • 2