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

.NET PasswordHasher<> V3在Node.js中的等效哈希与验证实现问询

在Node.js中实现与.NET Core PasswordHasher等效的密码哈希与验证

核心参数纠正(修正网上错误资料)

.NET Core PasswordHasher<T>的V3版本实际参数如下:

  • 算法:PBKDF2 with HMAC-SHA512
  • 迭代次数:100000
  • 盐长度:16字节(128位)
  • 子密钥长度:32字节(256位)
  • 哈希字节结构(大端UInt32):[0x01, PRF标识, 迭代次数, 盐长度, 盐字节, 子密钥字节]
    • PRF标识:HMAC-SHA512对应0x00000002(SHA256为0x00000001)

关键遗漏环节与解决方案

你之前的问题主要出在字节序列拼接格式和参数精准匹配上,以下是完整实现:

1. 密码哈希生成(模拟.NET随机盐逻辑)

const crypto = require('crypto');

function hashPassword(password) {
    // 生成16字节随机盐
    const salt = crypto.randomBytes(16);
    // 生成PBKDF2子密钥:HMAC-SHA512,100000次迭代,32字节输出
    const subkey = crypto.pbkdf2Sync(password, salt, 100000, 32, 'sha512');
    
    // 构建.NET格式的字节流
    const buffer = Buffer.alloc(1 + 4 + 4 + 4 + 16 + 32);
    let offset = 0;
    // 版本标识0x01
    buffer.writeUInt8(0x01, offset);
    offset += 1;
    // PRF标识:HMAC-SHA512 = 0x02
    buffer.writeUInt32BE(0x02, offset);
    offset += 4;
    // 迭代次数
    buffer.writeUInt32BE(100000, offset);
    offset += 4;
    // 盐长度
    buffer.writeUInt32BE(16, offset);
    offset += 4;
    // 写入盐
    salt.copy(buffer, offset);
    offset += 16;
    // 写入子密钥
    subkey.copy(buffer, offset);
    
    // 转Base64输出
    return buffer.toString('base64');
}

2. 密码验证(解析.NET生成的哈希值)

function verifyPassword(password, hashedPassword) {
    try {
        // 解码Base64得到字节流
        const buffer = Buffer.from(hashedPassword, 'base64');
        
        // 验证版本标识
        if (buffer.readUInt8(0) !== 0x01) {
            return false;
        }
        let offset = 1;
        
        // 读取PRF标识(仅处理SHA512场景)
        const prf = buffer.readUInt32BE(offset);
        offset += 4;
        if (prf !== 0x02) {
            return false;
        }
        
        // 读取迭代次数
        const iterations = buffer.readUInt32BE(offset);
        offset += 4;
        
        // 读取盐长度
        const saltLength = buffer.readUInt32BE(offset);
        offset += 4;
        
        // 读取盐
        const salt = buffer.slice(offset, offset + saltLength);
        offset += saltLength;
        
        // 读取子密钥
        const expectedSubkey = buffer.slice(offset);
        
        // 重新计算子密钥
        const computedSubkey = crypto.pbkdf2Sync(password, salt, iterations, expectedSubkey.length, 'sha512');
        
        // 安全比较(防止时序攻击)
        return crypto.timingSafeEqual(computedSubkey, expectedSubkey);
    } catch (err) {
        // 格式错误直接返回验证失败
        return false;
    }
}

3. 验证示例密码

用你提供的示例测试:

const samplePassword = 'sample123 !';
const sampleHash = 'AQAAAAEAACcQAAAAEAdmj6YuRrVMYBXbeGrV/j3VqSzvhIhE/xYWA0S1hpfxH5FuepoGJjite6n/Fh4quw==';

console.log(verifyPassword(samplePassword, sampleHash)); // 输出true

常见问题说明

  • 无需额外库:Node.js内置crypto.pbkdf2Sync已支持HMAC-SHA512,无需依赖pbkdf2-hmac。
  • 子密钥长度固定:.NET V3版本固定生成32字节(256位)子密钥,这是容易出错的参数点。
  • 大端字节序:所有UInt32类型字段必须用大端(BE)读写,这是.NET的标准处理逻辑,也是易遗漏细节。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 14:35:39