Hi,
can someone explain me why SSL client authentication is not widely used? You can use the same protocol you use to authenticate hosts to authenticate users, yet no one seem to do that nowadays.
I'm not professional web developer so maybe answer to this question is obvious (but I just don't know it).
Because SSL certificates are a hassle to use on the client side, and possibly cumbersome to generate. I used client certificates in a few projects, and while the idea sounds perfect, it's hard to implement, and at least I don't understand it thoroughly.
For public services, getting users to have keys and install them in their browsers is quite hard.
For APIs, it should be more manageable but many places stumble with key management and a lot of developers were resistant to learning enough about the tooling to do things like manage test instances.
One of the reasons it is hard is that most error reporting on certificate authentication is horrendously bad and there are a lot of ways it can go wrong. Dates can be wrong, the CN field can be wrong, the server or client might not agree on the quality of the ciphers, user can install the cert in the wrong place or with the wrong options, etc... If any of this goes wrong all you get is a "cannot connect to website" error and maybe if you're super lucky an error in the web server log like "certificate failure". For security reasons they never tell you what the actual problem is and just assume that the user must have a PHD in cybersecurity because they're trying to do crypto on a computer, so it should be no problem for them to check the thousand different possible failure points in the system.
I guess regarding the public services your statement may be correct.
But I wonder if anyone (any significant content provider) actually tried. The technology is available for > 10 years at least (including browsers support).
I think it's an issue for most people that they need to manage multiple passwords and it sometimes turns off people from actually using the service. With client certificates you install certificate once and (given enough support from web developers) forget about passwords "forever".
> With client certificates you install certificate once and (given enough support from web developers) forget about passwords "forever".
The problem is that this isn't really true: it's more like this:
1. You go through a tedious and convoluted process to get
the certificate, which requires using a largely-ignored browser feature which is now deprecated: (https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ke...). Even when it was implemented, the UI is not great – e.g. https://www.instantssl.com will fail if you fill out the form too quickly before the browser has finished generating a key.
2. Wait for the email to arrive and follow the retrieval process to get the certificate. Then follow the clunky UI to install it. You'll be told that it's really important to back it up but e.g. Firefox won't give you any instructions about where to even start to do that.
3. You then need a non-trivial amount of work to export the private key and certificate and install it on all of your devices, which is another process where the UX was apparently never considered seriously at any point over the last 20 years.
5. Every time you visit a site or send an email, you now have to select which key you want to use.
6. Every year, repeat the process starting at step 1.
Don't get me wrong, I'd love for this to be available and am still somewhat amazed that after however many years nobody has made a serious effort to improve the experience. It'd be really nice to have a LetsEncrypt-style effort to remove the warts from this process so it's approachable for normal people without a heavy support pool.
This is another area where I wish Mozilla hadn't prematurely killed Persona as it'd be really nice if there was a service which would allow you to associate different client certificates with a single user identity so private keys never needed to leave the device, and register things like tokens. A U2F-style focus on the user-experience would be really nice: once a year when you try to login it redirects you to a page which says “Enter your password and tap the token if you want to keep using it" and refreshes the certificate with no other ceremony.
> Wait for the email to arrive and follow the retrieval process to get the certificate
Is there a reason why the server couldn't send the certificate back to the browser via HTTPS?
> You then need a non-trivial amount of work to export the private key and certificate and install it on all of your devices,
Would it not be better to just use a different key for each device? That is, repeat steps 1 and 2 for every device you plan to use?
> Every time you visit a site or send an email, you now have to select which key you want to use.
Could the browser remember which website the client certificate was used for? If so, then the user won't have to make the selection more than once.
> Every year, repeat the process starting at step 1.
Outside of a device getting compromised, is there a good reason for updating certificates more often than once every 5 years?
> It'd be really nice to have a LetsEncrypt-style effort to remove the warts from this process so it's approachable for normal people without a heavy support pool.
I'm still doing more research on this, but what did the <keygen> HTML element lack that the process used by Let's Encrypt provide?
> This is another area where I wish Mozilla hadn't prematurely killed Persona as it'd be really nice if there was a service which would allow you to associate different client certificates with a single user identity so private keys never needed to leave the device
Shouldn't the private key be something that's associated with the browser? That is, when you install the browser, a private key is generated and used for all certificate signing requests. I think the process could be extended to add additional browser instances for a given account on a website. For example, you could take the CSR from the other device and use your first device to send it to the server, get the certficate and then copy it back to your other device.
A number of the undesirable factors described here (email, 12 month limit) are because that process isnt generating a client certificate for use on a private site, it's generating an S/MIME cert for handling encrypted/signed email.
I guess I'm not clear on the current process. If we had a process as shown below, I think it would be much easier to get people to adopt client certs.
1. Click on link to sign up for new account on news.ycombinator.com
2. Enter information for the account including a CSR that your browser generates for you
3. Submit the information to the server
4. Server servers another page that confirms account creation and includes the certificate
5. The browser provides a way to import that certificate to a client certificate store it maintains
6. Next time you visit the website, your browser knows to use that client certificate
Registering other browsers would require sending the CSR via the first registered browser and copying the certificate that the server returns to the second browser.
Of course, this would be for websites that don't have a need to verify your identity (like reddit or Hacker News). For banks, or credit cards, there would have to be a way to verify the identity of the person signing up for an account.
> > Wait for the email to arrive and follow the retrieval process to get the certificate
> Is there a reason why the server couldn't send the certificate back to the browser via HTTPS?
The public implementations are generally trying to verify current ownership of the specified email address. That's part of why I wish this could be linked to a third-party which already does that so users don't have to repeat the process as often.
> > You then need a non-trivial amount of work to export the private key and certificate and install it on all of your devices,
> Would it not be better to just use a different key for each device? That is, repeat steps 1 and 2 for every device you plan to use?
It would, but currently you can't do this if you use Google Chrome or Microsoft Edge. Again, remember that I'm talking about the practical impediments doing this now rather than any sort of conceptual problem: if the industry cared this could improve a lot very quickly.
>> Every year, repeat the process starting at step 1.
> Outside of a device getting compromised, is there a good reason for updating certificates more often than once every 5 years?
The general idea is that it protects against unknown, non-permanent mistakes but I think the main point here is that key rotation should be automated so it can happen simply since it reduces the window of problems for any mistakes considerably. I'd expect a modern implementation to have a tiered approach where e.g. keys generated on a secure enclave, token, etc. are trusted longer than ones where user error makes it possible to get access to the private key.
> > It'd be really nice to have a LetsEncrypt-style effort to remove the warts from this process so it's approachable for normal people without a heavy support pool.
> I'm still doing more research on this, but what did the <keygen> HTML element lack that the process used by Let's Encrypt provide?
It's been awhile since I looked at the discussions but I believe it was basically another case of an early feature chucked in in the 90s having a bunch of dubious design decisions which people didn't want to support for since it was rarely used. I'd be happy with it going away or substantially changing if there was a modern JavaScript API.
> > This is another area where I wish Mozilla hadn't prematurely killed Persona as it'd be really nice if there was a service which would allow you to associate different client certificates with a single user identity so private keys never needed to leave the device
> Shouldn't the private key be something that's associated with the browser? That is, when you install the browser, a private key is generated and used for all certificate signing requests.
I was referring to the two related concepts here: I like the model where each browser manages a private key (preferably stored in secure hardware) but you also need to handle the question which keys are allowed to sign responses for a specific person. Consider e.g. all of the sites which trust Google or Facebook to authenticate users and imagine what it'd be like if that could be extended so you could ask that trusted third-party which keys correspond to a verified email address. Having it be something which is commonly used would also be a great place for rotation if there was a seamless way to repeat the signing process every n days rather than a user having to do it the first time they access a site a year after the last time they renewed, when they may have forgotten a lot of the steps.
That last point underscores how much of this has nothing to do with PKI and everything to do with horrible UI: the failure mode for not having a valid certificate is generally horrible — looping selection dialogs, low-level TLS failure messages with no indication of what you can do to fix things, etc.
> The public implementations are generally trying to verify current ownership of the specified email address.
Are there any implementations that don't? For example, when I create an account on news.ycombinator.com, does it really need to verify my email address, rather than using a signed message sent via HTTPS during the sign up process?
> Consider e.g. all of the sites which trust Google or Facebook to authenticate users and imagine what it'd be like if that could be extended so you could ask that trusted third-party which keys correspond to a verified email address.
Perhaps we need to rethink using email for verification. For server side authentication, we have certificate authorities to handle verification of a given server's identity. In your example, Google or Facebook (or both) could serve as certificate authorities for the client certificate used for a given website.
Again, I would say that most websites do not (or should not) need my email address in order for me to sign up for an account. My web browser should be able to manage verifying my identity with a website as well as adding other trusted web browsers.
> That last point underscores how much of this has nothing to do with PKI and everything to do with horrible UI: the failure mode for not having a valid certificate is generally horrible
Unfortunately, that is very true. It would be nice if some serious effort could be directed to improve the process. I think that if we were using certificate authentication, as opposed to password based, it would be much harder for people's accounts to be compromised, even through "social engineering".
Client certificates, a.k.a. mutual TLS or "MTLS" authentication, are widely used within infrastructural deployments of TLS, where there are automated mechanisms to provision and rotate certificates.
For federated use cases, they are less popular, likely due to the added complexity being a blocker for adoption.
Personally I've always used x509 client certs with a self signed root authority / intermediate authority for internal tooling at companies i've worked for. This is possible because 1) i happen to already have a good understanding of openssl and how to use it, secure keys 2) i have control over the devices im provisioning so i can make them trust my root cert for timing/x509/etc.
It would be really cool if there was a service like letsyncrypt that would provision "client" certs for this sort of use but revocation lists and things are a little annoying for large scale use.
EDIT: Another reason why this can be a hassle is that while Safari/IE/Chrome use the system to evaluate trusted certs on all OSs i've tested, firefox uses its own implementation so you have to add all the certs yourself. This is ... frustrating from a management perspective because you have to keep two sets of docs explaining what to do for new hires and etc.
EDIT 2: I've always been curious if its a net security benefit that firefox does this. On one hand, they are less vulnerable to OS-specific attacks and can automatically un-trust root certs that are compromised for whatever reason, but you're then trusting Mozillas implementation of something that is admittedly very complex.
In Firefox, there's a configuration setting (from about:config) in Windows (not sure about other OSes) that can be used to tell Firefox to use the system certificate store for root CAs. There are also deployment mechanisms where this can be pushed as one of the default policies. [1]
The Firefox Enterprise mailing list is the place to go to for deeper level help on these things. [2]
SSL client authentication usually winds up authenticating physical devices similarly to SSH keys, but there is near zero infrastructure simplifying/protecting/distributing a single software certificate for an individual user (especially non-technical users!) across multiple devices -- and this is really complicated by mobile devices. (Enrolling a new cert on every machine is an exponential management nightmare.)
SSL client authentication is widely used by the US military on smartcards requiring additional hardware readers: https://en.wikipedia.org/wiki/Common_Access_Card. AFAIK using a smartcard doesn't work reliably on Mac without installing 3rd-party software. The difficulties of usage in practice has spawned a cottage industry of commercial software and support, like http://militarycac.com.
I assume companies selling end user hardware tokens like YubiKey would love to see client certificate authentication become more usable, but initiatives like FIDO U2F seem to be gaining momentum instead.
Poor support of SSL certificates in browsers is commonly attributed to bad UX but the real reason is that they are credentials that can be re-used by multiple services to track you as an individual. Newer standards like U2F completely compartmentalizes origins so that if you register to service X a different service Y will not know who you are.
SSL certificates also doesn't work in HTTP/2 (because of multiplexing multiple requests).
Benefits include storing private key in a hardware tokens, most OSes support them out of the box. You can just plug your token into USB port, visit site that requests a client certificate, enter PIN and be done (e.g. Yubico PIV applet).
HTML also has/had <keygen> element that would generate private key in a browser, send the public key to be signed to a webpage essentially creating private/public key credentials but that is being removed from browsers.
For inter-service communication I'd definitely consider using SSL client certificates pinning private keys e.g. to TPM but regular users can't be bothered with it.
If you're interested check out Token Binding that makes tokens (cookies, etc.) bound to TLS connections essentially providing security of client certificates for tokens.
I have worked with systems that use it to authenticate machine to machine communication (e.g. a web backend authenticating itself to another service doing work for it). In that environment it works well.
Using it to authenticate a person regardless of device doesn't work so well from a usability point of view.
I've been experimenting with using the server's public SSL key as a client certificate to authenticate self-hosted and cross-server web service requests since the cert should be available at runtime in common enterprise setups yet incentives align to keep it well-secured.
I would appreciate pointers to any open source libraries demonstrating best practices and/or promoting this approach, specifically protecting against replay attacks and race conditions that come up as the cert is renewed (much more often - thanks Let's Encrypt!).
Separately: client certificate authentication is apparently great for "Internet of Things" (buzzword alert!) device authentication, so some of the rough edges may be worn off as things move forward.
Unless you have a well controlled environment (that includes client machines), certificate provisioning, revocation and management would not only be painful, but also require complex ways to share the private key part securely (during first time installation and renewal). Expecting users to know how to install a certificate in the browsers, machines and devices they use would be a non-starter.
In my observation, people who try to go this route in an uncontrolled environment mess it up by sending the certificate (including the private key) in unencrypted email (which is the default in most cases) or using other insecure mechanisms. The only ones who'd even attempt this are those who may not go through a security check or audit.
[If there are easy ways to handle this in an uncontrolled environment, I'd like to know more.]
I also want to know. It's extremely secure. It's also how I'm blocking my origin ip to where only Cloudflare can access it in case it's leaked. Safer and easier than a whitelist.