Table of Contents

Fletcher Class

Definition

Namespace
Bodu.IO.Hashing.Checksums
Assembly
Bodu.IO.Hashing.dll
Package
Bodu.IO.Hashing 1.0.0
Source
Fletcher.cs

Provides a base class for the Fletcher checksum family (Fletcher-16, Fletcher-32, Fletcher-64).

public abstract class Fletcher : BlockNonCryptographicHashAlgorithm, IResumableHashAlgorithm
Inheritance
Fletcher
Implements
Derived
Inherited Members
Extension Methods

Remarks

Fletcher is a non-cryptographic position-dependent checksum that maintains two running accumulators (A and B) and combines them into the final hash. Derived types Fletcher16, Fletcher32, and Fletcher64 select the output width.

When to choose Fletcher. Fletcher was designed as a cheaper alternative to CRC for detecting accidental corruption in network protocols and file formats - TCP, Modbus ASCII, and ZFS all use a Fletcher variant. It catches single-bit errors and many burst errors at a fraction of CRC's per-byte cost, making it attractive on resource-constrained microcontrollers and in tight inner loops. Pick Fletcher16 for embedded protocols where 16 bits is enough, Fletcher32 as the workhorse for general file-integrity work, and Fletcher64 when a wider checksum reduces collision pressure on large datasets. For stronger error-detection guarantees prefer Crc; for hash-table keying prefer MurmurHash3 or CityHash, which give better avalanche than any positional-sum scheme.

Lifecycle and threading. Inherits the standard Append(ReadOnlySpan<byte>) / Reset() / GetCurrentHash() shape via BlockNonCryptographicHashAlgorithm. Snapshotting is non-destructive - call GetCurrentHash as often as needed. Instances are not thread-safe; share behind explicit synchronization, or allocate one per consumer.

important

This algorithm is not cryptographically secure and should not be used for password hashing, digital signatures, or integrity validation in security-sensitive applications.

using Bodu.IO.Hashing.Checksums;
using Bodu.IO.Hashing.Extensions;

// 32-bit Fletcher checksum of a packet payload.
var fletcher = new Fletcher32();
byte[] checksum = fletcher.ComputeHash(payload);

Constructors

Fletcher(int)

Initializes a new instance of the Fletcher class with the specified hash size.

protected Fletcher(int hashSize)

Parameters

hashSize int

The hash size in bits. Valid values are 16, 32, or 64.

Exceptions

ArgumentException

Thrown if hashSize is not 16, 32, or 64.

Properties

AlgorithmName

Gets the algorithm name in the form Fletcher-N, where N is the output width in bits.

public string AlgorithmName { get; }

Property Value

string

A string such as Fletcher-16, Fletcher-32, or Fletcher-64.

Methods

Append(ReadOnlySpan<byte>)

Consumes input with deferred modular reduction, amortizing the two modulo operations over a whole Bodu.IO.Hashing.Checksums.Fletcher.ReductionBatch-byte run instead of paying them per byte.

public override void Append(ReadOnlySpan<byte> source)

Parameters

source ReadOnlySpan<byte>

The input bytes to fold into the running accumulators.

Remarks

Both accumulators enter reduced (below Bodu.IO.Hashing.Checksums.Fletcher._modulus), and the batch length is bounded so the running B accumulator cannot overflow a 64-bit value. Reducing per batch is congruent to - and therefore produces the identical result as - the per-byte A = (A + b) mod m; B = (B + A) mod m recurrence, regardless of how the input is split across calls.

This overrides the base per-block driver directly: with a one-byte block size the residual buffer is never populated, so the base ProcessBlock(ReadOnlySpan<byte>) path is used only by the padding branch that ShouldPadFinalBlock() disables for production Fletcher variants.

Clone()

Creates a deep copy of the current algorithm instance, preserving accumulator state. Used by GetCurrentHashCore(Span<byte>) so that retrieving an intermediate hash does not disturb ongoing computation.

protected override BlockNonCryptographicHashAlgorithm Clone()

Returns

BlockNonCryptographicHashAlgorithm

A new instance with the same internal state as the current one.

CreateEmpty()

Creates a new, empty instance of the concrete Fletcher variant. Replaces the former new TSelf() CRTP construction as the factory the base Clone() uses to snapshot running state.

protected abstract Fletcher CreateEmpty()

Returns

Fletcher

A fresh instance of the derived variant with default accumulator state.

PadBlock(ReadOnlySpan<byte>, ulong)

Pads the final partial block of input data and appends the encoded total message length. This ensures that all input is padded and aligned to the block size required by the algorithm.

protected override byte[] PadBlock(ReadOnlySpan<byte> block, ulong messageLength)

Parameters

block ReadOnlySpan<byte>

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

messageLength ulong

The total number of bytes processed by the algorithm before padding, not including this block.

Returns

byte[]

A padded byte array consisting of one or more full blocks that include the input data and message-length encoding, ready to be passed to ProcessBlock(ReadOnlySpan<byte>).

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.

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.

ResetState()

Resets the derived algorithm's internal accumulators. Called from Reset() after base-class state is cleared.

protected override void ResetState()

Remarks

Derived types override this to restore any running state they own (for example, partial sums, index counters). The default implementation does nothing.

ShouldPadFinalBlock()

Determines whether the final block of input data should be padded before processing.

protected override bool ShouldPadFinalBlock()

Returns

bool

true if the final block should be padded; otherwise, false.

Remarks

By default this method returns true. Derived classes can override to indicate that trailing residual bytes should be processed verbatim without explicit padding.

TryComputeHashFrom(ReadOnlySpan<byte>, ReadOnlySpan<byte>, Span<byte>, out int)

Resumes a hash computation from a previously finalized hash value, processes additional input, and writes the new finalized hash to the specified destination span.

public bool TryComputeHashFrom(ReadOnlySpan<byte> previousHash, ReadOnlySpan<byte> newData, Span<byte> destination, out int bytesWritten)

Parameters

previousHash ReadOnlySpan<byte>

The previously finalized hash value to resume from.

newData ReadOnlySpan<byte>

The additional input data to include in the resumed hash calculation.

destination Span<byte>

The destination buffer to write the finalized hash value to.

bytesWritten int

Outputs the number of bytes written to the destination buffer.

Returns

bool

true if the resumed and finalized hash was written successfully; otherwise, false if the destination span was too small.

Remarks

Fletcher digests carry the complete accumulator state (the high half is B, the low half A, both big-endian), so resuming requires no finalization reversal: the halves seed the accumulators directly. The computation runs against saved-and-restored instance state, so any in-progress incremental state on the instance survives the call unchanged.

Exceptions

ArgumentException

Thrown if the previousHash length does not match HashLengthInBytes.

Explicit Interface Implementations

IResumableHashAlgorithm.get_HashLengthInBytes()

int IResumableHashAlgorithm.get_HashLengthInBytes()

Returns

int

Applies to

ProductVersions
.NET8, 10

See Also