Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SslStream and Authentication

I was reading MSDN info articles for quite a long time and still I fail to understand it.

Based on the assumption that client Authentication is not required:

1.When I call SslStream.AuthenticateAsServer(...) do I call this method on the server side or on the client side?

2.When establishing a SslStream is it only the responsibility of the server to establish the SslStream or both server and client?

3.If it is only the responsibility of the server, does it mean that the client can just use regular send() and receive() operations without creating a SslStream by himself?

4.Does the client need to get the certificate file in order to authenticate the server?

Thank you very much in advance, I really could not find much information about this topic and I've been searching for this information for a long time...

like image 583
WeinForce Avatar asked Jan 25 '17 22:01

WeinForce


People also ask

What is SslStream?

Provides a stream used for client-server communication that uses the Secure Socket Layer (SSL) security protocol to authenticate the server and optionally the client.

Is client authentication required for sslstream?

I must preface this answer that "client authentication not required" is the case for most of the SSL implementations. Client authentication is rare: you're likely to see it in VPN apps, the banking industry and other secure apps. So it would be wise when you are experimenting with SslStream () to start without client authentication.

How does sslstream work with SSL?

When the authentication process, also known as the SSL handshake, succeeds, the identity of the server (and optionally, the client) is established and the SslStream can be used by the client and server to exchange messages.

What should I do with the sslstream object after authentication?

You should close this object and remove all references to it so that it can be collected by the garbage collector. When the authentication process, also known as the SSL handshake, succeeds, the identity of the server (and optionally, the client) is established and the SslStream can be used by the client and server to exchange messages.

How do I check the security services provided by the sslstream?

You can check the security services provided by the SslStream using the IsEncrypted and IsSigned properties. The following table shows the elements that report the cryptographic settings used for authentication, encryption and data signing. The security protocol used to authenticate the server and, optionally, the client.


1 Answers

EDIT: the MSDN has a complete working example at the bottom of this page: https://msdn.microsoft.com/en-us/library/system.net.security.sslstream?f=255&MSPPError=-2147217396 - so you should really start experimenting there because that example has it all.

Original answer:

I must preface this answer that "client authentication not required" is the case for most of the SSL implementations. Client authentication is rare: you're likely to see it in VPN apps, the banking industry and other secure apps. So it would be wise when you are experimenting with SslStream() to start without client authentication.

When you browse to an HTTPS website, you don't authenticate your browser with a client cert, instead you just want to confirm the server name you are connecting to matches up to the CNAME found in the cert and that the server cert is signed by a CA that your machine trusts - there's more to it, but essentially that's what it boils down to.

So, having said that, let me answer your questions:

1) SslStream.AuthenticateAsServer(...) is done ONLY on server side with the server 509 certificate. On the client side, you must call SslStream.AuthenticateAsClient(serverName) with server name being the CNAME (common name) of your certificate (example: "domain.com")

2) SslStream must be created for both the client and the server. You create it simply by "wrapping" a TcpClient NetworkStream around it (for example, but there are other methods)

Example for the server:

// assuming an 509 certificate has been loaded before in an init method of some sort
X509Certificate serverCertificate = X509Certificate2.CreateFromCertFile("c:\\mycert.cer"); // for illustration only, don't do it like this in production
...

// assuming a TcpClient tcpClient was accepted somewhere above this code
slStream sslStream = new SslStream(tcpClient.GetStream(), false);
sslStream.AuthenticateAsServer(
                serverCertificate,
                false, 
                SslProtocols.Tls, 
                true);

3) No. The communication is encrypted on both ends. So both sides must use SslStream. Using receive() and send() on the client would yield binary encrypted data.

4) No. The client passes a callback method to the SslStream creation in order to validate the certificate received by the server.

Example:

// assuming a TcpClient tcpClient was connected to the server somewhere above this code
SslStream sslStream = new SslStream(
            tcpClient.GetStream(),
            false,
            new RemoteCertificateValidationCallback(ValidateServerCertificate),
            null
            ); 
sslStream.AuthenticateAsClient(serverName); // serverName: "domain.com" for example

then somewhere else in your code:

public static bool ValidateServerCertificate(
          object sender,
          X509Certificate certificate,
          X509Chain chain,
          SslPolicyErrors sslPolicyErrors)
    {
        if (sslPolicyErrors == SslPolicyErrors.None) {
            return true;
        }

        Console.WriteLine("Certificate error: {0}", sslPolicyErrors);

        // refuse connection
        return false;
    }
like image 76
Max Avatar answered Oct 14 '22 20:10

Max