Setting up a PKI

Since setting up my home network, I’ve been playing around with pieces of it. Today, when I was logging into the web interface of my EdgeLite Router, I noticed that dreaded red X through the https in Chrome, because Chrome didn’t trust the default self-signed certificate that came with the router. Why not replace that default cert with one I’ve signed myself, and import my signing cert as a trust certificate, thought I? So that’s what I did today.

To replace the certificate on an EdgeLite Router, I stumbled upon this website, which makes it sound pretty easy: replace the /etc/lighttpd/server.pem file with a certificate file I’ve generated myself. Of course, replacing it with a new self-signed cert wouldn’t accomplish much, since I wanted to set up my own CA, so I had to back up a few steps, and start with creating a root certificate.

To set up my root certificate, I followed this great tutorial by Didier Stevens. First, I created a new root CA certificate. Then, I created an intermediate certificate that was signed by that CA. Why? In case that signing certificate was compromised, I could revoke that cert without having to revoke the root cert. Finally, I create a new cert for my router, signed by that intermediate certificate. I also exported that intermediate certificate in a PKCS12 format for importing into my Windows certificate manager. Simple, no?

Unfortunately, it was not as simple as I hoped. When I did all of that, I still got the dreaded red X from Chrome. It turns out that my intermediate certificate was flagged as not allowed to sign other certificate, and thus the certificate chain was invalid. After some Googling, I found a lead: apparently, my intermediate certificate was an X509v1 cert, which is not trusted for signing other certs. The solution is to create an X509v3 certificate with the right attributes, which can be used to sign other certificates. This is done by creating an extfile with the proper data, which I dutifully did. I signed the router certificate again and…no dice.

It turns out I had followed that last website too well: I had included in my extfile the line basicConstraints=CA:FALSE, which was preventing the intermediate certificate from being allowed to sign other certs. Changing that to TRUE, re-signing the router certificate, and re-exporting the chain in PKCS12 format finally led me to success. Sort of.

In the end, Chrome still did not get rid of that red X. Although it did say that the certificate chain was valid and the site’s identity had been validated by myself, the lack of a public audit trail left that red X in place. Short of getting a cert signed by a public CA, that error isn’t going anywhere, so this is good enough. Incidentally, IE has no problem with my cert; Firefox flat-out refuses it, saying it can’t validate the trust chain.

This PKI setup will suffice for my internal websites, but it certainly is no substitute for a public chain of trust. Since I’ve created my own root CA certificate, protecting that private key is a must: so far all I’ve done is chmod 000 on those files so only root can access them; obviously, in a production environment, you want to protect that root cert tighter than Fort Knox. It’s a good learning experience, though, and from here on out I’ll have the joy of maintaining my own internal PKI.