Reputation: 21
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
Upvotes: 2
Views: 1467
Reputation: 11
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();
}
Upvotes: 1
Reputation: 13974
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
.
Upvotes: 1