You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP如何验证MySQL中存储的Dovecot生成的SSHA512格式密码

问题排查与修复方案

你现有代码的核心问题:

  • PHP内置的password_verify()仅支持PHP原生password_hash()生成的密码哈希格式(如bcrypt、Argon2、自带加盐规则的SHA系列格式),无法直接识别Dovecot使用的SSHA512自定义编码格式
  • 你直接截取{SSHA512}前缀后的内容传入password_verify()的逻辑完全不适用SSHA512的校验规则

正确的SSHA512校验逻辑说明

Dovecot存储的{SSHA512}xxx格式密码结构如下:

  • 前缀{SSHA512}为固定标识
  • 后续字符串为Base64编码内容,解码后前64字节是SHA512哈希值,剩余字节就是随机盐值

修复后的代码片段

$result = mysqli_stmt_get_result($stmt);

if ($row = mysqli_fetch_assoc($result)) {
    $stored_password = $row['password'];
    $pwdCheck = false;
    // 先校验前缀是否为SSHA512格式
    if (substr($stored_password, 0, 9) === '{SSHA512}') {
        // 去掉前缀,取出base64编码的哈希+盐拼接串
        $hash_base64 = substr($stored_password, 9);
        // 解码base64得到原始的哈希+盐二进制串
        $hash_raw = base64_decode($hash_base64);
        // 前64位是SHA512哈希值,剩下的都是盐
        $sha512_hash = substr($hash_raw, 0, 64);
        $salt = substr($hash_raw, 64);
        
        // 用用户输入的密码+提取到的盐做SHA512哈希,和存储的哈希对比
        $calculated_hash = hash('sha512', $password . $salt, true);
        $pwdCheck = hash_equals($sha512_hash, $calculated_hash);
    }

    if ($pwdCheck == false) {
        $_SESSION['ERRORS']['wrongpassword'] = '密码错误';
        header("Location: ../");
        exit();
    } else if ($pwdCheck == true) {
        session_start();
        // 后续登录成功的逻辑

注意事项

  • 哈希对比必须用hash_equals()而不能用普通的==或===,防止时序攻击
  • 如果你需要生成SSHA512格式密码存入数据库供Dovecot读取,可按规则反向实现:生成随机盐,对密码加盐做SHA512哈希,拼接哈希和盐后base64编码,加上{SSHA512}前缀即可

内容的提问来源于stack exchange,提问作者Joshua Tyler

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 03:36:04