-
Notifications
You must be signed in to change notification settings - Fork 4
Clarify nonce hashing #7
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
base: master
Are you sure you want to change the base?
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 | ||||
|---|---|---|---|---|---|---|
|
|
@@ -114,6 +114,18 @@ It contains the following fields: | |||||
|
|
||||||
| The value that is signed by the user’s authentication private key and included in the `signature` field is `hash(origin)+hash(challenge)`. The hash function is used before concatenation to ensure field separation as the hash of a value is guaranteed to have a fixed length. Otherwise the origin `example.com` with challenge `.eu1234` and another origin `example.com.eu` with challenge `1234` would result in the same value after concatenation. The hash function `hash` is the same hash function that is used in the signature algorithm, for example SHA256 in case of RS256. | ||||||
|
|
||||||
| #### Clarification on `nonce` (challenge) processing | ||||||
|
|
||||||
| - The `nonce` value is supplied by the Relying Party (RP) as a **Base64-encoded string** representing a cryptographically strong random value (at least 16 bytes of entropy recommended). | ||||||
|
Member
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.
Suggested change
Relying Party is an OpenID Connect term that does not apply in this context. Arnis used website elsewhere in the text, so we should use the same term. We require 32 Base64-encoded bytes, see next comment and source reference. Remove bold emphasis to align with the style of the rest of the document. |
||||||
| - The Web-eID application **verifies that the `nonce` is valid Base64** but does **not decode** it into raw bytes. | ||||||
|
Member
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. We do not verify that nonce is valid Base64, we only require that byte length is at least 44, the length of 32 Base64-encoded bytes to require at least 256 bits of entropy, see Remove bold emphasis to align with the style of the rest of the document. |
||||||
| - Instead, the **literal Base64 string** is UTF-8 encoded and used in the hashing step. | ||||||
|
Member
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 think this explanation makes it confusing. The nonce can actually not be Base64 encoded (some imaginary special cases during command-line use) and as we need to use some encoding in this case, we use standard UTF-8 which is a superset of the Base64 ASCII encoding. But for Base64 strings UTF-8 encoding is a no-op. The point is we don't really require it to be Base64, but Base64 is the sanest encoding for transmitting bytes through the web layer. So we treat the nonce as a "constant in presumably Base64 encoding that we don't Base64 decode". Can this be explained better? |
||||||
|
|
||||||
| Therefore, the backend must reproduce the exact same calculation: | ||||||
| ``` | ||||||
| Hash( Hash(origin.encode("utf-8")) + Hash(nonce.encode("utf-8")) ) | ||||||
| ``` | ||||||
| where `nonce.encode("utf-8")` is the UTF-8 encoding of the Base64 string, not the decoded bytes. | ||||||
|
|
||||||
| To verify the signature, the website has to reconstruct the signed data. Since the challenge value and the origin field are not included in the token in the proposed solution, the website is forced to reconstruct the signed data using the origin and challenge values from its trusted local storage. This provides an important security advantage as it is guaranteed that if the signature verification succeeds, then the origin and challenge have been implicitly and correctly verified without the need to implement any additional security checks. Furthermore, it also guarantees that the authentication proof was received from the same browser to which the corresponding challenge was issued, as the website is forced to lookup the challenge and, possibly, the origin, in case it can vary, from its local storage using an identifier specific to the browser session. | ||||||
|
|
||||||
| [^foolproof]: So simple, plain, or reliable as to leave no opportunity for error, misuse, or failure. | ||||||
|
|
||||||
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.
This document is actually historic and should in principle no longer be updated. But as there is value in clarifying
noncehandling here, let's get your changes in.But please also update the main format reference here:
https://github.com/web-eid/web-eid-system-architecture-doc/blob/master/README.md?plain=1#L386