C# Bouncy Castle将公私钥作为变量实现RSA加解密问题咨询
问题根因
cipher.Init() 方法要求第二个参数传入AsymmetricKeyParameter类型的强类型密钥参数对象,直接传入Base64字符串会触发类型不匹配的运行时错误。同作用域内生成密钥可正常跑通加解密流程,核心原因是密钥生成逻辑直接返回了RsaKeyParameters类型的实例,和Base64编码的字符串属于完全不同的数据结构,无法直接替换使用。
两个独立Azure Function App无法复用动态生成的密钥,是由Function的无状态运行特性决定的:冷启动、横向扩容产生的新实例内存完全隔离,运行时临时生成的密钥不会跨实例同步,必须通过预生成、配置注入的方式实现密钥跨实例、跨应用复用。
可直接复用的实现方案
1. 一次性生成标准格式RSA密钥对
不要自定义Base64转码逻辑,使用BouncyCastle自带的序列化工具导出标准SubjectPublicKeyInfo(公钥)、PrivateKeyInfo(私钥)格式的Base64字符串,这类标准格式不存在跨实例、跨版本的解析兼容问题:
using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Generators; using Org.BouncyCastle.Security; using System; // 本地执行一次生成密钥对,将输出的两个Base64字符串分别存入对应Function的配置中 public static (string PublicKeyBase64, string PrivateKeyBase64) GenerateStandardRsaKeyPair() { var keyGenerator = new RsaKeyPairGenerator(); keyGenerator.Init(new KeyGenerationParameters(new SecureRandom(), 2048)); AsymmetricCipherKeyPair keyPair = keyGenerator.GenerateKeyPair(); // 序列化公钥为标准格式Base64 byte[] pubKeyBytes = SubjectPublicKeyInfoFactory .CreateSubjectPublicKeyInfo(keyPair.Public) .GetEncoded(); string publicKeyBase64 = Convert.ToBase64String(pubKeyBytes); // 序列化私钥为标准格式Base64 byte[] privKeyBytes = PrivateKeyInfoFactory .CreatePrivateKeyInfo(keyPair.Private) .GetEncoded(); string privateKeyBase64 = Convert.ToBase64String(privKeyBytes); return (publicKeyBase64, privateKeyBase64); }
安全提示:私钥仅允许配置到负责解密的Function App中,公钥可分发到所有加密端,禁止将私钥随加密端配置、代码分发,避免密钥泄露风险
2. Function启动阶段加载密钥为强类型对象
不要每次API调用都重复解析密钥,在Function静态构造类或依赖注入容器中以单例形式加载一次即可,降低不必要的性能损耗:
using Org.BouncyCastle.Crypto; // 加密端加载公钥 public static AsymmetricKeyParameter GetPublicKeyFromBase64(string base64PublicKey) { byte[] keyBytes = Convert.FromBase64String(base64PublicKey); return PublicKeyFactory.CreateKey(keyBytes); } // 解密端加载私钥 public static AsymmetricKeyParameter GetPrivateKeyFromBase64(string base64PrivateKey) { byte[] keyBytes = Convert.FromBase64String(base64PrivateKey); return PrivateKeyFactory.CreateKey(keyBytes); }
3. 修正加解密调用逻辑
加载得到的AsymmetricKeyParameter实例直接传入cipher.Init()方法即可,禁止传入原始Base64字符串:
using Org.BouncyCastle.Crypto.Engines; using Org.BouncyCastle.Crypto.Encodings; // 加密逻辑 public static byte[] RsaEncrypt(byte[] plainBytes, AsymmetricKeyParameter publicKey) { var cipher = new OaepEncoding(new RsaEngine()); cipher.Init(true, publicKey); return cipher.ProcessBlock(plainBytes, 0, plainBytes.Length); } // 解密逻辑 public static byte[] RsaDecrypt(byte[] cipherBytes, AsymmetricKeyParameter privateKey) { var cipher = new OaepEncoding(new RsaEngine()); cipher.Init(false, privateKey); return cipher.ProcessBlock(cipherBytes, 0, cipherBytes.Length); }
常见避坑点
- 不要将密钥硬编码在业务代码中,优先存储在Azure Function应用配置或Azure Key Vault中,密钥轮换无需重新部署代码
- 两端加解密的填充规则必须完全对齐:当前使用的
OaepEncoding默认采用SHA1哈希算法,如果自定义哈希参数,加密、解密两端必须同步配置,否则会出现解密失败 - 不要在单次API调用逻辑中重复生成密钥对,无状态实例的运行机制决定了动态生成的密钥无法跨实例匹配
内容的提问来源于stack exchange,提问作者miguelito
相关产品推荐
相关产品推荐

