Mutual SSL using: Mono,C#, and Self-Signed Certificates


April 2019


9 time


Here is the project: I'm creating a TcpListener in C#, that will host on a Linux box using Mono.

Then I will have a TcpClient (also Mono on Linux) that will connect to it, and because I can't have a username/password auth, I would like it that clients connect with a "client certificate", that I will generate with my Root CA (also self-generated)

I can't only have the client connect securely to the server, I need my TcpListener to trust my client connection too.

What i have done so far: I have exported my server certificate as PFX:

And loaded this into the code:

sslCertificate = new X509Certificate2("myCert.pfx", "password");

Now, if I run the code as below:

bool requireClientCertificate = false; // <== turn on/off
SslStream sslStream = new SslStream(netStream, false, new RemoteCertificateValidationCallback(AcceptRemoteCertificate));
sslStream.AuthenticateAsServer(sslCertificate, requireClientCertificate, SslProtocols.Tls, false);

With requireClientCertificate = false, then I can use a browser to view this page perfectly fine. Of course, I would have already imported my Root CA, in order to see this page, otherwise Chrome gives me a certificate warning.

Right, so there is no problem with this so far... and SSL is established, but technically anyone could connect to this TcpListner.

Now I set requireClientCertificate = true, and this is where things fall apart.

I realize I need to generate a client certificate, so I did that, exported that, and imported it into my PC. I can see it under the certificate list in Chrome, and I am prompted to use it when I first attempt to connect the TcpListner.

However, doing all that, still does not solve things.

I have also installed the Root CA onto the server using:

  1. copy to /usr/share/ca-certificates/mozilla/MyRootCA.crt
  2. editing /etc/ca-certificates.conf
  3. update-ca-certificates (This showed 1 new certificate installed.. but still did'nt help)

Then I tried: certmgr -add -c -v -m Trust /home/Certs/MyRootCA.crt Still not working, so i tried: certmgr -add -c -v -m CA /home/Certs/MyRootCA.crt

So from what I can see the RootCA is installed.

If I try connect with Chrome I'm getting: RemoteCertificateChainErrors in the RemoteCertificateValidationCallback

And if I loop thought the chain, I get : PartialChain in the Status Information.

And if I test with OpenSSL, I get: RemoteCertificateChainErrors with: UntrustedRoot in the Status Information

The totally confusing part on this, is that, my RemoteCertificate of the TcpListner is not null - it is in fact a the certificate that I installed on the browser, and can see the RootCA that singed it too (Issuer).

If I actually do a: wget --certificate=/my.crt --private-key=/my.key --ca-certificate=/MyRootCA.crt, it connects and downloaded my expedited results.

So, questions:

  1. Is this connection actually mutually secure?
  2. What are those errors about? UntrustedRoot and PartialChain
  3. If it has these errors, but still can present a RemoteCertificate, does that mean its a mutually secure connection or not?

In the past I have done this on Windows Server with a commercial CA certificates (DigiCert E.V.), and other (out of my control) CPE's, and they worked without errors. This is the only difference I have noticed. Is this the reason? Does Linux / Mono, have some sort of additional knowledge about certificates, that if you generate your own Root CA... it can't trust it completely?

0 answers