生成PHP UTF-16 SHA1哈希以匹配C#方法

时间:2010-08-19 11:19:05

标签: c# php unicode encoding sha1

我正在尝试在PHP5中复制一些C#代码并遇到一些困难。

C#代码如下,重要的是要注意它无法更改:

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));

我编写的用于复制的PHP代码如下:

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

但是,两个输出不匹配。 我相信这是因为PHP中的SHA1方法适用于ASCII编码的字符串,而不是传入的字符串实际使用的编码。

我想让它工作,我无法通过改变c#代码来实现它(尽管毫无疑问这将是最简单的修复)。

请对任何想法提出建议吗?


好的,我已根据Artefacto的建议更改了代码,但仍未按预期工作。

PHP代码现在看起来像这样:

$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/>";

此方法的输出值为:

  

1 / Y5MCzI8vDJqc456YIicpwoyy0 =

但是,从C#代码中,值为:

  

VPf7BhT1ksAfWbzeJw35g + bVKwY =

3 个答案:

答案 0 :(得分:2)

好吧,试试这段代码:

$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

因为您错过了一次sha1来电。

更新

现在这段代码应该有效:

$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 />";

答案 1 :(得分:2)

UnicodeEncoding no-arg constructor的文档说明了这一点:

  

此构造函数创建一个使用little endian字节顺序的实例,提供Unicode字节顺序标记,并且在检测到无效编码时不会抛出异常。

现在,mb_convert_encoding将“UTF-16”假定为“UTF-16BE”(big-endian)。它也不提供BOM。因此,您必须改为:

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

正如Paja指出的那样,您也错过了对sha1的调用。

答案 2 :(得分:0)

  1. 此代码应该有效...

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