diff options
| author | Jack O'Connor <[email protected]> | 2022-03-02 17:21:24 -0500 |
|---|---|---|
| committer | Jack O'Connor <[email protected]> | 2022-03-02 17:39:25 -0500 |
| commit | ea3bc782d8128d7f52008d459ecd4df8b51979cf (patch) | |
| tree | 4bcea03e001253f3a3d4e332cc4f7ae3c6facbf7 | |
| parent | 4e84c8c7ae3da71d3aff5ba54d8ffa39a9b90fa0 (diff) | |
document the extended output security issue found by Aldo Gunsing
https://eprint.iacr.org/2022/283
| -rw-r--r-- | c/blake3.c | 2 | ||||
| -rw-r--r-- | src/lib.rs | 41 |
2 files changed, 32 insertions, 11 deletions
@@ -254,7 +254,7 @@ INLINE size_t compress_parents_parallel(const uint8_t *child_chaining_values, // As a special case when the SIMD degree is 1, this function will still return // at least 2 outputs. This guarantees that this function doesn't perform the // root compression. (If it did, it would use the wrong flags, and also we -// wouldn't be able to implement exendable ouput.) Note that this function is +// wouldn't be able to implement exendable output.) Note that this function is // not used when the whole input is only 1 chunk long; that's a different // codepath. // @@ -667,7 +667,7 @@ fn compress_parents_parallel( // As a special case when the SIMD degree is 1, this function will still return // at least 2 outputs. This guarantees that this function doesn't perform the // root compression. (If it did, it would use the wrong flags, and also we -// wouldn't be able to implement exendable ouput.) Note that this function is +// wouldn't be able to implement exendable output.) Note that this function is // not used when the whole input is only 1 chunk long; that's a different // codepath. // @@ -1340,16 +1340,37 @@ impl std::io::Write for Hasher { /// An incremental reader for extended output, returned by /// [`Hasher::finalize_xof`](struct.Hasher.html#method.finalize_xof). /// -/// Outputs shorter than the default length of 32 bytes (256 bits) -/// provide less security. An N-bit BLAKE3 output is intended to provide -/// N bits of first and second preimage resistance and N/2 bits of -/// collision resistance, for any N up to 256. Longer outputs don't -/// provide any additional security. +/// Shorter BLAKE3 outputs are prefixes of longer ones, and explicitly requesting a short output is +/// equivalent to truncating the default-length output. Note that this is a difference between +/// BLAKE2 and BLAKE3. /// -/// Shorter BLAKE3 outputs are prefixes of longer ones. Explicitly -/// requesting a short output is equivalent to truncating the -/// default-length output. (Note that this is different between BLAKE2 -/// and BLAKE3.) +/// # Security notes +/// +/// Outputs shorter than the default length of 32 bytes (256 bits) provide less security. An N-bit +/// BLAKE3 output is intended to provide N bits of first and second preimage resistance and N/2 +/// bits of collision resistance, for any N up to 256. Longer outputs don't provide any additional +/// security. +/// +/// [_Block-Cipher-Based Tree Hashing_ by Aldo Gunsing](https://eprint.iacr.org/2022/283) shows +/// that an extended BLAKE3 output doesn't protect the secrecy of its offset — that is the number +/// of output bytes that came before, or the argument to +/// [`seek`](struct.OutputReader.html#method.seek) or +/// [`position`](struct.OutputReader.html#method.position) — as well as it ideally could. Callers +/// who rely on secret output lengths or offsets need to pay attention to this, but the vast +/// majority of callers use constant and/or public lengths and offsets and aren't affected. +/// +/// The underlying issue is that the BLAKE3 compression function is invertible if an attacker +/// already knows the message and the key and also observes an extended output. In particular, +/// inverting the compression function doesn't require knowing the internal `t` parameter that +/// represents the offset. In other words, an output offset doesn't contribute any entropy towards +/// protecting its own secrecy or the secrecy of other inputs. However, the offset does benefit +/// from the entropy of the message and the key, so for example a caller using a 256-bit secret key +/// is also not affected. +/// +/// For comparison, AES-CTR has a similar property. If you know the key, you can decrypt a block +/// from an unknown position in the output stream to recover its block index. However, the Salsa +/// and ChaCha stream ciphers don't have this property, because they feed their offsets forward +/// into their output. #[derive(Clone)] pub struct OutputReader { inner: Output, |
