1

My question relates to the following posts:

HttpClient does not send client certificate on Windows using .NET Core

WebApi HttpClient not sending client certificate

My env:

Mac osx ( 10.15.6 )

Visual studio code for Mac ( 8.3.2 )

Goal:

I want to use self-signed certificates ( as an experiment ), to test TLS with c# and a nginx server. I can use this curl command to confirm that the crt and key allow me to access a resource:

curl --cert client.crt --key client.key -k https://localhost:443

I read the p12 keystore using this code

public X509Certificate2 readCertificates(String path, String password)
    {
        return new X509Certificate2(File.ReadAllBytes(path), password);
    }

I use this code to make a Https request. The loaded certificate has a subject, identifier, and private key that I expect. This confirms the above step.

public async System.Threading.Tasks.Task validateRequest(X509Certificate2 certificate)
{
    try
    {
        WebRequestHandler handler = new WebRequestHandler();
        handler.ClientCertificates.Add(certificate);
        handler.SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls;
        ServicePointManager.ServerCertificateValidationCallback = (a, b, c, d) => { return true; };
        handler.ClientCertificateOptions = ClientCertificateOption.Manual;

        HttpClient client = new HttpClient(handler);
        HttpRequestMessage httpContent = new HttpRequestMessage(HttpMethod.Get, new Uri("https://localhost:443"));
        HttpResponseMessage response = await client.SendAsync(httpContent);
        string resultContent = response.Content.ReadAsStringAsync().Result;

        if (response.IsSuccessStatusCode)
        {
            Console.WriteLine("## we authenticated...");
        }
        else {
            Console.WriteLine("### we have an issue");
        }

        response.Dispose();
        client.Dispose();
        httpContent.Dispose();
    }
    catch (Exception e) {
        Console.WriteLine("##### error:: " + e);
    }

}

After executing this code, my ngix server states:

 client sent no required SSL certificate while reading client request header

The c# side evalutes $resultContent$ to:

 400 No required SSL certificate was sent

 

If I replace the below lines, I get a different error:

// take this line
ServicePointManager.ServerCertificateValidationCallback = (a, b, c, d) => { return true; };
// replace it with the below
handler.ServerCertificateValidationCallback = (a, b, c, d) => { return true; };

I can observe an error on the ngix server with:

peer closed connection in SSL handshake while SSL handshaking

I can observe this error on the c# side:

Mono.Security.Interface.TlsException: CertificateUnknown

In reading the aforementioned stack posts, I was under the impression that I could read and ignore self-signed certificates by modifying ServerCertificateValidationCallback. This experiment is leading me to believe otherwise. Am I missing a key step in using self-signed certificates in making a https request?

Wowo Ot
  • 1,362
  • 13
  • 21
angryip
  • 2,140
  • 5
  • 33
  • 67
  • 1
    The following line needs to be changed : handler.SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls; TLS 1.0/1.1 was discontinued in June and you must use only TLS 1.2. Remove the 1.0/1.1 options. Also make sure you have latest API/dlls from you vendors which support TLS 1.2 – jdweng Aug 15 '20 at 14:57
  • Tip: In addition to previous comment you may use more modern `SocketsHttpHandler` instead of `WebRequestHandler`. It has somewhat different setup but it's rather faster and recommended by Microsoft. Also `HttpClient` is intended to be instantiated once per application, rather than per use. – aepot Aug 15 '20 at 15:03
  • @jdweng I updated the code to only use 1.2. I also updated the Nginx config to only use 1.2 the result remains. && I am not following the last sentence. All the references needed to make an HTTP request are in the System.Net.* and System.Security.* namespaces. I have the latest version of Visual studio – angryip Aug 15 '20 at 15:03
  • The is not true. The operating system has to support the security mode so the version of core also has to support the TLS version. The certificates also have to be properly generated using an encryption mode that is supported by TLS 1.2 (https://en.wikipedia.org/wiki/Transport_Layer_Security). And the certificate need to be added to the certificate stores. – jdweng Aug 15 '20 at 15:08
  • In case you have some real domain name, you can obtain the certificates for free from `Let's Encrypt` and avoid self-signed vulneravility, be safe from MITM attacks. – aepot Aug 15 '20 at 15:11
  • @jdweng got it. are you asking if mac osx supports tls 1.2? && i understand the other comment wrt to certificate stores. i'll make sure they are 1.2 compliant. – angryip Aug 15 '20 at 15:22
  • yes. You may have an old version of osx that doesn't support TLS 1.2. – jdweng Aug 15 '20 at 19:06

0 Answers0