Why I no longer have an old-school cert on my https site
29 points by pondidum
29 points by pondidum
Dig around in the headers of the response, looking for one named “Location”. Don’t follow it like a redirection. Why would you ever follow a Location header in a HTTP header, right
Maybe because it’s not a redirection. It’s a 201 Created
response. The parts I have read of this is full of such strange analyses. It’s focus on some details which looks strange in the first moment. But the greater content would explain it. This context is left out.
Another good example for this is the side note about the public exponent:
while looking at existing ACME clients, I found that at least one of them screws up their encoding of the publicExponent and ends up interpreting it as hex instead of decimal. That is, instead of 65537, aka 0x10001, it reads it as 0x65537, aka 415031!
So this explain others they fucked up there implementation while the author don’t understand whats the requirements for this numbers are. e only needs to be coprime with Phi(n) in mod N. For primes like 0x65537 and 0x10001 chances are good this is fulfilled.
Another example:
Write something that will do base64 style encoding, but not quite. The last two characters in the encoding set are usually + and /, but that won’t do for webshit, so you need to make it use - and _ instead.
This variant is literally defined in the RFC for base64 encoding for the exact purpose of being URL-safe.
After I POST /endpoint how do I know the URL of the resource that was just created?
https://www.rfc-editor.org/rfc/rfc9110.html#name-201-created
To provide the location of the newly created resource. This is standard practice with a 201
We can look at it from the OOP perspective. Response’s “Location” header is a property that has the same name (as web is all about locating resources, it’s no wonder), but slightly different meaning based on the response class.
class HTTPResponse;
class HTTPMovedPermanently extends HTTPResponse {
Location: string // where to find the moved resource
}
class HTTPCreated extends HTTPResponse {
Location: string // where to find the newly created resource
}
Then it’s up to the web agent to decide how to handle these two classes according to the agent’s purpose.
The author seems to be being weirdly harsh about the ‘hacky’ way that ACME works, as if they’ve only read the source code of a client and not any of the justifications or design docs.
I’m not sure why hand-rolling your own authentication and key generation code is desirable, but I guess I don’t maintain their server so /shrug
She has expanded on why she dislikes ACME in prior blog posts. She also came across CAs that do stuff the more sensible way, proving that it’s possible.
I’m not sure why hand-rolling your own authentication and key generation code is desirable
I don’t think it’s about that as much as understanding how the entire stack works. I think that’s a worthy goal.
I just can’t get over the fact that they are parsing the output of “openssl -text” from a C++ program, while complaining about fairly basic big-endian byte encodings.
I also saw a few odd notes, but I wouldn’t conclude from the blog post that Rachel’s code does parse openssl output? I read the “openssl dgst” as “write proper code that does something like (…)”, and - perhaps somewhat charitably - read the “openssl rsa” part similarly.
(Double-checking your fresh code against the openssl CLI is a pretty reasonable thing to do)
Having implemented an ACME client I think the spec is basically “fine”. It certainly sticks with web standards more than I would - I’ve fought and lost the good fight against JWTs myself - but that isn’t surprising for an IETF standard that started at Mozilla. I also think some of the complexity only makes sense if you are “web scale” which Let’s Encrypt unironically is.
Why not just use a web server that does it automatically? There’s quite a lot of them these days. Haven’t thought about this for almost 10 years.
Yes, I’m a big fan of Caddy for this - the DNS based plugins make it very easy to do internal certificates too!
Means I basically don’t have to think about certificates, they just work.
Exactly: https://caddyserver.com/
By default, Caddy automatically obtains and renews TLS certificates for all your sites.
If someone wants to implement it for themselves for learning, that’s another matter, but the excuse of ‘ACME is too hard’ doesn’t make sense any more.
Why not just use a web server that does it automatically?
Using something like caddy is the way to go for your personal servers or early stage startup. But since you asked this HAProxy issue highlights some of the downsides. To reduce exposure, HAProxy is designed so that it cannot access the disk after its config its loaded. Being able to handle ACME directly would mean allowing HAProxy to not only access the disk but write out
https://github.com/haproxy/haproxy/issues/1864
It also illustrates how there is a tension between convenience and security in a lot (most?) of cases.
Random side note: while looking at existing ACME clients, I found that at least one of them screws up their encoding of the publicExponent and ends up interpreting it as hex instead of decimal. That is, instead of 65537, aka 0x10001, it reads it as 0x65537, aka 415031!
Somehow, this anomaly exists and apparently doesn’t break anything? I haven’t actually run the client in question, but I imagine people are using it since it’s in apt.
I’d like to test this client. It sounds like a problem. I can’t decide whether it seems likely to be a security problem (I don’t initially see how it would) or just an interop problem. It seems like it might run a significant risk of making both key exchange and signature verification ambiguous sometimes.
The author might be interested in acme.sh
acme.sh is IMO a horrible piece of software. its name makes it sound like “oh, it’s just a little shell script”, until you realize it is over eight thousand lines long. all in a single file. with zero tests. and it comes with an additional 40.000 lines of .sh plugins.
if you want an auditable acme client, use acme-tiny, its 200 lines of python.
Knowing Rachel, I would assume she’d prefer to stay as far away from acme.sh as possible after The Incident.
dehydrated seems like a reasonable alternative.
Yeah I’ve used dehydrated in the past on servers I configured, and it’s used on chiark which hosts my website.
(I love the elaborate pun in the name, which comes from a Wile E Coyote cartoon featuring a box of “ACME dehydrated boulders” – plus the fact that the Let’s Encrypt CA software is called “boulder”.)
what’s wrong with https://github.com/go-acme/lego ?
I myself use lego via the acme nixos module, but I have have friends who strongly prefer freebsd and acme.sh. I am however now convinced against acme.sh thanks to the other responses.
I am not reading the entire article to find out what ACME is. Inform your readers before too long what they are reading the article for.
If you’ve stood up a web server in the past decade I’d expect you’d probably recognize the acronym. If you’ve ever used or looked into let’s encrypt, however superficially, you’d at least be aware of it. I’d think that would be a fairly significant chunk of lobsters users.
As it happens, I have done one or two in the last decade specifically with let’s encrypt. I remember they had a script that fundamentally just worked. I do not remember any specific protocol or anything of the sort.