Search code examples
c#x509certificatex509chain

How exactly is a Certificate chain built?


As the title states i want to know how the certificate chain is build internaly.

I have a self signed root certificate (CA) und an incoming user certificate, which supposedly has been signed by my root, which is what i have to test. Testing a X509Certificate2 can be done with the X509Certificate2.Verify() method, which uses the X509Chain with some standard settings. To have full control over the process i am using the X509Chain directly. As my root is not installed on the machine (not in trusted root certificate store) i am adding it to the ExtraStore of the ChainPolicy.

The whole magic happens within X509Chain.Build() method, where i pass my 'to be tested' user certificate. The chain gets build, starting with the passed certificate and ending with the self signed root. But how exactly? How does one test wether a certificate has been signed by one or another root? Does it use digital signatures internally?

I tried to debug the whole thing but ended at an DLL import, which uses the CertGetCertificateChain method from Libraries.Crypt32. That is C++ stuff, which exceeds my domain of knowledge.

Simplified code so far:

using (var chain = new X509Chain
            {
                ChainPolicy =
                {
                    RevocationMode = X509RevocationMode.NoCheck,
                    RevocationFlag = X509RevocationFlag.ExcludeRoot,
                    VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority,
                    VerificationTime = DateTime.Now,
                    UrlRetrievalTimeout = new TimeSpan(0, 0, 0)
                }
            })
            {
                chain.ChainPolicy.ExtraStore.Add(authority);

                if (!chain.Build(signedCertificate))
                {
                    //Errorhandling
                }

                //Root certificate should always be last in the X509ChainElements collection
                var isSignedByCorrectRootCert =
                    chain.ChainElements
                        .Cast<X509ChainElement>()
                        .Last()
                        .Certificate.Thumbprint == authority.Thumbprint;

                if (!isSignedByCorrectRootCert)
                {
                    //Errorhandling
                }
            }

Solution

  • Does it use digital signatures internally?

    exactly.

    I tried to debug the whole thing but ended at an DLL import, which uses the CertGetCertificateChain method from Libraries.Crypt32.

    yes, .NET X509Chain class is nothing else than plain wrapper over CryptoAPI native (C++) functions. I would say that 95+% of cryptography stuff in .NET are wrappers over CryptoAPI functions.

    Years ago I wrote a blog post that explains how chain building is performed in Microsoft Windows: Certificate Chaining Engine — how it works. This post explains how chaining engine builds the chain and bind certificates in the chain before sending it to validation routine. Chain validation is a much more complex process. Validation logic is described in RFC 5280, §6