Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I determine if a connection to a webserver is using Perfect Forward Secrecy?

Tags:

c#

https

ssl

I have a C# program that connects to a webserver and displays the expiration date of the SSL certificate.

What I would like to know is how to determine if the connection is using Perfect Forward Secrecy [PFS]?

using System;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            ServicePointManager.ServerCertificateValidationCallback += ServerCertificateValidationCallback;
            ServicePointManager.CheckCertificateRevocationList = true;

            var request = WebRequest.Create("https://www.microsoft.com/");

            var response = request.GetResponse();

            Console.WriteLine("Done.");
            Console.ReadLine();
        }
        private static bool ServerCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            Console.WriteLine("Certificate expires on " + certificate.GetExpirationDateString());

            return true;
        }
    }
}
like image 447
JonnyBoats Avatar asked Jan 02 '15 11:01

JonnyBoats


1 Answers

Preface: I'm not a cryptographer.

Per this Information Security answer, you want to look at the agreed upon cipher suite, namely the key exchange piece of the suite. According to that, anything based on Diffie-Hellman provides perfect forward secrecy. As erickson points out in the comments, this could be untrue and you'll want to understand the security complications of assuming Perfect Forward Secrecy is present when it really is not.

With that, you're looking for SslStream. That will allow you to gain access to the key exchange properties that you need.

It is not as easy as using a WebRequest or even a HttpRequest. You're going to have to write out the connection yourself. An example looks like:

string host = "www.microsoft.com";

using (var client = new TcpClient(host, 443))
using (var stream = client.GetStream())
using (var sslStream = new SslStream(stream))
{
    sslStream.AuthenticateAsClient(host);

    // figure out if sslStream.KeyExchangeAlgorithm support PFS here
}

In theory, KeyExchangeAlgorithm is a enumeration. And you could do if(sslStream.KeyExchangeAlgorithm == ExchangeAlgorithmType.DiffieHellman) and you'll know the answer[1]. But according to this Microsoft Forum post, ExchangeAlgorithmType may be 44550 which is equivalent to Elliptic curve Diffie-Hellman. Elliptic curve Diffie-Hellman does support Perfect Forward Secrecy.

If you want to modify your current code to make all of this happen in one connection, the remote certificate is available at sslStream.RemoteCertificate so you can get the certificate expiration date.

[1] It is possible that not all Diffie-Hellman exchanges support Perfect Forward Secrecy. Again, consider the security complications of this.

like image 152
Steven V Avatar answered Oct 21 '22 13:10

Steven V