There are a couple of things I strongly disagree with in the computing industry. Probably the biggest, is how SSL certificates got started.
In my view, instead of making Public Key Infrastructure free, open, and smart (like what PGP was supposed to be) – it quickly became a closed system, where only smart/rich companies quickly got on-top, and ruined everything.
Specifically, I mean Verisign. This was the company (in my memory) that decided to conflate: encryption with identity (which you PAY to prove). They made the case to all of the browser-makers (well, Netscape and IE at the time) that if they included the Verisign CA bundled in the browser, then people could feel secure that the site they are visiting is legit. Then, Verisign quickly made a billion-dollar company out of charging for SSL certificates. Then, other companies wanted in on the scam, and they had to pay HUGE dollars to get their CA included by default, in each browser. So, we are left with a world where you have to pay hundreds of dollars each year to get an SSL certificate which came from one of the Almighty, blessed CA’s.
Although I wasn’t involved in this, other similar-minded people put together www.letsencrypt.org – which strives to decouple: encryption from identity. In other words: let’s just encrypt everything, first of all. Then, if you want to establish the identity of the other party, that should be a second transaction. So, LetsEncrypt got their CA included in all of the major browsers. That means of course, that any certificate issued by them will be considered a “legitimate” certificate! The trick though is that LetsEncrypt gives out certificates for FREE! Not only that, but they insist that everyone automate their certificate requests and renewals (and even provide help via https://certbot.eff.org/)
OK, so that’s great. In the year 2017, if you have a public-facing website, you can now get a free SSL certificate and be out from under the thumb of Big Certificate after their 20-year reign.
What about internal/intranet stuff?
What should you do about your intranet at work? Or what about if you are a professional or hobbyist, what about stuff on your home network. Are you just supposed to LIVE with “cert nags” like:
This is so stupid, and so frustrating. Why, in the year 2017 is this still a thing?
The Solution – “just use OpenSSL!”, they said.
Oh, why didn’t you say so! OK, I’ll just spin up a Linux machine and use OpenSSL to create a certificate authority, and then generate all my leaf certificates, which are signed by that CA. Great! Super! How hard could that be? It’s literally too long to put in this blog post. There are literally sites dedicated to this complex topic. In short:
- Install OpenSSL (on Linux)
- Create several directories, set their permissions just right
- Modify the openssl.cnf file – and don’t mess up because you will lose days trying to figure out what setting you got wrong.
- Create the CA key.
- Create the CA certificate.
- Create a leaf key.
- Create the leaf certificate by signing it with the CA key (this is a doozy of a command)
- Then somehow get the .crt and .key files off that Linux box to where you need them.
This is not a simple task, and you can easily lose a couple of hours if you mess up one piece of this. You also need to become a bit of an expert just to use this. Do you know what protocols, algorithms, or key size you should use?
Argh. This is so stupid, convoluted and complicated. I don’t mean that as a dig against OpenSSL – it does the job. But I mean why in the year 2017 is this the only reasonable option?!!
This was so frustrating that I got mad. What do when I get mad about stupid software? I write a program.
The real Solution (well, another solution) – webCA:
I knew I wanted to have this be a containerized app. I thought it made sense that anywhere where you have Docker, you could just spin up a container of a web app, and via an API or web UI, manage your CA or leaf certificates. So, I started writing a NodeJS application. The API of that would call the various OpenSSL commands, and then return the output of those commands, via the API. I really started getting bogged down trying to adapt command-line output to properly-formatted JSON. In particular, even EOL line endings and how n was processed in Node vs the command-line was really jamming me up. That turned out to be a UTF8 vs Unicode problem.
In the end, I started over (with the API part) with .NET Core. I thought I would use Bouncy Castle. If you know me, you have heard me reference this library before. The idea is brilliant: encryption is nothing more than math. So, Bouncy Castle is ALL of the modern encryption algorithms written in pure code. This means that you can import them into anything. If you are a .NET Framework developer for example, you can only use System.Security.Cryptography from .NET Framework applications. Bouncy Castle you can use on any platform in many languages. There is a catch though: it is literally the WORST .NET code I’ve ever seen. Most of the API is not OO, nothing is consistent, you have weird errors all of the time, there is no argument validation – I could go on and on. Although it’s VERY frustrating to work with – it too, does technology work. So, that’s what I used.
With all that said, I lost a few days trying to figure out how to create a CA, and how to use that CA to generate a leaf certificate. Then, because I kind of don’t know what I’m doing, I lost a few days trying to figure out the correct format for the “certificate” and the “key” file. In the end, I got it working.
- This is a completely insecure CA. I’m adding a login part of it, and will likely make it a bit more secure – but that was not the point of this. The point is, I can now stand up a CA for my home lab, get rid of stupid cert nags in browsers, and use certificates like a civilized human being. This is NOT meant to replace a real CA – it’s meant to give you a simple, easy CA in places where it’s not as critical: in a home lab, on an intranet at a tiny company, infrastructure-facing communication where end-users don’t need access. For example, for intra-cluster communication – with 2 dozen machines… multiple that by a few dollars per year for “real” certs, you get the idea.
- The code is still a bit of a mess. I was trial-and-erroring until I got this working a few days ago. As of this writing, I haven’t had a chance yet to go back and clean out all of the junk, add unit tests, and make it a proper application.
So what is webCA?
Well, it’s a .NET Core Web API application. This is all API-first – although the API is a little messy and inconsistent at the moment. The front-end is Bootstrap 4 and AngularJS 1.x. If you have Docker, you basically just bring up a container, something like this:
$ docker run -d --name webCA -p 8080:80 division42llc/dotnet-webca
Then, on that same machine, open a browser to http://localhost:8080/ and you’ll see the running application:
From here, you can create your CA:
which results in:
and then by clicking on “New Cert” in the top nav, you can generate leaf certificates:
and that leads you here:
From here you can download the server certificate, private key, and the certificate of the CA – all the things you’d normally need, in Base64 “pem” format. You can also grab these programmatically too. For example, if you were logged on to the devserver1 machine, you could do something like:
$ wget http://myca-server:8080/api/leaf/download/97937E2646AE1FD0A1154A5F0B13AE903C1EFA3B/ –O ./devserver1.crt $ wget http://myca-server:8080/api/leaf/download/private/97937E2646AE1FD0A1154A5F0B13AE903C1EFA3B/ – O ./devserver1.key $ wget http://myca-server:8080/api/ca/download/ –O ./ca.crt
again, the API isn’t very consistent at the moment, but it does work. You can find these URL’s by hovering over the buttons above. You can also click into a certificate to go view it’s details – and there are download/delete buttons there as well:
Wait, how does this fix the “cert nag”?
One key piece of this, and which also underscores why this is not for internet use – or even wide use. This CA is brand new and not “trusted” by your computer. So, you will still see a cert nag, except now it will say it doesn’t trust the CA. To correct this, you need to tell your computer this CA certificate is a “trusted root certificate authority”.
In Windows – trusting your new CA:
Download your CA’s public key. It will be named “ca.crt”. Double-click it and you will see a window launch:
Click on Install Certificate – which launches a wizard:
I typically choose “Current User” and most-importantly, on the next screen – choose “Trusted Root Certificate Authorities”:
Click next and finish, and now – any certificates signed by this CA will show “green” in the toolbar:
In non-Windows – trusting your new CA:
On Linux and macOS, this works the same. Both Firefox and Chrome keep track of their own certificate information. In both browsers, go into Settings, and then Certificates – and then simply import the ca.crt file into the respective tab:
Where is it? How can I contribute?
This application is stored in GitHub. There is a webhook from Docker Hub so whenever I make a commit or push a new version tag, it does a build automatically. Because this is .NET Core and the app needs to be built AND the Docker image needs to be built, the Dockerfile pulls in the source, and the Docker Image build actually does the application build within the Docker image build.
And again, to run this locally see above – or there are more detailed instructions on the main github readme. If this is in the ballpark of what you need, but you need features – let me know or better – do a pull request.
Also, to be very clear, until we get to a world of “encryption is decoupled with identity”, this does NOT replace a real CA. The whole purpose of this is so that for small, lab, or home projects, you can quickly (literally in a few seconds) start generating legitimate certificates for your project on your private network.