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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 18:24:46