Client-side TLS certificates and root certificate authorities

I’m writing a set of applications for a product I’m building, including some on the web which you use via the browser, and I’ve chosen client certificates to help with both security and (part of) the authentication process. I had planned on using client certificates in both the native applications on the platforms I’ll support and the web apps. I still might.

My problem is that installing both client certificates signed by any certificate authority, root or not, is either impossible on some platforms or downright hostile on almost all others.

On top of that, installing new root certificates is quite a hostile experience for the end user on those browsers that do let you do so. The user trying to do so is discouraged from doing so at multiple points, and if the Windows certificate management infrastructure gets involved it’ll give the user an unfriendly UI that basically says, “sure, you can install the CA, but I still don’t trust it and neither should you”.

Apple are the best here, with Keychain having a friendly UI for creating a new CA that can sign S/MIME certificates, self-signed of course. Adding a root CA that you’ve created outside of Keychain is also done reasonably well.

Certificate trust policies for major browsers will also act as trust middlemen, untrusting roots even if the operating system does, at their discretion. This is mostly down to Diginotar and Comodo issuing improperly signed certificates and both of them being root CAs trusted by almost all client software in use in the world today.

So little old me, who wants to create his own root CA and handle his own certificate issuance and revocation for client certificates signed by that new root, is actively barred from doing so in a way that doesn’t scare off a majority of end users, and that’s just for those platforms where adding a new root CA is doable. It’s impossible in iOS without jailbreaking, or root access in Android, for example.

Of course there’s an incredibly good reason for that: certificate trust is important. Walking the certificate chain to determine if you trust the certificate, and by extension the signing authority, underpins client security for many important things we do with computers today, not least online banking. If you can install a root CA trivially without the system asking the end user, and thus the system, to trust it without further question, you can also trivially pretend to be my bank afterwards.

That said, systems come preinstalled with a web of trust that you have no involvement in. It’s not transparent and I can’t tell, for example, why Apple currently trust AffirmTrust on my behalf in OS X (and seemingly until December 31st 2040!). Look at the list of system-trusted roots (if you can!) now; who the hell are those companies and why are our systems setup to trust them? How do new root CAs get into that web of trust?

Without investing years of time and incredible amounts of energy, engineering and money into it it’s impossible to become a de-facto root CA trusted by all major OSes and browsers. Given the above you can argue it doesn’t even matter, since what is the end user actually allowing the OS to trust on their behalf.

I also realise that by the same token, why should you trust my new root CA under the same framework and UI experiences?

So how do I get around it, without controlling all of the browser certificate trust models in play today, establishing your trust in my new root CA? I could not bother and just use one of the already trusted roots to sign my client certs. But that means trusting them with security and authentication for my applications and my service. I have good reason to only trust myself, and have you only trust me, with the thing I’m building. Even if working with an existing trusted root was the right thing to do, none of them will let me programmatically generate new client certificates signed by them, for new users of my systems and applications, without significant financial cost.

If you know otherwise, let me know!

So I’m left without a nice, simple, cheap way to use one of the most established security mechanisms in play today in any meaningful way, without it being horribly painful for me and my end users.

There seems to be a gap in the market for a new root CA to pop up and do this very thing, being very friendly to developers where identity is established, integrated into the default security systems of operating systems and browsers (assuming the status quo is here to stay), and for reasonable cost.

Instinctively it just feels like modern computer security and network security is fundamentally broken if it’s at the behest of a small network of seemingly arbitrarily trusted roots, even if I do appreciate the security it gives me as the end-user in many cases. I want to be the root too, though, and that’s just really difficult.