A variable-length integer representing the maximum number of ack- eliciting packets the recipient of this frame can receive without <del> sending an immediate acknowledgment.  An immediate acknowledgement is sent when more than this number of ack-eliciting packets have been received, so value of 0 results in an immediate acknowledgement.  If an endpoint receives an ACK-Eliciting Threshold value that is larger than the maximum value the endpoint can represent, the endpoint MUST use the largest representable value instead. </del>  A variable-length integer representing the value to which the endpoint requests the peer update its "max_ack_delay"

NAME -- thoughts?
In , I noted that the text around a maximum value is a little squishy. It says: The problem here is not about representing values. We have to assume that 62-bit values can be represented easily by anything that can do QUIC. The real problem is that there is a value beyond which performance tanks badly. Endpoints might want to set a limit for this to prevent that from happening. Why not instead just say that endpoints can set a limit for this threshold? That means that we might need to provide some advice around setting the limit. For instance, maybe we might suggest that a value that exceeds the current congestion window (measured in MTUs) might be too high.
The receiver doesn't know the peer's congestion window, so that might be tricky. If there's a value beyond which performance tanks, isn't that an error on the part of the sender of the ACK_FREQUENCY frame? I agree one could use this frame to degrade performance, but the sender could also just set a max CWND of 1 to degrade performance, which would be a lit simpler.
I agree that providing advice on setting a limit is tricky and there are other ways to destroy performance. The worst case is actually when both the threshold and the max ack delay are unreasonably large.
We could bound the delay to the SRTT as measured locally. It's not guaranteed to be the same value the sender measures, but it could be close enough to mitigate large issues. That being said, I am still unsure if this is a problem worth solving, given the sender should have a strong incentive to specify good values.
I'm ambivalent regarding whether we provide advice on limits. We might try to capture some of this general advice. Or not. I'm mostly concerned that we remove this pointless clause.
That's there for a specific reason. If you store the threshold as a uint_8, and the peer sends you something larger we want clear and consistent guidance on what to do with it(ie: set the value to 255). If that's unclear, editorial suggestions are welcome.
FWIW, when I read this the first time, the thought that an implementation would limit the value to 8 or 16 bit came immediately to mind, like NAME describes.
This text is about choice of internal representation at the receiver. I do not recall what caused this to get added, but as I think about this more now, I am sympathetic to a part of NAME point of view. However, this isn't about performance (as NAME notes) -- we don't want the receiver second guessing the sender's intent. So the text currently says that a receiver can choose to limit the size of this threshold. However, we provide no guidance as to why a receiver might choose a lower value, leaving this question open to implementations. I think we have two choices: the text should be clear about the tradeoffs and how a receiver might make this choice, or simply not say anything here, with the expectation that receivers ought to respect the sender's request (use uint64). In the spirit of the rest of this draft, I propose that: we follow (2), and if there is a compelling reason to allow a receiver to use something smaller, introduce text to say that the receiver "SHOULD respect sender's request" and explain the compelling exceptional case. Do we have a compelling exception?
I think that (2) alone is fine. I don't have a compelling exception. Note that we also have a time limit. This value might be deliberately set high in order to engage the timer rather than the counter. BOTH might be set ridiculously high, in which case the connection might then faceplant spectacularly, but we don't have to make the protocol completely foolproof.
The original issue was . Microsoft is using a uint8_t for this field, not a uint64, so they can't represent the full value. We can remove the sentence and assume implementations will do the right thing, but we can't assume everyone will use a uint64.
I think the main trouble here is with the normative MUST when an endpoint chooses to go off-spec. As NAME noted, we folks do want to use a < 64-bit value, so it might still be useful to note something here. So here's what I propose: "An endpoint might use a local representation for this value that is smaller than 64 bits for optimization purposes. If it does so, and if it receives an ACK-Eliciting Threshold value that is larger than the maximum value it can represent locally, the endpoint can use the largest representable value instead."
I would prefer that people go off-spec rather than make allowances like this in the spec. Honestly though, msquic is probably safe with clamping to 255 maximum. No one can say they aren't compliant if they acknowledge earlier.
I'm fine with leaving the text out. I am sympathetic to NAME view, despite the fact that we've had this text in the spec. I'm ok with removing it. NAME NAME -- thoughts?
I added this text to address NAME issue, so I'll let him decide.
I don't care enough to die on this hill, but I do think it's better to have text indicating the peer might have limits and acknowledge earlier as a result, than to have to text at all.
Ok, I've reworded to simply say that a receiver can ack earlier. PTAL NAME NAME NAME NAME
WFM

A variable-length integer representing the maximum number of ack- eliciting packets the recipient of this frame can receive without  <ins> sending an acknowledgment.  In other words, an acknowledgement is sent when more than this number of ack-eliciting packets have been received.  Since this is a maximum value, a receiver can send an acknowledgement earlier.  A value of 0 results in a receiver immediately acknowledging every ack-eliciting packet. </ins> A variable-length integer representing the value to which the endpoint requests the peer update its "max_ack_delay"


The following metadata items are defined, all of which are OPTIONAL: <del> A string containing a URI identifying the current terms of service. </del>  <del> String containing an HTTP or HTTPS URL locating a website providing more information about the ACME server. </del>  <del> If present, MUST be an array of strings.  Each string MUST be a lowercase hostname which the ACME server recognises as referring to itself for the purposes of CAA record validation as defined in RFC6844.  This allows clients to determine the correct issuer domain name to use when configuring CAA record. </del>  Clients access the directory by sending a GET request to the directory URI. 6.3.2. <del> Once a client has created an account with an ACME server, it is possible that the private key for the account will be lost.  The recovery contacts included in the registration allows the client to recover from this situation, as long as it still has access to these contacts. By "recovery", we mean that the information associated with an old account key is bound to a new account key.  When a recovery process succeeds, the server provides the client with a new registration whose contents are the same as base registration object - except for the "key" field, which is set to the new account key.  The server reassigns resources associated with the base registration to the new registration (e.g., authorizations and certificates).  The server SHOULD delete the old registration resource after it has been used as a base for recovery. In addition to the recovery mechanisms defined by ACME, individual client implementations may also offer implementation-specific recovery mechanisms.  For example, if a client creates account keys deterministically from a seed value, then this seed could be used to recover the account key by re-generating it.  Or an implementation could escrow an encrypted copy of the account key with a cloud storage provider, and give the encryption key to the user as a recovery value. The client requests recovery by asking that the server send a message to one of the contact URIs registered for the account.  That message indicates some action that the server requires the client's user to perform, e.g., clicking a link in an email.  If the user successfully completes the server's required actions, then the server will bind the account to the new account key. (Note that this process is almost entirely out of band with respect to ACME.  ACME only allows the client to initiate the process, and the server to indicate the result.) To initiate recovery, the client sends a POST request to the server's recover-registration URI, with a body specifying which registration is to be recovered.  The body of the request MUST be signed by the client's new account key pair. The string "contact" The URI for the registration to be recovered. If the server agrees to attempt recovery, then it creates a new registration resource containing a stub registration object.  The stub registration has the client's new account key and contacts, but no authorizations or certificates associated.  The server returns the stub contact in a 201 (Created) response, along with a Location header field indicating the URI for the new registration resource (which will be the registration URI if the recovery succeeds). After recovery has been initiated, the server follows its chosen recovery process, out-of-band to ACME.  While the recovery process is ongoing, the client may poll the registration resource's URI for status, by sending a POST request with a trivial body ({"resource":"reg"}).  If the recovery process is still pending, the server sends a 202 (Accepted) status code, and a Retry-After header field.  If the recovery process has failed, the server sends an error code (e.g., 404), and SHOULD delete the stub registration resource. If the recovery process has succeeded, then the server will send a 200 (OK) response, containing the full registration object, with any necessary information copied from the old registration).  The client may now use this in the same way as if he had gotten it from a new- registration transaction. 6.3.3. </del> If a client no longer wishes to have an account key registered with the server, it may request that the server delete its account by sending a POST request to the account URI containing the "delete" 10.3. <del> The account recovery processes described in account-recovery allow authorization to be transferred from one account key to another, in case the former account key pair's private key is lost.  ACME needs to prevent these processes from being exploited by an attacker to hijack the authorizations attached to one key and assign them to a key of the attacker's choosing. Recovery takes place in two steps: 1.  Provisioning recovery information (contact or recovery key) 2.  Using recovery information to recover an account The provisioning process needs to ensure that only the account key holder ends up with information that is useful for recovery.  The recovery process needs to assure that only the (now former) account key holder can successfully execute recovery, i.e., that this entity is the only one that can choose the new account key that receives the capabilities held by the account being recovered. Account recovery uses both the ACME channel and the contact channel. The provisioning process is only visible to an ACME MitM, and even then, the MitM can only observe the contact information provided.  If the ACME attacker does not also have access to the contact channel, there is no risk. The security of the recovery process is entirely dependent on the security of the contact channel.  The details of this will depend on the specific out-of-band technique used by the server.  For example: If the server requires a user to click a link in a message sent to a contact address, then the contact channel will need to ensure that the message is only available to the legitimate owner of the contact address.  Otherwise, a passive attacker could see the link and click it first, or an active attacker could redirect the message. If the server requires a user to respond to a message sent to a contact address containing a secret value, then the contact channel will need to ensure that an attacker cannot observe the secret value and spoof a message from the contact address. In practice, many contact channels that can be used to reach many clients do not provide strong assurances of the types noted above. In designing and deploying recovery schemes, ACME servers operators will need to find an appropriate balance between using contact channels that can reach many clients and using contact-based recovery schemes that achieve an appropriate level of risk using those contact channels. 10.4. </del> As a protocol run over HTTPS, standard considerations for TCP-based and HTTP-based DoS mitigation also apply to ACME. or the rate at which validation can be requested within a given subtree of the DNS. <del> 10.5. </del>  The controls on issuance enabled by ACME are focused on validating that a certificate applicant controls the identifier he claims.

