We're trying to connect to an endpoint that does nothing more than verify whether a certificate has been correctly attached.
Our code is straightforward:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
using (var handler = new HttpClientHandler())
{
var rawcert = File.ReadAllText(@"C:\OpenSSL\bin\cert.pem");
var rawkey = File.ReadAllText(@"C:\OpenSSL\bin\private.key");
var provider = new CertificateFromFileProvider(rawcert, rawkey);
var certificate = provider.Certificate;
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
handler.ClientCertificates.Add(certificate);
handler.ServerCertificateCustomValidationCallback +=
(HttpRequestMessage req, X509Certificate2 cert2, X509Chain chain, SslPolicyErrors err) =>
{
Trace.WriteLine($"Sender: {req}");
Trace.WriteLine($"cert: {cert2}");
Trace.WriteLine($"chain: {chain}");
Trace.WriteLine($"sslPolicyErrors: {err}");
return true;
};
using (var client = new HttpClient(handler))
{
var response = await client.GetStringAsync("https://{uri}/mtlsTest");
return response;
}
}
(This is a sandbox environment for a proof of concept, so we're comfortable shortcutting the ValidationCallback for now.)
We can see the certificate is attached appears well-formed in the callback (origin and subject are as-expected), but we're getting a response from the server that indicates no certificate was attached. Why might that be?
We have also tried exporting the certificate as a pfx
and attaching that instead of the original pem
file, with an identical result.
Update
Thanks to useful comments below from @bartonjs and @Crypt32, we've tried adding the private key (using the handy Nuget Package from @stef-heyenrath), but although this results in the certificate that we add to the handler showing HasPrivateKey=true
:
... when the ValidationCallback fires, the X509Certificate2
traces HasPrivateKey=false
:
... and we get the same error as before - the server never acknowledges receiving the certificate.
If we package the .pem
and the private key into a .pfx
using open ssl:
pkcs12 -inkey private.key -in cert.pem -export -out cert.pfx
... then we get the same result again, and the server can find no certificate. Likewise if we install the certificate in the personal store and load it from there (same result). An inspection with Wireshark suggests the certificate is simply never being attached.
Why would this be? Full revised code above.
The initial problem here was a badly-formed certificate provided by our test host.
A further problem (once we had a good certificate to work with) was with the output of the CertificateFromFileProvider
method of the OpenSSL.X509Certificate2Provider
NuGet package.
For whatever reason, the certificate created would not work correctly. Taking the same input files and generating a .pfx
with OpenSSL resulted in an X509Certificate2
that worked fine.