Draft: draft-ietf-acme-acme

Commentary: 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 does n't sign over the old key . Both signatures have to include the parameter , so this request burns two nonces unnecessarily The server 's  checking code now has to switch between validating one signature and two Lots of JWS implementations do n'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 :
Paragraph (version B):
Note that this comparison is equivalent to computing the JWK
thumbprints of the two keys and comparing thumbprints.  The only
difference is that there is no requirement for a hash computation
(and thus it is independent of the choice of hash function) and no
risk of hash collision.
Paragraph (version A):
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.
Paragraph (version A):
Check that the JWS protected header contains a "jwk" field
containing a key that matches a currently active account.
Paragraph (version A):
Check that there are exactly two signatures on the JWS.
Paragraph (version A):
Check that one of the signatures validates using the account key
from (1).
Paragraph (version A):
Check that the "key" field contains a well-formed JWK that meets
key strength requirements.
Paragraph (version A):
Check that the "key" field is not equivalent to the current
account key or any other currently active account key.
Paragraph (version A):
Check that one of the two signatures on the JWS validates using
the JWK from the "key" field.
Paragraph (version B):
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.
Paragraph (version B):
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.
Paragraph (version B):
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).
Paragraph (version B):
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.
Paragraph (version B):
The inner JWS MUST have the same "url" parameter as the outer JWS.
Paragraph (version B):
The inner JWS is NOT REQUIRED to have a "nonce" parameter.  The
server MUST ignore any value provided for the "nonce" header
parameter.
Paragraph (version B):
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.