Table of Contents

Crc Class

Definition

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

General-purpose CRC (Cyclic Redundancy Check) engine driven by a CrcStandard parameter set - supports any catalogue width from 1 to 64 bits, snapshot-style intermediate digests, and resumption of a previous digest with additional input.

public sealed class Crc : NonCryptographicHashAlgorithm, IResumableHashAlgorithm
Inheritance
Crc
Implements
Inherited Members
Extension Methods

Remarks

CRCs are the workhorse of integrity checks in storage, networking, and file formats: every .zip, .png, Ethernet frame, USB packet, and Modbus message uses one. Each protocol bakes in slightly different choices - polynomial, initial value, input/output bit reflection, final XOR - and the same byte sequence can produce a different digest under CRC-16/ARC, CRC-16/MODBUS, or CRC-32/ISO-HDLC. Rather than ship a class per variant, Crc consumes the parameters from a CrcStandard and the same engine computes the right answer for every catalogue entry.

Picking a standard. The full RevEng catalogue is exposed two ways:

API surface. Crc derives from NonCryptographicHashAlgorithm and exposes the standard Append(ReadOnlySpan<byte>) / Reset() / GetCurrentHash() shape. The NonCryptographicHashAlgorithmExtensions companion adds one-shot ComputeHash, stream variants, and constant-time VerifyHash / TryVerifyHash on top.

Snapshot semantics. The final reflection, XOR-out, and width mask are applied to a copy of the running accumulator, so GetCurrentHash() can be called as often as the caller likes without disturbing further Append calls - useful for emitting progressive checksums of an unfinished stream.

Resumption. Crc implements IResumableHashAlgorithm: given a previously emitted digest and additional bytes, it produces the digest of the concatenated input without needing the original bytes back - handy for log-tail integrity checks and content-addressed storage. Resumption is only valid against a digest produced by an instance configured with the same CrcStandard.

Performance. Lookup tables are precomputed once per (width, polynomial, reflectIn) tuple and shared via GlobalCache, so creating multiple Crc instances for the same standard is cheap. The hot path uses byte-at-a-time table lookups; for throughput-critical code consider re-using a single instance and feeding it large spans rather than repeatedly constructing new ones. Instances are not thread-safe; share behind explicit synchronization.

important

CRC is not cryptographically secure. It detects accidental corruption, not adversarial tampering - collisions are easy to construct. Use a member of Bodu.Security.Cryptography or HashAlgorithm for password hashing, digital signatures, message authentication, or any context where a determined attacker could choose the input.

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

// 1. Standard PKZIP / Ethernet CRC-32 of a buffer.
var crc32 = new Crc(CrcStandard.CRC32_ISOHDLC);
byte[] digest = crc32.ComputeHash(File.ReadAllBytes("payload.bin"));

// 2. Modbus RTU - different polynomial/init/reflect choices, same engine.
var modbus = new Crc(CrcStandard.CRC16_MODBUS);
modbus.Append(frameHeader);
modbus.Append(framePayload);
byte[] frameCrc = modbus.GetCurrentHash(); // non-destructive snapshot

// 3. Resumption - fold an appended log segment into yesterday's digest without re-reading
// the original bytes.
var resumable = (IResumableHashAlgorithm)new Crc(CrcStandard.CRC32_ISOHDLC);
byte[] updated = resumable.ComputeHashFrom(digest, File.ReadAllBytes("payload.appended.bin"));

Constructors

Crc()

Initializes a new instance of the Crc class using the default CRC standard (CRC-32/ISO-HDLC).

public Crc()

Remarks

The default standard is CRC-32 (ISO-HDLC) with width 32, polynomial 0x04C11DB7, initial value 0xFFFFFFFF, reflected input and output, and final XOR 0xFFFFFFFF.

Crc(CrcStandard)

Initializes a new instance of the Crc class using the specified CrcStandard.

public Crc(CrcStandard crcStandard)

Parameters

crcStandard CrcStandard

The CRC parameters (polynomial, width, reflection, initial value, final XOR) to use.

Exceptions

ArgumentNullException

crcStandard is null.

ArgumentOutOfRangeException

The Size of crcStandard is outside the supported range (1 to 64 bits).

Properties

CrcStandard

Gets the CrcStandard parameters that configure this instance.

public CrcStandard CrcStandard { get; }

Property Value

CrcStandard

The immutable CrcStandard supplied to the constructor.

GlobalCache

Gets or sets the process-wide cache used to share CRC lookup tables across Crc instances.

public static CrcLookupTableCache GlobalCache { get; set; }

Property Value

CrcLookupTableCache

The active CrcLookupTableCache. A default cache is lazily created when first accessed.

Exceptions

ArgumentNullException

The value being assigned is null.

InitialValue

Gets the initial value used in the CRC calculation.

public ulong InitialValue { get; }

Property Value

ulong

Name

