如何用C#实现JavaScript CryptoJS的HmacSHA256加密逻辑?
把Crypto-JS的Postman脚本转换成C#实现
我来帮你搞定这个转换,其实System.Security.Cryptography里的类完全能实现你要的逻辑,咱们一步步拆解原JS的步骤,再对应到C#代码上。
首先先理清楚原JS的核心流程:
- 把JSON对象序列化为字符串,转成UTF8编码后再Base64编码(得到Payload)
- 用HmacSHA256对UTF8格式的payload加密,然后把加密结果转成UTF8字符串再Base64编码(得到Signature)
不过这里要先提个小问题:原JS里处理Signature的步骤可能有点多余(甚至可能导致数据丢失)——HmacSHA256的结果是二进制哈希值,直接转Base64才是常规操作,没必要转成UTF8字符串再转Base64(因为二进制哈希里的字节不一定都是有效的UTF8字符,转字符串会被替换成乱码,再转回去就不是原哈希了)。我会把两种实现都给你,你可以根据实际API要求选择。
第一步:引用必要的命名空间
不管用哪种实现,你都需要这些命名空间:
using System; using System.Security.Cryptography; using System.Text; using Newtonsoft.Json; // 如果你用Newtonsoft.Json序列化JSON;如果用.NET Core/.NET 5+,也可以用System.Text.Json
第二步:实现Payload的Base64编码(和JS完全一致)
这部分逻辑很直接,对应JS里的Payload生成:
// 假设你的payload是对应的C#类实例 var payload = new { vendor = new { email = "", firstName = "", lastName = "" }, purchaseId = "12345678" }; // 1. 序列化JSON对象为字符串(对应JS的JSON.stringify(payload)) var payloadString = JsonConvert.SerializeObject(payload); // 2. 转成UTF8字节数组(对应JS的crypto.enc.Utf8.parse(payloadString)) byte[] payloadUtf8Bytes = Encoding.UTF8.GetBytes(payloadString); // 3. 编码为Base64(对应JS的crypto.enc.Base64.stringify(payloadUTF8)) string payloadBase64 = Convert.ToBase64String(payloadUtf8Bytes); // 现在payloadBase64就是你要的Payload值,可以像Postman那样存起来用
第三步:实现Signature的生成
这里分两种情况:
情况1:严格对应原JS的写法(不推荐,可能有数据丢失)
完全照搬JS里的步骤,包括把哈希转成UTF8字符串再转Base64:
string secretKey = "key"; // 对应JS里的SecretKey byte[] keyUtf8Bytes = Encoding.UTF8.GetBytes(secretKey); using (HMACSHA256 hmac = new HMACSHA256(keyUtf8Bytes)) { // 1. 计算HmacSHA256哈希(对应JS的crypto.HmacSHA256(payloadUTF8, key)) byte[] signatureBytes = hmac.ComputeHash(payloadUtf8Bytes); // 2. 把哈希字节转成UTF8字符串(对应JS的crypto.enc.Utf8.stringify(signature),原JS里的parse其实是多此一举,本质是转成UTF8字符串再转回字节) string signatureUtf8String = Encoding.UTF8.GetString(signatureBytes); byte[] signatureUtf8Bytes = Encoding.UTF8.GetBytes(signatureUtf8String); // 3. 编码为Base64(对应JS的crypto.enc.Base64.stringify(signatureUTF8)) string signatureBase64 = Convert.ToBase64String(signatureUtf8Bytes); }
情况2:正确的HMAC转Base64方式(推荐,符合行业常规)
跳过不必要的UTF8转换,直接把二进制哈希转成Base64,这也是大多数API要求的方式:
string secretKey = "key"; byte[] keyUtf8Bytes = Encoding.UTF8.GetBytes(secretKey); using (HMACSHA256 hmac = new HMACSHA256(keyUtf8Bytes)) { byte[] signatureBytes = hmac.ComputeHash(payloadUtf8Bytes); // 直接把哈希字节转成Base64,对应JS里的crypto.enc.Base64.stringify(signature) string signatureBase64 = Convert.ToBase64String(signatureBytes); }
补充说明
- 如果你用的是
System.Text.Json而不是Newtonsoft.Json,序列化代码改成JsonSerializer.Serialize(payload)即可 - 一定要用
Encoding.UTF8,不要用Encoding.Default(它是系统默认编码,不同机器可能不一样,会导致编码不一致) - 建议先测试两种方式的结果和Postman里的对比,看API接受哪一种——大概率是第二种正确的方式,原JS的写法可能是个小失误
内容的提问来源于stack exchange,提问作者andrewb
相关产品推荐
相关产品推荐

