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

如何用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 19:30:48