We already removed token-based account recovery; this PR removes contact-based recovery. It was already almost entirely unspecified, due to it being a process that primarily takes place outside of ACME. Removing account recovery from ACME simplifies both the protocol and the security considerations. As an alternative, this PR adds an field to the dictionary in the directory, which the CA can use to expose account management functions such as recovery. But you can also imagine using this for more sophisticated account management functions, like associating an ACME account with some other account in a different system.
(Also threw in some editorial corrections, sorry)
The editorial corrections are good and IMO should be taken in any circumstances. I agree this change does what it says it does, so r+. One concern, which I will cross-post to the list, is that the placement of this URL in the directory means that it is not customizable; It could be a useful thing to, after a signed request, give back a URI that contains a one-time value that would help tie a browser session to a given account key. I don't see a good endpoint for such a thing at present, so the hour is probably too late for such a change.
NAME I agree that could be useful, but I can think of other, simpler ways to provide it (e.g., a link relation from a registration URI). If you think it's important, please file a follow-on issue.
NAME See my feedback on the ACME list. I disagree that this should be merged now. Could you please submit a revert and seek further discussion?
Sorry, I misunderstood. Will revert.

The following metadata items are defined, all of which are OPTIONAL:  <ins> A URI identifying the current terms of service. An HTTP or HTTPS URL locating a website providing more information about the ACME server. </ins>  <ins> Each string in this array MUST be a lowercase hostname which the ACME server recognises as referring to itself for the purposes of CAA record validation as defined in RFC6844.  This allows clients to determine the correct issuer domain name to use when configuring CAA record. </ins>  <ins> An HTTP or HTTPS URI indicating a website where a user can perform account-managment functions.  For example, this website might allow a user to associate a new account key pair to an account by proving possession of a registered contact, in the event that the user loses the account private key. </ins> Clients access the directory by sending a GET request to the directory URI. 6.3.2.  If a client no longer wishes to have an account key registered with the server, it may request that the server delete its account by sending a POST request to the account URI containing the "delete" 10.3.  As a protocol run over HTTPS, standard considerations for TCP-based and HTTP-based DoS mitigation also apply to ACME. or the rate at which validation can be requested within a given subtree of the DNS.  <ins> 10.4. </ins> The controls on issuance enabled by ACME are focused on validating that a certificate applicant controls the identifier he claims.


5.6. Creation of resources can be rate limited to ensure fair usage and <del> prevent abuse.  If rate limits are in place, the server SHOULD send the following three headers fields: Once the rate limit is exceeded, the server responds with an error with the code "rateLimited". </del>  5.7.

Rate limits can be used to show warnings to the user, e.g. when certificate issuance is limited to 5 certificates per 7 days and you already issued 3. A single client can't count these, because they may be on different servers using different clients.

5.6. Creation of resources can be rate limited to ensure fair usage and  <ins> prevent abuse.  Once the rate limit is exceeded, the server MUST respond with an error with the code "rateLimited".  Additionally, the server SHOULD send a "Retry-After" header indicating when the current request may succeed again.  If multiple rate limits are in place, that is the time where all rate limits allow access again for the current request with exactly the same parameters. 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 using the "rate-limit" relation. </ins> 5.7.


5. <del> This section describes several components that are used by ACME, and general rules that apply to ACME transactions. </del>  5.1. Each ACME function is accomplished by the client sending a sequence <del> of HTTPS requests to the server, carrying JSON messages.  Use of HTTPS is REQUIRED.  Clients SHOULD support HTTP public key pinning </del>  RFC7469, and servers SHOULD emit pinning headers.  Each subsection of certificate-management below describes the message formats used by the function, and the order in which messages are sent. Servers MUST NOT respond to GET requests for resources that might be considered sensitive. <del> An ACME request carries a JSON dictionary that provides the details of the client's request to the server.  In order to avoid attacks that might arise from sending a request object to a resource of the wrong type, each request object MUST have a "resource" field that indicates what type of resource the request is addressed to, as defined in the below table: Other fields in ACME request bodies are described below. </del> 5.3. <del> An ACME registration resource represents a set of metadata associated to an account key pair.  Registration resources have the following structure: The public key of the account key pair, encoded as a JSON Web Key object RFC7517. </del>  <del> An array of URIs that the server can use to contact the client for issues related to this authorization.  For example, the server may wish to notify the client about server-initiated revocation. 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. A URI from which a list of authorizations granted to this account can be fetched via a GET request.  The result of the GET request MUST be a JSON object whose "authorizations" field is an array of strings, where each string is the URI of an authorization belonging to this registration.  The server SHOULD include pending authorizations, and SHOULD NOT include authorizations that are invalid or expired.  The server MAY return an incomplete list, along with a Link header with link relation "next" indicating a URL to retrieve further entries. </del>  <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>  5.4. <del> An ACME authorization object represents server's authorization for an account to represent an identifier.  In addition to the identifier, an authorization includes several metadata fields, such as the status of the authorization (e.g., "pending", "valid", or "revoked") and which challenges were used to validate possession of the identifier. The structure of an ACME authorization resource is as follows: The identifier that the account is authorized to represent The type of identifier. The identifier itself. The status of this authorization.  Possible values are: "unknown", "pending", "processing", "valid", "invalid" and "revoked".  If this field is missing, then the default value is "pending". The timestamp after which the server will consider this authorization invalid, encoded in the format specified in RFC 3339 RFC3339.  This field is REQUIRED for objects with "valid" in the "status field. The challenges that the client needs to fulfill in order to prove 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 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. The only type of identifier defined by this specification is a fully- qualified domain name (type: "dns").  The value of the identifier MUST be the ASCII representation of the domain name.  Wildcard domain names (with "*" as the first label) MUST NOT be included in authorization requests.  See certificate-issuance below for more information about wildcard domains. 5.5. 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). When the server responds with an error status, it SHOULD provide additional information using problem document I-D.ietf-appsawg-http- problem.  To facilitate automatic response to errors, this document defines the following standard tokens for use in the "type" field (within the "urn:ietf:params:acme:error:" namespace): This list is not exhaustive.  The server MAY return errors whose "type" field is set to a URI other than those defined above.  Servers MUST NOT use the ACME URN namespace for errors other than the standard types.  Clients SHOULD display the "detail" field of such errors. Authorization and challenge objects can also contain error information to indicate why the server was unable to validate authorization. 5.6. </del> In order to protect ACME resources from any possible replay attacks, ACME requests have a mandatory anti-replay mechanism.  This mechanism is based on the server maintaining a list of nonces that it has value for each response, keep a list of issued nonces, and strike nonces from this list as they are used. <del> 5.6.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.6.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.  6. In this section, we describe the certificate management functions The remainder of this section provides the details of how these resources are structured and how the ACME protocol makes use of them.  6.2. In order to help clients configure themselves with the right URIs for

