Validate Certificate Revocation List(CRL) with HttpClient in c# .NET

So, you need to make sure the sites you talk to haven’t had their certificates revoked. Well, by default .NET doesn’t do this. Mainly because I think it is rare and it can be slow. Yes yes, caching, blah blah, but the first time and every cache refresh its slower.

Anyway, here is code to handle it.

 

using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
 
namespace SecureHTTPDemo
{
    static class Program
    {
        private const string Revokedurl = "https://revoked.badssl.com/";
        private const string ExpiredUrl = "https://expired.badssl.com/";
        private const string SelfSignedUrl = "https://self-signed.badssl.com/";
        private const string UntrustedRootUrl = "https://untrusted-root.badssl.com/";
 
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        public static void Main(string[] args) => Main().GetAwaiter().GetResult();
 
 
        static  async Task Main()
        {
            //check revoked without crl checks.
            await FetchPageSecurelyTest("Revoked", Revokedurl);
            await FetchPageSecurelyTest("Revoked", Revokedurl, true, true);
            //check expired
            await FetchPageSecurelyTest("Expired", ExpiredUrl,false,true);
 
            //check self signed
            await FetchPageSecurelyTest("Self signed", SelfSignedUrl, false, true);
            //check untrusted root
            await FetchPageSecurelyTest("Bad root", UntrustedRootUrl, false, true);
 
            Console.WriteLine("Any key to quit");
            Console.ReadKey();
        }
 
        static async Task FetchPageSecurelyTest(string test, string url, bool enforceCRL = false,
            bool expectException = false)
        {
            var result = await FetchPageSecurely(url, enforceCRL, expectException);
            Console.WriteLine(result ? $"{test} success." : $"{test} was not successful.");
        }
 
        static async Task<bool> FetchPageSecurely( string url,bool enforceCRL = false, bool expectException=false)
        {
            try
            {
                ServicePointManager.CheckCertificateRevocationList = enforceCRL;
                var fetcher = new HttpClient();
                var result = await fetcher.GetStringAsync(url);
                if (expectException) return false;
                var resultValid = !string.IsNullOrEmpty(result);
                return resultValid;
            }
            catch (Exception ex)
            {
                if (expectException) return true;
                Console.WriteLine("Exception unexpected:" + ex.Message);
                return false;
            }
        }
 
    }
 
    public class BriansSecureWebHandler : WebRequestHandler
    {
        public BriansSecureWebHandler()
        {
            
 
        }
    }
}

The remote certificate is invalid according to the validation procedure for FTP

I was testing a C# FTP application of mine and got this lovely gem of an error when connecting using SSL. I had a self signed certificate in the trusted store, but the FTP library kept screaming that the certificate was invalid.

Well, I found a great workaround for the time being. It should only be used by configuration or conditional compiling though.

Disable Certificate Chain Checking

[csharp]
ServicePointManager.ServerCertificateValidationCallback = delegate(object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; };
[/csharp]

Using the code above, your certificate checks will always be considered good. The channel will still be SSL protected, you just won’t be looking for man in the middle attacks nor identity mismatches. Something you don’t care about in development, just production.

Happy Coding!

Why does my .NET application with Authenticode signed dll’s take so long to load?

You thought to yourself, “Self, I think I should sign all of my dll’s with my authenticode certificate!”. Why ,not? It would make the application appear secure with digital signatures and all. I can use publisheridentity attributes for security and all should be well. Right?

The issue comes to the way the .NET loader handles the assemblies, especially when offline.

See, the .NET Framework will go out and verify each DLL’s certificate against the CRL. This requires making sure the CRL list is up to date and can incur an overhead of up to a couple of seconds. If you have a large number of dll’s, which many projects do, this can be quite the expensive task. What happens if your offline, well, it still tries to verify the signatures.

So, will the application run if it can’t verify the signatures? Yes. Yes it will.

Now you ask, “What do I gain by signing my dll’s?” If you are a vendor/publisher, you need it for Vista compliance.

Otherwise, I suggest you simply sign your EXE alone. There is a small performance hit, but if your application requires Elevation at least your customers will see the pretty name for your application and company instead of the dreaded “Unidentified Application” prompts.

You can take it from me, be careful of the performance impacts of authenticode signing your .NET assemblies. (Yes, it even checks them if they are GAC’ed.)

Here is a good reference post.

Happy coding!

How to use SSL transport security using a certificate in your WCF hosted service…

So you want to use some channel security in your WCF service. Maybe you even want to guarantee the server your are talking to is who they say they are.

Well, transport security is what you are looking for. It is really quite easy to implement.
Things you will need:
1) A certificate from a trusted signing authority (thawte,godaddy, verisign,etc)
2) A WCF service (duh)

You will need to make changes to the server app.config and the client app.config.

On the Server:

You will need to add this tag to the binding:
<security mode=”Transport”>
<transport clientCredentialType=”None”/>
</security>

We are basically saying here, use transport security but don’t look for a client certificate.

You will also need to create a service behavior.
<behaviors>
<serviceBehaviors>
<behavior name=”MyServiceBehavior”>
<serviceCredentials>
<serviceCertificate findValue=”CN=server.contoso.com” storeLocation=”LocalMachine” storeName=”My” x509FindType=”FindBySubjectDistinguishedName” />
<clientCertificate>
<authentication certificateValidationMode=”None” />
</clientCertificate>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>

Notice the serviceCertificate tag. This is the important one. the CN=XXXXX is the portion you need to change to your servers certificate subject.

Now the service is setup. You will need to modify the Client app.config as follows:

You need to change the bindings on the client the same way as the server. Example.
<bindings>
<netTcpBinding>
<binding  name=”TCP_Binding” …..>
<security mode=”Transport”>
<transport clientCredentialType=”None” />
</security>
</binding>
</netTcpBinding>
</bindings>

Now you have your service protected with SSL and validation.

Happy coding!

How to make your own SSL test certificate for IIS or WCF

I had to create a test ssl certificate to use with my WCF service.

Here is the simple way to do it in 2 Easy Steps!

1) Open the Visual Studio 2008 Command Prompt

2) Fire off this command. change bseekford00111 to your computer name or whatever name you want the certificate to be.

makecert -r -pe -n "CN=bseekford00111" -b 01/01/2000 -e 01/01/2050 -eku 1.3.6.1.5.5.7.3.1 -ss my -sr CurrentUser -sky exchange -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12

That is all there is to it.
It will drop it in the current user MY store. If you want it under local machine store, change CurrentUser to LocalMachine