Subject: [Acme] ACME signature mechanics

From: "Manger, James" <[email-masked]>
Date: Mon, 8 Dec 2014 17:38:44 +1100

draft-barnes-acme looks like a promising spec.
https://github.com/letsencrypt/acme-spec/blob/master/draft-barnes-acme.txt

A couple of comments:

1. The bytes to-be-signed for the various messages are the concatenation of a few fields, with no separators.
   signature-input = nonce || content
   signature-input = signature-nonce || identifier || server-nonce
   signature-input = signature-nonce || server-nonce
This looks problematic as the bytes to-be-signed are not unambiguous by themselves. The same signature (eg over ABC) is valid even if bytes are moved from a nonce to the content (eg nonce=A, content=BC; and nonce=AB, content=C). The same signature may be valid when treated as a different type of message (eg signature-nonce=A, identifier=B, server-nonce=C).

Suggestion: signature-input = <len1><field1> || <len2><field2> || ... (where <lenn> is  the length in bytes of the following field, encoded in 8 bytes)

[P.S. Watson Ladd pointed out a similar issue with HOBA earlier today in an email titled "[http-auth] Concatenation is not injective". http://www.ietf.org/mail-archive/web/http-auth/current/msg02053.html]

2. Appending 'path' to '.well-known/acme-challenge' as part of a simpleHttps challenge (section 6.1) looks dangerous if not done carefully. What if 'path' is "../../user/alice/whatever"?

Suggestion: I would be tempted to say: "take the 'path' string value, UTF-8 encode it, base64url-encode those bytes, then append to '.well-known/acme-challenge'".

3. 'nonce' is "at least 16 bytes, base64-encoded" according to section 5.2 "Signatures". Is the base64-encoding removed before using the nonce as part of the signature input?

--
James Manger

---

From: Richard Barnes <[email-masked]>
Date: Sun, 7 Dec 2014 22:59:13 -0800

Hey James,

Thanks for the comments.

> https://github.com/letsencrypt/acme-spec/blob/master/draft-barnes-acme.txt

Thanks!

> This looks problematic as the bytes to-be-signed are not unambiguous by
> themselves. The same signature (eg over ABC) is valid even if bytes are
> moved from a nonce to the content (eg nonce=A, content=BC; and nonce=AB,
> content=C). The same signature may be valid when treated as a different
> type of message (eg signature-nonce=A, identifier=B, server-nonce=C).
>
>
>
> Suggestion: signature-input = <len1><field1> || <len2><field2> || … (where
> <len*n*> is  the length in bytes of the following field, encoded in 8
> bytes)
>
>
>
> [P.S. Watson Ladd pointed out a similar issue with HOBA earlier today in
> an email titled “[http-auth] Concatenation is not injective”.
> http://www.ietf.org/mail-archive/web/http-auth/current/msg02053.html]
>

Adam Langley also pointed this out in a Github issue.

I think the simplest answer is going to be to just use JWS to sign the
entire request, including the nonce as a protected header field.  That gets
around these issues, and re-uses the JWS machinery.

> 2. Appending ‘path’ to ‘.well-known/acme-challenge’ as part of a
> simpleHttps challenge (section 6.1) looks dangerous if not done carefully.
> What if ‘path’ is “../../user/alice/whatever”?
>
>
>
> Suggestion: I would be tempted to say: “take the ‘path’ string value,
> UTF-8 encode it, base64url-encode those bytes, then append to
> ‘.well-known/acme-challenge’”.
>

Good point.  It seems like a simpler solution would just be to require that
the "path" value meet a certain ABNF, e.g., the URL-safe base64 alphabet.
The only reason that the client provides the path is to let it avoid
collisions if it has multiple validations in progress, so there's not a
need for it to be especially expressive.

> 3. ‘nonce’ is “at least 16 bytes, base64-encoded” according to section 5.2
> “Signatures”. Is the base64-encoding removed before using the nonce as part
> of the signature input?
>

That was my intent, but if we make the JWS change mentioned above, then
this won't matter.

--Richard

>
>
> --
>
> James Manger
>
>
>
> _______________________________________________
> Acme mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/acme
>
>

---

From: "Manger, James" <[email-masked]>
Date: Mon, 8 Dec 2014 18:15:35 +1100

2. Appending ‘path’ to ‘.well-known/acme-challenge’ as part of a simpleHttps challenge (section 6.1) looks dangerous if not done carefully. What if ‘path’ is “../../user/alice/whatever”?

Suggestion: I would be tempted to say: “take the ‘path’ string value, UTF-8 encode it, base64url-encode those bytes, then append to ‘.well-known/acme-challenge’”.

> Good point.  It seems like a simpler solution would just be to require that the "path" value meet a certain ABNF, e.g., the URL-safe base64 alphabet.  The only reason that the client provides the path is to let it avoid collisions if it has multiple validations in progress, so there's not a need for it to be especially expressive.

That might be simpler, but it relies on clients doing input validation on ‘path’. Telling the client to B64 whatever it gets might be just a smidgen safer.

--
James Manger

---

From: Richard Barnes <[email-masked]>
Date: Sun, 7 Dec 2014 23:45:08 -0800

On Sun, Dec 7, 2014 at 11:15 PM, Manger, James <
[email-masked]> wrote:

> > Good point.  It seems like a simpler solution would just be to require
> that the "path" value meet a certain ABNF, e.g., the URL-safe base64
> alphabet.  The only reason that the client provides the path is to let it
> avoid collisions if it has multiple validations in progress, so there's not
> a need for it to be especially expressive.
>
>
>
> That might be simpler, but it relies on clients doing input validation on
> ‘path’. Telling the client to B64 whatever it gets might be just a smidgen
> safer.
>

Relies on *servers* doing input validation; the client chooses the path.
And if the server isn't validating its inputs, we have bigger problems :)
Since not checking other inputs can lead to the issuance of bad certs.

--Richard