如何用JavaScript实现与C#带Salt的SHA256 ComputeHash一致结果
实现与C#带Salt的SHA256哈希一致的JavaScript代码
我有一个带Salt的C# SHA256哈希函数,代码如下:
using System; using System.Text; using System.Globalization; using System.Security.Cryptography; public class Program { public static int SaltValueSize = 4; public static string HashPassword(string clearData, string saltValue, HashAlgorithm hash) { var encoding = new UnicodeEncoding(); var binarySaltValue = new byte[SaltValueSize]; binarySaltValue[0] = byte.Parse(saltValue.Substring(0, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture.NumberFormat); binarySaltValue[1] = byte.Parse(saltValue.Substring(2, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture.NumberFormat); binarySaltValue[2] = byte.Parse(saltValue.Substring(4, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture.NumberFormat); binarySaltValue[3] = byte.Parse(saltValue.Substring(6, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture.NumberFormat); var valueToHash = new byte[SaltValueSize + encoding.GetByteCount(clearData)]; var binaryPassword = encoding.GetBytes(clearData); binarySaltValue.CopyTo(valueToHash, 0); binaryPassword.CopyTo(valueToHash, SaltValueSize); var hashValue = hash.ComputeHash(valueToHash); return BitConverter.ToString(hashValue); } public static void Main() { var data = HashPassword("MyPassword@12345!", "BA7D93EA", SHA256.Create()); Console.WriteLine("HashedPassword {0}", data); } }
我已经在JavaScript中完成了字节数组拼接,得到了和C#一致的待哈希字节序列,但缺少对应的哈希计算步骤,需要实现这一步来得到和C#相同的哈希结果。当前我的JavaScript代码如下:
const hashPassword = (password, salt) => { const binarySaltValue = []; binarySaltValue[0] = parseInt(salt.substring(0, 2), 16); binarySaltValue[1] = parseInt(salt.substring(2, 4), 16); binarySaltValue[2] = parseInt(salt.substring(4, 6), 16); binarySaltValue[3] = parseInt(salt.substring(6, 8), 16); const binaryPassword = []; Buffer.from(password) .toJSON() .data.forEach((v) => { binaryPassword.push(v); binaryPassword.push(0); }); const valueToHash = [...binarySaltValue, ...binaryPassword].join(''); // The result of valueToHash is the same as in C# example // 1861251472347701210800970115011501190111011401000640490500510520530330 return valueToHash; }; console.log(hashPassword('MyPassword@12345!', 'BA7D93EA'));
解决方案
你的JS代码中存在关键问题:将字节数组拼接成字符串会破坏原始字节数据,导致哈希结果错误。需要保留字节数组(Buffer)进行哈希计算,同时利用Node.js内置的crypto模块实现SHA256哈希,确保和C#逻辑完全一致。
修改后的完整JavaScript代码:
const crypto = require('crypto'); const hashPassword = (password, salt) => { // 直接将十六进制salt转为Buffer,替代手动解析 const binarySaltValue = Buffer.from(salt, 'hex'); // 将密码转为UTF-16LE编码,对应C#的UnicodeEncoding const binaryPassword = Buffer.from(password, 'utf16le'); // 拼接salt和密码的字节数据 const valueToHash = Buffer.concat([binarySaltValue, binaryPassword]); // 计算SHA256哈希 const hashValue = crypto.createHash('sha256').update(valueToHash).digest(); // 转换为和C# BitConverter.ToString一致的格式:大写十六进制,用'-'分隔 return hashValue.toString('hex').toUpperCase().match(/.{2}/g).join('-'); }; // 测试,输出结果与C#代码一致 console.log(hashPassword('MyPassword@12345!', 'BA7D93EA'));
关键说明
Buffer.from(salt, 'hex')可简洁将十六进制salt转为字节数组,避免手动解析的繁琐Buffer.from(password, 'utf16le')直接生成C#中UnicodeEncoding对应的UTF-16LE编码字节,替代手动添加0的操作Buffer.concat用于拼接字节数据,对应C#中的数组复制逻辑- 最后将哈希结果转换为大写、以
-分隔的十六进制字符串,完全匹配C#BitConverter.ToString的输出格式
内容的提问来源于stack exchange,提问作者Velar
相关产品推荐
相关产品推荐

