5.3.  It is common in deployment for the entity terminating TLS for HTTPS to be different from the entity operating the logical HTTPS server, with a "request routing" layer in the middle.  For example, an ACME having the resource check that requests have the same string in their "url" fields. <del> 5.3.1. </del>  The "url" header parameter specifies the URL to which this JWS object is directed RFC3986.  The "url" parameter MUST be carried in the protected header of the JWS.  The value of the "url" header MUST be a JSON string representing the URL. <del> 5.4. </del>  In order to protect ACME resources from any possible replay attacks, ACME requests have a mandatory anti-replay mechanism.  This mechanism value for each response, keep a list of issued nonces, and strike nonces from this list as they are used. <del> 5.4.1. </del>  The "Replay-Nonce" header field includes a server-generated value that the server can use to detect unauthorized replay in future The Replay-Nonce header field SHOULD NOT be included in HTTP request messages. <del> 5.4.2. </del>  The "nonce" header parameter provides a unique value that enables the verifier of a JWS to recognize when replay has occurred.  The "nonce" according to this encoding, then the verifier MUST reject the JWS as malformed. <del> 5.5. </del>  Creation of resources can be rate limited to ensure fair usage and prevent abuse.  Once the rate limit is exceeded, the server MUST header pointing to documentation about the specific hit rate limits using the "rate-limit" relation. <del> 5.6. </del>  Errors can be reported in ACME both at the HTTP layer and within ACME payloads.  ACME servers can return responses with an HTTP error registration in order to recover from a key compromise or proactively mitigate the impact of an unnoticed key compromise. <del> To change the key associated with an account, the client sends a POST request containing a key-change object with the following fields: </del>  The JWK representation of the original key (i.e., the client's current account key) The JWK representation of the new key <del> The JWS of this POST must have two signatures: one signature from the existing key on the account, and one signature from the new key that the client proposes to use.  This demonstrates that the client actually has control of the private key corresponding to the new public key.  The protected header must contain a JWK field containing the current account key. </del>  On receiving key-change request, the server MUST perform the following steps in addition to the typical JWS validation: <del> Check that the JWS protected header contains a "jwk" field containing a key that matches a currently active account. </del>  <del> Check that there are exactly two signatures on the JWS. </del>  <del> Check that one of the signatures validates using the account key from (1). </del>  <del> Check that the "key" field contains a well-formed JWK that meets key strength requirements. </del>  <del> Check that the "key" field is not equivalent to the current account key or any other currently active account key. </del>  <del> Check that one of the two signatures on the JWS validates using the JWK from the "key" field. </del>  If all of these checks pass, then the server updates the corresponding registration by replacing the old account key with the

As discussed (too ambiguously) at IETF 96, this refactor uses two nested JWS objects instead of one parallel JWS object. This preserves the pattern that every ACME message sent by the client is signed by exactly one account key, and saves clients from having to search through multiple signatures in the verification process.
Looking at the current mechanism in a little more detail, I have a few concerns with the parallel-signature approach that's there now: It's not clear which signature is by the old key and which is by the new key, and the new key doesn't sign over the old key. Both signatures have to include the parameter, so this request burns two nonces unnecessarily The server's JWS checking code now has to switch between validating one signature and two Lots of JWS implementations don't support multiple signatures If not for this, we could require the flattened JSON serialization You need a lot of duplication to deal with the copy/paste attacks (cf. ). (On the other hand, I like that both signatures cover the parameter; reduces replayability.) I would propose that we change the signatures from parallel back to serial, as illustrated below. It would cost a little bit of payload bloat (due to another layer of base64url encoding), but I think the benefits in terms of conceptual simplicity would be worth it.
Just noticed that if we keep to one signature per object, you can do nice stuff like this on the server:

5.3. <ins> At several points in the protocol, it is necessary for the server to determine whether two JWK objects represent the same key.  In performing these checks, the server MUST consider two JWKs to match if and only if they have the identical values in all fields included in the computation of a JWK thumbprint for that key.  That is, the keys must have the same "kty" value and contain identical values in the fields used in the computation of a JWK thumbprint for that key type: "RSA": "n", "e" "EC": "crv", "x", "y" Note that this comparison is equivalent to computing the JWK thumbprints of the two keys and comparing thumbprints.  The only difference is that there is no requirement for a hash computation (and thus it is independent of the choice of hash function) and no risk of hash collision. 5.4. </ins> It is common in deployment for the entity terminating TLS for HTTPS to be different from the entity operating the logical HTTPS server, with a "request routing" layer in the middle.  For example, an ACME having the resource check that requests have the same string in their "url" fields.  <ins> 5.4.1. </ins> The "url" header parameter specifies the URL to which this JWS object is directed RFC3986.  The "url" parameter MUST be carried in the protected header of the JWS.  The value of the "url" header MUST be a JSON string representing the URL.  <ins> 5.5. </ins> In order to protect ACME resources from any possible replay attacks, ACME requests have a mandatory anti-replay mechanism.  This mechanism value for each response, keep a list of issued nonces, and strike nonces from this list as they are used.  <ins> 5.5.1. </ins> The "Replay-Nonce" header field includes a server-generated value that the server can use to detect unauthorized replay in future The Replay-Nonce header field SHOULD NOT be included in HTTP request messages.  <ins> 5.5.2. </ins> The "nonce" header parameter provides a unique value that enables the verifier of a JWS to recognize when replay has occurred.  The "nonce" according to this encoding, then the verifier MUST reject the JWS as malformed.  <ins> 5.6. </ins> Creation of resources can be rate limited to ensure fair usage and prevent abuse.  Once the rate limit is exceeded, the server MUST header pointing to documentation about the specific hit rate limits using the "rate-limit" relation.  <ins> 5.7. </ins> Errors can be reported in ACME both at the HTTP layer and within ACME payloads.  ACME servers can return responses with an HTTP error registration in order to recover from a key compromise or proactively mitigate the impact of an unnoticed key compromise.  <ins> To change the key associated with an account, the client first constructs a key-change object describing the change that it would like the server to make: The URL for account being modified.  The content of this field MUST be the exact string provided in the Location header field in response to the new-registration request that created the account. </ins> The JWK representation of the original key (i.e., the client's current account key) The JWK representation of the new key  <ins> Both of these thumbprints MUST be computed as specified in RFC7638, using the SHA-256 digest.  The values in the "oldKey" and "newKey" fields MUST be the base64url encodings of the thumbprints. The client then encapsulates the key-change object in a JWS, signed with the client's current account key (i.e., the key matching the "oldKey" value). This inner JWS then become the payload of the JWS that the client sends to the server.  The outer JWS is signed with the key pair that the the client wishes to have the server use as its account key (i.e., the key pair matching the "newKey" value).  The client sends this outer JWS in a POST request to the server's "key-change" resource. The outer JWS MUST meet the normal requirements for an ACME JWS (see request-authentication).  The inner JWS MUST meet the normal requirements, with the following exceptions: The inner JWS MUST have the same "url" parameter as the outer JWS. The inner JWS is NOT REQUIRED to have a "nonce" parameter.  The server MUST ignore any value provided for the "nonce" header parameter. This transaction has signatures from both the old and new keys so that the server can verify that the holders of the two keys both agree to the change.  The signatures are nested to preserve the property that all signatures on POST messages are signed by exactly one key. </ins> On receiving key-change request, the server MUST perform the following steps in addition to the typical JWS validation:  <ins> Check that the payload of the JWS is a well-formed JWS object (the "inner JWS") Check that the JWS protected header of the inner JWS has a "jwk" field containing a key that matches a currently active account Check that the inner JWS verifies using the key in its "jwk" field </ins>  <ins> Check that the payload of the inner JWS is a well-formed key- change object (as described above) </ins>  <ins> Check that the "url" parameters of the inner and outer JWSs are the same </ins>  <ins> Check that the "account" field of the key-change object contains the URL for the registration matching the old key </ins>  <ins> Check that the "oldKey" field of the key-change object contains the thumbprint of the key used to sign the inner JWS </ins>  <ins> Check that the "newKey" field of the key-change object contains the thumbprint of the key used to sign the outer JWS </ins> If all of these checks pass, then the server updates the corresponding registration by replacing the old account key with the


6.4.1.  To download the issued certificate, the client simply sends a GET request to the certificate URL. "scope" field of the authorization to the URI for that application. Authorization resources are created by the server in response to <del> certificate applications submitted by an account key holder; their URLs are provided to the client in "authorization" requirement objects.  The authorization object is implicitly tied to the account key used to sign the new-application request. </del>  When a client receives an application from the server with an "authorization" requirement, it downloads the authorization resource <del> by sending a GET request to the indicated URL. </del>  6.5.1.

As discussed at IETF 96, even with the new-app flow, it is still useful to be able to request authorization outside of an issuance transaction. This PR re-adds the new-authz transaction.

6.4.1. <ins> The application process described above presumes that authorization objects are created reactively, in response to an application for issuance.  Some servers may also wish to enable clients to obtain authorization for an identifier proactively, outside of the context of a specific issuance.  For example, a client hosting virtual servers for a collection of names might wish to obtain authorization before any servers are created, and only create a certificate when a server starts up. In some cases, a CA running an ACME server might have a completely external, non-ACME process for authorizing a client to issue for an identifier.  In these case, the CA should provision its ACME server with authorization objects corresponding to thsee authorizations and reflect them as alread-valid requirements in any issuance applications requested by the client. If a CA wishes to allow pre-authorization within ACME, it can offer a "new authorization" resource in its directory by adding the key "new- authz" with a URL for the new authorization resource. To request authorization for an identifier, the client sends a POST request to the new-authorization resource specifying the identifier for which authorization is being requested and how the server should behave with respect to existing authorizations for this identifier. The identifier that the account is authorized to represent The type of identifier. The identifier itself. How an existing authorization should be handled.  Possible values are "accept" and "require". Before processing the authorization request, the server SHOULD determine whether it is willing to issue certificates for the identifier.  For example, the server should check that the identifier is of a supported type.  Servers might also check names against a blacklist of known high-value identifiers.  If the server is unwilling to issue for the identifier, it SHOULD return a 403 (Forbidden) error, with a problem document describing the reason for the rejection. If the authorization request specifies "existing" with a value of "accept" or "require", before proceeding, the server SHOULD determine whether there are any existing, valid authorization resources for the account and given identifier.  If one or more such authorizations exists, a response SHOULD returned with status code 303 (See Other) and a Location header pointing to the existing resource URL; processing of the request then stops.  If there are multiple such authorizations, the authorization with the latest expiry date SHOULD be returned.  If no existing authorizations were found and the value for "existing" was "require", then the server MUST return status code 404 (Not Found); if it was "accept" or was any other value or was absent, processing continues as follows. If the server is willing to proceed, it builds a pending authorization object from the inputs submitted by the client. "identifier" the identifier submitted by the client "status": MUST be "pending" unless the server has out-of-band information about the client's authorization status "challenges" and "combinations": As selected by the server's policy for this identifier The server allocates a new URI for this authorization, and returns a 201 (Created) response, with the authorization URI in a Location header field, and the JSON authorization object in the body.  The client then follows the process described in identifier-authorization to complete the authorization process. 6.4.2. </ins> To download the issued certificate, the client simply sends a GET request to the certificate URL. "scope" field of the authorization to the URI for that application. Authorization resources are created by the server in response to  <ins> certificate applications or authorization requests submitted by an account key holder; their URLs are provided to the client in the responses to these requests.  The authorization object is implicitly tied to the account key used to sign the request. </ins> When a client receives an application from the server with an "authorization" requirement, it downloads the authorization resource  <ins> by sending a GET request to the indicated URL.  If the client initiates authorization using a request to the new authorization resource, it will have already recevied the pending authorization object in the response to that request. </ins> 6.5.1.


server MUST reject the request as unauthorized. Except for the directory resource, all ACME resources are addressed <del> with URLs provided to the client by the server.  In such cases, the client MUST set the "url" field to the exact string provided by the server (rather than performing any re-encoding on the URL). </del>  5.3.1.

As discussed at IETF 96, ACME server processing of the "url" field should perform an exact string equality test between the URL string provided to the client and the string provided by the client in its "url" parameter. Effectively, this turns "url" values into opaque service labels, which just happen to have the side effect of being able to direct an HTTP request.

server MUST reject the request as unauthorized. Except for the directory resource, all ACME resources are addressed  <ins> with URLs provided to the client by the server.  For these resources, the client MUST set the "url" field to the exact string provided by the server (rather than performing any re-encoding on the URL).  The server SHOULD perform the corresponding string equality check, configuring each resource with the URL string provided to clients and having the resource check that requests have the same string in their "url" fields. </ins> 5.3.1.


server.  The client generates an asymmetric key pair and associates this key pair with a set of contact information by signing the contact information.  The server acknowledges the registration by <del> replying with a registration object echoing the client's input.  The server can also provide terms of service at this stage, which the client can present to a human user. </del>  Once the client is registered, there are three major steps it needs to take to get a certificate: structure: The public key of the account key pair, encoded as a JSON Web Key <del> object RFC7517. </del>  The status of this registration.  Possible values are: "valid", "deactivated", and "revoked". "deactivated" should be used to issues related to this authorization.  For example, the server may wish to notify the client about server-initiated revocation. <del> A URI referring to a subscriber agreement or terms of service provided by the server (see below).  Including this field indicates the client's agreement with the referenced terms. </del>  <del> A URI from which an array of URIs for application objects submitted by this account can be fetched via a GET request. </del>  6.1.2.1. If the server wishes to present the client with terms under which the ACME service is to be used, it MUST indicate the URI where such terms <del> can be accessed in a Link header with link relation "terms-of- service".  As noted above, the client may indicate its agreement with these terms by updating its registration to include the "agreement" field, with the terms URI as its value.  When these terms change in a way that requires an agreement update, the server MUST use a different URI in the Link header. </del>  If the client wishes to update this information in the future, it sends a POST request with updated information to the registration

This mitigates confusion about how clients should respond when terms of service change.
Updated based on review. Took out the echoing of the field on subsequent requests, because it makes things simpler and clearer.

server.  The client generates an asymmetric key pair and associates this key pair with a set of contact information by signing the contact information.  The server acknowledges the registration by  <ins> replying with a registration object echoing the client's input. </ins> Once the client is registered, there are three major steps it needs to take to get a certificate: structure: The public key of the account key pair, encoded as a JSON Web Key  <ins> object RFC7517.  This field is not updateable by the client. </ins> The status of this registration.  Possible values are: "valid", "deactivated", and "revoked". "deactivated" should be used to issues related to this authorization.  For example, the server may wish to notify the client about server-initiated revocation.  <ins> Including this field in a new-registration request, with a value of true, indicates the client's agreement with the terms of service.  This field is not updateable by the client. </ins>  <ins> A URI from which a list of authorizations submitted by this account can be fetched via a GET request.  The result of the GET request MUST be a JSON object whose "applications" field is an array of strings, where each string is the URI of an authorization belonging to this registration.  The server SHOULD include pending applications, and SHOULD NOT include applications that are invalid.  The server MAY return an incomplete list, along with a Link header with link relation "next" indicating a URL to retrieve further entries.  This field is not updateable by the client. </ins> 6.1.2.1. If the server wishes to present the client with terms under which the ACME service is to be used, it MUST indicate the URI where such terms  <ins> can be accessed in the "terms-of-service" subfield of the "meta" field in the directory object, and the server SHOULD reject new- registration requests that do not contain "terms-of-service-agreed": true. </ins> If the client wishes to update this information in the future, it sends a POST request with updated information to the registration


consider this authorization valid for all applications until the authorization expires. [[ Open issue: More flexible scoping? ]] <del> The challenges that the client needs to fulfill in order to prove </del>  possession of the identifier (for pending authorizations).  For final authorizations, the challenges that were used.  Each array entry is a dictionary with parameters required to validate the <del> challenge, as specified in identifier-validation-challenges. A collection of sets of challenges, each of which would be sufficient to prove possession of the identifier.  Clients complete a set of challenges that covers at least one set in this array.  Challenges are identified by their indices in the challenges array.  If no "combinations" element is included in an authorization object, the client completes all challenges. </del>  The only type of identifier defined by this specification is a fully- qualified domain name (type: "dns").  The value of the identifier status of "valid" or "invalid", corresponding to whether it considers the account authorized for the identifier.  If the final state is "valid", the server MUST add an "expires" field to the authorization. <del> When finalizing an authorization, the server MAY remove the "combinations" field (if present) or remove any challenges still pending.  The server SHOULD NOT remove challenges with status "invalid". </del>  Usually, the validation process will take some time, so the client will need to poll the authorization resource to see when it is "http-05" - but not one labeled "http-04", since challenge in version -04 was compatible with one in version -04. ]] <del> [[ Editor's Note: Operators SHOULD NOT issue "combinations" arrays in authorization objects that require the client to perform multiple challenges over the same type, e.g., ["http-03", "http-05"]. Challenges within a type are testing the same capability of the domain owner, and it may not be possible to satisfy both at once. ]] </del> 7.1. Several of the challenges in this document makes use of a key

This is a fairly complicated part of the protocol, and not used in practice. For instance, in Let's Encrypt's implementation, there are always three challenges, any one of which may be fulfilled by the client. After this change, all challenges are considered to be combined with an "OR." That is, any challenge within an authorization may be completed to make the authorization valid. Authorizations within the new-application object are considered to be combined with an "AND." That is, all of them must become valid before the certificate will be issued. The combination of the two means that we have similar expressiveness as before, even without the combinations array.

consider this authorization valid for all applications until the authorization expires. [[ Open issue: More flexible scoping? ]]  <ins> The challenges that the client can fulfill in order to prove </ins> possession of the identifier (for pending authorizations).  For final authorizations, the challenges that were used.  Each array entry is a dictionary with parameters required to validate the  <ins> challenge, as specified in identifier-validation-challenges.  A client should attempt to fulfill at most one of these challenges, and a server should consider any one of the challenges sufficient to make the authorization valid. </ins> The only type of identifier defined by this specification is a fully- qualified domain name (type: "dns").  The value of the identifier status of "valid" or "invalid", corresponding to whether it considers the account authorized for the identifier.  If the final state is "valid", the server MUST add an "expires" field to the authorization.  <ins> When finalizing an authorization, the server MAY remove challenges other than the one that was completed.  The server SHOULD NOT remove challenges with status "invalid". </ins> Usually, the validation process will take some time, so the client will need to poll the authorization resource to see when it is "http-05" - but not one labeled "http-04", since challenge in version -04 was compatible with one in version -04. ]]  7.1. Several of the challenges in this document makes use of a key


