Skip to content

Commit

Permalink
Breaking Change in HKDF Definition for v3
Browse files Browse the repository at this point in the history
See https://eprint.iacr.org/2010/264 Definition 7 for more information
  • Loading branch information
paragonie-security committed Jul 29, 2021
1 parent 32606a5 commit 6c6eb51
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 18 deletions.
21 changes: 10 additions & 11 deletions docs/01-Protocol-Versions/Version3.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ implicit assertion `i` (which defaults to empty string):
2. Generate 32 random bytes from the OS's CSPRNG
to get the nonce, `n`.
3. Split the key into an Encryption key (`Ek`) and Authentication key (`Ak`),
using HKDF-HMAC-SHA384, with `n` as the HKDF salt.
using HKDF-HMAC-SHA384, with `n` appended to the info rather than the salt.
* The output length **MUST** be 48 for the first key derivation and 32 for `Ak`.
* The derived key will be the leftmost 32 bytes of the first HKDF derivation.

Expand All @@ -23,16 +23,16 @@ implicit assertion `i` (which defaults to empty string):
tmp = hkdf_sha384(
len = 48
ikm = k,
info = "paseto-encryption-key",
salt = n
info = "paseto-encryption-key" || n,
salt = NULL
);
Ek = tmp[0:32]
n2 = tmp[32:]
Ak = hkdf_sha384(
len = 32
ikm = k,
info = "paseto-auth-key-for-aead",
salt = n
info = "paseto-auth-key-for-aead" || n,
salt = NULL
);
```
5. Encrypt the message using `AES-256-CTR`, using `Ek` as the key and
Expand Down Expand Up @@ -61,7 +61,6 @@ Given a message `m`, key `k`, and optional footer `f`
(which defaults to empty string), and an optional
implicit assertion `i` (which defaults to empty string):


1. If `f` is not empty, implementations **MAY** verify that the value appended
to the token matches some expected string `f`, provided they do so using a
constant-time string compare function.
Expand All @@ -73,7 +72,7 @@ implicit assertion `i` (which defaults to empty string):
* `t` to the rightmost 48 bytes
* `c` to the middle remainder of the payload, excluding `n` and `t`
4. Split the key (`k`) into an Encryption key (`Ek`) and an Authentication key
(`Ak`), `n` as the HKDF salt.
(`Ak`), `n` appended to the HKDF info.
* For encryption keys, the **info** parameter for HKDF **MUST** be set to
**paseto-encryption-key**.
* For authentication keys, the **info** parameter for HKDF **MUST** be set to
Expand All @@ -86,16 +85,16 @@ implicit assertion `i` (which defaults to empty string):
tmp = hkdf_sha384(
len = 48
ikm = k,
info = "paseto-encryption-key",
salt = n
info = "paseto-encryption-key" || n,
salt = NULL
);
Ek = tmp[0:32]
n2 = tmp[32:]
Ak = hkdf_sha384(
len = 32
ikm = k,
info = "paseto-auth-key-for-aead",
salt = n
info = "paseto-auth-key-for-aead" || n,
salt = NULL
);
```
5. Pack `h`, `n`, `c`, `f`, and `i` together (in that order) using
Expand Down
22 changes: 15 additions & 7 deletions docs/Rationale-V3-V4.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,17 +158,25 @@ half was used as an AES-CTR nonce. This is tricky to analyze and didn't extend
well for the v4.local proposal.

For the sake of consistency and easy-to-analyze security designs, in both v3.local
and v4.local, we now use the entire 32-byte salt in the HKDF step. The nonce
used by AES-256-CTR and XChaCha20 will be derived from the HKDF output (which
is now 48 bytes for v3.local and 56 bytes for v4.local). The first 32 bytes of
each HKDF output will be used as the key. The remaining bytes will be used as
the nonce for the underlying cipher.
and v4.local, we now use the entire 32-byte random value in the HKDF step.

Instead of being used as a salt, however, it will be appended to the info tag.
This subtle change allows us to use the
[standard security definition for HKDF](https://eprint.iacr.org/2010/264)
in arguments for PASETO's security, rather than treating it as just a
pseudo-random function (PRF). This security definition requires only one salt
to be used, but for many contexts (info tags).

The nonce used by AES-256-CTR and XChaCha20 will be derived from the HKDF output
(which is now 48 bytes for v3.local and 56 bytes for v4.local). The first 32
bytes of each HKDF output will be used as the key. The remaining bytes will be
used as the nonce for the underlying cipher.

Local PASETOs in v3 and v4 will always have a predictable storage size, and the
security of these constructions is more obvious:

* The probability space for either mode is 256-bits of salt + 256-bits of key,
for a total of 512 bits.
* The probability space for either mode is 256-bits of randomness + 256-bits of
key, for a total of 512 bits.
* The HKDF output in v3.local is 384 bits.
* The HKDF output in v4.local is 448 bits.
* Neither of these output sizes reduces the security against collisions.
Expand Down

0 comments on commit 6c6eb51

Please sign in to comment.