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

C#验证Django pbkdf2_sha256哈希密码失败的问题求助

Django pbkdf2_sha256 密码验证在C#中不匹配的问题解决

问题根源

你的代码核心问题在于Django使用URL安全的Base64编码存储盐和哈希,而当前解码逻辑未处理这种编码格式差异:

  • Django会把标准Base64中的+替换为-,/替换为_,并且省略末尾的填充字符=
  • 原解码方法仅补充了=,但未还原-和_为标准Base64字符,导致盐的字节数组错误,最终计算出的哈希自然不匹配。

修复后的代码

修改解码逻辑以兼容URL安全Base64,同时采用密码验证的安全最佳实践(常量时间比较):

public static bool VerifyPassword(string enteredPassword, string storedPasswordHash) 
{ 
    var parts = storedPasswordHash.Split('$');
    if (parts.Length != 4 || parts[0] != "pbkdf2_sha256")
    {
        Console.WriteLine("Invalid password format.");
        return false;
    }

    if (!int.TryParse(parts[1], out int iterations))
    {
        Console.WriteLine("Invalid iterations count.");
        return false;
    }

    byte[] saltBytes = DecodeUrlSafeBase64(parts[2]);
    if (saltBytes == null)
    {
        return false;
    }

    byte[] storedHashBytes = DecodeUrlSafeBase64(parts[3]);
    if (storedHashBytes == null)
    {
        return false;
    }

    byte[] passwordBytes = Encoding.UTF8.GetBytes(enteredPassword);
    byte[] computedHashBytes;

    using (var pbkdf2 = new Rfc2898DeriveBytes(passwordBytes, saltBytes, iterations, HashAlgorithmName.SHA256))
    {
        computedHashBytes = pbkdf2.GetBytes(storedHashBytes.Length); // 适配存储的哈希长度
    }

    // 常量时间比较,防止时序攻击
    return CryptographicOperations.FixedTimeEquals(computedHashBytes, storedHashBytes);
}

private static byte[] DecodeUrlSafeBase64(string input)
{
    // 还原URL安全Base64的特殊字符
    string base64 = input.Replace('-', '+').Replace('_', '/');
    
    // 补充缺失的填充字符
    switch (base64.Length % 4)
    {
        case 2: base64 += "=="; break;
        case 3: base64 += "="; break;
    }

    try
    {
        return Convert.FromBase64String(base64);
    }
    catch (FormatException)
    {
        Console.WriteLine("Error decoding Base64 string.");
        return null;
    }
}

关键修改说明

  1. URL安全Base64解码:新增DecodeUrlSafeBase64方法,先将-和_替换回标准Base64的+和/,再处理填充,完全兼容Django的编码规则。
  2. 动态哈希长度:不再固定生成32字节哈希,而是根据存储的哈希长度动态生成,适配不同的Django配置。
  3. 安全比较方式:使用CryptographicOperations.FixedTimeEquals替代直接数组相等判断,避免攻击者通过时序差异猜测密码,提升验证安全性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 10:42:36