Downloading a SSL/TLS certificate in .NET
I recently needed to set up an alert when a certificate expires soon or when it uses an insecure signature algorithm. The first step is to get the certificate. In .NET you can use the SslStream
class to do the hard job. Then, you can set up a recurring task using Azure Pipelines or GitHub Actions to validate certificates every day, but this is not part of this post.
C#
static class CertificateDownloader
{
// Accept any certificate, even if the certificate is invalid
// We don't care about security here. The only goal is to get the certificate, not to transmit data.
private static readonly RemoteCertificateValidationCallback s_certificateCallback = (_, _, _, _) => true;
public static async Task<X509Certificate2?> GetCertificateAsync(string domain, int port = 443)
{
using var client = new TcpClient(domain, port);
using var sslStream = new SslStream(client.GetStream(), leaveInnerStreamOpen: true, s_certificateCallback);
// Initiate the connection, so it will download the server certificate
await sslStream.AuthenticateAsClientAsync(domain).ConfigureAwait(false);
// Duplicate the certificate because "serverCertificate" won't be accessible
// after disposing the stream, so not accessible outsite this method
var serverCertificate = sslStream.RemoteCertificate;
if (serverCertificate != null)
return new X509Certificate2(serverCertificate);
return null;
}
}
Here is how to use this class to get a certificate:
C#
static async Task Main()
{
var certificate = await CertificateDownloader.GetCertificateAsync("www.meziantou.net");
Console.WriteLine($"Subject: {certificate.Subject}");
Console.WriteLine($"Issuer: {certificate.Issuer}");
Console.WriteLine($"NotBefore: {certificate.NotBefore}");
Console.WriteLine($"NotAfter: {certificate.NotAfter}");
Console.WriteLine($"Algorithm: {certificate.SignatureAlgorithm.FriendlyName}");
}
Do you have a question or a suggestion about this post? Contact me!
Enjoy this blog?💖 Sponsor on GitHub