我期望slappasswd
产生一个固定的哈希值,但看起来输出是随机的,因为对于相同的输入密码我永远不会得到相同的输出:
$ slappasswd -s secret
{SSHA}mCXsPZkfgQYZr2mKHpy5Iav+2S2XlVU3
$ slappasswd -s secret
{SSHA}62oXsalJBuopYfHhi6hGp6AESuWNIVnd
$ slappasswd -s secret
{SSHA}0Ulc8+ugMi3NbTtWnclOFW1LKCqRdsT8
在身份验证过程中,拍打知道如何以相同的方式对提供的密码进行随机化哈希处理,以便它可以与首先定义的密码匹配?
答案1
SSHA 是加盐的 SHA-1。默认情况下,最后 4 个字节是盐。slappasswd 的输出是
'{<Hash Method>}<base64 converted hash and salt>'
因此,为了测试纯文本密码是否等于加盐 SHA,您需要:
- 使用例如 sed 来删除哈希方法说明符。
- 解码 base64 字符串
- 提取最后 4 个字节,这就是盐
- 将盐连接到纯文本密码
- 哈希
- 比较
base64 解码后的字符串包含二进制形式的哈希值,无法打印,因此我们将使用 od 将其转换为十六进制。前 3 个步骤由以下代码完成:
#!/bin/bash
output=$(slappasswd -h {SSHA} -s password)
hashsalt=$( echo -n $output | sed 's/{SSHA}//' | base64 -d)
salt=${hashsalt:(-1),(-4)}
echo $output
echo $(echo -n $hashsalt | od -A n -t x1)
echo "Salt: $salt"
输出可能是:
{SSHA}fDu0PgKDn1Di9W1HMINpPXRqQ9jTYjuH
7c 3b b4 3e 02 83 9f 50 e2 f5 6d 47 30 83 69 3d 74 6a 43 d8 d3 62 3b 87
<------------------------- Hash --------------------------> <-- Salt-->
Salt: ▒b;▒
因此,现在我们必须将盐连接到纯文本密码并对其进行哈希处理,这次无需加盐!我遇到的问题是,盐实际上可以是任何字符,包括不可打印的字符。为了连接这些不可打印的字符,我们将使用 printf 及其十六进制表示:
slappasswd -h {SHA} -s $(printf 'password\xd3\x62\x3b\x87') | sed 's/{SHA}//' | base64 -d | od -A n -t x1
输出为:
7c 3b b4 3e 02 83 9f 50 e2 f5 6d 47 30 83 69 3d 74 6a 43 d8
这与上面的哈希值相等。现在我们已经验证了“密码”与加盐 SHA 匹配。
感谢并进一步阅读:http://cpansearch.perl.org/src/GSHANK/Crypt-SaltedHash-0.09/lib/Crypt/SaltedHash.pm
答案2
这里我冒个险,但我假设 slappasswd 使用的是加盐哈希而不是普通哈希。这意味着它会在您的密码中添加一个随机前缀,并将该随机前缀保存为您在 slappasswd 输出中看到的字符串的一部分。当您输入密码时,它会将前缀添加到密码中,对结果进行哈希处理,并将其与 slappasswd 输出中的字符串进行比较。如果匹配,则您成功了。如果不匹配,则您的密码错误 :)