【问题标题】:Generate a PHP UTF-16 SHA1 hash to match C# method生成 PHP UTF-16 SHA1 哈希以匹配 C# 方法
【发布时间】:2010-08-19 11:19:05
【问题描述】:

我正在尝试在 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=

【问题讨论】:

  • 为什么要将“空格”连接到 base64 编码的哈希?
  • “我”没有.. 但我怀疑这是添加额外级别的(基本)加密

标签: c# php unicode encoding sha1


【解决方案1】:

好吧,试试这个代码:

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

【讨论】:

  • 感谢您指出这一点 :) 遗憾的是,这不是整体问题。
【解决方案2】:

UnicodeEncodingno-arg constructor 的文档是这样说的:

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

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

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

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

【讨论】:

  • 我试过这个,但正如我现在编辑的评论所示,结果仍然有很大不同。我是不是做错了什么?
  • @Sk93 这没有帮助。把encoding.GetBytes的UTF-16数据贴出来(两次)。
【解决方案3】:
  1. 这段代码应该可以工作...

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-02-26
    • 2014-10-01
    • 1970-01-01
    • 2016-10-27
    • 1970-01-01
    • 2019-10-10
    • 1970-01-01
    • 2018-12-20
    相关资源
    最近更新 更多