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

为何dotNet Core中RSACng的SignHash与Mono下BouncyCastle结果不同

问题根因分析与解决方案

可能的根因

  • 私钥参数转换异常:BouncyCastle的密钥参数默认使用大端字节序,转换为.NET标准RSAParameters的过程中如果字节序处理不当,会导致私钥参数不匹配,最终签名结果错误。
  • Mono的RSACryptoServiceProvider实现差异:Mono环境下的RSA.Create()默认返回RSACryptoServiceProvider,部分版本的该实现对SignHash方法的处理和.NET Core的RSACng存在不一致,比如对PKCS#1填充所需的DigestInfo结构处理错误,即使显式指定哈希算法和填充模式也会出现结果偏差。
  • 编码默认值差异:UnicodeEncoding的默认构造函数在不同环境下可能存在BOM、字节序的默认值差异,导致输入数据编码后的字节数组不一致,哈希计算结果不同。

验证定位步骤

先按以下顺序排除浅层问题:

  1. 两边使用相同的输入字符串,将计算得到的hash字节数组转Base64对比,如果结果不一致,优先修复编码问题:显式指定UnicodeEncoding的构造参数,固定为小端、无BOM:new UnicodeEncoding(bigEndian: false, byteOrderMark: false)
  2. 如果哈希结果完全一致,说明问题出在签名环节,直接采用下方的最优解决方案即可。

最优解决方案:直接使用BouncyCastle原生签名逻辑

完全避开Mono的RSA实现和私钥参数转换的坑,直接用BouncyCastle的原生API完成签名,和.NET Core侧的结果100%对齐,代码示例如下:

using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Signers;
using System.Text;

// 此处privateKeyParam为你之前获取到的BouncyCastle私钥参数实例RsaPrivateCrtKeyParameters privateKeyParam
var signer = new RsaDigestSigner(new Sha1Digest());
signer.Init(true, privateKeyParam);

// 显式指定编码参数,避免环境差异
byte[] data = new UnicodeEncoding(bigEndian: false, byteOrderMark: false).GetBytes(uuid);
signer.BlockUpdate(data, 0, data.Length);

byte[] signatureData = signer.GenerateSignature();
string signature = Convert.ToBase64String(signatureData);

备选方案:修复参数转换问题

如果必须使用.NET标准的RSA接口,先对比.NET Core侧和Mono侧导出的RSAParameters各个字段的Base64值(Modulus、D、P、Q、DP、DQ、InverseQ),确保参数完全一致;如果参数一致仍签名错误,强制指定使用RSACng(如果Mono环境支持)或者手动实现DigestInfo封装后再调用SignData方法替代SignHash。


内容的提问来源于stack exchange,提问作者mgodoy-br

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 16:06:03