首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在PHP中根据SSHA256散列验证密码

在PHP中根据SSHA256散列验证密码
EN

Stack Overflow用户
提问于 2013-02-17 22:50:36
回答 2查看 1.7K关注 0票数 2

对于Dovecot的身份验证,我使用SSHA256散列,但我不知道如何根据现有散列验证给定的密码。以下PHP函数(在web上找到)用于创建SSHA256散列:

代码语言:javascript
复制
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,因为Dovecot1.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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-02-17 23:00:07

您不应使用SHA系列进行密码散列。它们是fast,专为快速散列文件而设计。你需要密码哈希是昂贵的。使用bcrypt、PHPass或者只使用这个类,这个类是我自己编写的(但要等到你学会在它上面挑洞):

代码语言:javascript
复制
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);
    }
}

您必须对给定的明文进行散列,并将该散列与您存储的散列进行比较。盐存储在散列中,并且应该是随机的。如果你喜欢,可以加点胡椒。您还应该将工作速率设置为变量,以便您可以在需要时随时更改工作速率,同时仍能让系统正常工作。

如果,就像您所说的,您没有办法实现这一点,您可以按如下方式解压散列:

代码语言:javascript
复制
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个字符是散列

票数 2
EN

Stack Overflow用户

发布于 2013-02-17 22:52:46

您需要将盐与散列值一起存储。

当您需要验证密码时,您只需使用用户输入的密码+存储的盐再次计算散列即可。如果散列匹配,则用户输入了正确的密码。

对于您的格式,首先使用base64_decode,结果的最后4个字节将是盐。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14922302

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档