Gets the name of the CRC standard.

public string Name { get; }

Property Value

string

Polynomial

Gets the polynomial used in the CRC calculation.

public ulong Polynomial { get; }

Property Value

ulong

ReflectIn

Gets a value indicating whether input bytes are reflected (bit-reversed) before being processed.

public bool ReflectIn { get; }

Property Value

bool

ReflectOut

Gets a value indicating whether the CRC result is reflected before XOR-ing with XOrOut.

public bool ReflectOut { get; }

Property Value

bool

Size

Gets the size, in bits, of the CRC checksum.

public int Size { get; }

Property Value

int

XOrOut

Gets the value to XOR the final CRC result with.

public ulong XOrOut { get; }

Property Value

ulong

Methods

Append(ReadOnlySpan<byte>)

When overridden in a derived class, appends the contents of source to the data already processed for the current hash computation.

public override void Append(ReadOnlySpan<byte> source)

Parameters

source ReadOnlySpan<byte>

The data to process.

ComputeHash(ReadOnlySpan<byte>)

Computes and returns the CRC hash of the specified input in a single call, resetting internal state both before and after the computation.

public byte[] ComputeHash(ReadOnlySpan<byte> data)

Parameters

data ReadOnlySpan<byte>

The input data to hash.

Returns

byte[]

A byte array containing the finalized CRC value, sized according to Size.

Remarks

State is reset after finalization as well as before, matching the reset-before-and-after semantics of the shared ComputeHash extension (GetHashAndReset). This keeps the instance reusable for a subsequent Append(ReadOnlySpan<byte>) without the prior input bleeding into the new digest.

ComputeHashFrom(byte[], byte[])

Resumes a hash computation from a previously finalized hash value and processes additional input, returning the new finalized hash result as a byte array.

public byte[] ComputeHashFrom(byte[] previousHash, byte[] newData)

Parameters

previousHash byte[]

The previously finalized hash value to resume from. Must not be null.

newData byte[]

The additional input data to include in the resumed hash calculation. Must not be null.

Returns

byte[]

A byte array containing the new finalized hash result.

Remarks

Reverses finalization on previousHash by undoing XOR-out and reflection (if applicable), continues the CRC computation with the full newData array, and returns the finalized CRC hash value as a new byte array.

Exceptions

ArgumentNullException

previousHash or newData is null.

ArgumentException

Thrown if the previousHash length does not match HashLengthInBytes.

ComputeHashFrom(byte[], byte[], int, int)

Resumes a hash computation from a previously finalized hash value and processes a specified range of new data, returning the new finalized hash result as a byte array.

public byte[] ComputeHashFrom(byte[] previousHash, byte[] newData, int offset, int length)

Parameters

previousHash byte[]

The previously finalized hash value to resume from. Must not be null.

newData byte[]

The buffer containing additional input data. Must not be null.

offset int

The zero-based offset into newData at which to begin reading data.

length int

The number of bytes to read from newData.

Returns

byte[]

A byte array containing the new finalized hash result.

Remarks

Reverses finalization on previousHash and continues the CRC computation with a sliced segment of newData (starting at offset and spanning length).

Exceptions

ArgumentNullException

previousHash or newData is null.

ArgumentException

Thrown if the previousHash length does not match HashLengthInBytes, or if the offset and length exceed the bounds of newData.

ComputeHashFrom(ReadOnlySpan<byte>, ReadOnlySpan<byte>)

Resumes a hash computation from a previously finalized hash value and processes additional input, returning the new finalized hash result as a byte array.

public byte[] ComputeHashFrom(ReadOnlySpan<byte> previousHash, ReadOnlySpan<byte> newData)

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.

Returns

byte[]

A byte array containing the new finalized hash result.

Remarks

Reverses finalization on previousHash, resumes the CRC computation with the contents of newData, and returns the final CRC hash as a new byte array.

Exceptions

ArgumentException

Thrown if the previousHash length does not match HashLengthInBytes.

GetCurrentHashCore(Span<byte>)

When overridden in a derived class, writes the computed hash value to destination without modifying accumulated state.

protected override void GetCurrentHashCore(Span<byte> destination)

Parameters

destination Span<byte>

The buffer that receives the computed hash value.

Remarks

Finalization (output reflection, XOR-out, and width-masking) is applied to a snapshot of the accumulator so that the instance remains usable for further Append(ReadOnlySpan<byte>) calls after retrieval.

Reset()

When overridden in a derived class, resets the hash computation to the initial state.

public override void Reset()

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

Reverses finalization on previousHash by undoing the XOR-out and reflection (if applicable), continues the CRC computation with newData, and finalizes the result into destination. The computation is performed against a local copy of the CRC state; any in-progress incremental state on the instance is preserved and a subsequent Append(ReadOnlySpan<byte>) continues from where the prior Append(ReadOnlySpan<byte>) calls left off.

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