Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

BLAKE3 hashing and key derivation

std.crypto provides BLAKE3’s three native modes. Each produces 32 bytes and accepts std.bytes.Bytes input. The incremental forms use the same Digest and Mac methods and range rules as SHA and HMAC.

Upstream code, used as-is. Every mode is the BLAKE3 team’s blake3 crate, vendored unmodified; Plenty implements none of the hash. See std.crypto for this policy.

FunctionResultContract
blake3(data: &[u8])Result[Bytes, CryptoError]Unkeyed hash
digest(Algorithm.Blake3)Result[Digest, CryptoError]Incremental unkeyed hash
blake3_keyed(key: &[u8], data: &[u8])Result[Bytes, CryptoError]Native keyed hash; exactly 32 key bytes
blake3_keyed_hasher(key: &[u8])Result[Mac, CryptoError]Incremental keyed hash, including constant-time verify
blake3_derive_key(context: &str, key_material: &[u8])Result[Bytes, CryptoError]Derive a key from high-entropy material under a context
blake3_derive_hasher(context: &str)Result[Digest, CryptoError]Incremental key derivation

output_size(Algorithm.Blake3) is 32. A keyed constructor rejects any other key length with CryptoError.InvalidKeyLength. Generate keys with std.secrets.token_bytes(32). This keyed mode is BLAKE3’s own construction; hmac(Algorithm.Blake3, key) returns CryptoError.UnsupportedAlgorithm.

For derivation, choose a fixed, globally unique, application-specific context that identifies the purpose, such as "example.org messenger 2026-10-27 session key". The context is public UTF-8 text, not a salt, password or secret key. Different purposes should use different contexts. The key material must already have sufficient entropy: this API is not password hashing or password stretching.

State, allocation and implementation

Each constructor makes one fallible state allocation. BLAKE3 has a larger fixed-size inline tree stack than SHA; it uses a separate object layout, so adding this algorithm does not increase SHA/HMAC state allocations. Context hashing in the derivation constructor needs no extra allocation.

update, update_text, finish_into and Mac.verify allocate nothing, including when input crosses tree-chunk boundaries. finish allocates an output buffer; one-shot functions allocate a state and output buffer. An output allocation failure leaves the state unfinished and retryable. Invalid ranges also leave it unchanged. A successful finish or a verification (including a mismatch) ends the state.

The runtime wraps the BLAKE3 team’s blake3 crate 1.8.7 rather than implementing a cryptographic primitive. Both runtime builds use its pure feature without std or Rayon: Rust SIMD implementations select SSE2, SSE4.1 or AVX2 at runtime on supported processors, with a portable fallback. There are no worker threads, assembly or AVX-512 paths in this configuration. Only the standard 32-byte output is exposed; extendable output is not exposed.

Finishing or dropping a BLAKE3 state overwrites the stored state using volatile writes. This includes keyed and derivation modes. Caller-owned keys, input buffers, result buffers and temporary upstream stack copies are not scrubbed; see key material.

The unmodified sources and licenses are vendored alongside arrayvec 0.7.8, constant_time_eq 0.4.2 and cpufeatures 0.3.1. Release notices include these Cargo dependencies. Tests use the upstream 1.8.7 known-answer vectors for all three modes and allocation-failure instrumentation for the Plenty API.

Acknowledgements

  • Wraps the BLAKE3 team’s blake3 1.8.7 implementation and uses its published test vectors (CC0-1.0 OR Apache-2.0 OR Apache-2.0 WITH LLVM-exception); code and licenses are vendored in the runtime.
  • BLAKE3’s vendored dependencies are arrayvec 0.7.8 for its inline tree stack (MIT OR Apache-2.0), constant_time_eq 0.4.2 for comparison support (CC0-1.0 OR MIT-0 OR Apache-2.0), and RustCrypto’s cpufeatures 0.3.1 for processor detection (MIT OR Apache-2.0).