Link header with link relation "next" indicating a URL to retrieve further entries. <del> A URI from which a list of certificates issued for this account can be fetched via a GET request.  The result of the GET request MUST be a JSON object whose "certificates" field is an array of strings, where each string is the URI of a certificate.  The server SHOULD NOT include expired or revoked certificates.  The server MAY return an incomplete list, along with a Link header with link relation "next" indicating a URL to retrieve further entries. </del> 6.1.3. An ACME registration resource represents a client's request for a

The registration object already contains a list of certificate applications, and each application contains a link to the resulting certificate if one was issued. This reduces the number of primitives that an ACME server has to support.

Link header with link relation "next" indicating a URL to retrieve further entries.  6.1.3. An ACME registration resource represents a client's request for a


A "key-change" resource <del> For the "new-X" resources above, the server MUST have exactly one resource for each function.  This resource may be addressed by multiple URIs, but all must provide equivalent functionality. </del>  ACME uses different URIs for different management functions.  Each function is listed in a directory along with its corresponding URI,

Prior to this PR the specification seems to be contradictory, indicating that the "new-X" resources must not be duplicated, but that they can live at different URIs. It's not clear to me what this MUST is trying to prevent, especially in light of an allowance of multiple URIs if functionality is equivalent. Similarly, while the text prior to this PR says "new-X" I believe the intentions of the statements that follow would include some of the resources that have been added since, e.g. "key-change". This PR updates the "new-X" language to include the additional singular resources and removes the MUST. If I've missed the mark in this clarification perhaps someone who was involved with the spec at the time of this paragraph's writing can help guide us to something both clear & accurate to the original spirit.

