对于使用Dovecot的身份验证,我使用SSHA256哈希,但我不知道如何针对现有哈希验证给定密码。以下PHP函数(在Web中找到它们)用于创建SSHA256哈希:
function ssha256($pw) {
$salt = make_salt();
return "{SSHA256}" . base64_encode( hash('sha256', $pw . $salt, true ) . $salt );
}
function make_salt() {
$len = 4;
$bytes = array();
for ($i = 0; $i < $len; $i++ ) {
$bytes[] = rand(1,255);
}
$salt_str = '';
foreach ($bytes as $b) {
$salt_str .= pack('C', $b);
}
return $salt_str;
}
示例输出:{SSHA256}lGq49JTKmBC49AUrk7wLyQVmeZ7cGl/V13A9QbY4RVKchckL
我必须提取盐,但是如何? 我完全迷失了解决这个问题的方法,有人提示这个吗?
感谢大家的帮助!
哦,对不起,我必须使用SSHA256,因为Dovecot 1.2.15仅支持这些方案:
CRYPT MD5 MD5-CRYPT SHA SHA1 SHA256 SMD5 SSHA SSHA256 PLAIN CLEARTEXT CRAM-MD5 HMAC-MD5 DIGEST-MD5 PLAIN-MD4 PLAIN-MD5 LDAP-MD5 LANMAN NTLM OTP SKEY RPA
答案 0 :(得分:2)
您需要将盐与散列值一起存储。
当您需要验证密码时,只需使用用户输入密码+存储的盐再次计算哈希值。如果哈希匹配,则用户输入正确的密码。
对于你的格式,首先使用base64_decode
,结果的最后4个字节将是盐。
答案 1 :(得分:2)
您不应该使用SHA系列进行密码散列。它们快速,专为哈希文件加速而设计。您需要将pashword哈希 昂贵 。使用bcrypt,PHPass或者只使用我自己滚动的这个类(但是直到你学会在其中选择漏洞):
class PassHash {
public static function rand_str($length) {
$total = $length % 2;
$output = "";
if ($total !== 0) {
$count = floor($length / 2);
$output .= ".";
} else $count = $length / 2;
$bytes = openssl_random_pseudo_bytes($count);
$output .= bin2hex($bytes);
// warning: prepending with a dot if the length is odd.
// this can be very dangerous. no clue why you'd want your
// bcrypt salt to do this, but /shrug
return $output;
}
// 2y is an exploit fix, and an improvement over 2a. Only available in 5.4.0+
public static function hash($input) {
return crypt($input, "$2y$13$" . self::rand_str(22));
}
// legacy support, add exception handling and fall back to <= 5.3.0
public static function hash_weak($input) {
return crypt($input, "$2a$13$" . self::rand_str(22));
}
public static function compare($input, $hash) {
return (crypt($input, $hash) === $hash);
}
}
您必须对给定的明文进行散列并将该散列与您存储的散列进行比较。盐存储在哈希中,应该是随机的。如果你愿意,加一个胡椒粉。您还应该创建工作率变量,以便您可以在需要时随时更改工作量,并使系统仍然有效。
如果像你说的那样,你无法实现这个,你可以按如下方式解压缩哈希:
function unpack_hash($hash) {
$hash = base64_decode($hash);
$split = str_split($hash, 64);
return array("salt" => $split[1], "hash" => $split[0]);
这是因为SHA256是256位或64位十六进制字符。您可以随时假设前64个字符是哈希