Move description of registration and authorization objects to Certificate Management section Re-frame Protocol Elements section to be more clearly about the transport layer Fix some references

5.  <ins> ACME uses a combination of HTTPS and JWS to create a messaging layer with a few important security properties. Communications between an ACME client and an ACME server are done over HTTPS, using JWS to provide som additional security properties for messages sent from the client to the server.  HTTPS provides server authentication and confidentiality.  With some ACME-specific extensions, JWS provides authentication of the client's request payloads, anti-replay protection, and a degree of integrity for the HTTPS request URI. </ins> 5.1. Each ACME function is accomplished by the client sending a sequence  <ins> of HTTPS requests to the server, carrying JSON messages RFC7159.  Use of HTTPS is REQUIRED.  Clients SHOULD support HTTP public key pinning </ins> RFC7469, and servers SHOULD emit pinning headers.  Each subsection of certificate-management below describes the message formats used by the function, and the order in which messages are sent. Servers MUST NOT respond to GET requests for resources that might be considered sensitive.  5.3.  <ins> It is common in deployment 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 CA might have a content delivery network terminate TLS connections from clients so that it can inspect client requests for denial-of-service protection. These intermediaries can also change values in the request that are not signed in the HTTPS request, e.g., the request URI and headers. ACME uses JWS to provides a limited integrity mechanism, which protects against an intermediary changing the request URI to anothe ACME URI of a different type.  (It does not protect against changing between URIs of the same type, e.g., from one authorization URI to another). </ins>  <ins> An ACME request carries a JSON dictionary that provides the details of the client's request to the server.  Each request object MUST have a "resource" field that indicates what type of resource the request is addressed to, as defined in the below table: </ins>  <ins> Other fields in ACME request bodies are described below. </ins> 5.4.  In order to protect ACME resources from any possible replay attacks, ACME requests have a mandatory anti-replay mechanism.  This mechanism is based on the server maintaining a list of nonces that it has value for each response, keep a list of issued nonces, and strike nonces from this list as they are used.  <ins> 5.4.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.4.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.5. 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). When the server responds with an error status, it SHOULD provide additional information using problem document I-D.ietf-appsawg-http- problem.  To facilitate automatic response to errors, this document defines the following standard tokens for use in the "type" field (within the "urn:ietf:params:acme:error:" namespace): This list is not exhaustive.  The server MAY return errors whose "type" field is set to a URI other than those defined above.  Servers MUST NOT use the ACME URN namespace for errors other than the standard types.  Clients SHOULD display the "detail" field of such errors. Authorization and challenge objects can also contain error information to indicate why the server was unable to validate authorization. </ins> 6. In this section, we describe the certificate management functions The remainder of this section provides the details of how these resources are structured and how the ACME protocol makes use of them. <ins> 6.1.1. An ACME registration resource represents a set of metadata associated to an account key pair.  Registration resources have the following structure: The public key of the account key pair, encoded as a JSON Web Key object RFC7517. An array of URIs that the server can use to contact the client for issues related to this authorization.  For example, the server may wish to notify the client about server-initiated revocation. 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. A URI from which a list of authorizations granted to this account can be fetched via a GET request.  The result of the GET request MUST be a JSON object whose "authorizations" field is an array of strings, where each string is the URI of an authorization belonging to this registration.  The server SHOULD include pending authorizations, and SHOULD NOT include authorizations that are invalid or expired.  The server MAY return an incomplete list, along with a Link header with link relation "next" indicating a URL to retrieve further entries. 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. 6.1.2. An ACME authorization object represents server's authorization for an account to represent an identifier.  In addition to the identifier, an authorization includes several metadata fields, such as the status of the authorization (e.g., "pending", "valid", or "revoked") and which challenges were used to validate possession of the identifier. The structure of an ACME authorization resource is as follows: The identifier that the account is authorized to represent The type of identifier. The identifier itself. The status of this authorization.  Possible values are: "unknown", "pending", "processing", "valid", "invalid" and "revoked".  If this field is missing, then the default value is "pending". The timestamp after which the server will consider this authorization invalid, encoded in the format specified in RFC 3339 RFC3339.  This field is REQUIRED for objects with "valid" in the "status field. The challenges that the client needs to fulfill in order to prove 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 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. The only type of identifier defined by this specification is a fully- qualified domain name (type: "dns").  The value of the identifier MUST be the ASCII representation of the domain name.  Wildcard domain names (with "*" as the first label) MUST NOT be included in authorization requests.  See certificate-issuance below for more information about wildcard domains. </ins> 6.2. In order to help clients configure themselves with the right URIs for


The following metadata items are defined, all of which are OPTIONAL: <del> A URI identifying the current terms of service. An HTTP or HTTPS URL locating a website providing more information about the ACME server. </del>  <del> Each string in this array MUST be a lowercase hostname which the ACME server recognises as referring to itself for the purposes of CAA record validation as defined in RFC6844.  This allows clients to determine the correct issuer domain name to use when configuring CAA record. </del>  <del> An HTTP or HTTPS URI indicating a website where a user can perform account-managment functions.  For example, this website might allow a user to associate a new account key pair to an account by proving possession of a registered contact, in the event that the user loses the account private key. </del>  Clients access the directory by sending a GET request to the directory URI. 6.3.2.  If a client no longer wishes to have an account key registered with the server, it may request that the server delete its account by sending a POST request to the account URI containing the "delete" 10.3.  As a protocol run over HTTPS, standard considerations for TCP-based and HTTP-based DoS mitigation also apply to ACME. or the rate at which validation can be requested within a given subtree of the DNS. <del> 10.4. </del>  The controls on issuance enabled by ACME are focused on validating that a certificate applicant controls the identifier he claims.

This reverts commit 5ea8bb3afe51fa14b34593341b895e0262b454ca, reversing changes made to 278c6e8ab49e3013708cbf544c76df868973635f.

