【发布时间】:2017-10-15 23:25:51
【问题描述】:
我们有一个拥有数千个旧密码哈希的客户,他们希望我们能够验证/匹配这些密码,以便将这些登录信息转移到更现代的安全考虑中。
哈希值类似于 SHA1(十六进制和 40 个字符),并且是在 ASP.NET 中生成的。我们有一些测试用例包含明文密码、base64 编码的 salt 和 base64 编码的哈希 - 我们需要能够根据给定的密码和 salt 重现哈希。
我一直使用https://forums.asp.net/p/1336657/2899172.aspx 作为参考来编写一个PHP 脚本来重现散列。这是我试图直接重写的sn-p:
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);
}
看起来很简单 - 获取密码的字节数组,对 salt 进行 base64 解码,将它们连接起来,然后通过 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
【问题讨论】:
-
因为它是您无法复制的哈希值。您可以做的是设置表以保存另一列,检查它们是否有新的哈希。如果不是,请检查无哈希或旧哈希,然后使用
password_hash()创建一个新哈希。 -
@JayBlanchard 它应该为给定的输入产生相同的哈希值(如果正确),对吧? SHA1-ing
test将始终给出a94a8fe5ccb19ba61c4c0873d391e987982fbbd3。见this answer -
@JayBlanchard 感谢您的输入,但事实并非如此——SHA1 是一对一的转换,相同的字符串总是产生相同的哈希值。我只是缺少 ASP.NET 如何创建预散列密码/盐的组件。您能否深入了解我所缺少的内容?
-
你是对的——从 sha1 到 sha1 确实产生了同样的结果。我应该更清楚,因为对我来说,哈希是用盐产生的。快速研究表明,其他人也无法生产这种产品。
-
我认为你在最后用 PHP 和 ASP.NET 把它放在了前面