X509Certificate2.Verify () method always returns false for a valid certificate

I use a smart card for authentication.

The SecurityTokenService (authentication service) is hosted only on my machine. The smart card has a valid certificate, and its root certificate is also installed in the local computer store on my machine.

When I use the X509Certificate2.Verify method to verify the certificate in my service, it always returns false .

Can someone help me understand why the X509Certificate2.Verify () method always returns false?

Note: I used X509Chain and checked all flags ( X509VerificationFlags.AllFlags ). When I create a chanin, it returns true with ChainStatus as RevocationStatusUnknown .


EDIT 1:

I noticed that the X509Certificate2.Verify() method returns true if I write this code in a Windows form application. It returns false only in utility code. Why is that? Strange, but true!

+4
c # x509certificate2
source share
2 answers

X509VerificationFlags are suppressions, so specifying X509VerificationFlags.AllFlags actually prevents Build from returning false in most situations.

The answer of RevocationStatusUnknown seems especially relevant. What certificate does it report that for it cannot be confirmed that it is not revoked. Verify method can be modeled as

 public bool Verify() { using (X509Chain chain = new X509Chain()) { // The defaults, but expressing it here for clarity chain.ChainPolicy.RevocationMode = X509RevocationMode.Online; chain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot; chain.ChainPolicy.VerificationTime = DateTime.Now; chain.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag; return chain.Build(this); } } 

That, because it does not approve X509VerificationFlags.IgnoreCertificateAuthorityRevocationUnknown or X509VerificationFlags.IgnoreEndRevocationUnknown , when it requests an X509RevocationMode other than None , fails.

First you must determine which certificates are missing in the chain (/ are):

 using (X509Chain chain = new X509Chain()) { // The defaults, but expressing it here for clarity chain.ChainPolicy.RevocationMode = X509RevocationMode.Online; chain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot; chain.ChainPolicy.VerificationTime = DateTime.Now; chain.Build(cert); for (int i = 0; i < chain.ChainElements.Count; i++) { X509ChainElement element = chain.ChainElements[i]; if (element.ChainElementStatus.Length != 0) { Console.WriteLine($"Error at depth {i}: {element.Certificate.Subject}"); foreach (var status in element.ChainElementStatus) { Console.WriteLine($" {status.Status}: {status.StatusInformation}}}"); } } } } 

If you look at any invalid certificate in Windows CertUI (double-click the .cer icon in Explorer or in the MMC Certificates snap-in), find the "CRL Distribution Points" field. These are the URLs that will be received at runtime. Your system may have a data output restriction that prevents you from requesting these specific values. You can always try publishing a web request from your web service to see if it can retrieve URLs without the context of being present in the certificate subsystem.

+1
source share

I think the problem is with the proxy server and some security settings in my organization. I cannot give the correct reason why it works with the WinForm client and why not from the code hosted in IIS.

But the fact that I want to tell readers is that the Verify() method also worked on the server side when I hosted the service on IIS running on a machine outside my regular domain! This way you can check if your domain / organization's firewall settings are appropriate.

0
source share

All Articles