Issue
I am writing C# code that deals with certificates. I have a certificate chain which terminates in a self-signed root. On Windows, my code works fine, but on Linux it fails. I get an X509ChainStatus object containing status X509ChainStatusFlags.PartialChain and the status information unable to get local issuer certificate.
My code looks like this:
X509Certificate2Collection collection = GetCertificateCollectionFromResource(X509KeyStorageFlags.EphemeralKeySet);
var leaf = collection[0];
var parents = new[] { collection[1], collection[2] };
var chain = CreateChain(parents);
var valid = chain.Build(leaf);
if (!valid)
throw new Exception("Chain.Build returned false");
// We expect the root to be untrusted. It is a self-signed certificate. So the UntrustedRoot flag is harmless.
var illegalFlags = chain.ChainStatus.Where(f => f.Status != X509ChainStatusFlags.UntrustedRoot).ToList();
if (illegalFlags.Any())
{
var firstIllegalFlag = illegalFlags.First();
throw new Exception($"Illegal status flag found: {firstIllegalFlag.Status} ({firstIllegalFlag.StatusInformation})");
}
else
{
Console.WriteLine("Certificate collection is valid!");
}
I have a full working example here (containing just the public parts of all the certificates): https://github.com/CAP-3Shape/CertificateValidatorSample
When I run the sample on Windows using dotnet run
, it works. When I run it on Linux I get this:
Unhandled exception. System.Exception: Illegal status flag found: PartialChain (unable to get local issuer certificate) at ClausAppel.CertificateValidatorSample.Program.InstanceMain() in /home/devops/actions-runner/work/Raven.KeyManagementService/Raven.KeyManagementService/CertificateValidatorSample/Program.cs:line 30 at ClausAppel.CertificateValidatorSample.Program.Main(String[] args) in /home/devops/actions-runner/work/Raven.KeyManagementService/Raven.KeyManagementService/CertificateValidatorSample/Program.cs:line 13
Does anyone know what to do about this? Might I need to install some software or make other changes to my Linux machine?
I could allow this particular status flag, but I very much don't want to do that. That would introduce a lot of false negatives (i.e., chains that are not valid but which would look valid if we allow this status flag).
I have tried to add the parent certificates using X509Store, but that didn't seem to help.
EDIT: The problem does not happen on every Linux machine. I have seen it happen on some Linux machines running Ubuntu 20.04 (Focal Fossa) and Ubuntu 22.04 (Jammy Jellyfish). But I have also seen it pass on some machines running Ubuntu 20.04 (Focal Fossa). So it apparently depends on the settings and software installed on the Linux runner.
Solution
I found a workaround: My leaf certificate contained X509KeyUsageFlags.None. Apparently some newer cryptography libraries consider this an error. When we changed our certificates to use another flag, they started working on all Linux versions.
I was able to reproduce the error on the following Linux Docker images:
mcr.microsoft.com/dotnet/aspnet:6.0-alpine
mcr.microsoft.com/dotnet/aspnet:6.0-jammy
This Linux Docker image would accept the certificate even with X509KeyUsageFlags.None:
mcr.microsoft.com/dotnet/aspnet:6.0-focal
See also:
- https://www.reddit.com/r/dotnet/comments/17ppihk/c_cryptography_certificate_chain_is_ok_on_windows/
- https://ubuntuforums.org/showthread.php?t=2492375
Answered By - Claus Appel Answer Checked By - Candace Johnson (WPSolving Volunteer)