The following metadata items are defined, all of which are OPTIONAL:  <ins> A string containing a URI identifying the current terms of service. </ins>  <ins> String containing an HTTP or HTTPS URL locating a website providing more information about the ACME server. </ins>  <ins> If present, MUST be an array of strings.  Each string MUST be a lowercase hostname which the ACME server recognises as referring to itself for the purposes of CAA record validation as defined in RFC6844.  This allows clients to determine the correct issuer domain name to use when configuring CAA record. </ins> Clients access the directory by sending a GET request to the directory URI. 6.3.2. <ins> Once a client has created an account with an ACME server, it is possible that the private key for the account will be lost.  The recovery contacts included in the registration allows the client to recover from this situation, as long as it still has access to these contacts. By "recovery", we mean that the information associated with an old account key is bound to a new account key.  When a recovery process succeeds, the server provides the client with a new registration whose contents are the same as base registration object - except for the "key" field, which is set to the new account key.  The server reassigns resources associated with the base registration to the new registration (e.g., authorizations and certificates).  The server SHOULD delete the old registration resource after it has been used as a base for recovery. In addition to the recovery mechanisms defined by ACME, individual client implementations may also offer implementation-specific recovery mechanisms.  For example, if a client creates account keys deterministically from a seed value, then this seed could be used to recover the account key by re-generating it.  Or an implementation could escrow an encrypted copy of the account key with a cloud storage provider, and give the encryption key to the user as a recovery value. The client requests recovery by asking that the server send a message to one of the contact URIs registered for the account.  That message indicates some action that the server requires the client's user to perform, e.g., clicking a link in an email.  If the user successfully completes the server's required actions, then the server will bind the account to the new account key. (Note that this process is almost entirely out of band with respect to ACME.  ACME only allows the client to initiate the process, and the server to indicate the result.) To initiate recovery, the client sends a POST request to the server's recover-registration URI, with a body specifying which registration is to be recovered.  The body of the request MUST be signed by the client's new account key pair. The string "contact" The URI for the registration to be recovered. If the server agrees to attempt recovery, then it creates a new registration resource containing a stub registration object.  The stub registration has the client's new account key and contacts, but no authorizations or certificates associated.  The server returns the stub contact in a 201 (Created) response, along with a Location header field indicating the URI for the new registration resource (which will be the registration URI if the recovery succeeds). After recovery has been initiated, the server follows its chosen recovery process, out-of-band to ACME.  While the recovery process is ongoing, the client may poll the registration resource's URI for status, by sending a POST request with a trivial body ({"resource":"reg"}).  If the recovery process is still pending, the server sends a 202 (Accepted) status code, and a Retry-After header field.  If the recovery process has failed, the server sends an error code (e.g., 404), and SHOULD delete the stub registration resource. If the recovery process has succeeded, then the server will send a 200 (OK) response, containing the full registration object, with any necessary information copied from the old registration).  The client may now use this in the same way as if he had gotten it from a new- registration transaction. 6.3.3. </ins> If a client no longer wishes to have an account key registered with the server, it may request that the server delete its account by sending a POST request to the account URI containing the "delete" 10.3. <ins> The account recovery processes described in account-recovery allow authorization to be transferred from one account key to another, in case the former account key pair's private key is lost.  ACME needs to prevent these processes from being exploited by an attacker to hijack the authorizations attached to one key and assign them to a key of the attacker's choosing. Recovery takes place in two steps: 1.  Provisioning recovery information (contact or recovery key) 2.  Using recovery information to recover an account The provisioning process needs to ensure that only the account key holder ends up with information that is useful for recovery.  The recovery process needs to assure that only the (now former) account key holder can successfully execute recovery, i.e., that this entity is the only one that can choose the new account key that receives the capabilities held by the account being recovered. Account recovery uses both the ACME channel and the contact channel. The provisioning process is only visible to an ACME MitM, and even then, the MitM can only observe the contact information provided.  If the ACME attacker does not also have access to the contact channel, there is no risk. The security of the recovery process is entirely dependent on the security of the contact channel.  The details of this will depend on the specific out-of-band technique used by the server.  For example: If the server requires a user to click a link in a message sent to a contact address, then the contact channel will need to ensure that the message is only available to the legitimate owner of the contact address.  Otherwise, a passive attacker could see the link and click it first, or an active attacker could redirect the message. If the server requires a user to respond to a message sent to a contact address containing a secret value, then the contact channel will need to ensure that an attacker cannot observe the secret value and spoof a message from the contact address. In practice, many contact channels that can be used to reach many clients do not provide strong assurances of the types noted above. In designing and deploying recovery schemes, ACME servers operators will need to find an appropriate balance between using contact channels that can reach many clients and using contact-based recovery schemes that achieve an appropriate level of risk using those contact channels. 10.4. </ins> As a protocol run over HTTPS, standard considerations for TCP-based and HTTP-based DoS mitigation also apply to ACME. or the rate at which validation can be requested within a given subtree of the DNS.  <ins> 10.5. </ins> The controls on issuance enabled by ACME are focused on validating that a certificate applicant controls the identifier he claims.


The following metadata items are defined, all of which are OPTIONAL: <del> A string containing a URI identifying the current terms of service. </del>  <del> String containing an HTTP or HTTPS URL locating a website providing more information about the ACME server. </del>  <del> If present, MUST be an array of strings.  Each string MUST be a lowercase hostname which the ACME server recognises as referring to itself for the purposes of CAA record validation as defined in RFC6844.  This allows clients to determine the correct issuer domain name to use when configuring CAA record. </del>  Clients access the directory by sending a GET request to the directory URI.

(Re-adding the editorial changes that got lumped in )
r+; thanks for pulling these out alone

The following metadata items are defined, all of which are OPTIONAL:  <ins> A URI identifying the current terms of service. </ins>  <ins> An HTTP or HTTPS URL locating a website providing more information about the ACME server. </ins>  <ins> Each string MUST be a lowercase hostname which the ACME server recognises as referring to itself for the purposes of CAA record validation as defined in RFC6844.  This allows clients to determine the correct issuer domain name to use when configuring CAA record. </ins> Clients access the directory by sending a GET request to the directory URI.


6.3.2. <del> Once a client has created an account with an ACME server, it is possible that the private key for the account will be lost.  The recovery contacts included in the registration allows the client to recover from this situation, as long as it still has access to these contacts. By "recovery", we mean that the information associated with an old account key is bound to a new account key.  When a recovery process succeeds, the server provides the client with a new registration whose contents are the same as base registration object - except for the "key" field, which is set to the new account key.  The server reassigns resources associated with the base registration to the new registration (e.g., authorizations and certificates).  The server SHOULD delete the old registration resource after it has been used as a base for recovery. In addition to the recovery mechanisms defined by ACME, individual client implementations may also offer implementation-specific recovery mechanisms.  For example, if a client creates account keys deterministically from a seed value, then this seed could be used to recover the account key by re-generating it.  Or an implementation could escrow an encrypted copy of the account key with a cloud storage provider, and give the encryption key to the user as a recovery value. The client requests recovery by asking that the server send a message to one of the contact URIs registered for the account.  That message indicates some action that the server requires the client's user to perform, e.g., clicking a link in an email.  If the user successfully completes the server's required actions, then the server will bind the account to the new account key. (Note that this process is almost entirely out of band with respect to ACME.  ACME only allows the client to initiate the process, and the server to indicate the result.) To initiate recovery, the client sends a POST request to the server's recover-registration URI, with a body specifying which registration is to be recovered.  The body of the request MUST be signed by the client's new account key pair. The string "contact" The URI for the registration to be recovered. If the server agrees to attempt recovery, then it creates a new registration resource containing a stub registration object.  The stub registration has the client's new account key and contacts, but no authorizations or certificates associated.  The server returns the stub contact in a 201 (Created) response, along with a Location header field indicating the URI for the new registration resource (which will be the registration URI if the recovery succeeds). After recovery has been initiated, the server follows its chosen recovery process, out-of-band to ACME.  While the recovery process is ongoing, the client may poll the registration resource's URI for status, by sending a POST request with a trivial body ({"resource":"reg"}).  If the recovery process is still pending, the server sends a 202 (Accepted) status code, and a Retry-After header field.  If the recovery process has failed, the server sends an error code (e.g., 404), and SHOULD delete the stub registration resource. If the recovery process has succeeded, then the server will send a 200 (OK) response, containing the full registration object, with any necessary information copied from the old registration).  The client may now use this in the same way as if he had gotten it from a new- registration transaction. 6.3.3. </del> If a client no longer wishes to have an account key registered with the server, it may request that the server delete its account by sending a POST request to the account URI containing the "delete" 10.3. <del> The account recovery processes described in account-recovery allow authorization to be transferred from one account key to another, in case the former account key pair's private key is lost.  ACME needs to prevent these processes from being exploited by an attacker to hijack the authorizations attached to one key and assign them to a key of the attacker's choosing. Recovery takes place in two steps: 1.  Provisioning recovery information (contact or recovery key) 2.  Using recovery information to recover an account The provisioning process needs to ensure that only the account key holder ends up with information that is useful for recovery.  The recovery process needs to assure that only the (now former) account key holder can successfully execute recovery, i.e., that this entity is the only one that can choose the new account key that receives the capabilities held by the account being recovered. Account recovery uses both the ACME channel and the contact channel. The provisioning process is only visible to an ACME MitM, and even then, the MitM can only observe the contact information provided.  If the ACME attacker does not also have access to the contact channel, there is no risk. The security of the recovery process is entirely dependent on the security of the contact channel.  The details of this will depend on the specific out-of-band technique used by the server.  For example: If the server requires a user to click a link in a message sent to a contact address, then the contact channel will need to ensure that the message is only available to the legitimate owner of the contact address.  Otherwise, a passive attacker could see the link and click it first, or an active attacker could redirect the message. If the server requires a user to respond to a message sent to a contact address containing a secret value, then the contact channel will need to ensure that an attacker cannot observe the secret value and spoof a message from the contact address. In practice, many contact channels that can be used to reach many clients do not provide strong assurances of the types noted above. In designing and deploying recovery schemes, ACME servers operators will need to find an appropriate balance between using contact channels that can reach many clients and using contact-based recovery schemes that achieve an appropriate level of risk using those contact channels. 10.4. </del> As a protocol run over HTTPS, standard considerations for TCP-based and HTTP-based DoS mitigation also apply to ACME. or the rate at which validation can be requested within a given subtree of the DNS. <del> 10.5. </del>  The controls on issuance enabled by ACME are focused on validating that a certificate applicant controls the identifier he claims.

