必须用rsa.create(2048)生成密钥对,导出私钥用exportrsaprivatekey()(pkcs#8格式),公钥用exportrsapublickey()(subjectpublickeyinfo格式),.net原生不支持pem封装,需手动拼接头尾;加密须用oaep-sha256且校验明文长度,签名验签须严格匹配哈希与填充方式。

别用 RSACryptoServiceProvider,它在 .NET 6+ 已过时,Linux/macOS 上直接报 PlatformNotSupportedException;所有新代码必须从 RSA.Create() 开始。
怎么生成和导出密钥对(.NET 6+ 推荐路径)
密钥生成必须用 RSA.Create(2048) 或更高位数,不能 new 旧类。导出时注意用途区分:
-
ExportRSAPrivateKey()→ 得到 PKCS#8 格式私钥字节数组(推荐,OpenSSL 兼容) -
ExportRSAPublicKey()→ 得到 SubjectPublicKeyInfo 格式公钥字节数组(标准 PEM 公钥内容) - 若需 PEM 字符串(带
-----BEGIN RSA PRIVATE KEY-----头尾),得自己封装:用Convert.ToBase64String()+ 拼接头尾,.NET 原生不提供 PEM 序列化 - 硬编码
ExportParameters(true)是陷阱:返回的RSAParameters是结构体,无法直接跨平台序列化,且不含完整 PKCS#8 语义
公钥加密失败常见原因(CryptographicException: The parameter is incorrect.)
这错误 90% 出在填充或长度上,不是密钥本身有问题:
- 必须显式指定
RSAEncryptionPadding.OaepSHA256,写RSAEncryptionPadding.Oaep会退化为 SHA1,已不安全 - 明文长度超限:2048 位密钥下 OAEP-SHA256 最多加密
rsa.KeySize / 8 - 66字节(≈190 字节),UTF8 编码后算真实字节数,不是字符数 - 加密用了私钥、解密用了公钥——这是签名逻辑,不是加解密流程;RSA 加解密必须是「公钥加密 → 私钥解密」
- 解密时没用同一实例或同一私钥字节数组重新导入,
RSA对象不是长期可复用的“句柄”,每次操作建议新建并 Import
签名和验签别和加密混淆(SignData vs Encrypt)
签名不是“用私钥加密原文”,而是对摘要做数学运算。接口完全独立,混用必错:
- 签名必须用
SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)或OaepSHA256(仅限特定场景) - 验签用
VerifyData(data, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1),参数顺序、哈希、填充必须完全一致 -
Encrypt()和Decrypt()只用于机密性;SignData()和VerifyData()只用于完整性与身份认证 - 私钥严禁以明文字符串形式存配置文件或日志,导出后应走安全存储(如 Azure Key Vault、Windows DPAPI、Linux keyring)
最易被忽略的一点:RSA 不适合加密任意长数据。哪怕你绕过了长度检查,性能也会断崖下跌。真实场景中,该用 AES 加密业务数据,再用 RSA 加密那个 AES 密钥——混合加密才是落地常态。










