-
Notifications
You must be signed in to change notification settings - Fork 112
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Quick fix for Ayer's duplicate-signature key selection attack #217
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1649,9 +1649,8 @@ The client serializes the validation object to UTF-8, then uses its account | |
private key to sign a JWS with the serialized JSON object as its payload. This | ||
JWS is NOT REQUIRED to have the "nonce" header parameter. | ||
|
||
The client will compute Z, the SHA-256 of the "signature" value from the JWS. | ||
The hash is calculated over the base64-encoded signature string. Z is encoded | ||
in hexadecimal form. | ||
The client will compute Z, the SHA-256 of the JWS encoded in UTF-8. | ||
Z is encoded in hexadecimal form. | ||
|
||
The client will generate a self-signed certificate with the | ||
subjectAlternativeName extension containing the dNSName | ||
|
@@ -1682,8 +1681,7 @@ validation (required, string): | |
Given a Challenge/Response pair, the ACME server verifies the client's control | ||
of the domain by verifying that the TLS server was configured appropriately. | ||
|
||
1. Verify the validation JWS using the account key for which the challenge | ||
was issued. | ||
1. Verify the validation JWS using the account key. | ||
2. Decode the payload of the JWS as UTF-8 encoded JSON. | ||
3. Verify that there are exactly two fields in the decoded object, and that: | ||
* The "type" field is set to "dvsni" | ||
|
@@ -1861,12 +1859,12 @@ The client serializes the validation object to UTF-8, then uses its account | |
private key to sign a JWS with the serialized JSON object as its payload. This | ||
JWS is NOT REQUIRED to have the "nonce" header parameter. | ||
|
||
The record provisioned to the DNS is the "signature" value from the JWS, i.e., | ||
the base64-encoded signature value. The client constructs the validation domain | ||
name by appending the label "_acme-challenge" to the domain name being | ||
validated, then provisions a TXT record with the signature value under that | ||
name. For example, if the domain name being validated is "example.com", then the | ||
client would provision the following DNS record: | ||
The record provisioned to the DNS is the base64-encoded SHA-256 of the JWS | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not just use the SHA-256 of the serialized challenge? I don't understand why the client needs to construct the JWS over the challenge if the signature never gets verified. i.e., step 5 is comparing two JWS values for equality but doesn't verify either JWS. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The signature does get verified. Step 1 verifies the JWS. Step 5 verifies that the JWS (from step 1) is located in the DNS record. It makes sure that the ACME client has control of the account key, and the authorization (DNS entry/certificate) is explicitly linked to the validation response. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (I understand this issue is closed - however, I'm replying here for thread continuity.) The signature gets verified in step 1 on the request from the client, not on the DNS value. Why not just put sha256 of the payload in DNS (instead of SHA256 of signature over the payload)? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The challenge payload doesn't contain the public portion of the account key which I believe is necessary. I was also trying to maintain some uniformity with the existing SimpleHTTP challenge (provide the full validation JWS). Here is one attack that I was trying to protect against. Imagine a client communicating with an "evil" ACME server (or any untrustworthy TLS endpoint). The "evil" ACME server could attain authorization over a domain it doesn't own with its own public key from a legitimate ACME server. The evil ACME server would forward requests to the true ACME server except swap out its own public key for all of the requests. When the authorization step came, the client would unwittingly allow the evil ACME server to use the same validation challenge. |
||
encoded in UTF-8. The client constructs the validation domain name by | ||
appending the label "_acme-challenge" to the domain name being validated, then | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: should this be "prepending" not "appending"? |
||
provisions a TXT record with the signature value under that name. For example, | ||
if the domain name being validated is "example.com", then the client would | ||
provision the following DNS record: | ||
|
||
~~~~~~~~~~ | ||
_acme-challenge.example.com. 300 IN TXT "gfj9Xq...Rg85nM" | ||
|
@@ -1894,15 +1892,14 @@ validation (required, JWS): | |
|
||
To validate a DNS challenge, the server performs the following steps: | ||
|
||
1. Verify the validation JWS using the account key for which this challenge was | ||
issued | ||
1. Verify the validation JWS using the account key. | ||
2. Decode the payload of the JWS as UTF-8 encoded JSON | ||
3. Verify that there are exactly two fields in the decoded object, and that: | ||
* The "type" field is set to "dns" | ||
* The "token" field matches the "token" value in the challenge | ||
4. Query for TXT records under the validation domain name | ||
5. Verify that the contents of one of the TXT records match the "signature" | ||
value in the "validation" JWS | ||
5. Verify that the contents of one of the TXT records match the base64-encoded | ||
SHA-256 of the "validation" JWS. | ||
|
||
If all of the above verifications succeed, then the validation is successful. | ||
If no DNS record is found, or DNS record and response payload do not pass these | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment/question as for DNS: why not use simple serialization instead of JWS
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I attempted to answer this after the DNS comment.