在 PHP 中生成哈希以匹配 T-SQL HASHBYTES 输出

Generating a hash in PHP to match T-SQL HASHBYTES output

我需要在 PHP 中生成一个与 T-SQL.

中的 HASHBYTES 函数输出相匹配的散列

这里是最初用于在T-SQL中生成哈希的代码:

 declare @input varchar(15) =  [this is the incoming value entered by the user]
 declare @salt binary(32) =  CRYPT_GEN_RANDOM(32)
 declare @saltchars nvarchar(32) = cast(@salt as nvarchar(32) )
 declare @inputchars nvarchar(50) = cast(@input as nvarchar(50) )
 declare @sha binary(32) = HASHBYTES('SHA2_256', @passwordchars + @saltchars)

对于输入“pete1234matt”,我们得到输出:

 salt =  0x75D6215CA44339B645E86BE790FF562D3EE4BC51034FDC6A9697F767BB961B5B
 sha  =  0x979EEAC93B5F6624269634202D9F3B5B8008113B03A83D104784184E0F9361F8

现在这是我编写的 PHP 代码,我接受提供的和输入,然后将它们编码为 UTF-16LE,正如我希望转换为 nvarchar 那样。对吗?

$password = 'pete1234matt'; 
$salt = 0x75D6215CA44339B645E86BE790FF562D3EE4BC51034FDC6A9697F767BB961B5B;
$saltchars = mb_convert_encoding($salt, 'UTF-16LE');
$passwordchars = mb_convert_encoding($password, 'UTF-16LE');
$sha = hash('sha256', $passwordchars . $saltchars);
//$sha ==   17b87bd0491f32f1e474ad9293e2fe5db56ed0a5c9939435f0984fdc04806dc5
//Expected: 979EEAC93B5F6624269634202D9F3B5B8008113B03A83D104784184E0F9361F8

我倾向于 salt 存在编码问题,但不太清楚我哪里出错了。任何对字符编码和 T-SQl 有更多了解的人都可以帮我一下!!

  1. 您使用的十六进制表示法仅适用于 PHP 中的数字。您想将其作为字符串放入并调用 hex2bin().
  2. 我不知道你为什么要将 salt 转换为 UTF16,但不要那样做。
$password = 'pete1234matt'; 
$salt = hex2bin('75D6215CA44339B645E86BE790FF562D3EE4BC51034FDC6A9697F767BB961B5B');
$saltchars = $salt;
$passwordchars = mb_convert_encoding($password, 'UTF-16LE');
$sha = hash('sha256', $passwordchars . $saltchars);
//Expected: 979EEAC93B5F6624269634202D9F3B5B8008113B03A83D104784184E0F9361F8

var_dump($sha);

输出:

string(64) "979eeac93b5f6624269634202d9f3b5b8008113b03a83d104784184e0f9361f8"

不要养成在未明确指定源编码的情况下调用任何字符集转换函数的习惯。 PHP 字符串本质上只是没有编码概念的字节数组。 PHP 具有控制 假定默认字符集 的配置设置,但使用正确解码的十六进制调用 mb_convert_encoding($salt, 'UTF-16LE'); 会根据 PHP 解释字符串默认,可能是 UTF8 或 ISO-8859-1,并将其转换为 mojibake。实际上,该字符串已经是 UTF16LE。

例如:

$test_8   = 'hello ';
$test_16  = mb_convert_encoding($test_8, 'UTF-16LE', 'UTF-8');
$mojibake = mb_convert_encoding($test_16, 'UTF-16LE');

var_dump(
    bin2hex($test_8),
    bin2hex($test_16),
    bin2hex($mojibake)
);

输出:

string(20) "68656c6c6f20f09f8d86"
string(32) "680065006c006c006f0020003cd846df"
string(64) "68000000650000006c0000006c0000006f000000200000003c003f0046003f00"