Change:
registration in order to recover from a key compromise or proactively mitigate the impact of an unnoticed key compromise. <del> To change the key associated with an account, the client sends a POST request containing a key-change object with the following fields: </del> <ins> To change the key associated with an account, the client first constructs a key-change object describing the change that it would like the server to make: The URL for account being modified.  The content of this field MUST be the exact string provided in the Location header field in response to the new-registration request that created the account. </ins> The JWK representation of the original key (i.e., the client's current account key) The JWK representation of the new key <del> The JWS of this POST must have two signatures: one signature from the existing key on the account, and one signature from the new key that the client proposes to use.  This demonstrates that the client actually has control of the private key corresponding to the new public key.  The protected header must contain a JWK field containing the current account key. </del> <ins> Both of these thumbprints MUST be computed as specified in RFC7638, using the SHA-256 digest.  The values in the "oldKey" and "newKey" fields MUST be the base64url encodings of the thumbprints. The client then encapsulates the key-change object in a JWS, signed with the client's current account key (i.e., the key matching the "oldKey" value). This inner JWS then become the payload of the JWS that the client sends to the server.  The outer JWS is signed with the key pair that the the client wishes to have the server use as its account key (i.e., the key pair matching the "newKey" value).  The client sends this outer JWS in a POST request to the server's "key-change" resource. The outer JWS MUST meet the normal requirements for an ACME JWS (see request-authentication).  The inner JWS MUST meet the normal requirements, with the following exceptions: The inner JWS MUST have the same "url" parameter as the outer JWS. The inner JWS is NOT REQUIRED to have a "nonce" parameter.  The server MUST ignore any value provided for the "nonce" header parameter. This transaction has signatures from both the old and new keys so that the server can verify that the holders of the two keys both agree to the change.  The signatures are nested to preserve the property that all signatures on POST messages are signed by exactly one key. </ins> On receiving key-change request, the server MUST perform the following steps in addition to the typical JWS validation: <del> Check that the JWS protected header contains a "jwk" field containing a key that matches a currently active account. </del> <ins> Check that the payload of the JWS is a well-formed JWS object (the "inner JWS") Check that the JWS protected header of the inner JWS has a "jwk" field containing a key that matches a currently active account Check that the inner JWS verifies using the key in its "jwk" field </ins> <del> Check that there are exactly two signatures on the JWS. </del> <ins> Check that the payload of the inner JWS is a well-formed key- change object (as described above) </ins> <del> Check that one of the signatures validates using the account key from (1). </del> <ins> Check that the "url" parameters of the inner and outer JWSs are the same </ins> <del> Check that the "key" field contains a well-formed JWK that meets key strength requirements. </del> <ins> Check that the "account" field of the key-change object contains the URL for the registration matching the old key </ins> <del> Check that the "key" field is not equivalent to the current account key or any other currently active account key. </del> <ins> Check that the "oldKey" field of the key-change object contains the thumbprint of the key used to sign the inner JWS </ins> <del> Check that one of the two signatures on the JWS validates using the JWK from the "key" field. </del> <ins> Check that the "newKey" field of the key-change object contains the thumbprint of the key used to sign the outer JWS </ins> If all of these checks pass, then the server updates the corresponding registration by replacing the old account key with the

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