Verifying the X509 Remote Server Certificate Using a CA Certificate File

I created a CA and several certificates (signed by CA) using OpenSSL, and I have a client and .NET / C # server using SslStream , each of which has its own certificates / keys, mutual authentication is enabled and canceled is disabled.

I use RemoteCertificateValidationCallback for SslStream to verify the certificate of a remote server, and I was hoping I could just load the open CA certificate (as a file) into the program and use it to verify the remote certificate, and then actually install the CA in the Windows certificate store. The problem is that the X509Chain will not show anything unless I install CA in the repository or the Windows CryptoAPI shell when opening the PEM version of one of the certificates.

My question is, how can I verify that the certificate was signed by my particular CA, simply using the CA certificate file without using the Windows or WCF certificate store , when RemoteCertificateValidationCallback , X509Certificate and X509Chain do not seem to give me anything to work with?

+7
source share
2 answers

Since the CA certificate is NOT in the root certificate store, you must have the SslPolicyErrors.RemoteCertificateChainErrors error flag in RemoteCertificateValidationCallback (); the possibility is to explicitly check the certificate chain for your own X509Certificate2Collection, since you are not using the local store.

 if (sslPolicyErrors == SslPolicyErrors.RemoteCertificateChainErrors) { X509Chain chain0 = new X509Chain(); chain0.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; // add all your extra certificate chain chain0.ChainPolicy.ExtraStore.Add(new X509Certificate2(PublicResource.my_ca)); chain0.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority; isValid = chain0.Build((X509Certificate2)certificate); } 

You can also reuse the chain passed in the callback, add an additional certificate to the ExtraStore collection, and check the AllowUnknownCertificateAuthority checkbox, which is necessary because you are adding untrusted certificate (s) to the chain.

You can also prevent the original error by adding the CA certificate programmatically to the trusted root store (of course, it opens a pop-up window, since the main security problem is to globally add a new trusted CA root):

 var store = new X509Store(StoreName.Root, StoreLocation.CurrentUser); store.Open(OpenFlags.ReadWrite); X509Certificate2 ca_cert = new X509Certificate2(PublicResource.my_ca); store.Add(ca_cert); store.Close(); 
+5
source

How can I verify a certificate signed by my particular CA only with an open CA certificate file without using the Windows or WCF certificate store when RemoteCertificateValidationCallback, X509Certificate and X509Chain do not seem to give me anything to work with?

The following code avoids storing Windows certificates and checking the chain. It is slightly different from JB code, especially when using flags. The code below does not require AllowUnknownCertificateAuthority (but it uses X509RevocationMode.NoCheck since I do not have CRL).

The name of the function does not matter. Below, VerifyServerCertificate is the same callback as RemoteCertificateValidationCallback in the SslStream class. You can also use it for ServerCertificateValidationCallback in the ServicePointManager .

 static bool VerifyServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { try { String CA_FILE = "ca-cert.der"; X509Certificate2 ca = new X509Certificate2(CA_FILE); X509Chain chain2 = new X509Chain(); chain2.ChainPolicy.ExtraStore.Add(ca); // Check all properties chain2.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag; // This setup does not have revocation information chain2.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; // Build the chain chain2.Build(new X509Certificate2(certificate)); // Are there any failures from building the chain? if (chain2.ChainStatus.Length == 0) return true; // If there is a status, verify the status is NoError bool result = chain2.ChainStatus[0].Status == X509ChainStatusFlags.NoError; Debug.Assert(result == true); return result; } catch (Exception ex) { Console.WriteLine(ex); } return false; } 

I did not understand how to use this chain ( chain2 below) by default, so there is no need for a callback. That is, install it in the ssl socket, and the connection will "just work". And I did not understand how to set it in such a way that it goes in the callback. That is, I have to build a chain for each callback call. I think these are architectural flaws in .Net, but I could have missed something obvious.

+1
source

All Articles