How to build certificate chain with BouncyCastle in .net (not with Portable.BouncyCastle)

42 Views Asked by At

Based on the posting Build certificate chain in BouncyCastle in C# I was using the Portable.BouncyCastle (v. 1.9.0) to create a certificate chain from primary and some additional certificates in .net (core) / c# using the following static helper method - due to i now need to use the official BouncyCastle.Cryptography library the X509CollectionStoreParameters type and PkixBuilderParameter.AddStore method are no longer available.

Full method:

 static IEnumerable<X509Certificate> BuildCertificateChain(byte[] primary, IEnumerable<byte[]> additionalCertificates)
    {
        X509CertificateParser parser = new();
        PkixCertPathBuilder builder = new();
        List<X509Certificate> chainedCertificates = [];
        HashSet<TrustAnchor> trustAnchors = [];

        // Separate root and subordinate certificates
        foreach (byte[] additionalCertificateBytes in additionalCertificates)
        {
            X509Certificate parsedCertificate = parser.ReadCertificate(additionalCertificateBytes);
            // Separate root and subordinate certificates
            if (parsedCertificate.IssuerDN.Equivalent(parsedCertificate.SubjectDN)) // Root certificate
                trustAnchors.Add(new TrustAnchor(parsedCertificate, null));
            else
                chainedCertificates.Add(parsedCertificate);
        }

        // Create chain for this certificate starting with the primary certificate
        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;
    }

Does anybody have a suggestion how to build the chain with the official libary?

I've tried to follow java related examples, but the related classes, types and methods are always missing. When using the following updated method, the Certificate chain is build, but all additional certificates are missing, due to i can't find a way to add them during build.

 public static IEnumerable<X509Certificate> BuildCertificateChain2(byte[] primary, IEnumerable<byte[]> additional)
    {
        X509CertificateParser parser = new X509CertificateParser();
        
        // CAN'T FIND WAY TO INCLUDE THE rest of the certificates in the chain
        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);

        // Assuming primary certificate is not a root
        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>();
    }
0

There are 0 best solutions below