Writing

Feed Software, technology, sysadmin war stories, and more.

Wednesday, January 4, 2023

Another look at the steps for issuing a cert

Oh boy. Yesterday's post has riled people up. A lot of them don't like what I said about the ACME protocol. I get the impression a few of these people haven't looked at the problem that needs to be solved in a different light.

How about we give that a shot now? Let's just go through the steps for getting a secure web site going, and ignore the specifics of the protocol for the moment.

First, the baseline assumptions: there's a key. There's a certificate signing request which references that key. Then there's the certificate itself with a signature which attaches it to the "web of trust" (ehhh...) that is largely accepted by most clients. Okay?

1. You generate a key. It'll eventually need to be installed on the web server somewhere. It's just a blob of gunk that's been encoded in ASCII with that whole --- BEGIN/END blah blah --- stuff at either end. You should probably generate it with a certain algorithm and with a certain complexity (i.e., number of bits).

2. You generate the CSR. It needs to read from that key in order to pick up its identity, but the CSR itself doesn't contain sensitive key material. The CSR has a bunch of fields that almost nobody uses: country, organization name and unit name, an e-mail address, and so on. Some of them used to mean something in a different age, but you'll probably find that a CA ignores all of them and generates something else entirely in the resulting certificate. Case in point: the cert for my site has CN = rachelbythebay.com and that's it.

3. You tell the CA that you want a cert by sending them that CSR.

4. The CA says "ok, prove you own this domain, punk" and gives you a URL or two that you can populate with some magic string in order to do exactly that. Or, it gives you some DNS entries for that domain that you can create with a magic string - maybe the same string as the URL, maybe not.

5. You stand up the magic URL with the magic data, or drop in a DNS entry with the magic data.

6. You either poke the CA to say "ok, go look", or (much more likely) you just sit there feeling stupid until they happen to retry and notice. They usually don't provide much in the way of being able to trigger this on-demand, so this can add a bunch of delay to the process.

7. The CA eventually sees the right thing in the right place and says "okay, this can't be chance, so they must actually control the document root and/or DNS or whatever", and that's enough for them. They issue a cert for that key and domain name. (In the old days, they'd start looking at DUNS numbers and stuff like that instead as verification.)

8. You check back and notice it is in fact available. It would be nice if it poked you somehow, but odds are, they won't, or at least, they won't do it faster than you could check for it. You download the cert which is yet another --- BEGIN --- ... --- END --- ... blob of gunk.

9. You install the key and cert on the web server and swing the config around to reference it.

10. You kick the web server in whatever fashion it requires to make it start using the new key/cert and stop using the old one - reload, restart, reconfigure, whatever.

11. You load the site up and verify that it actually works, and that it's using the new cert and not the old one.

Now, when you're talking to the CA, it's likely they are going to want you to authenticate yourself. Notice though, at no point did I say that you should now throw down and start doing your own crypto (*cough* JWT) in order to generate some kind of "proof" of some "claim" to convince them that you are in fact who you say you are.

You could just, you know, pass them an opaque token that they issued to you when you logged in... just like people have been doing with the web for years and years. Ever call Stripe from inside a program? You get an API key. How about Wavefront? Another API key. Gandi? API key. It gets set in the headers. Now they know who you are. Done.

When you're working in these terms, it's a matter of building up a request in a format they desire. It'll probably be a POST because sane people don't create things with just a GET. So you fire some form data containing the CSR at them, or maybe you send them a blob of JSON, and stick your auth token in a header. This goes over https to them, and so it's as secure as anything else you'll be doing with this stuff.

See how much more accessible that is? See how evil rolling your own crypto can be?

It's evil. Very evil. Don't enable their goofy auth schemes and don't roll your own crypto.

No, really.

How long since the last alg=none JWT vulnerability? It's 14 days as I write this, and this is January 2023. 2023!

BTW, to the person that said these protocols are "... an opportunity to pull in as many 'standards' as one can ..."? You nailed it. That's what I meant when I said "web kool-aid" in the original post.