### Hash Standard Input Example Source: https://docs.rs/blake3/latest/src/blake3/lib.rs.html Demonstrates how to hash standard input using `update_reader`. This example requires the `std` feature to be enabled. ```rust # use std::fs::File; # use std::io; # fn main() -> io::Result<()> { # // Hash standard input. # let mut hasher = blake3::Hasher::new(); # hasher.update_reader(std::io::stdin().lock())?; # println!("{}", hasher.finalize()); # Ok(()) # } ``` -------------------------------- ### derive_key Usage Example Source: https://docs.rs/blake3/latest/blake3/fn.derive_key.html An example demonstrating the usage of the derive_key function and its equivalent using the Hasher API. ```APIDOC let key = blake3::derive_key(CONTEXT, b"key material, not a password"); let key: [u8; 32] = blake3::Hasher::new_derive_key(CONTEXT) .update(b"key material, not a password") .finalize() .into(); ``` -------------------------------- ### Example: Computing Interior Hashes in a 3-Chunk Tree Source: https://docs.rs/blake3/latest/blake3/hazmat/index.html Demonstrates how to compute the chaining values for individual chunks and merge them to form parent nodes, culminating in the final root hash. This example highlights the use of `set_input_offset`, `update`, `finalize_non_root`, `merge_subtrees_non_root`, and `merge_subtrees_root`. ```APIDOC ## Example: Computing Interior Hashes in a 3-Chunk Tree This example demonstrates computing the chaining values for individual chunks and merging them to form parent nodes, culminating in the final root hash. It highlights the use of `set_input_offset`, `update`, `finalize_non_root`, `merge_subtrees_non_root`, and `merge_subtrees_root`. ```rust use blake3::{Hasher, CHUNK_LEN}; use blake3::hazmat::{merge_subtrees_non_root, merge_subtrees_root, Mode}; use blake3::hazmat::HasherExt; // an extension trait for Hasher let chunk0 = [b'a'; CHUNK_LEN]; let chunk1 = [b'b'; CHUNK_LEN]; let chunk2 = [b'c'; 42]; // The final chunk can be short. // Compute the non-root hashes ("chaining values") of all three chunks. Chunks or subtrees // that don't begin at the start of the input use `set_input_offset` to say where they begin. let chunk0_cv = Hasher::new() // .set_input_offset(0) is the default. .update(&chunk0) .finalize_non_root(); let chunk1_cv = Hasher::new() .set_input_offset(CHUNK_LEN as u64) .update(&chunk1) .finalize_non_root(); let chunk2_cv = Hasher::new() .set_input_offset(2 * CHUNK_LEN as u64) .update(&chunk2) .finalize_non_root(); // Join the first two chunks with a non-root parent node and compute its chaining value. let parent_cv = merge_subtrees_non_root(&chunk0_cv, &chunk1_cv, Mode::Hash); // Join that parent node and the third chunk with a root parent node and compute the hash. let root_hash = merge_subtrees_root(&parent_cv, &chunk2_cv, Mode::Hash); // Double check that we got the right answer. let mut combined_input = Vec::new(); combined_input.extend_from_slice(&chunk0); combined_input.extend_from_slice(&chunk1); combined_input.extend_from_slice(&chunk2); assert_eq!(root_hash, blake3::hash(&combined_input)); ``` ``` -------------------------------- ### Key Derivation Incremental Example Source: https://docs.rs/blake3/latest/src/blake3/lib.rs.html Demonstrates the equivalent key derivation computation using the incremental `Hasher` API. ```rust let key = blake3::derive_key(CONTEXT, b"key material, not a password"); # let key1 = key; let key: [u8; 32] = blake3::Hasher::new_derive_key(CONTEXT) .update(b"key material, not a password") .finalize() .into(); # let key2 = key; # assert_eq!(key1, key2); ``` -------------------------------- ### Derive Key Context Example Source: https://docs.rs/blake3/latest/blake3/hazmat/fn.hash_derive_key_context.html Demonstrates how to use `hash_derive_key_context` to create a `ContextKey` and then use it with `Hasher::new_from_context_key` to derive a key. This is compared against the direct `blake3::derive_key` function. ```rust use blake3::Hasher; use blake3::hazmat::HasherExt; let context_key = blake3::hazmat::hash_derive_key_context("foo"); let mut hasher = Hasher::new_from_context_key(&context_key); hasher.update(b"bar"); let derived_key = *hasher.finalize().as_bytes(); assert_eq!(derived_key, blake3::derive_key("foo", b"bar")); ``` -------------------------------- ### Hashing an input all at once Source: https://docs.rs/blake3/latest/blake3 This example demonstrates how to compute the BLAKE3 hash of an input byte slice in a single operation. ```APIDOC ## hash ### Description The default hash function. Computes the BLAKE3 hash of an input byte slice. ### Function Signature `blake3::hash(data: &[u8]) -> blake3::Hash` ### Parameters * `data` (bytes) - The input data to hash. ### Returns A `blake3::Hash` struct representing the computed hash. ### Example ```rust let hash = blake3::hash(b"foobarbaz"); println!("{}", hash); ``` ``` -------------------------------- ### Example: Hashing Multiple Chunks in Parallel Source: https://docs.rs/blake3/latest/blake3/hazmat/index.html Illustrates how hashing multiple chunks together can improve performance by leveraging internal SIMD parallelism. It shows how to compute a subtree's chaining value by processing multiple chunks simultaneously. ```APIDOC ## Example: Hashing Multiple Chunks in Parallel Hashing many chunks together is important for performance, because it allows the implementation to use SIMD parallelism internally. (AVX-512 for example needs 16 chunks to really get going.) We can reproduce `parent_cv` by hashing `chunk0` and `chunk1` at the same time: ```rust let left_subtree_cv = Hasher::new() // .set_input_offset(0) is the default. .update(&combined_input[..2 * CHUNK_LEN]) .finalize_non_root(); assert_eq!(left_subtree_cv, parent_cv); // Using multiple updates gives the same answer, though it's not as efficient. let mut subtree_hasher = Hasher::new(); // Again, .set_input_offset(0) is the default. subtree_hasher.update(&chunk0); subtree_hasher.update(&chunk1); assert_eq!(left_subtree_cv, subtree_hasher.finalize_non_root()); ``` However, hashing multiple chunks together **must** respect the overall tree structure. Hashing `chunk0` and `chunk1` together is valid, but hashing `chunk1` and `chunk2` together is incorrect and gives a garbage result that will never match a standard BLAKE3 hash. The implementation includes a few best-effort asserts to catch some of these mistakes, but these checks aren’t guaranteed. For example, this second call to `update` currently panics: ⓘ```rust let oops = Hasher::new() .set_input_offset(CHUNK_LEN as u64) .update(&chunk1) // PANIC: "the subtree starting at 1024 contains at most 1024 bytes" .update(&chunk2) .finalize_non_root(); ``` For more on valid tree structures, see the docs for and `left_subtree_len` and `max_subtree_len`, and see section 2.1 of the BLAKE3 paper. Note that the merging functions (`merge_subtrees_root` and friends) don’t know the shape of the left and right subtrees you’re giving them, and they can’t help you catch mistakes. The best way to catch mistakes with these is to compare your root output to the `blake3::hash` of the same input. ``` -------------------------------- ### Keyed Hash Incremental Example Source: https://docs.rs/blake3/latest/src/blake3/lib.rs.html Demonstrates the equivalent keyed hash computation using the incremental `Hasher` API. ```rust let mac = blake3::keyed_hash(KEY, b"foo"); # let mac1 = mac; let mac = blake3::Hasher::new_keyed(KEY).update(b"foo").finalize(); # let mac2 = mac; # assert_eq!(mac1, mac2); ``` -------------------------------- ### BLAKE3 keyed_hash example Source: https://docs.rs/blake3/latest/blake3/fn.keyed_hash.html Demonstrates the basic usage of the keyed_hash function for generating a MAC. For security, compare the resulting Hash values using constant-time comparison methods. ```rust let mac = blake3::keyed_hash(KEY, b"foo"); ``` -------------------------------- ### BLAKE3 Tree Hashing Example Source: https://docs.rs/blake3/latest/src/blake3/hazmat.rs.html Demonstrates how to compute a subtree hash using multiple updates and verify it against a parent hash. This is useful for understanding BLAKE3's tree structure and for manual verification. ```rust # use blake3::{Hasher, CHUNK_LEN}; # use blake3::hazmat::HasherExt; # fn main() { # let chunk0 = [b'a'; CHUNK_LEN]; # let chunk1 = [b'b'; CHUNK_LEN]; # let parent_cv = Hasher::new().update(&chunk0).update(&chunk1).finalize_non_root(); # let mut combined_input = Vec::with_capacity(2 * CHUNK_LEN); //! # combined_input.extend_from_slice(&chunk0); //! # combined_input.extend_from_slice(&chunk1); //! let left_subtree_cv = Hasher::new() //! // .set_input_offset(0) is the default. //! .update(&combined_input[..2 * CHUNK_LEN]) //! .finalize_non_root(); //! assert_eq!(left_subtree_cv, parent_cv); //! //! // Using multiple updates gives the same answer, though it's not as efficient. //! let mut subtree_hasher = Hasher::new(); //! // Again, .set_input_offset(0) is the default. //! subtree_hasher.update(&chunk0); //! subtree_hasher.update(&chunk1); //! assert_eq!(left_subtree_cv, subtree_hasher.finalize_non_root()); //! # } ``` -------------------------------- ### BLAKE3 Hashing Examples in Rust Source: https://docs.rs/blake3/latest/blake3 Demonstrates both one-shot and incremental hashing with BLAKE3. The incremental approach allows for hashing data in chunks. It also shows how to use the extended output functionality for reading more than the standard hash length and how to print the hash as a hexadecimal string. ```rust let hash1 = blake3::hash(b"foobarbaz"); ``` ```rust let mut hasher = blake3::Hasher::new(); hasher.update(b"foo"); hasher.update(b"bar"); hasher.update(b"baz"); let hash2 = hasher.finalize(); assert_eq!(hash1, hash2); ``` ```rust let mut output = [0; 1000]; let mut output_reader = hasher.finalize_xof(); output_reader.fill(&mut output); assert_eq!(hash1, output[..32]); ``` ```rust println!("{}", hash1); ``` -------------------------------- ### BLAKE3 incremental keyed hash example Source: https://docs.rs/blake3/latest/blake3/fn.keyed_hash.html Shows the equivalent incremental hashing approach using Hasher::new_keyed, update, and finalize. This is an alternative to the direct keyed_hash function for multi-write scenarios. ```rust let mac = blake3::Hasher::new_keyed(KEY).update(b"foo").finalize(); ``` -------------------------------- ### Extended Output Hashing (XOF) Source: https://docs.rs/blake3/latest/index.html Demonstrates how to use `finalize_xof` to get an extendable output, which can be read like a stream. ```APIDOC ## Hasher::finalize_xof ### Description Finalizes the incremental hash computation and returns an `OutputReader` for extended output. ### Function Signature `hasher.finalize_xof() -> blake3::OutputReader` ### Parameters None ### Request Example ```rust let mut output_reader = hasher.finalize_xof(); ``` ### Response #### Success Response (200) - **output_reader** (blake3::OutputReader) - A reader that provides the extended output. #### Response Example ```rust // Example usage of OutputReader // let mut output = [0; 1000]; // output_reader.fill(&mut output); ``` ``` -------------------------------- ### Hashing Standard Input with Hasher Source: https://docs.rs/blake3/latest/blake3/struct.Hasher.html This example demonstrates how to hash data from standard input using `update_reader`. It requires the `std` Cargo feature, which is enabled by default. This method is more performant than using `std::io::copy` for large inputs. ```rust let mut hasher = blake3::Hasher::new(); hasher.update_reader(std::io::stdin().lock())?; println!("{}", hasher.finalize()); ``` -------------------------------- ### Hash a 2-chunk subtree in steps Source: https://docs.rs/blake3/latest/blake3/hazmat/fn.merge_subtrees_root_xof.html This example demonstrates hashing a 2-chunk subtree by first finalizing each chunk as a non-root chaining value and then merging them into a root OutputReader. Note that only the final chunk can be shorter than CHUNK_LEN. The resulting OutputReader is then used to fill a byte array, and the result is double-checked against a direct hashing approach. ```rust use blake3::hazmat::{merge_subtrees_root_xof, HasherExt, Mode}; use blake3::{Hasher, CHUNK_LEN}; // Hash a 2-chunk subtree in steps. Note that only // the final chunk can be shorter than CHUNK_LEN. let chunk0 = &[42; CHUNK_LEN]; let chunk1 = b"hello world"; let chunk0_cv = Hasher::new() .update(chunk0) .finalize_non_root(); let chunk1_cv = Hasher::new() .set_input_offset(CHUNK_LEN as u64) .update(chunk1) .finalize_non_root(); // Obtain a blake3::OutputReader at the root and extract 1000 bytes. let mut output_reader = merge_subtrees_root_xof(&chunk0_cv, &chunk1_cv, Mode::Hash); let mut output_bytes = [0; 1_000]; output_reader.fill(&mut output_bytes); // Double check the answer. let mut hasher = Hasher::new(); hasher.update(chunk0); hasher.update(chunk1); let mut expected = [0; 1_000]; hasher.finalize_xof().fill(&mut expected); assert_eq!(output_bytes, expected); ``` -------------------------------- ### Determining the Start Flag for BLAKE3 Chunk Compression Source: https://docs.rs/blake3/latest/src/blake3/lib.rs.html Returns the `CHUNK_START` flag if no blocks have been compressed yet, otherwise returns 0. This flag is used to indicate the beginning of a chunk's compression. ```rust fn start_flag(&self) -> u8 { if self.blocks_compressed == 0 { CHUNK_START } else { 0 } } ``` -------------------------------- ### BLAKE3 Invalid Tree Hashing Panic Example Source: https://docs.rs/blake3/latest/src/blake3/hazmat.rs.html Illustrates a scenario where incorrect input offsets lead to a panic during tree hashing. This highlights the importance of maintaining correct tree structure and input offsets to avoid runtime errors. ```rust # fn main() { # use blake3::{Hasher, CHUNK_LEN}; # use blake3::hazmat::HasherExt; # let chunk0 = [b'a'; CHUNK_LEN]; # let chunk1 = [b'b'; CHUNK_LEN]; # let chunk2 = [b'c'; 42]; let oops = Hasher::new() .set_input_offset(CHUNK_LEN as u64) .update(&chunk1) // PANIC: "the subtree starting at 1024 contains at most 1024 bytes" .update(&chunk2) .finalize_non_root(); # } ``` -------------------------------- ### Compute Interior Hashes in a 3-Chunk BLAKE3 Tree Source: https://docs.rs/blake3/latest/src/blake3/hazmat.rs.html Demonstrates computing the chaining values of individual chunks and merging them into a parent and then a root hash. Use `set_input_offset` for chunks not starting at the beginning of the input. `finalize_non_root` computes intermediate hashes, and `merge_subtrees_non_root`/`merge_subtrees_root` combine them. ```rust use blake3::{Hasher, CHUNK_LEN}; use blake3::hazmat::{merge_subtrees_non_root, merge_subtrees_root, Mode}; use blake3::hazmat::HasherExt; // an extension trait for Hasher let chunk0 = [b'a'; CHUNK_LEN]; let chunk1 = [b'b'; CHUNK_LEN]; let chunk2 = [b'c'; 42]; // The final chunk can be short. // Compute the non-root hashes ("chaining values") of all three chunks. Chunks or subtrees // that don't begin at the start of the input use `set_input_offset` to say where they begin. let chunk0_cv = Hasher::new() // .set_input_offset(0) is the default. .update(&chunk0) .finalize_non_root(); let chunk1_cv = Hasher::new() .set_input_offset(CHUNK_LEN as u64) .update(&chunk1) .finalize_non_root(); let chunk2_cv = Hasher::new() .set_input_offset(2 * CHUNK_LEN as u64) .update(&chunk2) .finalize_non_root(); // Join the first two chunks with a non-root parent node and compute its chaining value. let parent_cv = merge_subtrees_non_root(&chunk0_cv, &chunk1_cv, Mode::Hash); // Join that parent node and the third chunk with a root parent node and compute the hash. let root_hash = merge_subtrees_root(&parent_cv, &chunk2_cv, Mode::Hash); // Double check that we got the right answer. let mut combined_input = Vec::new(); combined_input.extend_from_slice(&chunk0); combined_input.extend_from_slice(&chunk1); combined_input.extend_from_slice(&chunk2); assert_eq!(root_hash, blake3::hash(&combined_input)); ``` -------------------------------- ### Get Current Read Position Source: https://docs.rs/blake3/latest/blake3/struct.OutputReader.html Returns the current read position in the output stream. The position starts at 0 and advances with each read operation. ```rust pub fn position(&self) -> u64 ``` -------------------------------- ### Get Current Read Position in Output Stream Source: https://docs.rs/blake3/latest/src/blake3/lib.rs.html Returns the current read position in the output stream as a `u64`. This is equivalent to `Seek::stream_position` but does not return a `Result`. The position starts at 0 and advances with each read operation. ```rust pub fn position(&self) -> u64 { self.inner.counter * BLOCK_LEN as u64 + self.position_within_block as u64 } ``` -------------------------------- ### Get Maximum Subtree Length Source: https://docs.rs/blake3/latest/blake3/hazmat/fn.max_subtree_len.html Calculates the maximum length of a subtree in bytes, given its starting offset. Returns `None` for an input offset of zero, and `Some(u64)` for other valid offsets. Panics if `input_offset` is not a multiple of `CHUNK_LEN`. ```rust pub fn max_subtree_len(input_offset: u64) -> Option ``` -------------------------------- ### max_subtree_len Source: https://docs.rs/blake3/latest/blake3/hazmat/index.html Determines the maximum length in bytes a subtree can have, given its starting offset within the overall input. ```APIDOC ## max_subtree_len The maximum length of a subtree in bytes, given its starting offset in bytes. ### Parameters - `offset`: The starting offset of the subtree in bytes. ### Returns The maximum allowed length in bytes for the subtree. ``` -------------------------------- ### Constructing a new Hasher Source: https://docs.rs/blake3/latest/src/blake3/lib.rs.html Shows how to create a new `Hasher` instance for different hashing modes: regular, keyed, and key derivation. For keyed and derive-key modes, specific key or context material is required. ```rust pub fn new() -> Self { Self::new_internal(IV, 0) } ``` ```rust pub fn new_keyed(key: &[u8; KEY_LEN]) -> Self { let key_words = platform::words_from_le_bytes_32(key); Self::new_internal(&key_words, KEYED_HASH) } ``` ```rust pub fn new_derive_key(context: &str) -> Self { let context_key = hazmat::hash_derive_key_context(context); let context_key_words = platform::words_from_le_bytes_32(&context_key); Self::new_internal(&context_key_words, DERIVE_KEY_MATERIAL) } ``` -------------------------------- ### Get Total Bytes Hashed Source: https://docs.rs/blake3/latest/src/blake3/lib.rs.html Returns the total number of bytes that have been processed by the hasher. This count is not affected by `set_input_offset` and only reflects bytes passed to `update`. ```rust pub fn count(&self) -> u64 { // Account for non-zero cases of Hasher::set_input_offset. Note that initial_chunk_counter // is always 0 for callers who don't use the hazmat module. (self.chunk_state.chunk_counter - self.initial_chunk_counter) * CHUNK_LEN as u64 + self.chunk_state.count() as u64 } ``` -------------------------------- ### Incremental Hashing with Hasher Source: https://docs.rs/blake3/latest/blake3/struct.Hasher.html Demonstrates how to incrementally hash data using the blake3 Hasher. Multiple calls to `update` can be made before finalizing the hash. This is useful for hashing data that does not fit into memory. ```rust let mut hasher = blake3::Hasher::new(); hasher.update(b"foo"); hasher.update(b"bar"); hasher.update(b"baz"); assert_eq!(hasher.finalize(), blake3::hash(b"foobarbaz")); ``` -------------------------------- ### Get SIMD Degree for Platform Source: https://docs.rs/blake3/latest/src/blake3/platform.rs.html Returns the SIMD degree (number of parallel operations) for a given BLAKE3 `Platform`. This value is asserted to be less than or equal to `MAX_SIMD_DEGREE`. ```rust pub fn simd_degree(&self) -> usize { let degree = match self { Platform::Portable => 1, #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] Platform::SSE2 => 4, #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] Platform::SSE41 => 4, #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] Platform::AVX2 => 8, #[cfg(blake3_avx512_ffi)] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] Platform::AVX512 => 16, #[cfg(blake3_neon)] Platform::NEON => 4, #[cfg(blake3_wasm32_simd)] Platform::WASM32_SIMD => 4, }; debug_assert!(degree <= MAX_SIMD_DEGREE); degree } ``` -------------------------------- ### Hashing All At Once Source: https://docs.rs/blake3/latest/blake3/index.html Demonstrates how to compute the BLAKE3 hash of an input byte slice directly. ```APIDOC ## hash ### Description Computes the BLAKE3 hash of an input byte slice. ### Function Signature `fn hash(input: &[u8]) -> Hash` ### Parameters - **input** (`&[u8]`): The byte slice to hash. ### Returns - `Hash`: The resulting BLAKE3 hash. ### Example ```rust let hash = blake3::hash(b"foobarbaz"); println!("{}", hash); ``` ``` -------------------------------- ### Parallel Chunk Hashing with BLAKE3 Hazmat Source: https://docs.rs/blake3/latest/blake3/hazmat/index.html Illustrates how to hash multiple chunks in parallel for performance gains using BLAKE3's hazmat module. It also shows an alternative method using multiple updates to a single Hasher. ```rust let left_subtree_cv = Hasher::new() // .set_input_offset(0) is the default. .update(&combined_input[..2 * CHUNK_LEN]) .finalize_non_root(); assert_eq!(left_subtree_cv, parent_cv); // Using multiple updates gives the same answer, though it's not as efficient. let mut subtree_hasher = Hasher::new(); // Again, .set_input_offset(0) is the default. subtree_hasher.update(&chunk0); subtree_hasher.update(&chunk1); assert_eq!(left_subtree_cv, subtree_hasher.finalize_non_root()); ``` -------------------------------- ### HasherExt::set_input_offset Source: https://docs.rs/blake3/latest/src/blake3/hazmat.rs.html Configures the Hasher to process input starting at a specific byte offset within the overall input data, crucial for correctly constructing hash trees. ```APIDOC ## HasherExt::set_input_offset ### Description Configure the `Hasher` to process a chunk or subtree starting at `offset` bytes into the whole input. You must call this function before processing any input with [`update`](Hasher::update) or similar. This step isn't required for the first chunk, or for a subtree that includes the first chunk (i.e. when the `offset` is zero), but it's required for all other chunks and subtrees. The starting input offset of a subtree implies a maximum possible length for that subtree. See [`max_subtree_len`] and section 2.1 of [the BLAKE3 paper](https://github.com/BLAKE3-team/BLAKE3-specs/blob/master/blake3.pdf). Note that only subtrees along the right edge of the whole tree can have a length less than their maximum possible length. See the [module level examples](index.html#examples). ### Panics This function panics if the `Hasher` has already accepted any input with [`update`](Hasher::update) or similar. ``` -------------------------------- ### BLAKE3 compress_in_place for different platforms Source: https://docs.rs/blake3/latest/src/blake3/platform.rs.html Selects the appropriate `compress_in_place` implementation based on the detected platform. This function is safe to call only after `detect()` has confirmed platform support. ```rust match self { Platform::Portable => portable::compress_in_place(cv, block, block_len, counter, flags), // Safe because detect() checked for platform support. #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] Platform::SSE2 | Platform::SSE41 => unsafe { crate::sse41::compress_in_place(cv, block, block_len, counter, flags) }, // Safe because detect() checked for platform support. #[cfg(blake3_avx512_ffi)] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] Platform::AVX512 => unsafe { crate::avx512::compress_in_place(cv, block, block_len, counter, flags) }, // No NEON compress_in_place() implementation yet. #[cfg(blake3_neon)] Platform::NEON => portable::compress_in_place(cv, block, block_len, counter, flags), #[cfg(blake3_wasm32_simd)] Platform::WASM32_SIMD => { crate::wasm32_simd::compress_in_place(cv, block, block_len, counter, flags) } } ``` -------------------------------- ### Get Hash as Byte Slice Source: https://docs.rs/blake3/latest/src/blake3/lib.rs.html Returns the raw bytes of the `Hash` as a slice. Use this for serialization. For comparisons, prefer the `Hash` type's `PartialEq` implementation for constant-time security. ```rust pub const fn as_slice(&self) -> &[u8] { self.0.as_slice() } ``` -------------------------------- ### Key Derivation Function (KDF) Source: https://docs.rs/blake3/latest/index.html Demonstrates how to use the key derivation function to generate keys from input. ```APIDOC ## derive_key ### Description The key derivation function. Generates a key from input data. ### Function Signature `blake3::derive_key(context: &[u8], input: &[u8]) -> [u8; blake3::KEY_LEN]` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```rust let context = b"my-app-context"; let input = b"secret-material"; let key = blake3::derive_key(context, input); ``` ### Response #### Success Response (200) - **key** ([u8; blake3::KEY_LEN]) - The derived key. #### Response Example ```rust // Example key bytes (actual value will differ) // assert_eq!(key.len(), blake3::KEY_LEN); ``` ``` -------------------------------- ### SSE4.1 platform constructor Source: https://docs.rs/blake3/latest/src/blake3/platform.rs.html Returns an `Option` containing `Platform::SSE41` if SSE4.1 instructions are detected on the current CPU. Requires `x86` or `x86_64` target architecture. ```rust pub fn sse41() -> Option { if sse41_detected() { Some(Self::SSE41) } else { None } } ``` -------------------------------- ### Set Input Offset for Hasher Source: https://docs.rs/blake3/latest/src/blake3/hazmat.rs.html Sets the starting offset for input data within a chunk. The offset must be a multiple of CHUNK_LEN and the hasher must not have accepted any input yet. This is crucial for correctly implementing tree hashing. ```rust assert_eq!(self.count(), 0, "hasher has already accepted input"); assert_eq!( offset % CHUNK_LEN as u64, 0, "offset ({offset}) must be a chunk boundary (divisible by {CHUNK_LEN})", ); let counter = offset / CHUNK_LEN as u64; self.chunk_state.chunk_counter = counter; self.initial_chunk_counter = counter; self ``` -------------------------------- ### Compress Data for XOF with SSE4.1 Source: https://docs.rs/blake3/latest/src/blake3/ffi_sse41.rs.html Performs a BLAKE3 compression operation for an extendable-output function (XOF) using SSE4.1. Returns 64 bytes of output. This function is unsafe and requires SSE4.1 support. ```rust pub unsafe fn compress_xof( cv: &CVWords, block: &[u8; BLOCK_LEN], block_len: u8, counter: u64, flags: u8, ) -> [u8; 64] { unsafe { let mut out = [0u8; 64]; ffi::blake3_compress_xof_sse41( cv.as_ptr(), block.as_ptr(), block_len, counter, flags, out.as_mut_ptr(), ); out } } ``` -------------------------------- ### Create By Reference Adapter Source: https://docs.rs/blake3/latest/blake3/struct.OutputReader.html Creates a "by reference" adapter for the OutputReader instance. ```rust fn by_ref(&mut self) -> &mut Self ``` -------------------------------- ### Derive Key using blake3::derive_key Source: https://docs.rs/blake3/latest/blake3/fn.derive_key.html This snippet shows how to derive a key using the direct `blake3::derive_key` function. Ensure the context string is hardcoded, globally unique, and application-specific. ```rust let key = blake3::derive_key(CONTEXT, b"key material, not a password"); ``` -------------------------------- ### Implement Seek Trait for OutputReader Source: https://docs.rs/blake3/latest/src/blake3/lib.rs.html Implements the `std::io::Seek` trait for `OutputReader`, enabling seeking within the output stream. It supports `SeekFrom::Start` and `SeekFrom::Current` but not `SeekFrom::End`. It handles potential overflow and seeks before the start. ```rust impl std::io::Seek for OutputReader { fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result { let max_position = u64::max_value() as i128; let target_position: i128 = match pos { std::io::SeekFrom::Start(x) => x as i128, std::io::SeekFrom::Current(x) => self.position() as i128 + x as i128, std::io::SeekFrom::End(_) => { return Err(std::io::Error::new( std::io::ErrorKind::InvalidInput, "seek from end not supported", )); } }; if target_position < 0 { return Err(std::io::Error::new( std::io::ErrorKind::InvalidInput, "seek before start", )); } self.set_position(cmp::min(target_position, max_position) as u64); Ok(self.position()) } } ``` -------------------------------- ### Initialize Hasher with Context Key Source: https://docs.rs/blake3/latest/src/blake3/hazmat.rs.html Creates a new Hasher instance initialized with a specific context key for key derivation. This is useful for creating keyed hashes or deriving keys. ```rust let context_key_words = crate::platform::words_from_le_bytes_32(context_key); Hasher::new_internal(&context_key_words, crate::DERIVE_KEY_MATERIAL) ``` -------------------------------- ### Initialize OutputReader Source: https://docs.rs/blake3/latest/src/blake3/lib.rs.html Creates a new `OutputReader` from an existing `Output` struct. ```rust impl OutputReader { fn new(inner: Output) -> Self { Self { inner, position_within_block: 0, } } // ... other methods ``` -------------------------------- ### BLAKE3 Derive Key from Context Key Source: https://docs.rs/blake3/latest/src/blake3/hazmat.rs.html Shows how to create a new Hasher instance pre-configured with a context key for derive-key mode. This is an optimization to avoid re-hashing the context string repeatedly in loops. ```rust use blake3::Hasher; use blake3::hazmat::HasherExt; let context_key = blake3::hazmat::hash_derive_key_context("foo"); let mut hasher = Hasher::new_from_context_key(&context_key); hasher.update(b"bar"); let derived_key = *hasher.finalize().as_bytes(); assert_eq!(derived_key, blake3::derive_key("foo", b"bar")); ``` -------------------------------- ### Derive Key using blake3::Hasher Source: https://docs.rs/blake3/latest/blake3/fn.derive_key.html This snippet demonstrates deriving a key incrementally using `blake3::Hasher`. This is equivalent to using `blake3::derive_key` but allows for multiple updates before finalizing. The context string should be hardcoded, globally unique, and application-specific. ```rust let key: [u8; 32] = blake3::Hasher::new_derive_key(CONTEXT) .update(b"key material, not a password") .finalize() .into(); ``` -------------------------------- ### Set Input Offset for Hasher Source: https://docs.rs/blake3/latest/blake3/hazmat/trait.HasherExt.html Configures the Hasher to process input starting at a specific byte offset. This must be called before any input is processed with `update` and is required for chunks or subtrees not including the first byte of the overall input. Panics if the Hasher has already accepted input. ```rust hasher.set_input_offset(offset); ``` -------------------------------- ### Incremental Hashing with blake3::Hasher Source: https://docs.rs/blake3/latest/blake3/fn.hash.html This demonstrates the incremental hashing approach using `Hasher::new`, `Hasher::update`, and `Hasher::finalize`. It is equivalent to the direct `blake3::hash` function but allows for multiple writes. ```rust let hash = blake3::Hasher::new().update(b"foo").finalize(); ``` -------------------------------- ### max_subtree_len Source: https://docs.rs/blake3/latest/blake3/hazmat/fn.max_subtree_len.html The maximum length of a subtree in bytes, given its starting offset in bytes. If you try to hash more than this many bytes as one subtree, you’ll end up merging parent nodes that shouldn’t be merged, and your output will be garbage. `Hasher::update` will currently panic in this case, but this is not guaranteed. ```APIDOC ## Function max_subtree_len ### Signature ```rust pub fn max_subtree_len(input_offset: u64) -> Option ``` ### Description Calculates the maximum length of a subtree in bytes, given its starting offset. For input offset zero, there is no maximum length and this function returns `None`. For all other offsets, it returns `Some`. Valid offsets must be a multiple of `CHUNK_LEN` (1024). ### Panics This function currently panics if `input_offset` is not a multiple of `CHUNK_LEN`. This is not guaranteed. ``` -------------------------------- ### OutputReader::position Source: https://docs.rs/blake3/latest/blake3/struct.OutputReader.html Returns the current read position within the output stream. This is analogous to `Seek::stream_position` but returns a `u64` directly without a `Result`. A newly created `OutputReader` starts at position 0, and this position is incremented by the number of bytes read after each `fill` or `Read::read` operation. ```APIDOC ## OutputReader::position ### Description Returns the current read position in the output stream. This is equivalent to `Seek::stream_position`, except that it doesn’t return a `Result`. The position of a new `OutputReader` starts at 0, and each call to `fill` or `Read::read` moves the position forward by the number of bytes read. ### Method `position(&self) -> u64` ### Returns - **u64**: The current read position in the output stream. ``` -------------------------------- ### Hashing an input all at once Source: https://docs.rs/blake3/latest/index.html Demonstrates how to compute the hash of an entire input byte slice in a single operation. ```APIDOC ## hash ### Description The default hash function. Computes the hash of an input byte slice. ### Function Signature `blake3::hash(input: &[u8]) -> blake3::Hash` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```rust let hash = blake3::hash(b"foobarbaz"); ``` ### Response #### Success Response (200) - **hash** (blake3::Hash) - The computed hash value. #### Response Example ```rust // Example hash value (actual value will differ) // assert_eq!(hash.to_string(), "..."); ``` ``` -------------------------------- ### AVX-512 platform constructor Source: https://docs.rs/blake3/latest/src/blake3/platform.rs.html Returns an `Option` containing `Platform::AVX512` if AVX-512 instructions are detected on the current CPU. Requires the `blake3_avx512_ffi` feature and `x86` or `x86_64` target architecture. ```rust pub fn avx512() -> Option { if avx512_detected() { Some(Self::AVX512) } else { None } } ``` -------------------------------- ### SSE2 platform constructor Source: https://docs.rs/blake3/latest/src/blake3/platform.rs.html Returns an `Option` containing `Platform::SSE2` if SSE2 instructions are detected on the current CPU. Requires `x86` or `x86_64` target architecture. ```rust pub fn sse2() -> Option { if sse2_detected() { Some(Self::SSE2) } else { None } } ``` -------------------------------- ### Portable platform constructor Source: https://docs.rs/blake3/latest/src/blake3/platform.rs.html Returns a `Platform` instance representing the portable implementation. This is always available. ```rust pub fn portable() -> Self { Self::Portable } ``` -------------------------------- ### Platform Constructors Source: https://docs.rs/blake3/latest/src/blake3/platform.rs.html Provides methods to construct a Platform enum variant based on detected CPU features. These are useful for benchmarking or explicitly selecting an implementation. ```APIDOC ## Portable Constructor ### Description Returns the portable, unoptimized BLAKE3 implementation. ### Method `portable()` ### Returns `Platform::Portable` ## SSE2 Constructor ### Description Returns the SSE2-optimized BLAKE3 implementation if SSE2 is detected. ### Method `sse2() -> Option` ### Returns `Some(Platform::SSE2)` if SSE2 is detected, `None` otherwise. ## SSE41 Constructor ### Description Returns the SSE41-optimized BLAKE3 implementation if SSE41 is detected. ### Method `sse41() -> Option` ### Returns `Some(Platform::SSE41)` if SSE41 is detected, `None` otherwise. ## AVX2 Constructor ### Description Returns the AVX2-optimized BLAKE3 implementation if AVX2 is detected. ### Method `avx2() -> Option` ### Returns `Some(Platform::AVX2)` if AVX2 is detected, `None` otherwise. ## AVX512 Constructor ### Description Returns the AVX512-optimized BLAKE3 implementation if AVX512 is detected. ### Method `avx512() -> Option` ### Returns `Some(Platform::AVX512)` if AVX512 is detected, `None` otherwise. ## NEON Constructor ### Description Returns the NEON-optimized BLAKE3 implementation. Assumed to be safe if the `blake3_neon` feature is enabled. ### Method `neon() -> Option` ### Returns `Some(Platform::NEON)` if the `blake3_neon` feature is enabled. ## WASM32 SIMD Constructor ### Description Returns the WASM32 SIMD-optimized BLAKE3 implementation. Assumed to be safe if the `blake3_wasm32_simd` feature is enabled. ### Method `wasm32_simd() -> Option` ### Returns `Some(Platform::WASM32_SIMD)` if the `blake3_wasm32_simd` feature is enabled. ``` -------------------------------- ### Extended Output Hashing (XOF) Source: https://docs.rs/blake3/latest/blake3/index.html Demonstrates how to use `finalize_xof` for extended output and reading the hash incrementally. ```APIDOC ## OutputReader ### Description An incremental reader for extended output, returned by `Hasher::finalize_xof`. ### Struct `struct OutputReader` ### Methods #### `fill(&mut self, buf: &mut [u8])` Fills the provided buffer with data from the extended output. ### Example ```rust let mut hasher = blake3::Hasher::new(); hasher.update(b"some data"); let mut output_reader = hasher.finalize_xof(); let mut output = [0; 1000]; output_reader.fill(&mut output); // The hash is available in the first 32 bytes of `output` ``` ``` -------------------------------- ### Compute Tree Hashes with BLAKE3 Hazmat Source: https://docs.rs/blake3/latest/blake3/hazmat/index.html Demonstrates computing chaining values for individual chunks and merging them into a root hash using BLAKE3's hazmat functions. This is useful for understanding the internal tree structure of BLAKE3 hashing. ```rust use blake3::{Hasher, CHUNK_LEN}; use blake3::hazmat::{merge_subtrees_non_root, merge_subtrees_root, Mode}; use blake3::hazmat::HasherExt; // an extension trait for Hasher let chunk0 = [b'a'; CHUNK_LEN]; let chunk1 = [b'b'; CHUNK_LEN]; let chunk2 = [b'c'; 42]; // The final chunk can be short. // Compute the non-root hashes ("chaining values") of all three chunks. Chunks or subtrees // that don't begin at the start of the input use `set_input_offset` to say where they begin. let chunk0_cv = Hasher::new() // .set_input_offset(0) is the default. .update(&chunk0) .finalize_non_root(); let chunk1_cv = Hasher::new() .set_input_offset(CHUNK_LEN as u64) .update(&chunk1) .finalize_non_root(); let chunk2_cv = Hasher::new() .set_input_offset(2 * CHUNK_LEN as u64) .update(&chunk2) .finalize_non_root(); // Join the first two chunks with a non-root parent node and compute its chaining value. let parent_cv = merge_subtrees_non_root(&chunk0_cv, &chunk1_cv, Mode::Hash); // Join that parent node and the third chunk with a root parent node and compute the hash. let root_hash = merge_subtrees_root(&parent_cv, &chunk2_cv, Mode::Hash); // Double check that we got the right answer. let mut combined_input = Vec::new(); combined_input.extend_from_slice(&chunk0); combined_input.extend_from_slice(&chunk1); combined_input.extend_from_slice(&chunk2); assert_eq!(root_hash, blake3::hash(&combined_input)); ``` -------------------------------- ### AVX2 platform constructor Source: https://docs.rs/blake3/latest/src/blake3/platform.rs.html Returns an `Option` containing `Platform::AVX2` if AVX2 instructions are detected on the current CPU. Requires `x86` or `x86_64` target architecture. ```rust pub fn avx2() -> Option { if avx2_detected() { Some(Self::AVX2) } else { None } } ``` -------------------------------- ### Platform Detection Source: https://docs.rs/blake3/latest/src/blake3/platform.rs.html The `detect` method determines the most performant platform-specific implementation available on the current system, falling back to a portable implementation if no optimized versions are found. ```APIDOC ## `Platform::detect()` ### Description Detects the optimal hardware acceleration for BLAKE3 hashing available on the current platform. It prioritizes specific SIMD instruction sets like AVX512, AVX2, SSE41, SSE2, NEON, and WASM32_SIMD, falling back to a portable implementation if none are detected or supported. ### Method `pub fn detect() -> Self` ### Returns A `Platform` enum variant representing the detected hardware acceleration (e.g., `Platform::AVX512`, `Platform::SSE2`, `Platform::Portable`). ``` -------------------------------- ### Keyed Hashing Source: https://docs.rs/blake3/latest/blake3/index.html Explains how to perform keyed BLAKE3 hashing using the `keyed_hash` function. ```APIDOC ## keyed_hash ### Description Computes the BLAKE3 hash of an input byte slice using a secret key. ### Function Signature `fn keyed_hash(key: &[u8; KEY_LEN], input: &[u8]) -> Hash` ### Parameters - **key** (`&[u8; KEY_LEN]`): The secret key, which must be 32 bytes long. - **input** (`&[u8]`): The byte slice to hash. ### Returns - `Hash`: The resulting keyed BLAKE3 hash. ### Example ```rust use blake3::{KEY_LEN, Hash}; let key = [0u8; KEY_LEN]; // Replace with your actual 32-byte key let message = b"secret message"; let hash = blake3::keyed_hash(&key, message); println!("Keyed hash: {}", hash); ``` ``` -------------------------------- ### Multi-threaded Memory-Mapped File Hashing with BLAKE3 Source: https://docs.rs/blake3/latest/src/blake3/lib.rs.html This method hashes a file using memory mapping and multi-threading via the `rayon` crate, offering substantial speedups for large files. It includes a performance warning about potential slowdowns on spinning disks or when CPU cores are already busy. Requires `mmap` and `rayon` Cargo features. ```rust use std::io; use std::path::Path; fn main() -> io::Result<()> { #[cfg(feature = "rayon")] { let path = Path::new("big_file.dat"); let mut hasher = blake3::Hasher::new(); hasher.update_mmap_rayon(path)?; println!("{}", hasher.finalize()); } Ok(()) } ``` -------------------------------- ### Test Compress Functionality with SSE2 Source: https://docs.rs/blake3/latest/src/blake3/ffi_sse2.rs.html Tests the `compress_in_place` and `compress_xof` functions if SSE2 is detected. It relies on a helper function `crate::test::test_compress_fn`. ```rust #[test] fn test_compress() { if !crate::platform::sse2_detected() { return; } crate::test::test_compress_fn(compress_in_place, compress_xof); } ```