A "key-change" resource  <ins> For the singular resources above ("directory", "new-registration", "new-application", "revoke-certificate", and "key-change") the resource may be addressed by multiple URIs, but all must provide equivalent functionality. </ins> ACME uses different URIs for different management functions.  Each function is listed in a directory along with its corresponding URI,


The string "proofOfPossession-01" <del> An array of certificates, in Base64-encoded DER format, that </del>  contain acceptable public keys. In response to this challenge, the client uses the private key

They should be base64url rather than base64, for symmetry with rest of spec.
Don't think this is totally necessary, since we say at the front that when we say "base64", we mean the special variant. But happy to be clearer here.

The string "proofOfPossession-01"  <ins> An array of certificates, in Base64url-encoded DER format, that </ins> contain acceptable public keys. In response to this challenge, the client uses the private key


If the server wishes to present the client with terms under which the ACME service is to be used, it MUST indicate the URI where such terms can be accessed in the "terms-of-service" subfield of the "meta" <del> field in the directory object, and the server SHOULD reject new- registration requests that do not contain "terms-of-service-agreed": true. </del>  If the client wishes to update this information in the future, it sends a POST request with updated information to the registration 6.3.1.  A client may wish to change the public key that is associated with a registration in order to recover from a key compromise or proactively mitigate the impact of an unnoticed key compromise. responds with an error status code and a problem document describing the error. <del> 6.3.2. </del>  A client may deactivate an account by posting a signed update to the server with a status field of "deactivated."  Clients may wish to do

Right now, it's not clear when the client needs to agree to the server's terms, and what the server should do if it needs the client to re-agree. This PR addresses both with a dedicated error code and some related behaviors.

If the server wishes to present the client with terms under which the ACME service is to be used, it MUST indicate the URI where such terms can be accessed in the "terms-of-service" subfield of the "meta"  <ins> field in the directory object, and the server MUST reject new- registration requests that do not have the "terms-of-service-agreed" set to "true". </ins> If the client wishes to update this information in the future, it sends a POST request with updated information to the registration 6.3.1. <ins> As described above, a client can indicate its agreement with the CA's terms of service by setting the "terms-of-service-agreed" field in its registration object to "true". If the server has changed its terms of service since a client initially agreed, and the server is unwilling to process a request without explicit agreement to the new terms, then it MUST return an error response with status code 403 (Forbidden) and type "urn:ietf:params:acme:error:agreementRequired".  This response MUST include a Link header with link relation "terms-of-service" and the latest terms-of-service URL. The problem document returned with the error MUST also include an "instance" field, indicating a URL that the client should direct a human user to visit in order for instructions on how to agree to the terms. 6.3.2. </ins> A client may wish to change the public key that is associated with a registration in order to recover from a key compromise or proactively mitigate the impact of an unnoticed key compromise. responds with an error status code and a problem document describing the error.  <ins> 6.3.3. </ins> A client may deactivate an account by posting a signed update to the server with a status field of "deactivated."  Clients may wish to do


The only type of identifier defined by this specification is a fully- qualified domain name (type: "dns").  The value of the identifier <del> MUST be the ASCII representation of the domain name.  Wildcard domain names (with "*" as the first label) MUST NOT be included in authorization requests. </del>  6.2.

requires IDNs be encoded in this way in order to be stored in the X509 certificate dNSNames field. Compliance with this RFC is one of the requirements of the CABForum which CAs are expected to adhere to. We already require domain names transmitted via ACME to use the ASCII encoding, this just formalizes how IDNs should be converted.

The only type of identifier defined by this specification is a fully- qualified domain name (type: "dns").  The value of the identifier  <ins> MUST be the ASCII representation of the domain name.  If a domain name contains Unicode characters it MUST be encoded using the rules defined in RFC3492.  Servers MUST verify any identifier values that begin with the ASCII Compatible Encoding prefix "xn-" as defined in RFC5890 are properly encoded.  Wildcard domain names (with "*" as the first label) MUST NOT be included in authorization requests. </ins> 6.2.


taken to fulfill the challenge, e.g., removing files that have been provisioned to a web server. <del> Presumably, the client's responses provide the server with enough information to validate one or more challenges.  The server is said to "finalize" the authorization when it has completed all the validations it is going to complete, and assigns the authorization a </del>  status of "valid" or "invalid", corresponding to whether it considers the account authorized for the identifier.  If the final state is "valid", the server MUST add an "expires" field to the authorization.

With the combinations array now removed, this is no longer accurate.
If you could re-wrap that paragraph to get rid of the short line, LGTM.
I tend not to re-wrap Markdown on edits because it makes diffs & blames more meaningful. Do you feel strongly about the wrapping?

taken to fulfill the challenge, e.g., removing files that have been provisioned to a web server.  <ins> The server is said to "finalize" the authorization when it has completed one of the validations, by assigning the authorization a </ins> status of "valid" or "invalid", corresponding to whether it considers the account authorized for the identifier.  If the final state is "valid", the server MUST add an "expires" field to the authorization.


The JWK representation of the new key The client then encapsulates the key-change object in a JWS, signed <del> with the client's current account key (i.e., the key matching the "oldKey" value). This inner JWS then become the payload of the JWS that the client sends to the server.  The outer JWS is signed with the key pair that the the client wishes to have the server use as its account key (i.e., the key pair matching the "newKey" value).  The client sends this outer JWS in a POST request to the server's "key-change" resource. </del>  The outer JWS MUST meet the normal requirements for an ACME JWS (see request-authentication).  The inner JWS MUST meet the normal On receiving key-change request, the server MUST perform the following steps in addition to the typical JWS validation:  Check that the payload of the JWS is a well-formed JWS object (the "inner JWS") Check that the JWS protected header of the inner JWS has a "jwk" <del> field containing a key that matches a currently active account </del>  Check that the inner JWS verifies using the key in its "jwk" field the URL for the registration matching the old key Check that the "oldKey" field of the key-change object contains <del> the thumbprint of the key used to sign the inner JWS </del>  Check that the "newKey" field of the key-change object contains <del> the thumbprint of the key used to sign the outer JWS </del>  If all of these checks pass, then the server updates the corresponding registration by replacing the old account key with the

Signing with the current account key allows servers to use the same message transport authentication that they use for other requests, simplifying the verification. Also fix two spots where we still described newKey/oldKey as thumbprints.
LGTM. I had only done that signing order to be forward-compatible with some imagined future recovery scheme, but if we decide to do that someday, that patch can differ in signature order as well as whatever else.

The JWK representation of the new key The client then encapsulates the key-change object in a JWS, signed  <ins> with the requested new account key (i.e., the key matching the "newKey" value). </ins> The outer JWS MUST meet the normal requirements for an ACME JWS (see request-authentication).  The inner JWS MUST meet the normal On receiving key-change request, the server MUST perform the following steps in addition to the typical JWS validation: <ins> Validate the POST request belongs to a currently active account, as described in Message Transport. </ins> Check that the payload of the JWS is a well-formed JWS object (the "inner JWS") Check that the JWS protected header of the inner JWS has a "jwk"  <ins> field. </ins> Check that the inner JWS verifies using the key in its "jwk" field the URL for the registration matching the old key Check that the "oldKey" field of the key-change object contains  <ins> the current account key. </ins> Check that the "newKey" field of the key-change object contains  <ins> the key used to sign the inner JWS. </ins> If all of these checks pass, then the server updates the corresponding registration by replacing the old account key with the


