If you want to actually implement an ACME client from first principles, reading the RFC (plus related RFCs for JOSE etc) is probably easier than you think. I did exactly that when I made a client for myself. I also wrote up a digested description of the issuance flow here: https://www.arnavion.dev/blog/2019-06-01-how-does-acme-v2-wo... It's not a replacement for reading the RFCs, but it presents the information in th…
Implementing an ACME client is part of the final lab assignment for MIT’s security class: https://css.csail.mit.edu/6.858/2023/labs/lab5.html
Why I no longer have an old-school cert on my HTTPS site
191–200 of 437 posts
Re: Why I no longer have an old-school cert on my HTTPS site
#192> So, yes, instead of saying that "e" equals "65537", you're saying that "e" equals "AQAB". Aren't you glad you did those extra steps? Oh JSON. For those unfamiliar with the reason here, it’s that JSON parsers cannot be relied upon to treat numbers properly. Is 4723476276172647362476274672164762476438 a valid JSON number? Yes, of course it is. What will a JSON parser due with it? Silently truncate it to a 64-bit or 6…
I feel like not understanding why JSON won out is being intentionally obtuse. JSON can easily be hand written, edited, and read for most data. Canonical S-expressions are not as easy to read and much harder to write by hand; having to prefix every atom with a length makes is very tedious to write by hand. If you have a JSON object you want to hand edit, you can just type... for an Canonical S-expression, you have to count how many characters you are typing/deleting, and then update the prefix.
You might not think the ability to hand generate, read, and edit is important, but I am pretty sure that is a big reason JSON has won in the end.
Oh, and the Ruby JSON parser handles that large number just fine.
Re: Why I no longer have an old-school cert on my HTTPS site
#193> So, yes, instead of saying that "e" equals "65537", you're saying that "e" equals "AQAB". Aren't you glad you did those extra steps? Oh JSON. For those unfamiliar with the reason here, it’s that JSON parsers cannot be relied upon to treat numbers properly. Is 4723476276172647362476274672164762476438 a valid JSON number? Yes, of course it is. What will a JSON parser due with it? Silently truncate it to a 64-bit or 6…
Is this ok ? Python 3.13.3 (main, May 21 2025, 07:49:52) [GCC 14.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import json >>> json.loads('47234762761726473624762746721647624764380000000000000000000000000000000000000000000') 47234762761726473624762746721647624764380000000000000000000000000000000000000000000
Re: Why I no longer have an old-school cert on my HTTPS site
#194> So, yes, instead of saying that "e" equals "65537", you're saying that "e" equals "AQAB". Aren't you glad you did those extra steps? Oh JSON. For those unfamiliar with the reason here, it’s that JSON parsers cannot be relied upon to treat numbers properly. Is 4723476276172647362476274672164762476438 a valid JSON number? Yes, of course it is. What will a JSON parser due with it? Silently truncate it to a 64-bit or 6…
What I don't understand is why you (and a lot of other people) just expect S-expression parsers to not have the exact same problems.
Now, S-expressions as used for programming languages such as Lisp do have numbers, but again Lisp has bignums. As for parsers of Lisp S-expressions written in other languages: if they want to comply with the standard, they need to support bignums.
Re: Why I no longer have an old-school cert on my HTTPS site
#195I’m the technical lead for the Let’s Encrypt SRE/infra team. So I spend a lot of time thinking about this. The salt here is deserved! JSON Web Signatures are a gnarly format, and the ACME API is pretty enthusiastic about being RESTful. It’s not what I’d design. I think a lot of that came via the IETF wanting to use other IETF standards, and a dash of design-by-committee. A few libraries (for JWS, JSON and HTTP) go a…
Re: Why I no longer have an old-school cert on my HTTPS site
#196Re: Why I no longer have an old-school cert on my HTTPS site
#197> So, yes, instead of saying that "e" equals "65537", you're saying that "e" equals "AQAB". Aren't you glad you did those extra steps? Oh JSON. For those unfamiliar with the reason here, it’s that JSON parsers cannot be relied upon to treat numbers properly. Is 4723476276172647362476274672164762476438 a valid JSON number? Yes, of course it is. What will a JSON parser due with it? Silently truncate it to a 64-bit or 6…
Go can decode numbers losslessly as strings: https://pkg.go.dev/encoding/json#Number json.Number is (almost) my “favorite” arbitrary decimal: https://github.com/ncruces/decimal?tab=readme-ov-file#decima... I'm half joking, but I'm not sure why S-expressions would be better here. There are LISPs that don't do arbitrary precision math.
Re: Why I no longer have an old-school cert on my HTTPS site
#198Re: Why I no longer have an old-school cert on my HTTPS site
#199I don't understand the tone of aggression against ACME and their plethora of clients. I know it isn't a skill issue because of who the author is. So I can only imagine it is some sort of personal opinion that they dislike ACME as a concept or the tooling around ACME in general. We've been using LE for a while (since 2019 I think) for handful of sites, and the best nonsense client _for us_ was https://github.com/do-kn…
> I don't understand the tone of aggression against ACME and their plethora of clients. > ACME idea good, ACME implementation bad. Maybe I'm misreading but it sounds like you're on a similar page to the author. As they said at the top of the article: > Many of the existing clients are also scary code, and I was not about to run any of them on my machines. They haven't earned the right to run with privileges for my pr…
Re: Why I no longer have an old-school cert on my HTTPS site
#200Earlier quoted context omitted.
Yes, JOSE is certainly overengineered and JWK is arguably somewhat overengineered as well. But "the rest" of ACME also include X.509 certificates and PKCS#10 Certificate Signing Requests, which are in turn based on ASN.1 (you're fortunate enough you only need DER encoding) and RSA parameters. ASN.1 and X.509 are devilishly complex if you don't let openssl do everything for you and even if you do. The first few paragr…
>ASN.1 and X.509 are devilishly complex Most of it is unused though, only CN, SANs and public key are used.
Issuer: We need to know who issued this cert, then we can check whether we trust them and whether the signature on the certificate is indeed from them, and potentially repeat this process - this cert was issued by Let's Encrypt's E5 intermediate
Validity: We need to know when this cert was or will be valid, a perfectly good certificate for 2019 ain't much good now, this one is valid from early May until early August
Now we get a public key, in this case a nice modern elliptic curve P-256 key
We need to know how the signature works, in this case it's ECDSA with SHA-384
And we need a serial number for the certificate, this unique number helps sidestep some nasty problems and also gives us an easy shorthand if reporting problems, 05:6B:9D:B0:A1:AE:BB:6D:CA:0B:1A:F0:61:FF:B5:68:4F:5A will never be any other cert only this one.
We get a mandatory notice that this particular certificate is NOT a CA certificate, it's just for a web server, and we get the "Extended key use" which says it's for either servers or for clients (Let's Encrypt intends to cease offering "for client" certificates in the next year or so, today they're the default)
Then we get a URL for the CRL where you can find out if this certificate (or others like it) were revoked since issuance, info with a URL for OCSP (also going away soon) and a URL where you can get your own copy of the issuer's certificate if you somehow do not have that.
We get a policy OID, this is effectively a complicated way to say "If you check Let's Encrypt's formal policy documents, this certificate was specifically issued under the policy identified with this OID", these do change but not often.
Finally we get two embedded SCTs, these are proof that two named Certificate Transparency Log services have seen this certificate, or rather, the raw data in the certificate, although they might also have the actual certificate.
So, quite a lot more than you listed.
[A correct decoder also needs to actually verify the signature, I did not list that part, obviously ignoring the signature would be a bad idea for a live system as then anybody can lie about anything]