Table of Contents

Blake3 Class

Definition

Namespace
Bodu.Security.Cryptography
Assembly
Bodu.Security.Cryptography.dll
Package
Bodu.Security.Cryptography 1.2.0
Source
Blake3.cs

Computes a 256-bit cryptographic hash using the BLAKE3 algorithm designed by Jack O'Connor, Jean-Philippe Aumasson, Samuel Neves, and Zooko Wilcox-O'Hearn. This class cannot be inherited.

public sealed class Blake3 : DeferredFinalBlockHashAlgorithm, ICryptoTransform, IDisposable
Inheritance
Blake3
Implements
Inherited Members
Extension Methods

Examples

using var blake3 = new Blake3();
byte[] digest = blake3.ComputeHash(message);

Remarks

BLAKE3 is a cryptographic hash function that combines the speed of non-cryptographic hashes with strong security guarantees. It is based on a binary tree structure where each leaf (chunk) processes up to 1024 bytes of input and each internal (parent) node combines two child chaining values. All compression is performed by a single ARX-based function derived from the BLAKE2 and ChaCha families.

Input is divided into 1024-byte chunks, each compressed block-by-block into an 8-word (256-bit) chaining value. When more than one chunk exists the chaining values are folded pairwise into parent nodes until a single root chaining value remains. The root compression call is distinguished by the ROOT domain-separation flag, which enables XOF-style output extraction; this implementation fixes the output length at 256 bits.

This implementation inherits its 64-byte residual buffer, running byte counter, and defer-on-full-block buffering loop from DeferredFinalBlockHashAlgorithm. The final 64-byte block is not compressed until HashFinal() is called, ensuring that chunk-level and tree-level domain flags can be applied correctly.

This implementation supports the standard, unkeyed hash mode only. Keyed-hash and key-derivation modes are not exposed.

Parameters at a glance.

  • Output size: 256 bits (32 bytes), fixed.
  • Block size: 64 bytes; chunk size: 1024 bytes (the leaf of the hash tree).
  • Construction: binary Merkle tree over chunks, ARX compression derived from BLAKE2 / ChaCha.
  • Mode: standard unkeyed hash only - keyed hash and KDF modes are not exposed.

When to choose BLAKE3. Reach for BLAKE3 when raw throughput on long inputs is the priority - its tree structure is naturally parallel-friendly and outperforms Blake2b, SHA-2, and SHA-3 on multi-megabyte messages. For short inputs the difference shrinks and any of the BLAKE2 / SHA-2 variants is fine. Use Blake2b if a configurable output size or RFC 7693-compatible MAC mode is required; use MerkleTree if you want RFC 6962's tree, its proofs, and explicit control over the block size and the underlying leaf hash.

Constructors

Blake3()

Initializes a new instance of the Blake3 class, configured to produce a 256-bit digest.

public Blake3()

Remarks

Every hash runs on the calling thread; see MaxDegreeOfParallelism.

Blake3(int)

Initializes a new instance of the Blake3 class, configured to produce a 256-bit digest, with the specified bound on the threads each write may use.

public Blake3(int maxDegreeOfParallelism)

Parameters

maxDegreeOfParallelism int

The greatest number of threads one write may use, the calling thread included; -1 for up to one per processor.

Remarks

The digest never depends on the bound; see MaxDegreeOfParallelism.

Exceptions

ArgumentOutOfRangeException

maxDegreeOfParallelism is zero or less than -1.

Properties

AlgorithmName

Gets the canonical, fully-qualified algorithm name for this instance, including any size or variant qualifiers (for example, "Tiger/192", "Skein-512-256", "BLAKE2b-512", "ASCON-HASH256", "SipHash-2-4-64").

public override string AlgorithmName { get; }

Property Value

string

A string identifying the algorithm and its current configuration.

Remarks

Derived classes implement this property to expose a stable, consumer-facing identifier suitable for logging, telemetry, registry keys, or interop with hash-name catalogues. Implementations should be pure and side-effect-free - the value may be queried before any input has been consumed and after disposal as part of error reporting.

CanReuseTransform

Gets a value indicating whether this transform instance can be reused after a hash operation is completed.

public override bool CanReuseTransform { get; }

Property Value

bool

true; Blake3 resets its state automatically and may be reused across multiple ComputeHash calls.

CanTransformMultipleBlocks

