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
Won 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
CanTransformMultipleBlocks
When overridden in a derived class, gets a value indicating whether multiple blocks can be transformed.
public override bool CanTransformMultipleBlocks { get; }
Property Value
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
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
arraybyte[]The input byte array containing the data to hash.
ibStartintThe zero-based index in
arrayat which to begin reading data.cbSizeintThe number of bytes to process from
array.
Exceptions
- ArgumentNullException
arrayis null.- ArgumentOutOfRangeException
ibStartis less than zero.-or-
cbSizeis less than zero.- ArgumentException
ibStartandcbSizespecify a range that exceeds the length ofarray.- 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
sourceReadOnlySpan<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
blockReadOnlySpan<byte>The final block of unprocessed input, typically containing 0 to BlockSize-1 bytes.
messageLengthulongThe 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.destinationSpan<byte>The span receiving the padded block or blocks; at least two blocks (
2 × BlockSize / 8bytes) 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
blockReadOnlySpan<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
blockis 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
| Product | Versions |
|---|---|
| .NET | 8, 10 |