我有一个正在运行的具有用户身份验证的C#应用。我使用Encoding.Unicode使用SHA1Managed类加密密码。现在,我们正在开发一个新的PHP Web应用程序,似乎PHP sha1方法使用ASCII,因此加密的密码略有不同。
我无法更改我的C#代码,因为它在许多不同的服务器上运行,并且所有用户密码均已加密。不能更改此密码,因为这将暗示向所有用户询问其密码(不可行)。
我已经阅读了以下解决方案,但是我无法解决它们的问题:
这是我的C#代码,无法更改:
byte[] msgBytes = Encoding.Unicode.GetBytes(data);
SHA1Managed sha1 = new SHA1Managed();
byte[] hashBytes = sha1.ComputeHash(msgBytes);
StringBuilder hashRet = new StringBuilder("");
foreach (byte b in hashBytes)
hashRet.AppendFormat("{0:X}", b);
return hashRet.ToString();
这是到目前为止实现的PHP代码:
$str=mb_convert_encoding($password.$SALT, 'UTF-16LE');
$result=strtoupper(sha1($str));
[在C#中为示例字符串“ 1981”获得的结果D4CEDCADB729F37C30EBF41BC8F2929AF526AD3
在PHP中,我得到:D4CEDCADB729F37C30EBF41BC8F29209AF526AD3
可以看出,每个字符之间的唯一区别是0(零)字符。这在所有字符串中都会发生,但是0出现在不同的位置。
编辑
如https://stackoverflow.com/users/1839439/dharman所述,由于我的字符串具有SALT,因此无法完全再现结果。但是,即使没有SALT,结果也应有所不同。
SOLUTION用户提出了解决我问题的建议。不幸的是,他删除了答案,然后我才发布它起作用。当我在StringBuilder中将字节解析为字符串时,问题出在C#中。格式为{0:X},并且忽略字节中的任何前导0。例如,将01解析为1,将0D解析为D。
因此,我不得不遍历在PHP中获得的结果对,并删除其中的前导零。
PHP的最终代码如下:
$str=mb_convert_encoding($password.$SALT, 'UTF-16LE');
$result=strtoupper(sha1($str));
$array = str_split($result, 2);
foreach ($array as &$valor) {
$valor = ltrim($valor, '0');
}
unset($valor);
$result = implode($array);
我有一个正在运行的具有用户身份验证的C#应用。我使用Encoding.Unicode使用SHA1Managed类加密密码。现在,我们正在开发一个新的PHP Web应用程序,似乎PHP sha1方法...
您不喜欢我的回答,但在这里。首先,问题不在于PHP,PHP很简单并且可以正常工作。您的C#代码中有一个严重的错误。它需要尽快修复其中一种方法。