Table of Contents

Whirlpool Class

Definition

Namespace
Bodu.Security.Cryptography
Assembly
Bodu.Security.Cryptography.dll
Package
Bodu.Security.Cryptography 1.2.0
Source
Whirlpool.Constants.cs

Computes a 512-bit cryptographic hash using the Whirlpool algorithm designed by Paulo S. L. M. Barreto and Vincent Rijmen. Supports all three published revisions: Whirlpool-0 (2000), Whirlpool-T (2001) and the final Whirlpool function standardized by ISO/IEC 10118-3 in 2003. This class cannot be inherited.

public sealed class Whirlpool : BlockHashAlgorithm, ICryptoTransform, IDisposable
Inheritance
Whirlpool
Implements
Inherited Members
Extension Methods

Examples

using var whirlpool = new Whirlpool { Version = WhirlpoolVersion.WhirlpoolInfo3 };
byte[] digest = whirlpool.ComputeHash(message);

Remarks

Whirlpool is a Merkle-Damgård construction wrapped around an internal 512-bit block cipher (W) that borrows the wide-trail design principles of the Rijndael family. Input is consumed in 64-byte blocks; the final message length (in bits) is appended in a 256-bit big-endian trailer after a single 0x80 padding byte, in the standard manner.

The selected revision is controlled by Version. The default is WhirlpoolInfo3, which matches the ISO/IEC 10118-3 standard. Version may be changed before any input has been consumed; attempting to change it once hashing has started throws CryptographicUnexpectedOperationException. Calling Initialize() returns the instance to the reconfigurable state.

Parameters at a glance.

  • Output size: 512 bits (64 bytes), fixed.
  • Block size: 64 bytes (512 bits); 256-bit big-endian length field.
  • Internal cipher W on the wide-trail (Rijndael-family) design principle.
  • Selectable revision: WhirlpoolInfo1 (2000), WhirlpoolInfo1 (Whirlpool-T, 2001), or WhirlpoolInfo3 (ISO/IEC 10118-3, 2003 - default).

When to choose Whirlpool. Pick Whirlpool when interoperability with software that produces or expects ISO/IEC 10118-3 Whirlpool digests is required - TrueCrypt-era disk encryption metadata, certain European e-government standards, and some content-addressed stores. For a modern 512-bit cryptographic hash without an interop constraint use SHA-512 or Blake2b; both are faster on contemporary hardware.

This implementation is constant-time in its control flow, but the S-box lookup tables are read at message-dependent indices, so hashing secret data (for example inside a keyed construction) is not hardened against timing or cache-based side-channel attacks.

Constructors

Whirlpool()

Initializes a new instance of the Whirlpool class configured for WhirlpoolInfo3, the standardized ISO/IEC 10118-3 revision.

public Whirlpool()

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 the current transform can be reused.

public override bool CanReuseTransform { get; }

Property Value

bool

Always true.

CanTransformMultipleBlocks

When overridden in a derived class, gets a value indicating whether multiple blocks can be transformed.

public override bool CanTransformMultipleBlocks { get; }

Property Value

bool

true if multiple blocks can be transformed; otherwise, false.

Version

Gets or sets the published WhirlpoolVersion used to compute the hash value.

public WhirlpoolVersion Version { get; set; }

Property Value

WhirlpoolVersion

The Whirlpool revision selected for subsequent hashing operations.

Remarks

The revision must be assigned before any input has been consumed. Once TransformBlock(byte[], int, int, byte[], int) or any ComputeHash overload has started a computation, the value becomes immutable until Initialize() is called.

Exceptions

ArgumentOutOfRangeException

The assigned value is not a defined WhirlpoolVersion member.

ObjectDisposedException

The hash algorithm instance has been disposed.

CryptographicUnexpectedOperationException

The hash computation has already started and the algorithm is no longer reconfigurable.

Methods

Dispose(bool)

Releases resources used by the algorithm and clears the internal state.

protected override void Dispose(bool disposing)

Parameters

disposing bool

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

HashCore(byte[], int, int)

Validates the supplied byte-array slice and forwards it to the HashCore(ReadOnlySpan<byte>) overload that derived classes implement.

protected override void HashCore(byte[] array, int ibStart, int cbSize)

Parameters

array byte[]

The input byte array containing the data to hash.

ibStart int

The zero-based index in array at which to begin reading data.

cbSize int

The number of bytes to process from array.

Exceptions

ArgumentNullException

array is null.

ArgumentOutOfRangeException

ibStart is less than zero.

-or-

cbSize is less than zero.

ArgumentException

ibStart and cbSize specify a range that exceeds the length of array.

ObjectDisposedException

The algorithm instance has been disposed.

CryptographicUnexpectedOperationException

On target frameworks prior to .NET 6, the hash algorithm has already been finalized and cannot accept more input data.

HashCore(ReadOnlySpan<byte>)

Processes the entirety of the input source and feeds it into the computation pipeline. This method updates the internal hash state accordingly by consuming the entire input span.

protected override void HashCore(ReadOnlySpan<byte> source)

Parameters

source ReadOnlySpan<byte>

The input byte span containing the data to hash.

Remarks

This method is part of the core hashing process and is automatically invoked by methods such as TransformBlock(byte[], int, int, byte[], int) and ComputeHash(byte[]). It handles processing of raw byte array input and ensures the hash algorithm receives data in properly sized blocks.

This method internally buffers incomplete blocks between calls to ensure proper alignment. Full blocks are immediately processed; any remaining bytes are stored until more data arrives or finalization occurs.

Exceptions

CryptographicUnexpectedOperationException

The hash algorithm has already been finalized and cannot accept more input data.

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.

PadBlock(ReadOnlySpan<byte>, ulong, Span<byte>)

Pads the final partial block of input data into destination and appends the encoded total message length, without allocating a padded copy on the heap.

protected override int PadBlock(ReadOnlySpan<byte> block, ulong messageLength, Span<byte> destination)

Parameters

block ReadOnlySpan<byte>

The final block of unprocessed input, typically containing 0 to BlockSize-1 bytes.

messageLength ulong

The total number of message bytes consumed by the algorithm, including the bytes in block. This is the value most Merkle-Damgård length encodings append.

destination Span<byte>

The span receiving the padded block or blocks; at least two blocks (2 × BlockSize / 8 bytes) long. The caller clears the span after processing.

Returns

int

The number of bytes written - one or two whole blocks, ready for ProcessBlock(ReadOnlySpan<byte>).

Remarks

The default implementation delegates to the array-returning PadBlock(ReadOnlySpan<byte>, ulong) overload and clears the intermediate array; see that overload's remarks for the override contract.

ProcessBlock(ReadOnlySpan<byte>)

Transforms a complete block of input data and updates the internal hash state.

protected override void ProcessBlock(ReadOnlySpan<byte> block)

Parameters

block ReadOnlySpan<byte>

The input block to process. Its length must match the algorithm's configured block size.

Remarks

This method performs the core transformation logic of the hash algorithm. It is called repeatedly with aligned input blocks and is not responsible for padding or finalization steps.

Exceptions

ArgumentException

Thrown if the block is not the expected size.

ProcessFinalBlock()

Finalizes the hash computation and produces the final hash output.

protected override byte[] ProcessFinalBlock()

Returns

byte[]

A byte array containing the final computed hash value.

Remarks

This method is invoked after all input has been processed and padded. It reads from the internal hash state and serializes the result to a byte array in the format expected by consumers of the algorithm (e.g., big-endian or little-endian).

Applies to

ProductVersions
.NET8, 10