Subject: Re: [Acme] Unparallelizing roll-over

From: Jacob Hoffman-Andrews <[email-masked]>
Date: Sat, 6 Aug 2016 09:53:16 -0700

On 07/28/2016 02:54 PM, Richard Barnes wrote:
> #164 - Unparallelize signatures on key-change
> https://github.com/ietf-wg-acme/acme/pull/164
I don't like the JWS approach of "just wrap it in another layer of
base64url," but I agree that this is a bit of an improvement over the
existing scheme. When I proposed the two-signatures approach, I was
thinking that both keys would automatically be covered by the whole
signature, but looking more closely I see that's not the case, so the
benefit's not there. So overall I'm supportive of going back to nested
signatures.

I see that you changed oldKey and newKey to thumbprints instead of full
JWK objects. Why is that? It seems like it introduces an extra step that
is unnecessary, and adds another place where we hardcode a hash
function. I'd prefer to keep them as the full JWK objects.

Also, why require a distinct nonce on the inner and outer JWS? I would
rather require that the nonce and URL parameters must match between the
inner and outer JWS.

---

From: Richard Barnes <[email-masked]>
Date: Sat, 6 Aug 2016 14:03:49 -0400

> function. I'd prefer to keep them as the full JWK objects.

- Less bloat
- Implementations are already going to need to have a thumbprint
implementation around for the challenges.
- Not worried about pinning a hash function because we (1) seems unlikely
we'll need to change soon and (2) we can define a new rollover endpoint if
we need to change

> rather require that the nonce and URL parameters must match between the

- Never re-use nonces
- ... for example, because that would require special handling in your JWS
verification method

--Richard

---

From: Jacob Hoffman-Andrews <[email-masked]>
Date: Sat, 6 Aug 2016 11:16:10 -0700

> - Less bloat
I think that's not a concern for this rarely used endpoint.

> - Not worried about pinning a hash function because we (1) seems
> unlikely we'll need to change soon and (2) we can define a new
> rollover endpoint if we need to change
These two aren't reasons why it's good to do a thumbprint, they're
reasons why it might not be bad. If the only reason it's good is less
bloat, I'm in favor of less manipulation, fewer steps, and less
hardcoding of crypto primitives.

>     rather require that the nonce and URL parameters must match
The nonce is a property of the request, not the signature. These aren't
like ECDSA nonces where reuse is fatal.
> - ... for example, because that would require special handling in your
> JWS verification method
This is already going to require a separate JWS verification method,
because the key to be validated is not currently associated with any
account.

---

From: Richard Barnes <[email-masked]>
Date: Fri, 19 Aug 2016 12:31:13 -0400

On Sat, Aug 6, 2016 at 2:16 PM, Jacob Hoffman-Andrews <[email-masked]> wrote:

> These two aren't reasons why it's good to do a thumbprint, they're reasons
> why it might not be bad. If the only reason it's good is less bloat, I'm in
> favor of less manipulation, fewer steps, and less hardcoding of crypto
> primitives.
>

Actually I thought of another reason, which is more compelling: There's no
specified algorithm for comparing JWKs.  Do you include, e.g., "kid" or
"x5t"?

So we would need to specify a comparison algorithm.  It seems like the most
likely candidate for that would be "compare the fields that go into a
thumbprint calculation", in which case it's probably less code to just
compute the thumbprint.

> because the key to be validated is not currently associated with any

On further thought, I think I would like to propose that we go back to not
caring about the nonce.

Requiring the nonce to be handled at the ACME layer seems like a huge pain,
on the client side especially.  Normally, nonces are just a transport-layer
concept that the ACME layer doesn't need to know about, so requiring them
to be the same would be a layering violation.  On the server side, it's not
so bad; the transport layer just needs to tell the ACME layer what nonce
was used.  But on the client side, the ACME layer now needs to both get a
nonce from the transport layer and ensure that that nonce is used for the
ultimate message.

I don't think there are security risks that would arise from this
decision.  It would mean that the inner JWS could be used on a different
key-change transaction, but only by the same new account key holder, for
the same old key/account, on the same server.  Within that scope, it
actually seems like it's more of a feature than a bug -- if the nonces have
to be equal, then you need to have a full RTT between the old and new key
holders (N->O: nonce, O->N: signed object).  That RTT needs to be pretty
real-time, because the nonce still needs to be valid.  If the inner JWS can
be nonce-less (or have an ignored nonce), then the old key holder can just
provide the new key holder with a signed object and the old key holder can
use it at its leisure.

This non-real-time aspect does have some risk.  Namely, since the
key-change object only identifies the registration by key, and we can now
change keys, it could be possible for the new key holder to take over a
unexpected account:

Initial state: (keyA for acct1) and (keyB for acct2)
- keyA signs key-change doc (keyA -> keyC), intending to transfer acct1
- keyB and keyA do (keyB -> keyA) for acct2, so now keyA is bound to acct2
- keyC can now claim acct2 instead of acct1

(If you reverse the order of the keys, you end up with the old key holder
being able to give the new key holder an unexpected account.) I think the
way to address this is just to have the inner JWS reflect the URL of the
account/registration for which the transfer is being done, by adding a
parameter alongside "oldKey" and "newKey.

Updated the PR to reflect these considerations:

---

From: Jacob Hoffman-Andrews <[email-masked]>
Date: Fri, 19 Aug 2016 11:30:19 -0700

On 08/19/2016 09:31 AM, Richard Barnes wrote:
> Actually I thought of another reason, which is more compelling: There's
> no specified algorithm for comparing JWKs.  Do you include, e.g., "kid"
> or "x5t"?
> 
> So we would need to specify a comparison algorithm.

This is already a problem for each authenticated ACME POST. Right now
the user is identified solely by their full account key, and it's up to
the ACME server to determine how to look up a user by that key. I think
this isn't a problem by itself. The server can do a thumbprint itself,
preserving the option to switch hashes without breaking any clients.

However, this relates to another change I've been meaning to propose:
Identifying POSTs by account URLs instead of by key.

This encourages servers to implement this logic:

 - verify a POST using the account key from the JWS header
 - then, look up that account key in a database of users

Instead of this logic:

 - look up an account's key in a database of users
 - then, verify the POST using that account key

The latter better fits the best practice of "don't process untrusted
input until after you've verified the signature." The former is
vulnerable if the attacker can make their own key that happens to
coincide with another in the database.

Instead, the client can use the account URL rather than the full key to
identify each request after registration. This requires that the server
keep track of keys and properly validate them. It also makes lookup more
straightforward for the server with regards to the question you raised
about comparison of JWKs.

For instance, the client could provide the account URL in the JWS "kid"
header instead of the full key in the JWS "jwk" header.

This matches nicely with your proposed use of the account URL in the
inner key-change payload. I think providing the account URL there also
removes the need for the oldKey field. I still strongly believe we need
the full newKey. So we'd wind up with:

account (required, string):
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.

newKey (requrired, JWK):
The JWK representation of the new key

> On further thought, I think I would like to propose that we go back to
> not caring about the nonce.

There was some earlier discussion about why the nonce on the inner
payload was valuable. Could you quote that here and specifically rebut?
I think I agree with dropping it this but I want to make sure we keep
the context of the original discussion.

---

From: Jacob Hoffman-Andrews <[email-masked]>
Date: Sun, 21 Aug 2016 16:04:21 -0700

Here are my proposed edits to Richard's current unparallelizing
roll-over branch: https://github.com/ietf-wg-acme/acme/pull/177