This PR is a re-do of . It only removes recovery; it does not add the "account-mgmt" metadata item.
LGTM
We removed recovery in . If we refactor roll-over as proposed in , however, recovery can be done much more simply, at least if you assume the client is provisioned with a MAC key (possibly out of band).
Agreed at IETF 96 that we will not specify recovery. Instead, we will add some guidance for CAs as to how to handle loss of account keys.

6.3.2.  If a client no longer wishes to have an account key registered with the server, it may request that the server delete its account by sending a POST request to the account URI containing the "delete" 10.3.  As a protocol run over HTTPS, standard considerations for TCP-based and HTTP-based DoS mitigation also apply to ACME. or the rate at which validation can be requested within a given subtree of the DNS.  <ins> 10.4. </ins> The controls on issuance enabled by ACME are focused on validating that a certificate applicant controls the identifier he claims.


The public key of the account key pair, encoded as a JSON Web Key object RFC7517.  An array of URIs that the server can use to contact the client for issues related to this authorization.  For example, the server may wish to notify the client about server-initiated revocation. 6.3.2. <del> If a client no longer wishes to have an account key registered with the server, it may request that the server delete its account by sending a POST request to the account URI containing the "delete" field. delete (required, boolean): The boolean value "true". The request object MUST contain the "resource" field as required above (with the value "reg").  It MUST NOT contain any fields besides "resource" and "delete". </del>  <del> Note that although this object is very simple, the risk of replay or fraudulent generation via signing oracles is mitigated by the need for an anti-replay token in the protected header of the JWS. </del>  <del> On receiving a POST to an account URI containing a "delete" field, the server MUST verify that no other fields were sent in the object (other than "resource"), and it MUST verify that the value of the "delete" field is "true" (as a boolean, not a string).  If either of these checks fails, then the server MUST reject the request with status code 400 (Bad Request). If the server accepts the deletion request, then it MUST delete the account and all related objects and send a response with a 200 (OK) status code and an empty body.  The server SHOULD delete any authorization objects related to the deleted account, since they can no longer be used.  The server SHOULD NOT delete certificate objects related to the account, since certificates issued under the account continue to be valid until they expire or are revoked. </del>  6.4. If a client wishes to relinquish its authorization to issue certificates for an identifier, then it may request that the server <del> delete the authorization.  The client makes this request by sending a POST request to the authorization URI containing a payload in the same format as in deleting-an-account.  The only difference is that the value of the "resource" field is "authz". The server MUST perform the same validity checks as in deleting-an- account and reject the request if they fail.  If the server deletes the account then it MUST send a response with a 200 (OK) status code and an empty body. </del>  6.5.

This simplifies both the spec and the implementation, and does not attempt to impose specific data retention policy on the CA.
I don't really agree about that one. Why not delete completely the data instead of deactivating? Why shouldn't a user be able to request full deletion and no retention of any of their account data?
Nothing in this change prevents CAs from choosing to delete account data immediately upon deactivation, but the spec should not try to dictate policy.
I think this PR is fine in principal, but I have some minor concerns: If we're going to use the field, we should prefer to use the values that are already there, namely and . Do you think there's a semantic difference between that and what you're proposing? Your edits remove the guidance on what the server should return from these requests. Please add that back in. It occurs to me looking at this that the first version of authz deletion should have specified that the server MUST verify that the account is the owner of the authz before allowing it to deactivate the authz. Could you please add that while you're editing here?
Done.

The public key of the account key pair, encoded as a JSON Web Key object RFC7517. <ins> "good" or "deactivated" </ins> An array of URIs that the server can use to contact the client for issues related to this authorization.  For example, the server may wish to notify the client about server-initiated revocation. 6.3.2.  <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 this when the account key is compromised. </ins>  <ins> The server MUST verify that the request is signed by the account key. If the server accepts the deactivation request, it should reply with a 200 (OK) status code and the current contents of the registration object. </ins>  <ins> Once an account is deactivated, the server MUST NOT accept further requests authorized by that account's key.  It is up to server policy how long to retain data related to that account, whether to revoke certificates issued by that account, and whether to send email to that account's contacts.  ACME does not proviate a way to reactivate a deactivated account. </ins> 6.4. If a client wishes to relinquish its authorization to issue certificates for an identifier, then it may request that the server  <ins> deactivate each authorization associated with that identifier. The server MUST verify that the request is signed by the account key corresponding to the account that owns the authorization.  If the server accepts the deactivation, it should reply with a 200 (OK) status code and the current contents of the registration object. The server MUST NOT treat deactivated authorization objects as sufficient for issuing certificates. </ins> 6.5.


The default format of the certificate is DER (application/pkix-cert). The client may request other formats by including an Accept header in <del> its request. </del>  The server provides metadata about the certificate in HTTP headers. <del> In particular, the server MUST include a Link relation header field RFC5988 with relation "up" to provide a certificate under which this certificate was issued, and one with relation "author" to indicate the registration under which this certificate was issued. </del>  If the CA participates in Certificate Transparency (CT) RFC6962, then they may want to provide the client with a Signed Certificate

As PHB noted in his presentation at IETF 95, the examples in the doc should indicate clearly the start and end of payload of the JWS object, e.g.:
The spec indicates that it’s possible to request certificates of types other than DER; however, there is no indication of what those MIME types are. PEM would be a very useful format; would it be useful to indicate in here what that MIME type is, or at least where to find a list of MIME types that would work here?
The answer is :) But I can agree that it would be good to remind people of this in the spec.
CA certificates are
The documentation seems unclear as to how certificate “up” links are to handle the case of multiple intermediate certificates between root and the issued certificate. Are both certificates part of the payload of the “up” link? Does each “up” link whose payload is not a root certificate (or “last-before-root”) have its own “up” link? Thank you!
It seems pretty clear to me that the right answer is to have one "up" link per parent cert, but allow multiple links per cert. We can add some text to clarify this.

The default format of the certificate is DER (application/pkix-cert). The client may request other formats by including an Accept header in  <ins> its request.  For example, the client may use the media type application/x-pem-file to request the certificate in PEM format. </ins> The server provides metadata about the certificate in HTTP headers.  <ins> In particular, the server send MUST 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. The server MUST also provide a link relation header field with relation "author" to indicate the registration under which this certificate was issued. </ins> If the CA participates in Certificate Transparency (CT) RFC6962, then they may want to provide the client with a Signed Certificate


