Resolving the "Server Certificate Verification Failed" Error
When establishing a TLS/SSL connection, the server presents its certificate, and the component verifies it before continuing. If the verification fails and the certificate is not accepted, the connection is closed with error 280, "Server certificate verification failed. Connection aborted."
Common Causes
The most common reasons a server certificate fails verification are:
- The certificate is self-signed, or is issued by a private certificate authority (CA) that is not trusted by the client system.
- The server does not send the intermediate CA certificates, so the chain to a trusted root cannot be built.
- The host name used to connect does not match the names in the certificate (e.g., when connecting by IP address, or by a name that is not listed in the certificate).
- The certificate has expired or is not yet valid.
- The certificate has been revoked (when revocation checking is enabled with the SSLCheckCRL or SSLCheckOCSP configuration settings).
Finding the Cause
The SSLServerAuthentication event fires with information about the server certificate during the handshake. When the certificate fails verification, the Accept parameter is false, and the Status parameter describes why.
http.OnSSLServerAuthentication += (s, e) =>
{
Console.WriteLine("Subject: " + e.CertSubject);
Console.WriteLine("Issuer: " + e.CertIssuer);
Console.WriteLine("Status: " + e.Status);
};
The SSLStatus event also reports the verification result, which is useful when logging the full handshake.
Resolving the Error
The options below are listed from most to least preferred.
Fix the Server Certificate
When the server is under the organization's control, the best solution is to install a certificate issued by a trusted CA that matches the host name used to connect, and to configure the server to send the full certificate chain (including intermediate certificates). This resolves the error for all clients, not only those using the component.
Trust the Issuing CA
When the certificate is issued by a private CA (e.g., an internal enterprise CA), install the CA's certificate in the trusted root store of the client system. The component uses the certificates trusted by the system when verifying the server certificate.
If the CA certificate cannot be installed on the system, it can be provided to the component using the SSLServerCACerts configuration setting instead. The value is one or more PEM-encoded certificates, separated by CR/LF.
string caCert = File.ReadAllText("C:\certs\internal-ca.pem");
http.Config("SSLServerCACerts=" + caCert);
Accept a Specific Certificate
When the certificate cannot be changed or trusted (e.g., a self-signed certificate on a test server or a device), the component can be told to accept that specific certificate.
To do this, set the SSLAcceptServerCert property to the server's certificate. If the certificate presented by the server matches it, the certificate is accepted even if it fails verification.
// The server certificate in PEM or DER format, saved to a file.
http.SSLAcceptServerCert = new Certificate("C:\certs\server.cer");
http.Get("https://test.example.com/");
Alternatively, handle the SSLServerAuthentication event, and set the Accept parameter to true only if the certificate is the one that is expected. The thumbprint of the expected certificate can be found by logging the ThumbprintSHA256 property in this event once.
const string expectedThumbprint = "..."; // The SHA-256 thumbprint of the server certificate.
http.OnSSLServerAuthentication += (s, e) =>
{
if (e.Accept) return; // The certificate is trusted.
Certificate cert = new Certificate(e.CertEncodedB);
if (string.Equals(cert.ThumbprintSHA256, expectedThumbprint, StringComparison.OrdinalIgnoreCase))
{
e.Accept = true;
}
};
Warning: Accepting a certificate that fails verification removes the protection that verification provides. The connection is still encrypted, but the identity of the server is no longer confirmed by a trusted CA. Never set Accept to true for every certificate, since this allows any server (including an attacker intercepting the connection) to be accepted.
We appreciate your feedback. If you have any questions, comments, or suggestions about this article please contact our support team at support@nsoftware.com.