Some questions about acme-v1


I’m finishing up a sprint on some features for our SSL Cert Manager (which is v1) and have a small question about how letsencrypt/boulder/acme handles some things.

Our client is based off an earlier version of the acme-tiny library (which now hits the v2 endpoint)

The flow I see is this:

  • /acme/new-reg is hit with the account key if not registered before
  • /acme/new-authz is hit for each domain to be validated with the account key; challenges are validated
  • /acme/new-cert is hit with the csr and account key

So my understanding is the csr (or a token/session relating to it) is only sent to /new-cert; any relationship of the CSR between the /new-authz and /new-cert is happening through the shared account key on boulder.

is that right or am I just missing something. I expected the csr to be related to the auth and cert commands.


The final signed certificate essentially says that: public key XXX is to be trusted for DNS names [a,b,c].

The sole purpose of the CSR: to convey the intended certificate public key, proof of control of the intended certificate private key, and the list of DNS names to the CA, so the CA can then include those details on the signed certificate.

You could use any private key for the CSR, or provide a CSR signed by a new private key every time, Let’s Encrypt wouldn’t care.

Edit: To answer question directly (I guess?), yes, the CSR only matters during new-cert, as it serves no purpose up until then.


That’s correct.

That’s correct as well but you forgot one other use of the CSR: the client can also convey the request that the issued certificate include the OCSP Must Staple flag by including the relevant extension in the CSR.

You could imagine replacing the CSR with a JSON object that contained a public key, a list of identifiers, some optional extensions, and a signature from the private key corresponding to the public key. ACME uses a CSR for this purpose primarily on the back of easing integration with legacy software that knows how to spit out CSRs for classical CAs.


Boulder engineer

    May 18

Edit: To answer question directly (I guess?), yes, the CSR only matters during new-cert, as it serves no purpose up until then.

That’s correct


Going into the analysis, I expected there to be something tying the CSR into the domain auth directly, not just an indirect link trough the account key (eg “this auth is for signing this particular certificate” or “this auth and this car are part of a session”). It looks like acme2 does that… But I was surprised to not see this during v1.

I’m writing some bookkeeping code to track the various endpoint calls and make sure all challenges are completed (this way any lost pending ones can be identified).

In the case of a failed cert with a retry, it seems like a successfully completed challenge would not have to be completed again if done within a short timespan. I’m not planning on doing this – it just seems that acme works like that.


Even still it doesn’t. @_az and @cpu were actually describing what happens with the ACMEv2 process where you provide a CSR twice.

With either version authorizations are bound to the account key and not any keypair provided in the CSR.

The timespan is 30 days:

This old API announcement explains how it works at the API level:


ah! okay. I just glanced at the spec and saw the domains were provided early on as an ‘order’

Ah. This makes a lot of sense now - our client was written before this change.

One more question about the “Pending Authorizations” ratelimit on the LetsEncrypt page

Is an item a “Pending Authorization” if the two following criteria are met?

  • Challenges were created via /acme/new-authz
  • No challenges from that packet response were triggered for validation via the returned ‘url’

I think that’s what the definition is, but want to confirm. if so, there is a bug in my client (via acme-tiny) where a failure in a preliminary check to ensure the challenge works abort early and not trigger a validation.


Correct. They also expire after 7 days.

Note that you can deactivate the authorization instead of completing it if you know it isn’t going to work:


Thanks! A handful of posts here seemed to recommend failure over deactivation… but that may have been because of a (since fixed) bug in calculating rate limits. It seems another related update was to recycle the pending auth for 7 days on subsequent requests (so requesting an auth for same domain 301 times only counts as 1 auth, not 301).

I’ve updated our code to be aware of this, and opened a ticket on acme-tiny. It looks like many people here and on stack-overflow have had this issue for a few years, but never tracked down the exact cause.