7.1. <del> Several of the challenges in this document makes use of an "authorized key" object.  Such an object is a JSON object that encodes an authorization for a specific account key to fulfill a specific challenge. A random value that uniquely identifies a 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 outside the URL-safe Base64 alphabet. The account key being authorized </del>  7.2. The string "http-01" <del> A serialized authorized key object, base64-encoded.  The "key" field in this object MUST match the client's account key. </del>  <del> A client responds to this challenge by base64-decoding and parsing the authorized key object, verifying that its "key" field contains the client's account key, and provisioning it as a resource on the HTTP server for the domain in question.  That is, the server provisions a JSON object that is equivalent to the object encoded in the "authorizedKey" field sent by the server.  (Note: The provisioned object need not be a byte-exact copy of the authorized keys object in the challenge.) </del>  The path at which the resource is provisioned is comprised of the fixed prefix ".well-known/acme-challenge/", followed by the "token" value in the challenge. The client's response to this challenge indicates its agreement to <del> this challenge: </del>  <del> The string "http-01" </del>  <del> The "token" value from the authorized key object in the challenge. On receiving a response, the server MUST verify that the "token" value in the response matches the "token" field in the authorized key object in the challenge.  If they do not match, then the server MUST return an HTTP error in response to the POST request in which the client sent the challenge </del>  Given a Challenge/Response pair, the server verifies the client's control of the domain by verifying that the resource was provisioned Form a URI by populating the URI template RFC6570 "http://{domain}/.well-known/acme-challenge/{token}", where: * the domain field is set to the domain name being verified; and * the <del> token field is set to the token in the authorized key object. </del>  Verify that the resulting URI is well-formed. HTTPS server. Verify that the Content-Type header of the response is either <del> absent, or has the value "application/json". Verify that the body of the response is well-formed authorized key object. </del>  <del> Verify that the "key" and "token" fields in the authorized key object match the values from the authorized key object in the challenge. </del>  <del> Comparisons of the "token" field MUST be performed in terms of Unicode code points, taking into account the encodings of the stored nonce and the body of the request. </del>  If all of the above verifications succeed, then the validation is successful.  If the request fails, or the body does not pass these The string "tls-sni-01" <del> A serialized authorized key object, base64-encoded.  The "key" field in this object MUST match the client's account key. </del>  Number of tls-sni-01 iterations <del> In response to the challenge, the client MUST decode and parse the authorized keys object and verify that it contains exactly one entry, whose "token" and "key" attributes match the token for this challenge and the client's account key.  The client then computes the SHA-256 digest Z0 of the JSON-encoded authorized key object (without base64-encoding), and encodes Z0 in UTF-8 lower-case hexadecimal form.  The client then generates iterated hash values Z1...Z(n-1) as follows: </del>  The client generates a self-signed certificate for each iteration of Zi with a single subjectAlternativeName extension dNSName that is The response to the TLS SNI challenge simply acknowledges that the client is ready to fulfill this challenge. <del> The string "tls-sni-01" The "token" value from the authorized key object in the challenge. </del>  <del> On receiving a response, the server MUST verify that the "token" value in the response matches the "token" field in the authorized key object in the challenge.  If they do not match, then the server MUST return an HTTP error in response to the POST request in which the client sent the challenge </del>  Given a Challenge/Response pair, the ACME server verifies the client's control of the domain by verifying that the TLS server was Choose a subset of the N iterations to check, according to local policy. <del> For each iteration, compute the Zi-value from the authorized keys object in the same way as the client. </del>  Open a TLS connection to the domain name being validated on the requested port, presenting the value The string "dns-01" <del> A serialized authorized key object, base64-encoded.  The "key" field in this object MUST match the client's account key. </del>  <del> In response to the challenge, the client MUST parse the authorized key object and verify that its "key" field contains the client's account key.  The client then computes the SHA-256 digest of the JSON-encoded authorized key object (without base64-encoding). </del>  The record provisioned to the DNS is the base64 encoding of this digest.  The client constructs the validation domain name by The response to the DNS challenge simply acknowledges that the client is ready to fulfill this challenge. <del> The string "dns-01" The "token" value from the authorized key object in the challenge. </del>  <del> On receiving a response, the server MUST verify that the "token" value in the response matches the "token" field in the authorized key object in the challenge.  If they do not match, then the server MUST return an HTTP error in response to the POST request in which the client sent the challenge </del>  To validate a DNS challenge, the server performs the following steps: <del> Compute the SHA-256 digest of the authorized key object </del>  Query for TXT records under the validation domain name

