X509Certificate2.Verify() method always return false for the valid certificate
c#, x509certificate2
Solution
The X509VerificationFlags values are suppressions, so specifying `X509VerificationFlags.AllFlags` actually prevents Build from returning false in most situations.
The `RevocationStatusUnknown` response seems particularly relevant. Whichever certificate it is reporting that for cannot be verified to be not revoked. The `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);
}
}
Which, since it is not asserting `X509VerificationFlags.IgnoreCertificateAuthorityRevocationUnknown` or `X509VerificationFlags.IgnoreEndRevocationUnknown` while requesting an X509RevocationMode other than `None`, fails.
First, you should identify which certificate(s) in the chain is(/are) failing:
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 failing certificate in the Windows CertUI (double-click the .cer in Explorer or in the Certificates MMC Snap-In), look for a field named "CRL Distribution Points". These are the URLs that will be retrieved during runtime. Perhaps your system has a data egress restriction that doesn't allow those particular values to be queried for. You can always try issuing a web request from your web service to see if it can fetch the URLs without the context of being in the certificate subsystem.
Problem
I am using smart card for authentication. The SecurityTokenService (authentication service) is hosted on my machine only. The smart card has a valid certificate and it's root certificate is also installed in Local Computer store on my machine. When I use `X509Certificate2.Verify` method to validate the certificate in my service, it always return `false`. Can someone help me to understand why X509Certificate2.Verify() method always return false? Note: I used `X509Chain` and checked for all the flags (`X509VerificationFlags.AllFlags`). When I build the chanin, it returns `true` with `ChainStatus` as `RevocationStatusUnknown`. EDIT 1: I observed that `X509Certificate2.Verify()` method returns `true` if i write this code in windows form application. It returns `false` only in the service side code. Why so? Strange but true!