C#借助Bouncy Castle用根证书生成子证书的实现方法
使用Bouncy Castle处理PFX文件与生成子证书的解决方案
针对你提出的三个核心问题,结合Bouncy Castle库的特性,以下是具体实现方案及修改后的完整代码:
1. 用Bouncy Castle读取PFX文件
Bouncy Castle提供Pkcs12Store类专门用于读取PKCS#12(PFX)格式文件,无需依赖微软的X509Certificate2实现:
using Org.BouncyCastle.Pkcs; using Org.BouncyCastle.X509; // 读取PFX文件 Pkcs12Store pfxStore = new Pkcs12Store( new FileStream("RootCertificate.pfx", FileMode.Open), "Server123".ToCharArray() ); // 遍历获取根证书(PFX中证书与私钥通常使用相同别名) X509Certificate caCert = null; foreach (string alias in pfxStore.Aliases) { if (pfxStore.IsCertificateEntry(alias)) { caCert = pfxStore.GetCertificate(alias).Certificate; break; } }
2. 从PFX获取AsymmetricKeyParameter私钥
通过Pkcs12Store的密钥条目直接提取私钥,同样按别名查找:
AsymmetricKeyParameter caPrivateKey = null; foreach (string alias in pfxStore.Aliases) { if (pfxStore.IsKeyEntry(alias)) { caPrivateKey = pfxStore.GetKey(alias).Key; break; } }
3. 将子证书与私钥打包为PFX文件
证书本身不包含私钥,需将生成的子证书和对应私钥一起打包成PKCS#12(PFX)格式文件,使用Pkcs12Store完成绑定与存储:
完整修改后的代码
整合上述步骤,替换原有的微软CryptoAPI实现,完整可运行代码如下:
using System; using System.IO; using System.Reflection; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Generators; using Org.BouncyCastle.Math; using Org.BouncyCastle.Pkcs; using Org.BouncyCastle.Security; using Org.BouncyCastle.X509; public static void GenerateChildCertificateWithPfx() { // 读取根证书PFX文件 string rootPfxPath = Path.Combine( Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "RootCertificate.pfx" ); char[] pfxPassword = "Server123".ToCharArray(); Pkcs12Store rootPfxStore = new Pkcs12Store( new FileStream(rootPfxPath, FileMode.Open), pfxPassword ); // 提取根证书和私钥 X509Certificate caCert = null; AsymmetricKeyParameter caPrivateKey = null; foreach (string alias in rootPfxStore.Aliases) { if (pfxStore.IsCertificateEntry(alias)) { caCert = rootPfxStore.GetCertificate(alias).Certificate; } if (pfxStore.IsKeyEntry(alias)) { caPrivateKey = rootPfxStore.GetKey(alias).Key; } } // 生成子证书密钥对 RsaKeyPairGenerator keyGen = new RsaKeyPairGenerator(); keyGen.Init(new KeyGenerationParameters(new SecureRandom(), 2048)); AsymmetricCipherKeyPair childKeyPair = keyGen.GenerateKeyPair(); // 构建子证书生成器 X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); certGen.SetSerialNumber(BigInteger.ProbablePrime(120, new Random())); certGen.SetSubjectDN(new X509Name("CN=Child Certificate")); certGen.SetIssuerDN(caCert.SubjectDN); certGen.SetNotBefore(DateTime.UtcNow); certGen.SetNotAfter(DateTime.UtcNow.AddMonths(10)); certGen.SetPublicKey(childKeyPair.Public); certGen.SetSignatureAlgorithm("SHA256WithRSA"); // 使用根证书私钥签名子证书 ISignatureFactory signatureFactory = new Asn1SignatureFactory( "SHA256WithRSA", caPrivateKey, new SecureRandom() ); X509Certificate childCert = certGen.Generate(signatureFactory); // 将子证书与私钥打包为PFX Pkcs12Store childPfxStore = new Pkcs12Store(); // 绑定私钥与证书 childPfxStore.SetKeyEntry( "ChildPrivateKey", new AsymmetricKeyEntry(childKeyPair.Private), new[] { new X509CertificateEntry(childCert) } ); // 单独添加证书条目(可选,方便单独读取证书) childPfxStore.SetCertificateEntry("ChildCertificate", new X509CertificateEntry(childCert)); // 保存子证书PFX文件 string childPfxPath = Path.Combine( Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "ChildCertificate.pfx" ); using (FileStream fs = new FileStream(childPfxPath, FileMode.Create)) { childPfxStore.Save(fs, "Client123".ToCharArray(), new SecureRandom()); } }
关键说明
- 读取PFX时,
Pkcs12Store会自动解析文件中的证书和密钥结构,无需手动处理字节流。 - 确保根证书PFX包含私钥(你通过PowerShell生成的根证书PFX是包含私钥的,可正常提取)。
- 打包子证书PFX时,
SetKeyEntry方法会将私钥与证书绑定,生成符合标准的PFX文件,可直接用于身份验证、加密等场景。
内容的提问来源于stack exchange,提问作者Nithin B
相关产品推荐
相关产品推荐