This PR updates the new challenges so that they no longer use a JSON object dictated by the server. Instead, they use a "key authorization" string that is canonically generated from the token and key for a given challenge. (And also, while we're here, changes "authorized key object" to "key authorization".)

7.1.  <ins> Several of the challenges in this document makes use of a key authorization string.  A key authorization expresses a domain holder's authorization for a specified key to satisfy a specified challenge, by concatenating the token for the challenge with a key fingerprint, separated by a "." character: 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 comprised entirely of characters in the base64 alphabet.  The "||" operator indicates concatenation of strings. In computations involving key authorizations, such as the digest computations required for the DNS and TLS SNI challenges, the key authorization string MUST be represented in UTF-8 form (or, equivalently, ASCII). </ins> 7.2. The string "http-01"  <ins> 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 outside the URL-safe Base64 alphabet. </ins>  <ins> A client responds to this challenge by constructing a key authorization from the "token" value provided in the challenge and the client's account key.  The client then provisions the key authorization as a resource on the HTTP server for the domain in question. </ins> The path at which the resource is provisioned is comprised of the fixed prefix ".well-known/acme-challenge/", followed by the "token" value in the challenge. The client's response to this challenge indicates its agreement to  <ins> this challenge by sending the server the key authorization covering the challenge's token and the client's account key: </ins>  <ins> The key authorization for this challenge.  This value MUST match the token from the challenge and the client's account key. </ins>  <ins> On receiving a response, the server MUST verify that the key authorization in the response matches the "token" value in the challenge and the client's account key.  If they do not match, then the server MUST return an HTTP error in response to the POST request in which the client sent the challenge. </ins> Given a Challenge/Response pair, the server verifies the client's control of the domain by verifying that the resource was provisioned Form a URI by populating the URI template RFC6570 "http://{domain}/.well-known/acme-challenge/{token}", where: * the domain field is set to the domain name being verified; and * the  <ins> token field is set to the token in the challenge. </ins> Verify that the resulting URI is well-formed. HTTPS server. Verify that the Content-Type header of the response is either  <ins> absent, or has the value "text/plain". </ins>  <ins> Verify that the body of the response is well-formed key authorization. </ins>  <ins> Verify that key authorization provided by the server matches the token for this challenge and the client's account key. </ins> If all of the above verifications succeed, then the validation is successful.  If the request fails, or the body does not pass these The string "tls-sni-01"  <ins> 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 outside the URL-safe Base64 alphabet. </ins> Number of tls-sni-01 iterations  <ins> A client responds to this challenge by constructing a key authorization from the "token" value provided in the challenge and the client's account key.  The client first computes the SHA-256 digest Z0 of the UTF8-encoded key authorization, and encodes Z0 in UTF-8 lower-case hexadecimal form.  The client then generates iterated hash values Z1...Z(n-1) as follows: </ins> The client generates a self-signed certificate for each iteration of Zi with a single subjectAlternativeName extension dNSName that is The response to the TLS SNI challenge simply acknowledges that the client is ready to fulfill this challenge.  <ins> The key authorization for this challenge.  This value MUST match the token from the challenge and the client's account key. </ins>  <ins> On receiving a response, the server MUST verify that the key authorization in the response matches the "token" value in the challenge and the client's account key.  If they do not match, then the server MUST return an HTTP error in response to the POST request in which the client sent the challenge. </ins> Given a Challenge/Response pair, the ACME server verifies the client's control of the domain by verifying that the TLS server was Choose a subset of the N iterations to check, according to local policy.  <ins> For each iteration, compute the Zi-value from the key authorization in the same way as the client. </ins> Open a TLS connection to the domain name being validated on the requested port, presenting the value The string "dns-01"  <ins> 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 outside the URL-safe Base64 alphabet. </ins>  <ins> A client responds to this challenge by constructing a key authorization from the "token" value provided in the challenge and the client's account key.  The client then computes the SHA-256 digest of the key authorization. </ins> The record provisioned to the DNS is the base64 encoding of this digest.  The client constructs the validation domain name by The response to the DNS challenge simply acknowledges that the client is ready to fulfill this challenge.  <ins> The key authorization for this challenge.  This value MUST match the token from the challenge and the client's account key. </ins>  <ins> On receiving a response, the server MUST verify that the key authorization in the response matches the "token" value in the challenge and the client's account key.  If they do not match, then the server MUST return an HTTP error in response to the POST request in which the client sent the challenge. </ins> To validate a DNS challenge, the server performs the following steps:  <ins> Compute the SHA-256 digest of the key authorization </ins> Query for TXT records under the validation domain name


subject name, or in an extensionRequest attribute RFC2985 requesting a subjectAltName extension. <del> The values provided in the CSR are only a request, and are not guaranteed.  The server SHOULD return an error if it cannot fulfil the request as specified, but MAY issue a certificate with contents other than those requested, according to its local policy (e.g., removing identifiers for which the client is not authorized). </del>  It is up to the server's local policy to decide which names are acceptable in a certificate, given the authorizations that the server

As discussed at IETF 95, the server should fail a new-cert request if it cannot fulfill it precisely. It must not modify the request to something it is willing to fulfill.
We need to clarify when an ACME server can ignore attributes in a request that it doesn't like, and when it should ignore them and proceed. For example, if a requested validity date is longer than the policy, should it error back or just ignore that attribute and issue a cert good for as long as it wants? That seems okay. But what about an unsupported request for issuance in the future? Ignoring that seems wrong, and risky.
I think in general ACME should take the approach of refusing to issue a cert if requested parameters (dates, or extensions) are unacceptable. It's cheap for the client to re-request with acceptable parameters, assuming the error message is detailed enough.
Scoping this down to new-certificate requests, since there's not really enough latitude in the other types of request to cause this problem.
Agreed in B.A. to fail, fail, fail, but return information helpful to a human, explicitly not machine-recoverable. It may be possible to give a trivial amount of altitude (e.g. 90 days--will it not be okay if 90-days minus 15 seconds is given?)

subject name, or in an extensionRequest attribute RFC2985 requesting a subjectAltName extension.  <ins> The server MUST return an error if it cannot fulfil the request as specified, and MUST NOT issue a certificate with contents other than those requested.  If the server requires the request to be modified in a certain way, it should indicate the required changes using an appropriate error code and description. </ins> It is up to the server's local policy to decide which names are acceptable in a certificate, given the authorizations that the server


successful.  If no DNS record is found, or DNS record and response payload do not pass these checks, then the validation fails.  8. [[ Editor's Note: Should we create a registry for tokens that go into

We need a challenge type to cover types of validation that can't be done automatically, in band to ACME. For example, a CA doing OV or EV validation might need the applicant to upload some documents through a web form. We should add a generic "out-of-band" challenge type that has a URL for a web site where the applicant gan go for instructions. I think the challenge object would look something like: There would be no response object; you just click the link, and when you complete the instructions there, the CA reflects this in the "status" field of the challenge object.
A few months back I wrote up a for this idea -- the hope is that ACME could evolve to become the language that all cert issuers talk to support a standard for cert management and exchange.
At IETF 95, agreed that this seemed reasonable to pursue, but needs to have a PR that describes what the URI characteristics are.

successful.  If no DNS record is found, or DNS record and response payload do not pass these checks, then the validation fails. <ins> 7.5. There may be cases where a server cannot perform automated validation of an identifier, for example if validation requires some manual steps.  In such cases, the server may provide an "out of band" (OOB) challenge to request that the client perform some action outside of ACME in order to validate possession of the identifier. The OOB challenge requests that the client have a human user visit a web page to receive instructions on how to validate possession of the identifier, by providing a URL for that web page. The string "oob-01" The URL to be visited.  The scheme of this URL MUST be "http" or "https" A client responds to this challenge by presenting the indicated URL for a human user to navigate to.  If the user choses to complete this challege (by vising the website and completing its instructions), the client indicates this by sending a simple acknowledgement response to the server. The string "oob-01" On receiving a response, the server MUST verify that the value of the "type" field is as required.  Otherwise, the steps the server takes to validate identifier possession are determined by the server's local policy. </ins> 8. [[ Editor's Note: Should we create a registry for tokens that go into


The string "reg", indicating an update to the registration. <del> The JWK thumbprint of the old key RFC7638, base64url-encoded </del>  <del> The client signs this object with the new key pair and encodes the </del>  object and signature as a JWS.  The client then sends this JWS to the <del> server in the "newKey" field of a request to update the registration. </del>  <del> On receiving a request to the registration URL with the "newKey" </del>  attribute set, the server MUST perform the following steps: <del> Check that the contents of the "newKey" attribute are a valid JWS </del>  <del> Check that the "newKey" JWS verifies using the key in the "jwk" header parameter of the JWS </del>  Check that the payload of the JWS is a valid JSON object Check that the "resource" field of the object has the value "reg" <del> Check that the "oldKey" field of the object contains the JWK thumbprint of the account key for this registration </del>  If all of these checks pass, then the server updates the registration by replacing the old account key with the public key carried in the <del> "jwk" header parameter of the "newKey" JWS object. </del>  If the update was successful, then the server sends a response with status code 200 (OK) and the updated registration object as its body.

As discussed in the thread about , we can have a fairly clean recovery story (assuming a MAC key can be provisioned. As a first step, we should reverse the order of the signatures in the roll-over request object. Just wanted to make sure everyone is aware that there's an ACME F2F meeting happening at the IETF this afternoon, 17:40-19:40 Argentina Time (13:40-15:40 US Pacific, 20:40-22:40 UTC). URL Remote participation is possible. You can find links to audio streaming, XMPP chat, and a MeetEcho room in ACME line on the above agenda page. See you there! --Richard

The string "reg", indicating an update to the registration.  <ins> The JWK thumbprint of the new key RFC7638, base64url-encoded </ins>  <ins> The client signs this object with the old key pair and encodes the </ins> object and signature as a JWS.  The client then sends this JWS to the  <ins> server in the "rollover" field of a request to update the registration. </ins>  <ins> On receiving a request to the registration URL with the "rollover" </ins> attribute set, the server MUST perform the following steps:  <ins> Check that the contents of the "rollover" attribute are a valid JWS </ins>  <ins> Check that the "rollover" JWS verifies using the account key correspdonding to this registration </ins> Check that the payload of the JWS is a valid JSON object Check that the "resource" field of the object has the value "reg"  <ins> Check that the "newKey" field of the object contains the JWK thumbprint of the account key used to sign the request </ins> If all of these checks pass, then the server updates the registration by replacing the old account key with the public key carried in the  <ins> "jwk" header of the request JWS. </ins> If the update was successful, then the server sends a response with status code 200 (OK) and the updated registration object as its body.


As a domain may resolve to multiple IPv4 and IPv6 addresses, the server will connect to at least one of the hosts found in A and AAAA <del> records.  Because many web servers allocate a default HTTPS virtual host to a particular low-privilege tenant user in a subtle and non- intuitive manner, the challenge must be completed over HTTP, not HTTPS. </del>  The string "http-01" The key authorization for this challenge.  This value MUST match the token from the challenge and the client's account key. <del> An IPv4 or IPv6 address, in dotted decimal form or RFC4291 form, respectively.  If given, this address MUST be included in the set of IP addresses to which the domain name resolves when the server attempts validation.  If given, the server SHOULD connect to that specific IP address instead of arbitrarily choosing an IP from the set of A and AAAA records to which the domain name resolves. </del> On receiving a response, the server MUST verify that the key authorization in the response matches the "token" value in the challenge and the client's account key.  If they do not match, then Verify that the resulting URI is well-formed. <del> If the client has supplied an address to use, verify that the address is included in the A or AAAA records to which the domain name resolves.  If the address is not included in the result, the validation fails. Dereference the URI using an HTTP GET request.  If an address was supplied by the client, use that address to establish the HTTP connection. </del>  Verify that the body of the response is well-formed key authorization.  The server SHOULD ignore whitespace characters at

This reverts commit a5cb357a64ce5e46815544c9faaf94b97b3eba56 I think we did not reach consensus on the list about this feature.
Oh, it's a shame that this was removed. I was hoping to use this feature to help when my servers were behind a load balancer. We should probably remove this reference as well:

As a domain may resolve to multiple IPv4 and IPv6 addresses, the server will connect to at least one of the hosts found in A and AAAA  <ins> records, at its discretion.  Because many webservers allocate a default HTTPS virtual host to a particular low-privilege tenant user in a subtle and non-intuitive manner, the challenge must be completed over HTTP, not HTTPS. </ins> The string "http-01" The key authorization for this challenge.  This value MUST match the token from the challenge and the client's account key.  On receiving a response, the server MUST verify that the key authorization in the response matches the "token" value in the challenge and the client's account key.  If they do not match, then Verify that the resulting URI is well-formed.  <ins> Dereference the URI using an HTTP GET request. </ins> Verify that the body of the response is well-formed key authorization.  The server SHOULD ignore whitespace characters at


9.4.  The controls on issuance enabled by ACME are focused on validating that a certificate applicant controls the identifier he claims. Before issuing a certificate, however, there are many other checks operators of ACME-based CAs will need to keep in mind when configuring their services.  For example: <del> It is advisable to perform DNS queries via TCP to mitigate DNS forgery attacks over UDP </del>  <del> [[ TODO: Other operational considerations ]] </del>  <del> 10.1. </del>  In many cases, TLS-based services are deployed on hosted platforms that use the Server Name Indication (SNI) TLS extension to the namespace used for the TLS-based challenge (the "acme.invalid" namespace for "tls-sni-02"). <del> 10.2. </del>  An ACME-based CA will often need to make DNS queries, e.g., to validate control of DNS names.  Because the security of such

Server side request forgery (SSRF) is possible through ACME when using http-01 because an attacker can use HTTP 3xx redirects to make the ACME verifier server perform an HTTP GET of any URL. Additionally, Boulder helpfully includes (part) of the HTTP body in the detail field of Unauthorized errors. In theory, an HTTP GET of any URL is idempotent and won't actually affect anything. But, if the ACME server returns any part of the HTTP body in error messages (like Boulder does), an attacker could potentially read sensitive data from internal servers. Typical targets for SSRF would be metadata services (like 169.254.169.254 in AWS or OpenStack), any not publicly exposed HTTP interface of the server's stack (like the HTTP API of the RabbitMQ management plugin), or any other internal HTTP server on the server's private network. Perhaps the IETF ACME protocol spec should acknowledge SSRF in its Security Considerations? One recommendation could be to not allow connections to internal network addresses. However, if someone wanted to use ACME for a private intranet CA, correct firewalling like that is much harder. The spec could also discourage including the HTTP body in an Unauthorized error's detail field. Or at least don't include the HTTP body if a redirect was followed. Also, this is mostly mitigated by the actual implementation of Let's Encrypt and Boulder. Notably, only 128 characters (maxResponseSize) of the HTTP body are . And it doesn't seem possible to get Let's Encrypt to access HTTP servers on any port other than 80 or 443, even with a port number specified in the redirect URL, which limits what an attacker could access. (I reported this privately to EMAIL before creating this GitHub issue. This is not an issue for Let's Encrypt.)
Thanks for reporting! Can you post this to the EMAIL mailing list for further discusion? Not everyone who participates in the WG follows the GitHub repo.

9.4. <ins> Server-Side Request Forgery (SSRF) attacks can arise when an attacker can cause a server to perform HTTP requests to an attacker-chosen URL.  In the ACME HTTP challenge validation process, the ACME server performs an HTTP GET request to a URL in which the attacker can choose the domain.  This request is made before the server has verified that the client controls the domain, so any client can cause a query to any domain. Some server implementations include information from the validation server's response (in order to facilitate debugging).  Such implementations enable an attacker to extract this information from any web server that is accessible to the ACME server, even if it is not accessible to the ACME client. The risk of SSRF through this channel is limited by the fact that the attacker can only control the domain of the URL, not the path. Nonetheless, in order to further limit the SSRF risk, ACME server operators should ensure that validation queries can only be sent to servers on the public Internet, and not, say, web services within the server operator's internal network.  Since the attacker could make requests to these public servers himself, he can't gain anything extra through an SSRF attack on ACME aside from a layer of anonymization. 9.5. </ins> The controls on issuance enabled by ACME are focused on validating that a certificate applicant controls the identifier he claims. Before issuing a certificate, however, there are many other checks operators of ACME-based CAs will need to keep in mind when configuring their services.  For example:  <ins> 10.1. </ins>  <ins> As noted above, DNS forgery attacks against the ACME server can result in the server making incorrect decisions about domain control and thus mis-issuing certificates.  Servers SHOULD verify DNSSEC when it is available for a domain.  When DNSSEC is not available, servers SHOULD perform DNS queries over TCP, which provides better resistance to some forgery attacks than DNS over UDP. </ins>  <ins> 10.2. </ins> In many cases, TLS-based services are deployed on hosted platforms that use the Server Name Indication (SNI) TLS extension to the namespace used for the TLS-based challenge (the "acme.invalid" namespace for "tls-sni-02").  <ins> 10.3. </ins> An ACME-based CA will often need to make DNS queries, e.g., to validate control of DNS names.  Because the security of such


registration in order to recover from a key compromise or proactively mitigate the impact of an unnoticed key compromise. <del> To change the key associate with an account, the client POSTs a key- change object with a "key" field containing a JWK representation of the new public key.  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:

The current mechanism has a potential copy/paste vulnerability. Karthik proposed on the list: That is, you need the full matrix of "X signs over Y" -- "new/old", "new/new", "old/old", "old/new" -- so that both sides explicitly agree to the (old, new) pair. But the current design has only has "old/new" and "new/new". That raises a risk that if you got an "old/new" signature, you could copy/paste the "new/new" signature and get a valid request. As long as we have parallel signatures (cf. ), we need to have both the old and new keys in the payloads.

registration in order to recover from a key compromise or proactively mitigate the impact of an unnoticed key compromise.  <ins> To change the key associate with an account, the client sends a POST request containing a key-change object with the following fields: The JWS representation of the original key (i.e., the client's current account key) The JWS representation of the new key 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. </ins> On receiving key-change request, the server MUST perform the following steps in addition to the typical JWS validation:


registration in order to recover from a key compromise or proactively mitigate the impact of an unnoticed key compromise. <del> To change the key associate with an account, the client sends a POST </del>  request containing a key-change object with the following fields: The JWK representation of the original key (i.e., the client's 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 container a "jwk" field </del>  containing a key that matches a currently active account. Check that there are exactly two signatures on the JWS.

Fixing two minor typos in Section 6.2.1 "Account Key Roll-over"

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 sends a POST </ins> request containing a key-change object with the following fields: The JWK representation of the original key (i.e., the client's On receiving key-change request, the server MUST perform the following steps in addition to the typical JWS validation:  <ins> Check that the JWS protected header contains a "jwk" field </ins> containing a key that matches a currently active account. Check that there are exactly two signatures on the JWS.


field. If the server already has a registration object with the provided <del> account key, then it MUST return a 409 (Conflict) response and provide the URI of that registration in a Location header field. This allows a client that has an account key but not the corresponding registration URI to recover the registration URI. </del>  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

It seem like the only way to retrieve an existing registration object for a given key is to provoke an error by attempting to register again with the same key and read the Location from it. As a client library implementor, I would expect to and to not be recoverable. I think its strange that the only way to recover the registration object is by triggering an error. Would it make sense to add an extra endpoint to simply retrieve the registration object? Alternatively, I don't see any reason for the endpoint not to return when already registered (instead of when it create the registration) as opposed to a . Also, the returned error type in boulder is , which does not make much sense to me since the request was not malformed. If its an expected behaviour to provoke an error to recover data from the response, the error type should be specify into the spec and unique so its can be recovered from easily. Implementation in boulder and initial discussion in the ruby .

field. If the server already has a registration object with the provided  <ins> account key, then it MUST return a 200 (OK) response and provide the URI of that registration in a Content-Location header field.  This allows a client that has an account key but not the corresponding registration URI to recover the registration URI. </ins> 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