I'm trying to set up a TCP stream (non-HTTP) on a server that will be exposed to the public internet, but only "chosen" clients should be able to connect to. As I understand it, this is generally handled by certificate pinning, but I'm not familiar with all the details of how this is done.
- Generate a SSL cert for the server. That's easy enough.
- Set up the server. Have it call something like the following when a client connects:
private SslStream GetSslStream(TcpClient client, string certificateFile)
{
var c = X509Certificate.CreateFromCertFile(certificateFile);
var cert = new X509Certificate2(c);
if (!cert.Verify()) {
throw new Exception("Certificate failed verification");
}
var stream = new SslStream(client.GetStream(), false, VerifyClientCert);
stream.AuthenticateAsServer(cert, true, true);
return stream;
}
- Where does the client certificate come from? Is it a copy of the server's SSL certificate? Is it a separate cert that has to be derived from the server's cert in some way? Is it a completely different cert?
- What goes in the
VerifyClientCertmethod to make sure it's the right certificate? JustVerify()and check theThumbprintagainst an expected value, or is there more that needs to happen? - Should every client get a copy of the same client cert?