I ran into the same issue when working with self-signed certificates and client certificate authentication in .NET Core 2.2 and Docker Linux containers. Everything worked fine on my Windows computer, but in Docker I got this error:
System.Security.Authentication.AuthenticationException: remote certificate is not valid according to the verification procedure
Fortunately, the certificate was created using a chain. Of course, you can always ignore this decision and use the above solutions.
So here is my solution:
I saved the certificate using Chrome on my computer in P7B format.
Convert the certificate to PEM format with this command:
openssl pkcs7 -inform DER -outform PEM -in <cert>.p7b -print_certs > ca_bundle.crt
Open ca_bundle.crt and delete all Subject entries, leaving a clean file. Example below:
-----BEGIN CERTIFICATE----- _BASE64 DATA_ -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- _BASE64 DATA_ -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- _BASE64 DATA_ -----END CERTIFICATE-----
- Put these lines in the Dockerfile (in the last steps):
# Update system and install curl and ca-certificates RUN apt-get update && apt-get install -y curl && apt-get install -y ca-certificates
- In the application:
var address = new EndpointAddress("https://serviceUrl"); var binding = new BasicHttpsBinding { CloseTimeout = new TimeSpan(0, 1, 0), OpenTimeout = new TimeSpan(0, 1, 0), ReceiveTimeout = new TimeSpan(0, 1, 0), SendTimeout = new TimeSpan(0, 1, 0), MaxBufferPoolSize = 524288, MaxBufferSize = 65536, MaxReceivedMessageSize = 65536, TextEncoding = Encoding.UTF8, TransferMode = TransferMode.Buffered, UseDefaultWebProxy = true, AllowCookies = false, BypassProxyOnLocal = false, ReaderQuotas = XmlDictionaryReaderQuotas.Max, Security = { Mode = BasicHttpsSecurityMode.Transport, Transport = new HttpTransportSecurity { ClientCredentialType = HttpClientCredentialType.Certificate, ProxyCredentialType = HttpProxyCredentialType.None } } }; var client = new MyWSClient(binding, address); client.ClientCredentials.ClientCertificate.Certificate = GetClientCertificate("clientCert.pfx", "passwordForClientCert");
GetClientCertificate Method:
private static X509Certificate2 GetClientCertificate(string clientCertName, string password) { //Create X509Certificate2 object from .pfx file byte[] rawData = null; using (var f = new FileStream(Path.Combine(AppContext.BaseDirectory, clientCertName), FileMode.Open, FileAccess.Read)) { var size = (int)f.Length; var rawData = new byte[size]; f.Read(rawData, 0, size); f.Close(); } return new X509Certificate2(rawData, password); }