Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create and verify x509 certificates in .Net

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?

like image 655
achibus Avatar asked Feb 13 '13 22:02

achibus


2 Answers

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.

like image 59
Maarten Bodewes Avatar answered Oct 17 '22 02:10

Maarten Bodewes


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.

like image 38
Simon Mattes Avatar answered Oct 17 '22 02:10

Simon Mattes