Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/298.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用PHP重新生成ASP SHA1 salt/hash_Php_Asp.net_Hash - Fatal编程技术网

使用PHP重新生成ASP SHA1 salt/hash

使用PHP重新生成ASP SHA1 salt/hash,php,asp.net,hash,Php,Asp.net,Hash,我们有一个拥有数千个遗留密码哈希的客户端,他们希望我们能够验证/匹配这些密码哈希,以便将这些登录转移到更现代的安全考虑 散列是类似SHA1的(十六进制和40个字符),是在ASP.NET中生成的。我们有一些测试用例具有明文密码、base64编码的salt和base64编码的哈希-我们需要能够基于给定的密码和salt复制哈希 我一直在使用它作为参考来编写一个PHP脚本来复制散列。下面是我试图直接重写的片段: public string EncodePassword(string pass, stri

我们有一个拥有数千个遗留密码哈希的客户端,他们希望我们能够验证/匹配这些密码哈希,以便将这些登录转移到更现代的安全考虑

散列是类似SHA1的(十六进制和40个字符),是在ASP.NET中生成的。我们有一些测试用例具有明文密码、base64编码的salt和base64编码的哈希-我们需要能够基于给定的密码和salt复制哈希

我一直在使用它作为参考来编写一个PHP脚本来复制散列。下面是我试图直接重写的片段:

public string EncodePassword(string pass, string saltBase64)
{
    byte[] bytes = Encoding.Unicode.GetBytes(pass);
    byte[] src = Convert.FromBase64String(saltBase64);
    byte[] dst = new byte[src.Length + bytes.Length];
    Buffer.BlockCopy(src, 0, dst, 0, src.Length);
    Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length);
    HashAlgorithm algorithm = HashAlgorithm.Create("SHA1");
    byte[] inArray = algorithm.ComputeHash(dst);
    return Convert.ToBase64String(inArray);
}
这看起来很简单——获取密码的字节数组,base64解码salt,连接它们,并通过SHA1运行它们。我觉得我已经完成了90%,但无论我尝试了什么变体,我都无法成功匹配提供的哈希

我怀疑我试图重现
Encoding.Unicode.GetBytes
是问题所在-
unpack
可能不是等效的。但经过一个小时左右的搜索,我找不到任何方法来接近。作为一名ASP开发人员,我确信我遗漏了一些细微差别——有人能指出哪里出了问题吗

以下是我的测试输出代码:

$test = [
    'plaintext' => 'overthis2:)',
    'salt' => '7LeJR68EGhBgaE7EYgL/gg==',
    'hash' => 'g54KVV4Wj5smOyXHOReyWnTnGDc='
];
$algos = [ 'sha1', 'ripemd160', 'tiger160,3', 'tiger160,4', 'haval160,3', 'haval160,4', 'haval160,5' ];
$raw = implode( '', unpack( "H*", $test['plaintext'] ) ) . base64_decode( $test['salt'] );

echo 'Plaintext:     ' . $test['plaintext'] . "\n";
echo 'Salt:          ' . $test['salt'] . "\n";
echo 'Raw:           ' . $raw . "\n\n";
echo 'Saved hash:    ' . $test['hash'] . "\n";
echo 'Decoded:       ' . bin2hex( base64_decode( $test['hash'] ) ) . "\n\n";

foreach ( $algos as $algo ) {
    echo str_pad( $algo . ':' , 15, ' ' ) . hash( $algo, $raw ) . "\n";
}
下面是它得到的结果-没有一个哈希值与提供的匹配:

Plaintext:     overthis2:)
Salt:          7LeJR68EGhBgaE7EYgL/gg==
Raw:           6f76657274686973323a29췉G�`hN�b��

Saved hash:    g54KVV4Wj5smOyXHOReyWnTnGDc=
Decoded:       839e0a555e168f9b263b25c73917b25a74e71837

sha1:          d0b448e50d81e6a42601ebcc8e7aa07423d12210
ripemd160:     4359afa37173388db43c47db5188cf5cc47f30d9
tiger160,3:    c2e22500127cef7141077049e9bda7747e0b298d
tiger160,4:    e03fc57f1d9259cd650aab3682cf54609a30d62b
haval160,3:    437838726fc63fb15969e1c5f0b34dc7f404cabc
haval160,4:    ec5cb7e38fe28534b65d25fabf756113c9e563d6
haval160,5:    48551660bbc519bb7db8d595556f4f167eeec749

NET代码将密码处理为UTF16LE字符串(
Encoding.Unicode
),因此每个字符的宽度为16位。这意味着在这种情况下,该部分中的每个其他字节都是零

您还错误地使用了salt和密码,不需要解包任何东西,.NET代码不使用十六进制值,而是使用原始字节

进行此更改,您将获得相同的哈希值:

$raw = base64_decode( $test['salt'] ).implode("\0", str_split($test['plaintext']))."\0";

这只需将salt解码,然后通过在每个字符后添加一个零字节将密码转换为UTF16,就是这样。

NET代码将密码处理为UTF16LE字符串(
Encoding.Unicode
),因此每个字符都有16位宽。这意味着在这种情况下,该部分中的每个其他字节都是零

您还错误地使用了salt和密码,不需要解包任何东西,.NET代码不使用十六进制值,而是使用原始字节

进行此更改,您将获得相同的哈希值:

$raw = base64_decode( $test['salt'] ).implode("\0", str_split($test['plaintext']))."\0";

这只是简单地获取salt,对其进行解码,然后通过在每个字符后添加一个零字节将密码转换为UTF16,就是这样。

因为它是一个无法复制的哈希。您可以做的是将表设置为容纳另一列,检查它们是否有新的哈希。如果没有,请检查无哈希或旧哈希,然后创建一个新哈希w/
密码\u hash()
@JayBlanchard它应该为给定的输入生成相同的哈希(如果正确),对吗?SHA1 ing
测试将始终给出
a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
。请参阅@JayBlanchard,感谢您的输入,但事实并非如此-SHA1是一对一的转换,相同的字符串总是生成相同的哈希。我只是缺少ASP.NET如何创建预哈希密码/salt的一个组件。你能洞察到我遗漏了什么吗?你是对的-sha1对sha1产生了同样的结果。我应该说得更清楚些,因为对我来说,杂烩是用盐做的。快速的研究表明,其他人也未能做到这一点。我认为PHP最终还是有优势的,ASP.NET将其放在了前面,因为它是一个无法复制的哈希。您可以做的是将表设置为容纳另一列,检查它们是否有新的哈希。如果没有,请检查无哈希或旧哈希,然后创建一个新哈希w/
密码\u hash()
@JayBlanchard它应该为给定的输入生成相同的哈希(如果正确),对吗?SHA1 ing
测试将始终给出
a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
。请参阅@JayBlanchard,感谢您的输入,但事实并非如此-SHA1是一对一的转换,相同的字符串总是生成相同的哈希。我只是缺少ASP.NET如何创建预哈希密码/salt的一个组件。你能洞察到我遗漏了什么吗?你是对的-sha1对sha1产生了同样的结果。我应该说得更清楚些,因为对我来说,杂烩是用盐做的。快速的研究表明,其他人也未能做到这一点。我想你最终用PHP和ASP.NET解决了这个问题。这确实完美地解决了我的问题-非常感谢!这确实完美地解决了我的问题-非常感谢!