provided by the server (see below).  Including this field indicates the client's agreement with the referenced terms. <del> A URI from which a list of authorizations submitted by this account can be fetched via a GET request.  The result of the GET request MUST be a JSON object whose "applications" field is an array of strings, where each string is the URI of an authorization belonging to this registration.  The server SHOULD include pending applications, and SHOULD NOT include applications that are invalid.  The server MAY return an incomplete list, along with a Link header with link relation "next" indicating a URL to retrieve further entries. </del>  6.1.3. request is a stub registration object containing only the "contact" field. <del> The server MUST ignore any values provided in the "key", "authorizations", and "certificates" fields in registration bodies sent by the client, as well as any other fields that it does not recognize.  If new fields are specified in the future, the specification of those fields MUST describe whether they may be provided by the client. </del>  The server creates a registration object with the included contact information.  The "key" element of the registration is set to the If the client wishes to update this information in the future, it sends a POST request with updated information to the registration <del> URI.  The server MUST ignore any updates to the "key", "authorizations, or "certificates" fields, and MUST verify that the request is signed with the private key corresponding to the "key" field of the request before updating the registration. </del>  For example, to update the contact information in the above registration, the client could send the following request:

In the "applications" field of the registration resource is described in great detail. This is confusing for two reasons: both the text and the example registration object are still using the "authorization" term that applications replace. the text is written as if the applications should be directly embedded in the registration object returned. This PR addresses both issues by describing the "applications" field as an array of application URIs that the client can fetch. The example "registration" object is updated accordingly. The note indicating a server SHOULD include pending applications and SHOULD NOT include invalid applications remains as-is. The note indicating a server MAY return an incomplete list is removed - it is more complicated and with only URIs being returned, likely an unneeded optimization. Finally, in there are three fields that must be ignored by the server in a registration body: key, authorizations and certificates. This should be "key" and "applications" and is updated accordingly.
NAME feedback addressed, and conflicts w/ master resolved. Thanks for the :eyes: !

provided by the server (see below).  Including this field indicates the client's agreement with the referenced terms.  <ins> A URI from which an array of URIs for application objects submitted by this account can be fetched via a GET request. 6.1.2.1. Each registration object includes an applications URI from which a list of applications created by the registration can be fetched via GET request.  The result of the GET request MUST be a JSON object whose "applications" field is an array of URIs, each identifying an applications belonging to the registration.  The server SHOULD include pending applications, and SHOULD NOT include applications that are invalid in the array of URIs.  The server MAY return an incomplete list, along with a Link header with link relation "next" indicating a URL to retrieve further entries. </ins> 6.1.3. request is a stub registration object containing only the "contact" field.  <ins> The server MUST ignore any values provided in the "key", and "applications" fields in registration bodies sent by the client, as well as any other fields that it does not recognize.  If new fields are specified in the future, the specification of those fields MUST describe whether they may be provided by the client. </ins> The server creates a registration object with the included contact information.  The "key" element of the registration is set to the If the client wishes to update this information in the future, it sends a POST request with updated information to the registration  <ins> URI.  The server MUST ignore any updates to the "key", or "applications" fields or any other fields it does not recognize.  The server MUST verify that the request is signed with the private key corresponding to the "key" field of the request before updating the registration. </ins> For example, to update the contact information in the above registration, the client could send the following request:


"alg" <del> "jwk" </del>  "nonce" (defined below) "url" (defined below) <del> Note that this implies that GET requests are not authenticated. Servers MUST NOT respond to GET requests for resources that might be considered sensitive. </del>  In the examples below, JWS objects are shown in the JSON or flattened JSON serialization, with the protected header and payload expressed 5.3. <del> At several points in the protocol, it is necessary for the server to </del>  determine whether two JSON Web Key (JWK) RFC7517 objects represent the same key.  In performing these checks, the server MUST consider two JWKs to match if and only if they have the identical values in

Previously, each authenticated POST included a copy of its public key in the JWS protected header. Servers were required to canonicalize this key in some way and look it up in a database, then verify the payload. However, servers also had the option of verifying the payload, and then looking up the key in the database. This opened up a category of potential bugs based on truncated database fields or hash collisions, where an attacker could craft a key pair the would potentially be matched to someone else's account. Incidental benefits: Switching to kid makes payloads somewhat smaller, and removes the need to define key equality in the ACME spec.
Updated based on feedback.
Updated. Rather than have a switch/case about how to authenticate revoke-cert, I split it into two resources, authenticated different ways: one by account, one by cert key.

"alg"  <ins> "jwk" (only for requests to new-reg and revoke-cert resources) "kid" (for all other requests). </ins> "nonce" (defined below) "url" (defined below)  <ins> The "jwk" and "kid" fields are mutually exclusive.  Servers MUST reject requests that contain both. For new-reg requests, and for revoke-cert requests authenticated by certificate key, there MUST be a "jwk" field. For all other requests, there MUST be a "kid" field.  This field must contain the account URI received by POSTing to the new-reg resource. Note that authentication via signed POST implies that GET requests are not authenticated.  Servers MUST NOT respond to GET requests for resources that might be considered sensitive. </ins> In the examples below, JWS objects are shown in the JSON or flattened JSON serialization, with the protected header and payload expressed 5.3.  <ins> At some points in the protocol, it is necessary for the server to </ins> determine whether two JSON Web Key (JWK) RFC7517 objects represent the same key.  In performing these checks, the server MUST consider two JWKs to match if and only if they have the identical values in


To download the issued certificate, the client simply sends a GET request to the certificate URL. <del> The default format of the certificate is DER (application/pkix-cert). The client may request other formats by including an Accept header in its request.  For example, the client may use the media type application/x-pem-file to request the certificate in PEM format. The server provides metadata about the certificate in HTTP headers. In particular, the server MUST send one or more link relation header fields RFC5988 with relation "up", each indicating a single certificate resource for the issuer of this certificate.  The server MAY also include the "up" links from these resources to enable the client to build a full certificate chain. </del>  The server MUST also provide a link relation header field with relation "author" to indicate the application under which this

One of the most common ACME deployment failures observed in practice is for servers to be configured to serve only the end-entity certificate, without the intermediate certificates. This is a particularly pernicious problem because some browsers will still trust the resulting one-certificate chain, due to caching or fetching of URLs from Authority Information Access. But other browsers will not, resulting in a "works on my computer" problem. Arguably this configuration is the result of incorrect clients, but we should expect that most clients will do the easiest thing. This change aligns the easiest thing with the most correct thing.
You should include advice here on omitting trust anchors. TLS 1.3 has you could crib from (see the definition of ).
Hi, the PEM text is not correct: application/x-pem-file is not a registered media type, among other things. Will post to mailing list with details.

To download the issued certificate, the client simply sends a GET request to the certificate URL.  <ins> The default format of the certificate is PEM (application/x-pem-file) as specified by RFC7468.  This format should contain the end-entity certificate first, followed by any intermediate certificates that are needed to build a path to a trusted root.  Servers SHOULD NOT include self-signed trust anchors.  The client may request other formats by including an Accept header in its request.  For example, the client may use the media type application/pkix-cert to request the end- entity certificate in DER format. The server MAY provide one or more link relation header fields RFC5988 with relation "alternate".  Each such field should express an alternative certificate chain starting with the same end-entity certificate.  This can be used to express paths to various trust anchors.  Clients can fetch these alternates and use their own heuristics to decide which is optimal. </ins> The server MUST also provide a link relation header field with relation "author" to indicate the application under which this


Verify that the resulting URI is well-formed. <del> Dereference the URI using an HTTP GET request. </del>  Verify that the body of the response is well-formed key authorization.  The server SHOULD ignore whitespace characters at Compute SAN A and SAN B in the same way as the client. <del> Open a TLS connection to the domain name being validated on the requested port, presenting SAN A in the SNI field.  In the ClientHello initiating the TLS handshake, the server MUST include a server_name extension (i.e., SNI) containing SAN A.  The server SHOULD ensure that it does not reveal SAN B in any way when making the TLS connection, such that the presentation of SAN B in the returned certificate proves association with the client. </del>  Verify that the certificate contains a subjectAltName extension containing dNSName entries of SAN A and SAN B and no other

I spotted a typo/error introduced by this PR and submitted a follow-up: URL
Since we did not get consensus around , we should be explicit that HTTP is TCP port 80, and HTTPS is TCP port 443, and that holds for redirects as well. The is pretty much a minor wording change only.

Verify that the resulting URI is well-formed.  <ins> Dereference the URI using an HTTP GET request.  This request MUST be sent to TCP port 80 on the server. </ins> Verify that the body of the response is well-formed key authorization.  The server SHOULD ignore whitespace characters at Compute SAN A and SAN B in the same way as the client.  <ins> Open a TLS connection to TCP port 443 the domain name being validated on the requested port, presenting SAN A in the SNI field.  In the ClientHello initiating the TLS handshake, the server MUST include a server_name extension (i.e., SNI) containing SAN A.  The server SHOULD ensure that it does not reveal SAN B in any way when making the TLS connection, such that the presentation of SAN B in the returned certificate proves association with the client. </ins> Verify that the certificate contains a subjectAltName extension containing dNSName entries of SAN A and SAN B and no other


Compute SAN A and SAN B in the same way as the client. <del> Open a TLS connection to TCP port 443 the domain name being validated on the requested port, presenting SAN A in the SNI field.  In the ClientHello initiating the TLS handshake, the server MUST include a server_name extension (i.e., SNI) containing SAN A.  The server SHOULD ensure that it does not reveal SAN B in any way when making the TLS connection, such that the presentation of SAN B in the returned certificate proves association with the client. </del>  Verify that the certificate contains a subjectAltName extension containing dNSName entries of SAN A and SAN B and no other

