如何在 PHP 和 C# 中实现一致的 SHA256 加盐哈希

如何在 PHP 和 C# 中实现一致的 SHA256 加盐哈希

phpc# 对同一密码加盐后生成的 sha256 哈希值不一致,通常源于盐(salt)与密码(password)拼接顺序不同:php 中误写为 `salt + password`,而 c# 中是 `password + salt`,导致哈希结果完全不同。修正拼接顺序即可实现跨语言哈希一致性。

在多平台身份认证场景中(如 ASP.NET 后端 + PHP 登录页),确保密码哈希逻辑完全一致至关重要。核心问题在于:哈希前的原始输入字符串必须严格相同。从您提供的代码可见:

  • ✅ C# 正确逻辑(以 pw + salt 拼接):

    byte[] hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(pw + salt));
    return Convert.ToBase64String(hash);
  • ❌ PHP 当前错误逻辑($salt . $extpassword → 相当于 salt + password):

    $pw = $salt . $extpassword; // 错误:顺序颠倒!
    return ($fromdb == base64_encode(hash('sha256', $pw, true)));
  • ✅ PHP 修正后(与 C# 保持 password + salt 顺序):

    Meku

    Meku

    AI应用和网页开发工具

    下载

    立即学习PHP免费学习笔记(深入)”;

    $pw = $extpassword . $salt; // 关键修复:先密码,后盐
    // 确保 UTF-8 编码一致性(C# 默认使用 UTF-8)
    if (!mb_check_encoding($pw, 'UTF-8')) {
        $pw = mb_convert_encoding($pw, 'UTF-8');
    }
    $hash = base64_encode(hash('sha256', $pw, true));
    return $fromdb === $hash;

⚠️ 重要注意事项

  • 编码必须统一:C# 的 Encoding.UTF8.GetBytes() 与 PHP 的 mb_convert_encoding(…, ‘UTF-8’) 都需确保输入字符串为标准 UTF-8,避免因 BOM、宽字符或编码隐式转换导致字节差异;
  • 盐值类型需一致:确认 C# 和 PHP 中使用的 $salt 是相同字符串(非 Base64 解码后的二进制、非 GUID 格式差异);建议在数据库中以明文字符串存储 salt(如 16 字符随机 ASCII 字符串),两端直接拼接;
  • 避免使用过时函数:hash(‘sha256’, …, true) 是正确用法(true 表示返回原始二进制,再经 base64_encode 得到与 C# Convert.ToBase64String 等效的结果);切勿使用 md5() 或未加盐的哈希;
  • 生产环境强烈建议升级:SHA256 + 自定义拼接属于基础哈希,不具备抗暴力破解能力。应迁移到 password_hash()(PHP)与 Rfc2898DeriveBytes(C#,即 PBKDF2)或 Argon2(.NET 6+ / PHP 7.2+)等密钥派生函数,并严格管理迭代次数与内存成本。

通过统一拼接顺序(password + salt)、校验编码、验证盐值原文,即可实现 PHP 与 C# 间 100% 兼容的哈希比对,为混合技术的身份系统提供可靠基础。

https://www.php.cn/faq/2038262.html

发表回复

Your email address will not be published. Required fields are marked *