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;
}
}
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With