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

在C#(.NET 4.7.2)中无CRT参数生成RSA签名的方案咨询

问题

我正在开发一款基于.NET Framework 4.7.2(Visual Studio 2019,无法升级)的C#应用,需要使用RSA为指定字节序列生成签名。目前仅拥有RSA密钥的Modulus、公钥Exponent和PrivateExponent(D),缺少CRT优化相关参数(P、Q、DP、DQ、InverseQ)。尝试使用System.Security.Cryptography的SignData方法及BouncyCastle库均因缺少CRT参数报错。

相关代码片段:

RSAParameters rsaKeyInfo = new RSAParameters();
for (i = 0; i<Constants.KEY_ID_TABLE_LENGTH_3072; i++)
{
    if((SigKeyTbl_3072.keyIdTbl_3072[i].KeyId == keyId) && 
      (SigKeyTbl_3072.keyIdTbl_3072[i].KeyType == keyType))
    {
        Console.WriteLine("KeyId found.");
         rsaKeyInfo.Modulus = SigKeyTbl_3072.keyIdTbl_3072[i].PublicModulus.ToArray();
         rsaKeyInfo.Exponent = SigKeyTbl_3072.keyIdTbl_3072[i].PublicExponent;
         rsaKeyInfo.D = SigKeyTbl_3072.keyIdTbl_3072[i].PrivatExponent.ToArray();
        return (ErrorCode: 0, rsaKeyInfo);
    }

签名代码:

using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
    rsa.ImportParameters(rsaKey);
    FscOut = rsa.SignData(fscIn, HashAlgorithmName.SHA512, RSASignaturePadding.Pss);
}

报错信息:

Message: 
System.ArgumentNullException : Value cannot be null. (Parameter 'p')

Stack Trace: 
RsaPrivateCrtKeyParameters.ValidateValue(BigInteger x, String name, String desc)
RsaPrivateCrtKeyParameters.ctor(BigInteger modulus, BigInteger publicExponent, BigInteger privateExponent, BigInteger p, BigInteger q, BigInteger dP, BigInteger dQ, BigInteger qInv)

现咨询:是否可通过System.Security.Cryptography或BouncyCastle在无CRT参数的情况下生成RSA签名?是否有支持该场景的特定配置或类?若无法实现,恢复缺失参数的难度如何?


回答

1. 使用System.Security.Cryptography实现签名

你当前用的RSACryptoServiceProvider是.NET Framework中的旧版RSA实现,它强制要求CRT参数来优化签名性能。但在.NET Framework 4.7.2中,可改用RSA基类的默认实现(Windows 10及以上系统通常返回RSACng实例),它支持仅通过Modulus、Exponent和D参数导入私钥并完成签名:

修改签名代码如下:

using (RSA rsa = RSA.Create())
{
    rsa.ImportParameters(rsaKey);
    FscOut = rsa.SignData(fscIn, HashAlgorithmName.SHA512, RSASignaturePadding.Pss);
}

这种方式不需要CRT参数,RSACng会自动处理基于纯私钥(D)的签名逻辑,仅性能略低于CRT优化的签名,但3072位密钥的性能差异在多数场景下可接受。

2. 使用BouncyCastle实现签名

BouncyCastle报错是因为误用了需要CRT参数的RsaPrivateCrtKeyParameters类。你需要改用RsaPrivateKeyParameters类,它仅需Modulus、PublicExponent和PrivateExponent即可创建私钥:

示例代码(需引用BouncyCastle库):

using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using System.Numerics;

// 将字节数组转换为BigInteger
BigInteger modulus = new BigInteger(1, rsaKey.Modulus);
BigInteger publicExponent = new BigInteger(1, rsaKey.Exponent);
BigInteger privateExponent = new BigInteger(1, rsaKey.D);

// 创建纯私钥参数
RsaPrivateKeyParameters privateKey = new RsaPrivateKeyParameters(modulus, privateExponent, publicExponent);

// 获取SHA512-PSS签名器
ISigner signer = SignerUtilities.GetSigner("SHA512withRSA/PSS");
signer.Init(true, privateKey);
signer.BlockUpdate(fscIn, 0, fscIn.Length);

// 生成签名
byte[] signature = signer.GenerateSignature();

这种方式完全不需要CRT参数,直接基于原始RSA私钥逻辑完成签名。

3. 恢复缺失CRT参数的难度

恢复CRT参数的核心是对RSA模数(Modulus)进行因数分解,即找到两个大质数P和Q,使得Modulus = P * Q。对于3072位的RSA模数,这在当前通用计算能力下几乎不可能完成——这也是RSA算法的安全性基础。除非模数存在设计缺陷(比如因子过小、重复因子等),否则没有可行方法在合理时间内分解出P和Q,也就无法恢复其他CRT参数。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 18:54:54