My program contains 2 root certs I know and trust. I have to verify certs of trustcenters and "user" certs issued by the trustcenters which all originate from these 2 root certs.
I use X509Chain class to verify but that only works if the root cert is in the windows certificate store.
I'm looking for a way to verify the certs without importing theeses root certs - somehow tell the X509Chain class that I do trust this root certs and it should check just the certs in the chain and nothing else.
Actual code:
X509Chain chain = new X509Chain();
chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
chain.ChainPolicy.ExtraStore.Add(root); // i do trust this
chain.ChainPolicy.ExtraStore.Add(trust);
chain.Build(cert);
Edit: It's a .NET 2.0 Winforms application.
Chrome has made it simple for any site visitor to get certificate information with just a few clicks: Click the padlock icon in the address bar for the website. Click on Certificate (Valid) in the pop-up. Check the Valid from dates to validate the SSL certificate is current.
In Windows: For the Root certificate and any intermediate certificates, highlight each (one at a time) and click View Certificate . From this window click View Details > Copy to File > use Base-64 encoded X. 509 (. cer) format and save each.
I opened an Issue on dotnet/corefx and they replied as follows:
If AllowUnknownCertificateAuthority is the only flag set then
chain.Build()
will return true if
The chain correctly terminated in a self-signed certificate (via ExtraStore, or searched persisted stores)
None of the certificates are invalid per the requested revocation policy
All of the certificates are valid under the (optional) ApplicationPolicy or CertificatePolicy values
All of the certificates' NotBefore values are at-or-before VerificationTime and all of the certificates' NotAfter values are (at-or-)after VerificationTime.
If that flag is not specified then an additional constraint is added:
The self-signed certificate must be registered as trusted on the system (e.g. in the LM\Root store).
So, Build() returns true, you know that a time-valid non-revoked chain is present. The thing to do at that point is read
chain.ChainElements[chain.ChainElements.Count - 1].Certificate
and determine if it is a certificate that you trust. I recommend comparingchainRoot.RawData
to abyte[]
representing a certificate that you trust as a root in context (that is, byte-for-byte compare rather than using a thumbprint value).(If other flags are set then other constraints are also relaxed)
So you should do it this way:
X509Chain chain = new X509Chain();
chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
chain.ChainPolicy.ExtraStore.Add(root);
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority;
var isValid = chain.Build(cert);
var chainRoot = chain.ChainElements[chain.ChainElements.Count - 1].Certificate;
isValid = isValid && chainRoot.RawData.SequenceEqual(root.RawData);
EDIT
Over the years we found several issues with the original X509Chain solution I had posted here due to X509Chain performing incorrect behaviors for certain edge cases. Thus I can no longer recommend using X509Chain for this problem. Our product has since moved to using Bouncy Castle to do all of our certificate chain verification and it has held up to all of our testing and always works as expected.
The basis of our new solution can be found here: Build certificate chain in BouncyCastle in C#
I have removed the original answer so no one is using a bad security solution.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With