Setting up gRPC encryption in C# (2)

96 views
Skip to first unread message

Sam

unread,
Jun 6, 2019, 2:58:41 AM6/6/19
to grpc.io
Hi all, 

I am attempting to create a secure connection between a gRPC client and server with the C# wrapper. By secure I mean that I want the safety properties that would avoid any kind of MITM attack, but I don’t need the authentication part (which will be done by higher application levels), the encryption is enough for my requirements.

Reading gRPCs C# code comments, it seems that on the server side I can use “SslClientCertificateRequestType.RequestButDontVerify”, I considered “SslClientCertificateRequestType.DontRequest" but I get the impression that this would not encrypt communications, even if I provide a key pair on the client side.

As far as I can see the client side would use a self-signed certificat (meaning he generates the certificate and the key pair, the certificate will be signed with the keypair).

I can’t figure out the correct way to set this up. As far as I can see, after generating the key pair and the certif, it should be something like this:

Client side - generate key pair and certificate:
var keyCertPair = new KeyCertificatePair(File.ReadAllText("cert.pem"), File.ReadAllText("key.pem")); 
var channelCredentials = new SslCredentials(File.ReadAllText("cert.pem"), keyCertPair); 
var channel = new Channel(“127.0.0.1:5000", channelCredentials);

* Notice that I’m not sure what to use for the root certificate, so I reuse the same.

Server side - generate a different key pair and certificate:
var keyCertPair = new KeyCertificatePair(File.ReadAllText("cert.pem"), File.ReadAllText("key.pem")); 
ServerCredentials credentials = new SslServerCredentials(new List<KeyCertificatePair> {keyCertPair}, null, 
    SslClientCertificateRequestType.RequestButDontVerify);


This will log the following server side: No match found for server name: 127.0.0.1

I'm out of ideas at this point, a part from just trying stuff to make it work. I’m just trying to encrypt the communication, not verify the identity of the peer. I'm using openssl on mac to generate the key pairs and certificates.

Thanks a lot. 
Sam


PS: If an admin could clean up my failed attempt at editing my original post would be great:
https://groups.google.com/forum/#!topic/grpc-io/vtut-JjzGxQ

Joseph Vaughan

unread,
Jun 6, 2019, 3:17:07 AM6/6/19
to grpc.io
Hi Sam,

You're pretty close with what you have. The root certificate is the public certificate for the Certificate Authority (CA) that you used to sign the other certificates. There are some good blogs describing the process using other languages, but the principle is the same. Try this one: https://bbengfort.github.io/programmer/2017/03/03/secure-grpc.html

What you have setup is Mutual TLS, where the client and server both have a public key pair and both ends are verified by each other. You could also load only your CA Root cert on the client and that will correctly verify the server's certificate only, not the peer's. My server is in C#, but my clients are other languages, so I'm guessing that the API will be similar to this:

Server - SSL Setup, pass the credentials to the Channel constructor.

var caCert = File.ReadAllText("Certs/MyProject_Root_CA.crt");
var serverCert = File.ReadAllText("Certs/myproject-server.crt");
var serverKey = File.ReadAllText("Certs/myproject-server.key");
var keypair = new KeyCertificatePair(serverCert, serverKey);
var sslCredentials = new SslServerCredentials(new List<KeyCertificatePair> {keypair}, caCert, SslClientCertificateRequestType.RequestButDontVerify);

Client - No mutual TLS

var caCert = File.ReadAllText("MyProject_Root_CA.crt");
var sslCredentials = new SslCredentials(caCert);
var channel = new Channel("127.0.0.1", 6222, sslCredentials);

One final note is that the "subject" must match the hostname, I am probably not explaining it correctly, but you may encounter an error such as "No match found for server name: 127.0.0.1.". If so, you can override the server name. Java clients have a simpler API, I believe the C# way would be something like this:

var channelOptions = new[] {new ChannelOption(ChannelOptions.SslTargetNameOverride, "myproject-server")};
var channel = new Channel("127.0.0.1", 6222, sslCredentials, channelOptions);



In production this may be a bad idea, but I'm not too sure having read some comments here https://github.com/grpc/grpc/issues/16759.

Hope this helps,
Joe.

Sam

unread,
Jun 6, 2019, 3:26:05 AM6/6/19
to grpc.io
Hi,

Great answer, thanks for the links. 

One question though, is the MyProject_Root_CA.crt the same file for both client and server ? Eventually I will want this on different machines and don't want to share any files between server and client if possible.

Joseph Vaughan

unread,
Jun 6, 2019, 4:04:29 AM6/6/19
to grpc.io
Yes it is. If you use a public certificate authority such as LetsEncrypt or DigiCert, etc, then these are already distributed for you by the OS maintainers, otherwise you need to distribute them yourself through some means.

Sam

unread,
Jun 7, 2019, 2:44:52 AM6/7/19
to grpc.io
So is there a way of bypassing the use of the CA in gRPC ? I know it seems weird I want to do this, but I don't need the authentification part (the whole point of using the CA right ?) I just need the connection to be encrypted.

umi...@gmail.com

unread,
Jun 10, 2019, 9:55:19 AM6/10/19
to grpc.io
+1 for this last question. Is there a way of bypassing the use of the CA in gRPC? Basically, if we have self-signed certificate, and we want to use mTLS, can we use that same self-signed certificate as root_CA.crt?

Jan Tattermusch

unread,
Jun 11, 2019, 2:30:20 AM6/11/19
to grpc.io
The original question says that you want to protect against MITM attack and there's no way of doing that without making sure that you are talking to the right backend (and that's why the server's cert needs to be signed by the CA , so the client can tell it's not talking to a fake server).

AFAIK while in theory the CA cert can be the same as the server cert, in practice the CA certificate cannot be identical as the the server certificate itself, because OpenSSL forbids that (the subject of the CA cert must not be equal to the server certificate subject, which is impossible to satisfy when they are the same file) and this is probably for a good reason.

Btw, feel free to refer some of the examples here:

On Friday, June 7, 2019 at 8:44:52 AM UTC+2, Sam wrote:

Sam

unread,
Jun 12, 2019, 8:49:29 AM6/12/19
to grpc.io
Thanks for the answer, it clarified a bit for me.

In your opinion is there another way I can encrypt my connection with gRPC ? 


Reply all
Reply to author
Forward
0 new messages