Gets a value indicating whether multiple blocks may be transformed in a single TransformBlock(byte[], int, int, byte[], int) call.

public override bool CanTransformMultipleBlocks { get; }

Property Value

bool

true; the implementation accumulates arbitrary-length input internally.

MaxDegreeOfParallelism

Gets the greatest number of threads one write may use to hash its input.

public int MaxDegreeOfParallelism { get; }

Property Value

int

1, the default, hashes every write on the calling thread. A larger value, or -1 for up to one thread per processor, lets the whole chunks of a large write be hashed on several threads at once. The digest never depends on this value.

Remarks

BLAKE3's tree makes every complete subtree independent of the others, so a large write is divided into parts of 64 KiB, claimed by the calling thread and the workers as each finishes the last, and the parts' chaining values are joined on the calling thread. A write of less than 256 KiB of whole chunks stays on the calling thread, where waking other threads would cost more than they save.

The default is 1 because a service that hashes many inputs at once already keeps every core busy, and would only add hand-offs. Raise it to hash one large input faster: a file, a download, a snapshot.

Exceptions

ObjectDisposedException

The instance has been disposed.

Methods

Dispose(bool)

Releases the resources used by the algorithm and zeros the residual buffer.

protected override void Dispose(bool disposing)

Parameters

disposing bool

true to release both managed and unmanaged resources; false to release only unmanaged resources.

Remarks

The dispose latch ensures that subsequent calls are no-ops and that the residual buffer is cleared at most once.

Derived classes that hold algorithm-specific state, buffers, keys, or other secret material should override Dispose(bool), clear their own state when disposing is true, and then call the base implementation.

HashCore(ReadOnlySpan<byte>)

Consumes the supplied input span. Whole chunks that start on a chunk boundary and are followed by more input are hashed as complete subtrees, many chunks at once; everything else goes through the block-by-block path of the base class, which keeps the final block deferred.

protected override void HashCore(ReadOnlySpan<byte> source)

Parameters

source ReadOnlySpan<byte>

The input bytes to consume. May be empty, partial, exact-block, or multi-chunk in length.

Exceptions

ObjectDisposedException

The algorithm instance has been disposed.

Initialize()

Resets the algorithm to its initial state by clearing the residual buffer and the running byte total. Derived classes override this method, call base.Initialize() first, and then reset their own algorithm-specific state (chaining variables, IV, key-derived schedule).

public override void Initialize()

Remarks

This method does not reset the State property explicitly on .NET 6+ targets — the framework manages that transition. On earlier targets, derived classes that need the already-finalized guard should reset their _finalized backing field from their own Initialize override.

Derived classes that need to validate state before the reset (for example, a keyed MAC that refuses to be re-initialized when no key has been set) should perform that validation before calling base.Initialize(). Once the base call returns, the residual buffer is empty, Bodu.Security.Cryptography.BufferedBlockHashAlgorithm._residualBytes is 0, and Bodu.Security.Cryptography.BufferedBlockHashAlgorithm._totalBytes is 0.

Exceptions

ObjectDisposedException

The instance has been disposed.

ProcessBlock(ReadOnlySpan<byte>, ulong, bool)

Advances the BLAKE3 compression state by one 64-byte block, applying the correct chunk-level and tree-level domain flags derived from totalBytesIncludingThisBlock.

protected override void ProcessBlock(ReadOnlySpan<byte> block, ulong totalBytesIncludingThisBlock, bool isFinal)

Parameters

block ReadOnlySpan<byte>

The 64-byte block to compress. Zero-padded by the base class when isFinal is true and the final message byte count is not a multiple of 64.

totalBytesIncludingThisBlock ulong

The cumulative byte count including the bytes in this block. Used to derive the chunk index, the block position within the chunk, and the true block length for the final block.

isFinal bool

true for the last compression call, raised by HashFinal(); otherwise false.

ProcessFinalBlock()

Extracts the digest from the algorithm's chaining variables after ProcessBlock(ReadOnlySpan<byte>, ulong, bool) has been called with isFinal: true for the last time.

protected override byte[] ProcessFinalBlock()

Returns

byte[]

A byte array containing the final computed hash value.

Remarks

This method is invoked once per HashFinal() call, immediately after the final compression. It reads from the internal hash state and serializes the result to a byte array in the format expected by consumers of the algorithm (typically little-endian for Blake-family hashes).

Applies to

ProductVersions
.NET8, 10

See Also