Pull request was recently merged to clarify that HTTP and TLS challenge requests must use port 80 and 443 respectively. The "TLS with Server Name Indication (TLS SNI)" section was updated to read: This is a typo ("port 443 the domain name") and also still includes the phrase "on the requested port", which is no longer true. This PR updates the SNI challenge description to fix the typo and to explicitly say that the server MUST use port 443 in the same style/manner as the HTTP edit from .
Thanks for fixing my lame typos

Compute SAN A and SAN B in the same way as the client.  <ins> Open a TLS connection to the domain name being validated, presenting SAN A in the SNI field.  This connection MUST be sent to TCP port 443 on the server.  In the ClientHello initiating the TLS handshake, the server MUST include a server_name extension (i.e., SNI) containing SAN A.  The server SHOULD ensure that it does not reveal SAN B in any way when making the TLS connection, such that the presentation of SAN B in the returned certificate proves association with the client. </ins> Verify that the certificate contains a subjectAltName extension containing dNSName entries of SAN A and SAN B and no other


are specified in the future, the specification of those fields MUST describe whether they may be provided by the client.  The server creates a registration object with the included contact information.  The "key" element of the registration is set to the public key used to verify the JWS (i.e., the "jwk" element of the JWS

As far as I am aware there has been no explicit use case for this and Boulder explicitly disallows URIs to be used. should be the only explicitly supported URI type in the spec and others should be left up to implementing CAs to document.
Conversation on-list went more in the direction of specifying that providing any contact with an unrecognized URI scheme should result in a hard error of . Renaming appropriately.

are specified in the future, the specification of those fields MUST describe whether they may be provided by the client. <ins> The server SHOULD validate that the contact URLs in the "contact" field are valid and supported by the server.  If the client provides the server with an invalid or unsupported contact URL, then the server MUST return an error of type "invalidContact", with a description describing the error and what types of contact URL the server considers acceptable. </ins> The server creates a registration object with the included contact information.  The "key" element of the registration is set to the public key used to verify the JWS (i.e., the "jwk" element of the JWS


can be accessed in the "terms-of-service" subfield of the "meta" field in the directory object, and the server MUST reject new-account requests that do not have the "terms-of-service-agreed" set to <del> "true". </del>  If the client wishes to update this information in the future, it sends a POST request with updated information to the account URI. CAs that use ACME to automate issuance will need to ensure that their servers perform all necessary checks before issuing.  10. There are certain factors that arise in operational reality that

It would be nice if it could be clarified whether "--agree-tos"-like switches that don't require the user to whitelist specific TOS versions are acceptable in ACME clients. certbot has one. On the other hand, the author of acmetool refuses to implement "--agree-tos"-like functionality without clarification in the spec, making it impossible to completely automate renewal with certbot. (hlandau/acme). If it isn't acceptable then we have the absurd situation of the de-facto official client being out of spec. (Note: I accidentally opened the issue against the wrong repo first (URL).)
There's a limit to what we can do here, because switches like this are not part of the protocol. We can say, however, that clients SHOULD NOT auto-agree by default (so that there's some user interaction at some point, even just at config time), and that CAs need to keep in mind that clients can automate. I'll post a PR shortly.
Thanks for the quick reply, but pr doesn't really answer the question. The question wasn't about the default case (ie, it's not about doing away with --agree-tos entirely), but about giving users the choice to blanket accept future versions of TOS by continued usage, after the initial configuration / initial acceptance of TOS, instead of having to change a config file everytime a new TOS is rolled out. From your answer and PR, I'm still not sure what your opinion on that question is.
Note that the protocol specifically handles only initial acceptance. If the CA wants a user to explicitly agree to a new ToS (this is exceptionally rare - most ToS have auto-update language), it does so by sending an error message with a link to a webpage with instructions for agreeing anew. So the only question that needs to be answered is whether a user can specify agreement to the current terms on initially running the client.
LE does it, breaking users renewals (for acmetool users). I'm concerned with automating renewals (and also automated from-scratch deployments), and this issue is specifically about keeping setups working without manual intervention. This is currently possible with certbot and not possible with acmetool, because the author is unsure if the spec allows what certbot already implements. "An error message with a link to a webpage" means broken automation (for acmetool, currently).
This is only an issue with the older revision, which is what Let's Encrypt currently implements. The current revision of the specification has clarified matters in this regard and it is unlikely, at least for Let's Encrypt, that the need for manual re-assent with regard to acmetool will occur again, especially after Let's Encrypt starts supporting . So this issue has already been rectified in the specification.
NAME LE does not require explicit agreement to new ToS. See the Subscriber Agreement at URL

can be accessed in the "terms-of-service" subfield of the "meta" field in the directory object, and the server MUST reject new-account requests that do not have the "terms-of-service-agreed" set to  <ins> "true".  Clients SHOULD NOT automatically agree to terms by default. Rather, they SHOULD require some user interaction for agreement to terms. </ins> If the client wishes to update this information in the future, it sends a POST request with updated information to the account URI. CAs that use ACME to automate issuance will need to ensure that their servers perform all necessary checks before issuing. <ins> CAs using ACME to allow clients to agree to terms of service should keep in mind that ACME clients can automate this agreement, possibly not involving a human user.  If a CA wishes to have stronger evidence of user consent, it may present an out-of-band requirement or challenge to require human involvement. </ins> 10. There are certain factors that arise in operational reality that


the date format defined in For pending orders, the authorizations that the client needs to <del> complete before the requested certificate can be granted (see </del>  identifier-authorization).  For final orders, the authorizations <del> that were completed.  Each entry is a dictionary with parameters describing the authorization: </del>  The status of the authorization.  This field MUST have the same value as it does in the underlying authorization object. A URL for the certificate that has been issued in response to this order. <del> The elements of the "authorizations" array are immutable once set, except for their "status" fields.  If any other part of the object changes after the object is created, the client MUST consider the order invalid. </del>  The "authorizations" array in the challenge SHOULD reflect all authorizations that the CA takes into account in deciding to issue, The order object returned by the server represents a promise that if the client fulfills the server's requirements before the "expires" time, then the server will issue the requested certificate.  In the <del> order object, any object in the "authorizations" array whose status is "pending" represents an authorization transaction that the client must complete before the server will issue the certificate (see identifier-authorization).  If the client fails to complete the required actions before the "expires" time, then the server SHOULD change the status of the order to "invalid" and MAY delete the order resource. </del>  The server MUST issue the requested certificate and update the order resource with a URL for the certificate as soon as the client has proactively issue the requested certificate and provide a URL for it in the "certificate" field of the order.  The server MUST, however, still list the completed authorizations in the "authorizations" <del> array, with the state "valid". </del>  Once the client believes it has fulfilled the server's requirements, it should send a GET request to the order resource to obtain its these requests.  The authorization object is implicitly tied to the account key used to sign the request. <del> When a client receives an order from the server with "pending" entry in the authorizations array, it downloads the authorization resource by sending a GET request to the indicated URL.  If the client initiates authorization using a request to the new authorization resource, it will have already recevied the pending authorization object in the response to that request. </del>  6.5.1.

As discussed at IETF 97, this PR removes the "requirements" abstraction, and changes the "requirements" field in an application/order object to be an "authorizations" field. This is a replacement for .
Let's Encrypt tell me that they have had a few reports of buggy clients creating enough pending authorizations to saturate their rate limits, so they need a way for clients to clear these out. These clients are also not keeping around authorization URLs, so they can't just go them. My proposed solution would be to re-add the "authorizations" field to the account object, which got lost in the refactor in or so. Together with deactivation, enabling clients to enumerate authorization URLs would solve this problem. You could also envision a more direct solution, offering an endpoint that just deletes all pending authorizations for a client or client+identifier.
This is definitely too specific to these buggy clients. For the flow, the list of orders is sufficient. It's true that technically you can create authorizations through a separate, optional, flow. But Let's Encrypt has no plans to implement that flow, because other CAs have said they cannot / would not implement it, so Let's Encrypt implementing it would split the market. I'm inclined to say let's not complicate the protocol, and hypothetical clients that want to do the flow with some hypothetical server need to keep proper track of their authzs. Also, I think the particular issue with hitting limits for pending authzs can be solved in several ways without modifying the protocol.
If is merged, I would expect that a reasonable ACME server supporting new-authz would return an exiting authz, instead of giving a rate limit error. Or return existing authz from the beginning.
Closing as a result of WG decision at IETF 98

the date format defined in For pending orders, the authorizations that the client needs to  <ins> complete before the requested certificate can be issued (see </ins> identifier-authorization).  For final orders, the authorizations  <ins> that were completed.  Each entry is a URL from which an authorization can be fetched with a GET request. </ins> The status of the authorization.  This field MUST have the same value as it does in the underlying authorization object. A URL for the certificate that has been issued in response to this order.  <ins> The elements of the "authorizations" array are immutable once set. If any change is made to the array after the object is created, the client MUST consider the order invalid. </ins> The "authorizations" array in the challenge SHOULD reflect all authorizations that the CA takes into account in deciding to issue, The order object returned by the server represents a promise that if the client fulfills the server's requirements before the "expires" time, then the server will issue the requested certificate.  In the  <ins> order object, any authorization referenced in the "authorizations" array whose status is "pending" represents an authorization transaction that the client must complete before the server will issue the certificate (see identifier-authorization).  If the client fails to complete the required actions before the "expires" time, then the server SHOULD change the status of the order to "invalid" and MAY delete the application resource. </ins> The server MUST issue the requested certificate and update the order resource with a URL for the certificate as soon as the client has proactively issue the requested certificate and provide a URL for it in the "certificate" field of the order.  The server MUST, however, still list the completed authorizations in the "authorizations"  <ins> array. </ins> Once the client believes it has fulfilled the server's requirements, it should send a GET request to the order resource to obtain its these requests.  The authorization object is implicitly tied to the account key used to sign the request.  <ins> When a client receives an order from the server it downloads the authorization resource by sending a GET request to the indicated URL. If the client initiates authorization using a request to the new authorization resource, it will have already recevied the pending authorization object in the response to that request. </ins> 6.5.1.


8. <del> [[ Editor's Note: Should we create a registry for tokens that go into the various JSON objects used by this protocol, i.e., the field names in the JSON objects? ]] </del> 8.1. The "Well-Known URIs" registry should be updated with the following 8.6.1.  This registry lists values that are used within URN values that are provided in the "type" field of problem documents in ACME. Initial contents: The codes and descriptions in the table in errors above, with the Reference field set to point to this specification. <del> 8.6.2. </del>  This registry lists the types of resources that ACME servers may list in their directory objects. [[ RFC EDITOR: Please replace XXXX above with the RFC number assigned to this document ]] <del> 8.6.3. </del>  This registry lists the types of identifiers that ACME clients may request authorization to issue in certificates. [[ RFC EDITOR: Please replace XXXX above with the RFC number assigned to this document ]] <del> 8.6.4. </del>  This registry lists the ways that ACME servers can offer to validate control of an identifier.  The "Identifier Type" field in template

As discussed at IETF 97, this PR creates specification-required registries of fields in ACME objects, so that they can be extended in an orderly fashion. Currently only applies to account and order objects, not authorizations. Not for any ideological reason -- I would be happy to add that for symmetry if people think there might be a need..

8.  8.1. The "Well-Known URIs" registry should be updated with the following 8.6.1. <ins> This registry lists field names that are defined for use in ACME account objects.  Fields marked as "client configurable" may be included in a new-account request. Template: Field name: The string to be used as a key in the JSON dictionary Field type: The type of value to be provided, e.g., string, boolean, array of string Client configurable: Boolean indicating whether the server should accept values provided by the client Reference: Where this field is defined Initial contents: The fields and descriptions defined in account- objects. 8.6.2. This registry lists field names that are defined for use in ACME order objects.  Fields marked as "client configurable" may be included in a new-account request. Template: Field name: The string to be used as a key in the JSON dictionary Field type: The type of value to be provided, e.g., string, boolean, array of string Client configurable: Boolean indicating whether the server should accept values provided by the client Reference: Where this field is defined Initial contents: The fields and descriptions defined in order- objects. 8.6.3. </ins> This registry lists values that are used within URN values that are provided in the "type" field of problem documents in ACME. Initial contents: The codes and descriptions in the table in errors above, with the Reference field set to point to this specification.  <ins> 8.6.4. </ins> This registry lists the types of resources that ACME servers may list in their directory objects. [[ RFC EDITOR: Please replace XXXX above with the RFC number assigned to this document ]]  <ins> 8.6.5. </ins> This registry lists the types of identifiers that ACME clients may request authorization to issue in certificates. [[ RFC EDITOR: Please replace XXXX above with the RFC number assigned to this document ]]  <ins> 8.6.6. </ins> This registry lists the ways that ACME servers can offer to validate control of an identifier.  The "Identifier Type" field in template


PKI are trusted to verify that an applicant for a certificate legitimately represents the domain name(s) in the certificate.  Existing Web PKI certificate authorities tend to run on a set of ad <del> hoc protocols for certificate issuance and identity verification.  A typical user experience is something like: </del>  Generate a PKCS#10 RFC2986 Certificate Signing Request (CSR). 2. <del> The major guiding use case for ACME is obtaining certificates for Web sites (HTTPS RFC2818).  In that case, the server is intended to speak for one or more domains, and the process of certificate issuance is intended to verify that the server actually speaks for the domain(s). Different types of certificates reflect different kinds of CA verification of information about the certificate subject.  "Domain Validation" (DV) certificates are by far the most common type.  For DV validation, the CA merely verifies that the requester has effective control of the web server and/or DNS server for the domain, but does not explicitly attempt to verify their real-world identity. (This is as opposed to "Organization Validation" (OV) and "Extended Validation" (EV) certificates, where the process is intended to also verify the real-world identity of the requester.) </del>  DV certificate validation commonly checks claims about properties related to control of a domain name - properties that can be observed process can be represented and performed by Internet protocols with no out-of-band human intervention. <del> When deploying a current HTTPS server, an operator generally gets a prompt to generate a self-signed certificate.  When an operator deploys an ACME-compatible web server, the experience would be something like this: </del>  The ACME client prompts the operator for the intended domain name(s) that the web server is to stand for. required to keep the server functional and its credentials up-to- date. <del> The overall idea is that it's nearly as easy to deploy with a CA- issued certificate as a self-signed certificate, and that once the operator has done so, the process is self-sustaining with minimal manual intervention.  Close integration of ACME with HTTPS servers, for example, can allow the immediate and automated deployment of certificates as they are issued, optionally sparing the human administrator from additional configuration work. </del>  3. identifiers.  For example, all of the identifier validation challenges described in identifier-validation-challenges below address validation of domain names.  The use of ACME for other <del> protocols will require further specification, in order to describe </del>  how these identifiers are encoded in the protocol, and what types of validation challenges the server might require.

Several comprehensibility improvements to the first three sections of the draft RFC. For clarity about the contents of this pull request, please consider using the option (git CLI) or the "rich diff" option (GitHub web interface) to evaluate it, in preference to a traditional line-based diff.
NAME - I think these changes are valuable. Thank you! I don't personally have any qualms/feedback having read through the diff but it would help get more eyes on this if you emailed the ACME mailing list with a brief mention of your PR (even though it's strictly editorial I think more folks monitor the list than the Github repo).
LGTM. Thanks NAME !

PKI are trusted to verify that an applicant for a certificate legitimately represents the domain name(s) in the certificate. <ins> Different types of certificates reflect different kinds of CA verification of information about the certificate subject.  "Domain Validation" (DV) certificates are by far the most common type.  For DV validation, the CA merely verifies that the requester has effective control of the web server and/or DNS server for the domain, but does not explicitly attempt to verify their real-world identity. (This is as opposed to "Organization Validation" (OV) and "Extended Validation" (EV) certificates, where the process is intended to also verify the real-world identity of the requester.) </ins> Existing Web PKI certificate authorities tend to run on a set of ad  <ins> hoc protocols for certificate issuance and identity verification.  In the case of DV certificates, a typical user experience is something like: </ins> Generate a PKCS#10 RFC2986 Certificate Signing Request (CSR). 2.  <ins> The guiding use case for ACME is obtaining certificates for Web sites (HTTPS RFC2818).  In this case, the user's web server is intended to speak for one or more domains, and the process of certificate issuance is intended to verify that this server actually speaks for the domain(s). </ins> DV certificate validation commonly checks claims about properties related to control of a domain name - properties that can be observed process can be represented and performed by Internet protocols with no out-of-band human intervention.  <ins> At time of writing, when deploying an HTTPS server, an operator typically gets a prompt to generate a self-signed certificate.  If the operator were instead deploying an ACME-compatible web server, the experience would be something like this: </ins> The ACME client prompts the operator for the intended domain name(s) that the web server is to stand for. required to keep the server functional and its credentials up-to- date.  <ins> In this way, it would be nearly as easy to deploy with a CA-issued certificate as with a self-signed certificate.  Furthermore, the maintenance of that CA-issued certificate would require minimal manual intervention.  Such close integration of ACME with HTTPS servers would allow the immediate and automated deployment of certificates as they are issued, sparing the human administrator from much of the time-consuming work described in the previous section. </ins> 3. identifiers.  For example, all of the identifier validation challenges described in identifier-validation-challenges below address validation of domain names.  The use of ACME for other  <ins> identifiers will require further specification, in order to describe </ins> how these identifiers are encoded in the protocol, and what types of validation challenges the server might require.


The JWS MUST NOT have the value "none" in its "alg" field  The JWS Protected Header MUST include the following fields: "alg" are not authenticated.  Servers MUST NOT respond to GET requests for resources that might be considered sensitive.  In the examples below, JWS objects are shown in the JSON or flattened JSON serialization, with the protected header and payload expressed as base64url(content) instead of the actual base64-encoded value, so

Also: Forbid the use of MAC-based JWS algorithms (in case this wasn't obvious) Sort error codes alphabetically
The server needs to support whatever the client sends. We should have an error code for this, and a way for the server to specify what algorithms it does support in the error message.

The JWS MUST NOT have the value "none" in its "alg" field <ins> The JWS MUST NOT have a MAC-based algorithm in its "alg" field </ins> The JWS Protected Header MUST include the following fields: "alg" are not authenticated.  Servers MUST NOT respond to GET requests for resources that might be considered sensitive. <ins> If the client sends a JWS signed with an algorithm that the server does not support, then the server MUST return an error with status code 400 (Bad Request) and type "urn:ietf:params:acme:error:badSignatureAlgorithm".  The problem document returned with the error MUST include an "algorithms" field with an array of supported "alg" values. </ins> In the examples below, JWS objects are shown in the JSON or flattened JSON serialization, with the protected header and payload expressed as base64url(content) instead of the actual base64-encoded value, so


the future, the specification of those fields MUST describe whether they may be provided by the client.  The server SHOULD validate that the contact URLs in the "contact" field are valid and supported by the server.  If the client provides the server with an invalid or unsupported contact URL, then the

In some cases, it might be important for a client to know that a server has or has not processed an extension field. For example, if we had an extension that requested some higher level of assurance, then a client would want to know that the CA was going to provide that level of assurance. This PR specifies some rudimentary feature detection to support this objective.

the future, the specification of those fields MUST describe whether they may be provided by the client. <ins> In general, the server MUST ignore any fields in the request object that it does not recognize.  In particular, it MUST NOT reflect unrecognized fields in the resulting account object.  This allows clients to detect when servers do not support an extension field. </ins> The server SHOULD validate that the contact URLs in the "contact" field are valid and supported by the server.  If the client provides the server with an invalid or unsupported contact URL, then the


order. The elements of the "authorizations" array are immutable once set. <del> If any change is made to the array after the object is created, the client MUST consider the order invalid. </del>  The "authorizations" array in the challenge SHOULD reflect all authorizations that the CA takes into account in deciding to issue,

Implements from the mailing list. On Tue, Nov 29, 2016 at 04:32:33PM -0500, Richard Barnes wrote: than server implementations. With the current language, the client must check that authorizations have not changed. The language for the server should be MUST NOT change the elements of the "authorizations" array once set.'', unambiguously putting the responsibility where it squarely belongs - with the server. The spec could further elaborate that clientsSHOULD consider the application invalid'' if a change is detected. I see no reason why clients should be burdened (by way of ``MUST'') with detecting a condition that will not arise with compliant servers, and is unlikely to cause practical issues if it does occur after a certificate has been issued. Thanks, Fraser

order. The elements of the "authorizations" array are immutable once set.  <ins> The server MUST NOT change the contents of the "authorizations" array after it is created.  If a client observes a change in the contents of the "authorizations" array, then it SHOULD consider the order invalid. </ins> The "authorizations" array in the challenge SHOULD reflect all authorizations that the CA takes into account in deciding to issue,


URL-TBD <del> No transformation needed.  The </del>  [[ RFC EDITOR: Please replace XXXX above with the RFC number assigned to this document, and replace URL-TBD with the URL assigned by IANA

Failure to synchronize between and . Also removes a stray word and some whitespace in the vicinity.
Also in the registries (and in the "Order Objects" section), is the authorizations property of an order object an array of strings (URLs) or an array of dictionaries (each of which contains status and URL parameters)?
NAME array of strings, since

URL-TBD  <ins> No transformation needed. </ins> [[ RFC EDITOR: Please replace XXXX above with the RFC number assigned to this document, and replace URL-TBD with the URL assigned by IANA


To get a fresh nonce, the client sends a HEAD request to the new- nonce resource on the server.  The server's response MUST include a Replay-Nonce header field containing a fresh nonce, and SHOULD have <del> status code 200 (OK).  The server SHOULD also respond to GET requests for this resource, returning an empty body (while still providing a Replay-Nonce header). </del>  Caching of responses from the new-nonce resource can cause clients to be unable to communicate with the ACME server.  The server MUST

The new-nonce endpoint added in defines a new endpoint which returns information just in headers, but with a 200 response code. I feel this would be more appropriate as a 204 No Content response code. I'm not sure what the approach to making this sort of change is. Should I create this change as a PR?
NAME A PR and a small note to the mailing list is probably the best approach. I'm not an HTTP status lawyer but it seems like 204 is the more-appropriate choice in this context and seems to agree with you: I would :+1: the PR to change to 204 for :-)

To get a fresh nonce, the client sends a HEAD request to the new- nonce resource on the server.  The server's response MUST include a Replay-Nonce header field containing a fresh nonce, and SHOULD have  <ins> status code 204 (No Content).  The server SHOULD also respond to GET requests for this resource, returning an empty body (while still providing a Replay-Nonce header). </ins> Caching of responses from the new-nonce resource can cause clients to be unable to communicate with the ACME server.  The server MUST


that were completed.  Each entry is a URL from which an authorization can be fetched with a GET request. <del> The status of the authorization.  This field MUST have the same value as it does in the underlying authorization object. A URL from which the authorization can be fetched with a GET request. </del> A URL for the certificate that has been issued in response to this order.

Removed unnecessary paragraphs from authorizations field description in order object.
Thanks NAME not sure how I missed that in :)

that were completed.  Each entry is a URL from which an authorization can be fetched with a GET request.  A URL for the certificate that has been issued in response to this order.


4. ACME allows a client to request certificate management actions using <del> a set of JSON messages carried over HTTPS.  In some ways, ACME </del>  functions much like a traditional CA, in which a user creates an <del> account, adds identifiers to that account (proving control of the domains), and requests certificate issuance for those domains while logged in to the account. In ACME, the account is represented by an account key pair.  The "add a domain" function is accomplished by authorizing the key pair for a given domain.  Certificate issuance and revocation are authorized by a signature with the key pair. </del>  <del> The first phase of ACME is for the client to register with the ACME server.  The client generates an asymmetric key pair and associates this key pair with a set of contact information by signing the contact information.  The server acknowledges the registration by replying with a account object echoing the client's input. </del>  <del> Once the client is registered, there are three major steps it needs to take to get a certificate: </del>  Submit an order for a certificate to be issued that the client has met its requirements, the server will issue the requested certificate and make it available to the client. <del> To revoke a certificate, the client simply sends a revocation request indicating the certificate to be revoked, signed with an authorized key pair.  The server indicates whether the request has succeeded. </del>  Note that while ACME is defined with enough flexibility to handle different types of identifiers in principle, the primary use case 5.2. <del> All ACME requests with a non-empty body MUST encapsulate the body in a JWS object, signed using the account key pair.  The server MUST verify the JWS before processing the request.  (For readability, however, the examples below omit this encapsulation.)  Encapsulating request bodies in JWS provides a simple authentication of requests by way of key continuity. </del>  JWS objects sent in ACME requests MUST meet the following additional criteria: For all other requests, there MUST be a "kid" field.  This field must contain the account URI received by POSTing to the new-reg resource. <del> Note that authentication via signed POST implies that GET requests are not authenticated.  Servers MUST NOT respond to GET requests for resources that might be considered sensitive. </del>  If the client sends a JWS signed with an algorithm that the server does not support, then the server MUST return an error with status

Several places talked about account key pairs as being the primary notion of an account, while the account is now primary and has a public key associated with it. Updated to clarify that. Clarified that the account request can contain more than just contact information. Fixed the order of operations in protocol summary to reflect new-order flow.

4. ACME allows a client to request certificate management actions using  <ins> a set of JSON messages carried over HTTPS.  In many ways, ACME </ins> functions much like a traditional CA, in which a user creates an  <ins> account, requests a certificate, and proves control of the domains in that certificate in order for the CA to sign the requested certificate. </ins>  <ins> The first phase of ACME is for the client to request an account with the ACME server.  The client generates an asymmetric key pair and requests a new account, optionally providing contact information, agreeing to terms of service, and/or associating the account with an existing account in another system.  The creation request is signed with the generated private key to prove that the client controls it. </ins>  <ins> Once an account is registered, there are three major steps the client needs to take to get a certificate: </ins> Submit an order for a certificate to be issued that the client has met its requirements, the server will issue the requested certificate and make it available to the client.  <ins> To revoke a certificate, the client sends a signed revocation request indicating the certificate to be revoked: </ins> Note that while ACME is defined with enough flexibility to handle different types of identifiers in principle, the primary use case 5.2.  <ins> All ACME requests with a non-empty body MUST encapsulate their payload in a JWS object, signed (in most cases) using the account's private key.  The server MUST verify the JWS before processing the request.  Encapsulating request bodies in JWS provides a simple authentication of requests. </ins> JWS objects sent in ACME requests MUST meet the following additional criteria: For all other requests, there MUST be a "kid" field.  This field must contain the account URI received by POSTing to the new-reg resource.  <ins> Note that authentication via signed JWS request bodies implies that GET requests are not authenticated.  Servers MUST NOT respond to GET requests for resources that might be considered sensitive. </ins> If the client sends a JWS signed with an algorithm that the server does not support, then the server MUST return an error with status


the status field. A CSR encoding the parameters for the certificate being requested <del> RFC2986.  The CSR is sent in the Base64url-encoded version of the DER format.  (Note: This field uses the same modified Base64 encoding rules used elsewhere in this document, so it is different from PEM.) </del>  The requested value of the notBefore field in the certificate, in the date format defined in the certificate to be issued: A CSR encoding the parameters for the certificate being requested <del> RFC2986.  The CSR is sent in the Base64url-encoded version of the DER format.  (Note: This field uses the same modified Base64 encoding rules used elsewhere in this document, so it is different from PEM.) </del>  The requested value of the notBefore field in the certificate, in the date format defined in issue the certificate (see identifier-authorization).  If the client fails to complete the required actions before the "expires" time, then the server SHOULD change the status of the order to "invalid" <del> and MAY delete the application resource. </del>  The server MUST issue the requested certificate and update the order <del> resource with a URL for the certificate as soon as the client has </del>  fulfilled the server's requirements.  If the client has already satisfied the server's requirements at the time of this request (e.g., by obtaining authorization for all of the identifiers in the 6.4.1. The order process described above presumes that authorization objects <del> are created reactively, in response to an application for issuance. Some servers may also wish to enable clients to obtain authorization for an identifier proactively, outside of the context of a specific </del>  issuance.  For example, a client hosting virtual servers for a collection of names might wish to obtain authorization before any servers are created, and only create a certificate when a server revoked: The certificate to be revoked, in the base64url-encoded version of <del> the DER format.  (Note: This field uses the same modified Base64 encoding rules used elsewhere in this document, so it is different from PEM.) </del>  <del> One of the revocation reasonCodes defined in RFC 5280 RFC5280 Section 5.3.1 to be used when generating OCSP responses and CRLs. If this field is not set the server SHOULD use the unspecified (0) reasonCode value when generating OCSP responses and CRLs.  The server MAY disallow a subset of reasonCodes from being used by the user. </del>  Revocation requests are different from other ACME request in that they can be signed either with an account key pair or the key pair in The "JWK_Thumbprint" step indicates the computation specified in RFC7638, using the SHA-256 digest.  As specified in the individual challenges below, the token for a challenge is a JSON string <del> comprised entirely of characters in the URL-safe Base64 alphabet. </del>  The "||" operator indicates concatenation of strings. In computations involving key authorizations, such as the digest A random value that uniquely identifies the challenge.  This value MUST have at least 128 bits of entropy, in order to prevent an attacker from guessing it.  It MUST NOT contain any characters <del> outside the URL-safe Base64 alphabet and MUST NOT contain any padding characters ("="). </del>  A client responds to this challenge by constructing a self-signed certificate which the client MUST provision at the domain name A random value that uniquely identifies the challenge.  This value MUST have at least 128 bits of entropy, in order to prevent an attacker from guessing it.  It MUST NOT contain any characters <del> outside the URL-safe Base64 alphabet and MUST NOT contain any padding characters ("="). </del>  A client responds to this challenge by constructing a key authorization from the "token" value provided in the challenge and

Also fix an example date and fix an RFC reference to not be redundant.
Merging based on manual review, since CircleCI for PRs seems to be busted.

the status field. A CSR encoding the parameters for the certificate being requested  <ins> RFC2986.  The CSR is sent in the base64url-encoded version of the DER format.  (Note: Because this field uses base64url, and does not include headers, it is different from PEM.) </ins> The requested value of the notBefore field in the certificate, in the date format defined in the certificate to be issued: A CSR encoding the parameters for the certificate being requested  <ins> RFC2986.  The CSR is sent in the base64url-encoded version of the DER format.  (Note: Because this field uses base64url, and does not include headers, it is different from PEM.) </ins> The requested value of the notBefore field in the certificate, in the date format defined in issue the certificate (see identifier-authorization).  If the client fails to complete the required actions before the "expires" time, then the server SHOULD change the status of the order to "invalid"  <ins> and MAY delete the order resource. </ins> The server MUST issue the requested certificate and update the order  <ins> resource with a URL for the certificate shortly after the client has </ins> fulfilled the server's requirements.  If the client has already satisfied the server's requirements at the time of this request (e.g., by obtaining authorization for all of the identifiers in the 6.4.1. The order process described above presumes that authorization objects  <ins> are created reactively, in response to a certificate order.  Some servers may also wish to enable clients to obtain authorization for an identifier proactively, outside of the context of a specific </ins> issuance.  For example, a client hosting virtual servers for a collection of names might wish to obtain authorization before any servers are created, and only create a certificate when a server revoked: The certificate to be revoked, in the base64url-encoded version of  <ins> the DER format.  (Note: Because this field uses base64url, and does not include headers, it is different from PEM.) </ins>  <ins> One of the revocation reasonCodes defined in RFC5280 Section 5.3.1 to be used when generating OCSP responses and CRLs.  If this field is not set the server SHOULD use the unspecified (0) reasonCode value when generating OCSP responses and CRLs.  The server MAY disallow a subset of reasonCodes from being used by the user. </ins> Revocation requests are different from other ACME request in that they can be signed either with an account key pair or the key pair in The "JWK_Thumbprint" step indicates the computation specified in RFC7638, using the SHA-256 digest.  As specified in the individual challenges below, the token for a challenge is a JSON string  <ins> comprised entirely of characters in the URL-safe base64 alphabet. </ins> The "||" operator indicates concatenation of strings. In computations involving key authorizations, such as the digest A random value that uniquely identifies the challenge.  This value MUST have at least 128 bits of entropy, in order to prevent an attacker from guessing it.  It MUST NOT contain any characters  <ins> outside the base64url alphabet and MUST NOT contain any padding characters ("="). </ins> A client responds to this challenge by constructing a self-signed certificate which the client MUST provision at the domain name A random value that uniquely identifies the challenge.  This value MUST have at least 128 bits of entropy, in order to prevent an attacker from guessing it.  It MUST NOT contain any characters  <ins> outside the base64url alphabet and MUST NOT contain any padding characters ("="). </ins> A client responds to this challenge by constructing a key authorization from the "token" value provided in the challenge and


5.7. <del> Errors can be reported in ACME both at the HTTP layer and within ACME payloads.  ACME servers can return responses with an HTTP error response code (4XX or 5XX).  For example: If the client submits a request using a method not allowed in this document, then the server MAY return status code 405 (Method Not Allowed). </del>  When the server responds with an error status, it SHOULD provide additional information using problem document RFC7807.  To facilitate standard types.  Clients SHOULD display the "detail" field of all errors. <del> Authorization and challenge objects can also contain error information to indicate why the server was unable to validate authorization. </del> 6. In this section, we describe the certificate management functions

Also switches the type of the challenge type to be instead of as JSON doesn't have dictionaries. I'll push a follow-up PR that will switch the rest of the -> .

5.7.  <ins> Errors can be reported in ACME both at the HTTP layer and within challenge objects as defined in identifier-validation-challenges. ACME servers can return responses with an HTTP error response code (4XX or 5XX).  For example: If the client submits a request using a method not allowed in this document, then the server MAY return status code 405 (Method Not Allowed). </ins> When the server responds with an error status, it SHOULD provide additional information using problem document RFC7807.  To facilitate standard types.  Clients SHOULD display the "detail" field of all errors.  6. In this section, we describe the certificate management functions


In addition to the human readable "detail" field of the error response, the server MAY send one or multiple tokens in the "Link" header pointing to documentation about the specific hit rate limits <del> using the "rate-limit" relation. </del>  5.7. client may fetch a chain of CA certificates that could be used to validate the certificate in the original resource. <del> The "directory" link relation is present on all resources other than the directory and indicates the directory URL. </del>  The following diagram illustrates the relations between resources on an ACME server.  For the most part, these relations are expressed by anchors.  Clients can fetch these alternates and use their own heuristics to decide which is optimal. <del> The server MUST also provide a link relation header field with relation "author" to indicate the order under which this certificate was issued. If the CA participates in Certificate Transparency (CT) RFC6962, then they may want to provide the client with a Signed Certificate Timestamp (SCT) that can be used to prove that a certificate was submitted to a CT log.  An SCT can be included as an extension in the certificate or as an extension to OCSP responses for the certificate. The server can also provide the client with direct access to an SCT for a certificate using a Link relation header field with relation "ct-sct". </del> A certificate resource represents a single, immutable certificate. If the client wishes to obtain a renewed certificate, the client initiates a new order process to request one.

As they are all fulfilled by the endpoint and are unnecessary. The relation is removed as the SCT will be provided by the CA via the certificate or a OCSP response, if it doesn't provide these then the client should be able to retrieve the SCT itself from the logs it expects to find the certificate in (or submit it itself). Also removes a paragraph about Certificate Transparency from the 'Downloading the Certificate' section as it is irrelevant to the section and discusses operations of the CA unrelated to the ACME protocol. Additionally changes the relation which is not registered with a URI extension using the ACME URN namespace .
Looks good. Was posted on the list two weeks ago, with no objections, so merging.

In addition to the human readable "detail" field of the error response, the server MAY send one or multiple tokens in the "Link" header pointing to documentation about the specific hit rate limits  <ins> using the "urn:ietf:params:acme:documentation" relation. </ins> 5.7. client may fetch a chain of CA certificates that could be used to validate the certificate in the original resource.  <ins> The "index" link relation is present on all resources other than the directory and indicates the directory URL. </ins> The following diagram illustrates the relations between resources on an ACME server.  For the most part, these relations are expressed by anchors.  Clients can fetch these alternates and use their own heuristics to decide which is optimal.  A certificate resource represents a single, immutable certificate. If the client wishes to obtain a renewed certificate, the client initiates a new order process to request one.


introduced in version -03 and a breaking change made in version -05, then there would be a challenge labeled "http-03" and one labeled "http-05" - but not one labeled "http-04", since challenge in version <del> -04 was compatible with one in version -04. ]] </del>  7.1.

Note is still required.
In this case it seems better to address the removal of the editor's note than to optimize its contents - do we know if this note is still required?

introduced in version -03 and a breaking change made in version -05, then there would be a challenge labeled "http-03" and one labeled "http-05" - but not one labeled "http-04", since challenge in version  <ins> -04 was compatible with one in version -03. ]] </ins> 7.1.