From ea3bc782d8128d7f52008d459ecd4df8b51979cf Mon Sep 17 00:00:00 2001 From: Jack O'Connor Date: Wed, 2 Mar 2022 17:21:24 -0500 Subject: document the extended output security issue found by Aldo Gunsing https://eprint.iacr.org/2022/283 --- src/lib.rs | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 8082dbf..1cd9fa0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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, -- cgit v1.2.3