Search code examples
c#.netwindows.net-6.0x509certificate2

X509Chain.Build() seems to ignore certificates in LocalComputer/My


I need to rebuild a certificate chain based on the end certificate and then export all the certificates in the chain. For this I use the method X509Chain.Build(endCertificate). My idea is that this way I can find all certificates as far as possible (from different sources, like folders (via ChainPolicy.ExtraStore) but also from all certificate stores of the system (like "My" or "Trusted Root Certification Authorities")). If a certificate is missing, I ask the user to select it manually (and it will be copied to a folder which is an ChainPolicy.ExtraStore in the next run). This is repeated until all certificates are known and the chain can be built successfully.

However, I now have the problem that I noticed in my test that the chain cannot be built because an Intermediate CA certificate is supposedly missing. However, this certificate is located in "LocalComputer/My". It works if the certificate is in "LocalComputer/Intermediate Certification Authorities".

Therefore the question: How can I ensure that the entire certificate store (LocalUser and LocalComputer with all substores) is used to search for certificates?

System: Windows 11 22H2; .NET-Version: net6.0-windows


Solution

  • By default certificate verification will not look at certificate stores such as My for trusted roots. You can add other stores to the ExtraStore property if you want.

    You also need to set X509VerificationFlags.AllowUnknownCertificateAuthority otherwise it will still be rejected. Note that this could cause a major security issue, depending on your use case, and you may want to do other manual checks on the trust chain.

    using var store1 = new X509Store(StoreName.My, StoreLocation.LocalMachine, OpenFlags.OpenExistingOnly);
    chain.ChainPolicy.ExtraStore.AddRange(store1.Certificates);
    chaim.VerificationFlags |= X509VerificationFlags.AllowUnknownCertificateAuthority;
    chain.Build(someCert);
    

    StoreName.Root CertificateAuthority and TrustedPeople are used by default, and AuthRoot is a subset of Root. It makes no sense to use Disallowed so that leaves you with My AddressBook and TrustedPublisher to add. That is for both StoreLocation.LocalMachine and CurrentUser. Again CurrentUser is more of a security risk.

    Put all stores in a using to dispose them when done.


    Ideally you would store intermediate and root certificates in the correct place in the first place.