Table of Contents

Shake Class

Definition

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

Computes a hash using the SHAKE family of extendable output functions (XOFs) as defined in NIST FIPS 202. Supports security levels of 128 and 256 bits with a configurable output size. This class cannot be inherited.

public sealed class Shake : BufferedBlockHashAlgorithm, ICryptoTransform, IDisposable
Inheritance
Shake
Implements
Inherited Members
Extension Methods

Examples

// SHAKE128 producing 256-bit output.
using var shake = new Shake(256, 128);
byte[] digest = shake.ComputeHash(Encoding.UTF8.GetBytes("hello"));

// SHAKE256 producing 512-bit output.
using var shake256 = new Shake(512, 256);
byte[] longer = shake256.ComputeHash(message);

Remarks

Shake is built on the same Keccak-f[1600] permutation as SHA-3, operating over a 1600-bit (200-byte) state. The two SHAKE variants differ only in their rate and, therefore, their security margin:

  • SHAKE128: rate = 168 bytes, capacity = 32 bytes, security level = 128 bits.
  • SHAKE256: rate = 136 bytes, capacity = 64 bytes, security level = 256 bits.

Unlike the fixed-length SHA-3 variants, SHAKE is an XOF - the output length is independent of the security parameter and may be any positive multiple of 8 bits. The domain separation byte 0x1F distinguishes SHAKE from SHA-3 ( 0x06) and from raw Keccak. Multi-rate padding (pad10*1) appends the domain byte, zero or more zero bytes, and a 0x80 byte at the last position of the final rate block.

When used via HashAlgorithm, HashSizeValue holds the desired output length in bits and securityLevel selects the SHAKE variant. ComputeHash(byte[]) therefore produces exactly outputBits / 8 bytes regardless of which security level is chosen.

Parameters at a glance.

  • State: 1600 bits (200 bytes); Keccak-f[1600] permutation.
  • Output size: configurable, any positive multiple of 8 bits.
  • Security level: 128 (SHAKE128) or 256 (SHAKE256).
  • Domain separation: 0x1F; multi-rate padding (pad10*1).
  • Specification: NIST FIPS 202.

When to choose SHAKE. Pick SHAKE when an extendable-output function is genuinely required - KMAC inputs, post-quantum signature schemes, hash-based DRBGs, and any protocol that needs more than the fixed-length output of SHA-3 / SHA-256. For ordinary fixed-length hashing prefer SHA-3 (FIPS 202) or Blake3 (faster on commodity hardware). Use SHAKE128 when 128-bit security is sufficient and throughput matters; use SHAKE256 when the higher capacity is required.

Constructors

Shake()

Initializes a new instance of the Shake class with a 256-bit output using SHAKE128 internals.

public Shake()

Shake(int, int)

Initializes a new instance of the Shake class with the specified output size and security level.

public Shake(int outputBits, int securityLevel)

Parameters

outputBits int

The desired output size in bits. Must be a positive value divisible by 8.

securityLevel int

The SHAKE security level in bits. Must be either 128 (SHAKE128, rate = 168 bytes) or 256 (SHAKE256, rate = 136 bytes).

Exceptions

ArgumentOutOfRangeException

outputBits is not a positive multiple of 8, or securityLevel is not 128 or 256.

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.

HashSize

Gets or sets the size, in bits, of the final computed hash output.

public int HashSize { get; set; }

Property Value

int

The current output size in bits. Must be a positive multiple of 8.

Remarks

Because SHAKE is an XOF, the output length may be changed freely between computations. The security level (and therefore the rate) is fixed at construction time and cannot be altered. Changing this property after input has already been absorbed throws CryptographicUnexpectedOperationException.

Exceptions

ArgumentOutOfRangeException

The assigned value is not a positive multiple of 8.

ObjectDisposedException

The algorithm instance has been disposed.

CryptographicUnexpectedOperationException

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

SecurityLevel

Gets the security level, in bits, of the SHAKE variant in use.

public int SecurityLevel { get; }

Property Value

int

Either 128 (SHAKE128) or 256 (SHAKE256).

Methods

Dispose(bool)

Releases the resources used by this instance and clears the internal sponge 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(ReadOnlySpan<byte>)

Consumes the supplied input span and updates the algorithm state. Derived classes implement the buffering loop appropriate to their family (immediate-fire-on-full-block for Merkle–Damgård hashes, defer-on-full-block for Blake-family hashes).

protected override void HashCore(ReadOnlySpan<byte> source)

Parameters

source ReadOnlySpan<byte>

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

Remarks

This overload is re-marked abstract by the grandparent to force every derived base to provide an explicit implementation. Without this, the default HashCore(ReadOnlySpan<byte>) implementation would allocate a temporary byte array and call back into HashCore(byte[], int, int), producing infinite recursion through the grandparent's forwarding override.

HashFinal()

Finalizes the hash computation by applying SHAKE multi-rate padding, absorbing the final block, and squeezing the requested number of output bytes from the sponge state.

protected override byte[] HashFinal()

Returns

byte[]

A byte array of length HashSize / 8 containing the squeezed output.

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.

Applies to

ProductVersions
.NET8, 10