In connection with my enterprise project (intranet only) I came across a question with the verification of certificates using .net System.Security.Cryptography.X509Certificates
Step 1: Creating a root certificate
Use makecert
to create a root certificate and install it into the Trusted Root Certification Authorities
makecert -r -pe -n "CN=Test Labs (CA)" -ss CA -sr CurrentUser -a sha256 -cy authority -sky signature -sv TestLabCA.pvk TestLabCA.cer
pvk2pfx -pvk TestLabCA.pvk -spc TestLabCA.cer -pfx TestLabCA.pfx
Step 2: Creating a certificate and sign it with the root certificate
Use makecert
to create a certificate, sign it with the root certificate and install it to the Trusted Publishers
makecert -pe -n "CN=Test Labs (SPC)" -a sha256 -cy end -sky signature -ic TestLabCA.cer -iv TestLabCA.pvk -sv TestLabSPC.pvk TestLabSPC.cer
pvk2pfx -pvk TestLabSPC.pvk -spc TestLabSPC.cer -pfx TestLabSPC.pfx
Step 3: Verify in code
This is the C# code sample to verify the certificates:
X509Certificate2 rootCertificate = new X509Certificate2("TestLabCA.cer");
X509Certificate2 certificate = new X509Certificate2("TestLabSPC.cer");
// will return true
Console.WriteLine("{0}, verified = {1}", rootCertificate.GetName(), rootCertificate.Verify());
// will return false
Console.WriteLine("{0}, verified = {1}", certificate.GetName(), certificate.Verify());
// validate the chain
var chain = new X509Chain();
chain.Build(certificate);
Console.WriteLine("{0}, verified root of chain = {1}", certificate.GetName(), chain.ChainElements[chain.ChainElements.Count-1].Certificate.Verify());
Question:
If I want to verify the certificate, do I have to check the chain and verify the last one in the chain, assuming that this is a root certificate?
Is there a better way to do it?
You have to create a chain of trust, yes. This means you have to trace it back to a certificate that is trusted by you. This does not have to be a root certificate, but it is common to trust the root certificate and not an intermediate certificate. Sometimes you only want to allow a single entity with a single certificate. As long as you are sure it is the correct certificate, you could simply trust that single leaf certificate, so the "chain" would consist of a single certificate. An example of this are self-signed root certificates that are sometimes used by web-services.
Note that the verification of the certificate chain is only part of the total validation of a certificate. You need to make sure that the certificate has not been revoked, that the certificate is still valid (between the effective date and date of expiry). Sometimes there are also additional, proprietary rules for validating certificates, e.g. presence of the certificate ID in a DB - whitelisting/blacklisting.
In addition to Maarten Bodewes' answer:
To easily verify if the chain is valid you can use the following code:
X509Certificate2 Certificate = new X509Certificate2( "Certificate.pfx" );
X509Chain CertificateChain = new X509Chain();
//If you do not provide revokation information, use the following line.
CertificateChain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
bool IsCertificateChainValid = CertificateChain.Build( Certificate );
IsCertificateChainValid then returns true when the certificate chain is correct. In cases it returns false you can use
CertificateChain.ChainStatus
for information about why the status is not valid. Possible values include NotTimeValid, UntrustedRoot.
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