RSA.Create()生成的密钥跨平台解密失败,因.NET默认用Windows CNG格式;需导出公钥用ExportSubjectPublicKeyInfo()、私钥用ExportPkcs8PrivateKey(),并确保Java/Python端填充方式一致。

为什么 RSA.Create() 生成的密钥不能直接用于跨平台解密
因为 .NET 默认用的是 Windows CNG(Cryptography Next Generation)密钥格式,私钥导出为 RSACryptoServiceProvider 兼容的 XML 或 PKCS#8 都得手动处理——否则 Java/Python 拿到私钥也解不开你用 RSA.Encrypt() 加的密。
实操建议:
- 加密端统一用
RSA.Create(2048)实例,调用Encrypt(data, RSAEncryptionPadding.Pkcs1) - 导出公钥必须用
ExportSubjectPublicKeyInfo()(X.509 SPKI 格式),不是ExportParameters(false) - 导出私钥要用
ExportPkcs8PrivateKey()(带密码保护可选),别用已废弃的ToXmlString(false) - 如果对方是 Java,注意 .NET 导出的 PKCS#8 私钥默认含 OID
1.2.840.113549.1.1.1,JavaPKCS8EncodedKeySpec能认;但某些老版本 BouncyCastle 可能要求去掉 ASN.1 封装头,得用AsnEncodedData手动剥离
RSA.ImportFromPem() 在 .NET 6+ 怎么安全加载 PEM 密钥
这个方法只在 .NET 6 及以上可用,且不支持密码保护的 PEM(即 -----BEGIN ENCRYPTED PRIVATE KEY-----)。一旦你传入带密码的 PEM,会直接抛 CryptographicException,错误信息是 "The specified password is incorrect." 或更模糊的 "Invalid key blob."。
实操建议:
- 公钥 PEM:确认以
-----BEGIN PUBLIC KEY-----开头,直接用RSA.ImportFromPem(pemBytes) - 私钥 PEM:必须是无密码的
-----BEGIN PRIVATE KEY-----(PKCS#8),不能是-----BEGIN RSA PRIVATE KEY-----(PKCS#1);后者需先转格式,例如用 OpenSSL:openssl pkcs8 -topk8 -inform PEM -outform PEM -in key.pem -out key-pkcs8.pem -nocrypt - 导入后务必校验:调用
rsa.KeySize看是否匹配预期(如 2048),再用rsa.ExportParameters(false).Exponent确认公钥指数是65537
用 RSASignaturePadding.Pkcs1 做签名时,为什么解密端验签失败
这不是“解密”,是验签(VerifyData),但很多人误以为和加解密流程对称。问题常出在填充方式不一致:C# 默认签名用 PKCS#1 v1.5,但 Java 的 Signature.getInstance("SHA256withRSA") 对应相同填充,而 Python 的 cryptography.hazmat.primitives.asymmetric.padding.PKCS1v15() 必须显式指定——漏写就默认用 PSS,导致验签必错。
实操建议:
- 签名时明确写全:
rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1) - 验签端必须严格匹配:C# 用
VerifyData+ 同样HashAlgorithmName和RSASignaturePadding.Pkcs1 - 别混用哈希:比如 C# 用
SHA256签名,Java 却用SHA1withRSA验,错误信息通常是"Signature length not correct"或"Bad signature" - 如果要兼容旧系统(如某些嵌入式设备只支持 SHA1),记得改两处:
HashAlgorithmName.SHA1和对应 padding,但别在新项目里用 SHA1
密钥长度选 2048 还是 3072?RSA.Create(3072) 在 Windows Server 2012 R2 上跑不起来
3072 是当前 NIST 推荐的最低安全强度,但 Windows Server 2012 R2 自带的 CNG 提供程序不支持大于 2048 的密钥生成(RSA.Create(3072) 会抛 CryptographicException,错误信息是 "The requested operation is not supported."),不是代码写错了,是 OS 层限制。
实操建议:
- 生产环境部署前,先用
RuntimeInformation.IsOSPlatform(OSPlatform.Windows)+Environment.OSVersion判断系统版本;Server 2012 R2 / Windows 8.1 及更早系统,只能用RSA.Create(2048) - 若必须用 3072,需升级到 Windows Server 2016+ 或启用第三方提供程序(如 BouncyCastle 的
RsaEngine),但会失去硬件加速 - 密钥长度影响性能:2048 位加密约比 3072 快 2.5 倍(实测),但解密差异更大;如果每秒要处理上千次小数据加密(如 JWT 密钥封装),2048 更稳
密钥参数配置不是填数字就行,得看运行时环境是否真正支持——尤其当你的 DLL 要跑在客户五年前的老服务器上时,RSA.Create(3072) 这行代码就是个隐藏的崩溃点。


















