Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# How can I validate a Root-CA-Cert certificate (x509) chain?

Tags:

Let's say I have three certificates (in Base64 format)

Root  |  --- CA      |      --- Cert (client/signing/whatever) 

How can I validate the certs and certificate path/chain in C#? (All those three certs may not be in my computer cert store)

Edit: BouncyCastle has the function to verify. But I'm trying not to use any third-party library.

    byte[] b1 = Convert.FromBase64String(x509Str1);     byte[] b2 = Convert.FromBase64String(x509Str2);     X509Certificate cer1 =          new X509CertificateParser().ReadCertificate(b1);     X509Certificate cer2 =         new X509CertificateParser().ReadCertificate(b2);     cer1.Verify(cer2.GetPublicKey()); 

If the cer1 is not signed by cert2 (CA or root), there will be exception. This is exactly what I want.

like image 359
Jacob Avatar asked Sep 07 '11 09:09

Jacob


People also ask

What C is used for?

C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...

What is the full name of C?

In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr. Stroustroupe.

Is C language easy?

C is a general-purpose language that most programmers learn before moving on to more complex languages. From Unix and Windows to Tic Tac Toe and Photoshop, several of the most commonly used applications today have been built on C. It is easy to learn because: A simple syntax with only 32 keywords.

Is C programming hard?

C is more difficult to learn than JavaScript, but it's a valuable skill to have because most programming languages are actually implemented in C. This is because C is a “machine-level” language. So learning it will teach you how a computer works and will actually make learning new languages in the future easier.


1 Answers

The X509Chain class was designed to do this, you can even customize how it performs the chain building process.

static bool VerifyCertificate(byte[] primaryCertificate, IEnumerable<byte[]> additionalCertificates) {     var chain = new X509Chain();     foreach (var cert in additionalCertificates.Select(x => new X509Certificate2(x)))     {         chain.ChainPolicy.ExtraStore.Add(cert);     }      // You can alter how the chain is built/validated.     chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;     chain.ChainPolicy.VerificationFlags = X509VerificationFlags.IgnoreWrongUsage;      // Do the validation.     var primaryCert = new X509Certificate2(primaryCertificate);     return chain.Build(primaryCert); } 

The X509Chain will contain additional information about the validation failure after Build() == false if you need it.

Edit: This will merely ensure that your CA's are valid. If you want to ensure that the chain is identical you can check the thumbprints manually. You can use the following method to ensure that the certification chain is correct, it expects the chain in the order: ..., INTERMEDIATE2, INTERMEDIATE1 (Signer of INTERMEDIATE2), CA (Signer of INTERMEDIATE1)

static bool VerifyCertificate(byte[] primaryCertificate, IEnumerable<byte[]> additionalCertificates) {     var chain = new X509Chain();     foreach (var cert in additionalCertificates.Select(x => new X509Certificate2(x)))     {         chain.ChainPolicy.ExtraStore.Add(cert);     }      // You can alter how the chain is built/validated.     chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;     chain.ChainPolicy.VerificationFlags = X509VerificationFlags.IgnoreWrongUsage;      // Do the preliminary validation.     var primaryCert = new X509Certificate2(primaryCertificate);     if (!chain.Build(primaryCert))         return false;      // Make sure we have the same number of elements.     if (chain.ChainElements.Count != chain.ChainPolicy.ExtraStore.Count + 1)         return false;      // Make sure all the thumbprints of the CAs match up.     // The first one should be 'primaryCert', leading up to the root CA.     for (var i = 1; i < chain.ChainElements.Count; i++)     {         if (chain.ChainElements[i].Certificate.Thumbprint != chain.ChainPolicy.ExtraStore[i - 1].Thumbprint)             return false;     }      return true; } 

I am unable to test this because I don't have a full CA chain with me, so it would be best to debug and step through the code.

like image 62
Jonathan Dickinson Avatar answered Oct 13 '22 04:10

Jonathan Dickinson