2

Adding client certificates to a typed HttpClient in .net 3.1 linux docker container works, but fails on upgrading to .net 5. I see that there is a breaking change in .net 5 to use TLS 1.3 and restricted Ciphersuites, how can I override that in .net 5 with a typed HttpClient ?
How can I use the SocketsHttpHandler.SslOptions with a typed HttpClient to specify a wider set of Ciphersuites. The site am try to send a payment request supports only tls 1.2 and its ssllabs report is this https://www.ssllabs.com/ssltest/analyze.html?d=mss.cpc.getswish.net

This is a sample of my code

 services.AddHttpClient<ISwishpayService, SwishpayService>() .ConfigurePrimaryHttpMessageHandler<SwishpayHandler>(); 
public class SwishpayHandler: HttpClientHandler { private readonly IConfiguration _config; private readonly ILogger<SwishpayHandler> _logger; public SwishpayHandler(IConfiguration config, ILogger<SwishpayHandler> logger) { _config = config; _logger = logger; SslProtocols = System.Security.Authentication.SslProtocols.Tls12 | System.Security.Authentication.SslProtocols.Tls13; ClientCertificateOptions = ClientCertificateOption.Manual; } protected override async Task<HttpResponseMessage> SendAsync( HttpRequestMessage request, CancellationToken cancellationToken) { if (ClientCertificates == null || ClientCertificates.Count == 0) { _logger.LogInformation("Invoked SwishpayHandler"); using (X509Store store = new X509Store(StoreName.CertificateAuthority, StoreLocation.CurrentUser, OpenFlags.ReadWrite)) { var certs = new X509Certificate2Collection(); certs.Import(Path.Combine("Certificates", _config.GetValue<string>("SwishApi:key:certificatefile")), GetCertificatePassword(), X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet); foreach (X509Certificate2 cert in certs) { if (cert.HasPrivateKey) { ClientCertificates.Add(cert); } else { store.Add(cert); } } store.Close(); } } return await base.SendAsync(request, cancellationToken).ConfigureAwait(false); } private string GetCertificatePassword() { var cert_password = File.ReadAllText(_config.GetValue<string>("SWISHPAY_CERT_PWD").Trim()).Replace(Environment.NewLine, ""); return cert_password; } } 

UPDATE

Exception in .net 5

System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception. ---> System.Security.Authentication.AuthenticationException: Authentication failed, see inner exception. ---> Interop+OpenSsl+SslException: SSL Handshake failed with OpenSSL error - SSL_ERROR_SSL. ---> Interop+Crypto+OpenSslCryptographicException: error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure 
3
  • The SslLabs report for the supported ciphersuites of that endpoint is the same list as the default ciphersuites for .NET 5 on Linux, so there should be a match. Something else must be going on, you'll probably have to get a network trace to see where the failure happened. Commented Feb 25, 2021 at 16:57
  • @bartonjs analyzing further noticed that the SSL handshake works on application startup but if left inactive for 2 minutes when a new instance of HttpClientHandler is created by the Factory method the SSL handshake fails. Is it possible that the certificates dont get added on the instances created by the HttpClientFactory? This behavior does not occur in 3.1 Commented Feb 25, 2021 at 19:40
  • Hi @KiruthigaMuthuswamy, Did you ever resolve this issue? I'm experiencing the exact same problem... Commented Aug 10, 2021 at 15:24

2 Answers 2

1

There are several issues with your code which isn't related to .NET 5.

Issue #1:

X509Store store = new X509Store(StoreName.CertificateAuthority, StoreLocation.CurrentUser, OpenFlags.ReadWrite) 

why you search for client certificates in StoreName.CertificateAuthority? It is incorrect, store name MUST be StoreName.My.

Issue #2:

certs.Import(Path.Combine("Certificates", _config.GetValue<string>("SwishApi:key:certificatefile")), GetCertificatePassword(), X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet); 

Sotre is opened in CurrentUser context, but you specify X509KeyStorageFlags.MachineKeySet for some unknown reason. Why? It MUST be X509KeyStorageFlags.UserKeySet.

Sign up to request clarification or add additional context in comments.

4 Comments

The issue occurs even if I don't use X509Store for getting the entire chain , CertificateAuthority was to create a temporary cache for the entire chain. I tried with StoreName.My that also does not work. Using X509KeyStorageFlags.DefaultKeySet did not help get , so tried using the MachineKeySet OR PersistKeySet. The X509 is based on another post stackoverflow.com/questions/61677247/…
Tested with StoreName.My and X509KeyStorageFlags.UserKeySet, but getting the same issue
Once you fix these issues in your code, you can debug it further. You didn't tell what exactly fails, no exception/stacktrace details.
Updated my original post with the exception that occurs in .net 5
1

Try the following,

 using (X509Store store = new X509Store(StoreName.CertificateAuthority, StoreLocation.CurrentUser, OpenFlags.ReadWrite)) { var certs = new X509Certificate2Collection(); certs.Import(settings.Value.ClientCertPath, settings.Value.ClientCertSecret, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet); foreach (X509Certificate2 cert in certs) { if (cert.HasPrivateKey) { ClientCertificates.Add(cert); logger.LogInformation("CertTest: " + cert.Thumbprint); } else { store.Add(cert); logger.LogInformation("CertTest store: " + cert.Thumbprint); } } store.Close(); } 

1 Comment

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.