.NET中使用官方BouncyCastle.Cryptography构建证书链的方法
基于BouncyCastle.Cryptography构建证书链的解决方案
问题背景
我之前使用Portable.BouncyCastle(v1.9.0)编写了静态辅助方法,在.NET(Core)/C#中从主证书和附加证书构建证书链。现在需要迁移到官方的BouncyCastle.Cryptography库,但原方法中的X509CollectionStoreParameters类型和PkixBuilderParameter.AddStore方法已被移除,导致原有代码无法正常工作。
旧版可正常工作的代码
static IEnumerable<X509Certificate> BuildCertificateChain(byte[] primary, IEnumerable<byte[]> additionalCertificates) { X509CertificateParser parser = new(); PkixCertPathBuilder builder = new(); List<X509Certificate> chainedCertificates = []; HashSet<TrustAnchor> trustAnchors = []; // 区分根证书和从属证书 foreach (byte[] additionalCertificateBytes in additionalCertificates) { X509Certificate parsedCertificate = parser.ReadCertificate(additionalCertificateBytes); // 区分根证书和从属证书 if (parsedCertificate.IssuerDN.Equivalent(parsedCertificate.SubjectDN)) // 根证书 trustAnchors.Add(new TrustAnchor(parsedCertificate, null)); else chainedCertificates.Add(parsedCertificate); } // 以主证书为起点构建链 X509CertStoreSelector targetConstraintsCert = new() { Certificate = parser.ReadCertificate(primary) }; chainedCertificates.Add(targetConstraintsCert.Certificate); PkixBuilderParameters builderParams = new(trustAnchors, targetConstraintsCert) { IsRevocationEnabled = false }; X509CollectionStoreParameters intermediateStoreParameters = new(chainedCertificates); builderParams.AddStore( X509StoreFactory.Create( "Certificate/Collection", intermediateStoreParameters)); PkixCertPathBuilderResult result = builder.Build(builderParams); return result.CertPath.Certificates; }
尝试的新版代码(存在问题)
我参考Java示例尝试修改,但相关类和方法不匹配。目前的新版代码虽然能构建链,但所有附加证书都未被包含,因为找不到在构建过程中添加它们的正确方式:
public static IEnumerable<X509Certificate> BuildCertificateChain2(byte[] primary, IEnumerable<byte[]> additional) { X509CertificateParser parser = new X509CertificateParser(); // 找不到将其余证书包含到链中的方法 List<X509Certificate> allCerts = new List<X509Certificate>(); HashSet<TrustAnchor> trustAnchors = new HashSet<TrustAnchor>(); foreach (byte[] certBytes in additional) { X509Certificate cert = parser.ReadCertificate(certBytes); allCerts.Add(cert); if (cert.IssuerDN.Equivalent(cert.SubjectDN)) { trustAnchors.Add(new TrustAnchor(cert, null)); } } X509Certificate primaryCert = parser.ReadCertificate(primary); allCerts.Add(primaryCert); // 假设主证书不是根证书 X509CertStoreSelector targetConstraints = new() { Certificate = primaryCert }; PkixBuilderParameters pkixParams = new(trustAnchors, targetConstraints) { IsRevocationEnabled = false, }; PkixCertPathBuilderResult result; try { PkixCertPathBuilder builder = new PkixCertPathBuilder(); result = builder.Build(pkixParams); } catch (PkixCertPathBuilderException e) { throw new Exception("Failed to build certificate path", e); } return result.CertPath.Certificates.Cast<X509Certificate>(); }
适配官方BouncyCastle.Cryptography的解决方案
在新版库中,X509CollectionStoreParameters被替换为CollectionStoreParameters,而PkixBuilderParameters.AddStore方法则被AddCertStore替代。同时,创建集合存储的方式也改为使用CertStore.CreateCollectionStore。以下是修正后的完整代码:
using Org.BouncyCastle.Cert; using Org.BouncyCastle.Cert.Store; using Org.BouncyCastle.Security; using System.Collections; using System.Collections.Generic; using System.Linq; public static IEnumerable<X509Certificate> BuildCertificateChain(byte[] primary, IEnumerable<byte[]> additionalCertificates) { var parser = new X509CertificateParser(); var builder = new PkixCertPathBuilder(); var intermediateCerts = new List<X509Certificate>(); var trustAnchors = new HashSet<TrustAnchor>(); // 解析附加证书,区分根证书和中间证书 foreach (var certBytes in additionalCertificates) { var cert = parser.ReadCertificate(certBytes); if (cert.IssuerDN.Equivalent(cert.SubjectDN)) { // 根证书加入信任锚 trustAnchors.Add(new TrustAnchor(cert, null)); } else { // 中间证书加入待选集合 intermediateCerts.Add(cert); } } // 解析主证书 var primaryCert = parser.ReadCertificate(primary); intermediateCerts.Add(primaryCert); // 设置目标证书约束 var targetSelector = new X509CertStoreSelector { Certificate = primaryCert }; // 初始化构建参数 var pkixParams = new PkixBuilderParameters(trustAnchors, targetSelector) { IsRevocationEnabled = false // 关闭吊销检查,根据需要调整 }; // 创建中间证书存储并添加到参数中 var certStore = CertStore.CreateCollectionStore(new CollectionStoreParameters(intermediateCerts)); pkixParams.AddCertStore(certStore); // 构建证书链 PkixCertPathBuilderResult result; try { result = builder.Build(pkixParams); } catch (PkixCertPathBuilderException ex) { throw new System.Exception("证书链构建失败", ex); } // 返回完整的证书链(从主证书到根证书) return result.CertPath.Certificates.Cast<X509Certificate>(); }
关键变化说明
- 存储创建方式:使用
CertStore.CreateCollectionStore替代原有的X509StoreFactory.Create,配合CollectionStoreParameters(替代X509CollectionStoreParameters)来创建基于证书集合的存储。 - 添加存储到参数:使用
pkixParams.AddCertStore()方法替代原有的AddStore(),将中间证书存储注入到链构建参数中。 - 逻辑保持一致:依然保留了区分根证书(作为信任锚)和中间证书的逻辑,确保链构建时能正确找到信任起点和中间层级。
内容的提问来源于Stack Exchange,提问作者joachim-heck
相关产品推荐
相关产品推荐

