Bodu.IO.Hashing
Bodu.IO.Hashing is the non-cryptographic hashing package of the Bodu suite, and one half of the Hashing & Cryptography topic. Everything in the package derives from NonCryptographicHashAlgorithm, so the lifecycle (Append / GetCurrentHash / Reset) is identical regardless of which algorithm you pick.
Adversary model: none. Nothing in this library is safe against an attacker who can choose inputs. Use it for error detection, distribution, fingerprinting, and identifier validation - for anything security-sensitive, see Bodu.Security.Cryptography.
The shape of the suite
Nothing in this library is designed against an adversary model. Its fingerprints, checksums, and check digits are tuned for speed, even distribution, and the detection of accidental errors on trusted input - every one of them is trivially forgeable by anyone who controls the bytes. That is the line between this package and Bodu.Security.Cryptography, whose ciphers, keyed hashes (MACs), and cryptographic digests are each designed so that even an attacker who knows the algorithm, observes many inputs and outputs, and chooses inputs adaptively cannot forge, invert, or find collisions. Cross that line the moment an attacker can influence the input or the result protects a security decision.
The library is organized around three subfamilies, each in its own namespace.
Namespaces and headline types
Bodu.IO.Hashing - Fingerprints
Fast, distribution-quality hash functions for hash-table keys, in-memory cache buckets, and content-addressable lookups.
| Type | Output | Notes |
|---|---|---|
| Fnv1a32 / Fnv1a64 | 32 / 64 bits | Constant-memory, streaming. Preferred over FNV-1 for better avalanche. |
| Fnv132 / Fnv164 | 32 / 64 bits | Original FNV-1; legacy interoperability only. |
| CityHash32 / CityHash64 / CityHash128 | 32 / 64 / 128 bits | SIMD-friendly; fastest on long inputs (buffers internally). |
| MurmurHash3_32 / MurmurHash3_128 | 32 / 128 bits | Seeded; excellent avalanche; widely used in databases. |
| Pearson | 8-2048 bits | Table-driven; configurable output width in 8-bit steps. |
| Bernstein | 32 bits | Classic djb2; configurable add-vs-XOR variant. |
| BKDR / SDBM / JSHash / Elf64 / ApHash / Pjw32 | 32-64 bits | Classic string hashes from compilers and early web servers. |
| SuperFastHash | 32 bits | Paul Hsieh's hash; designed for short keys. |
| BlockNonCryptographicHashAlgorithm | - | Abstract base for buffered block-oriented algorithms; the block-hash extension point. |
| IResumableHashAlgorithm | - | Optional contract: reverse-finalize a stored digest, append more bytes, finalize again. Implemented by Crc, the FNV family (Fnv132 / Fnv164 / Fnv1a32 / Fnv1a64), Fletcher16 / Fletcher32 / Fletcher64, and Adler32 / Adler32C / Adler64. |
BCL note.
XxHash32/XxHash64/XxHash3/XxHash128fromSystem.IO.Hashingalready cover the xxHash family - Bodu does not duplicate them. Use the BCL types directly when you want xxHash.
Bodu.IO.Hashing.Checksums - Checksums
Error-detection algorithms with characterized guarantees over specific error patterns, operating on binary buffers.
| Type | Output | Subfamily |
|---|---|---|
| Crc + CrcStandard + CrcStandards | 1-64 bits | Polynomial-remainder; 112 named standards from the RevEng catalogue, plus custom parameter sets. |
| CrcLookupTableBuilder / CrcLookupTableCache | - | Shared lookup-table cache so identical CRC parameter sets share a table. |
| Fletcher16 / Fletcher32 / Fletcher64 | 16 / 32 / 64 bits | Twin-accumulator; catches transpositions a simple sum or XOR misses. |
| Adler32 / Adler32C / Adler64 | 32 / 32 / 64 bits | Prime / power-of-two modulus twin accumulator; Adler-32 is the canonical zlib checksum. |
Bodu.IO.Hashing.CheckDigits - Check digits
Check-digit algorithms for human-typed identifiers - single-character schemes over decimal alphabets (credit card numbers, barcodes), single-character schemes over alphanumeric alphabets (ISBN-10, ISIN, CUSIP, SEDOL), and the two-character ISO 7064 Mod 97-10 schemes (IBAN, LEI).
| Type | Used by |
|---|---|
| Luhn | Credit cards (Visa, Mastercard, Amex), IMEI, SIN |
| Damm | General purpose; detects all single-digit and adjacent-transposition errors |
| Verhoeff | German ID, medical device codes; widest decimal-alphabet error coverage |
| Ean8 / Ean13 | Retail barcodes |
| Gtin14 | Shipping cartons |
| UpcA | US/Canada retail barcodes |
| Isin | International securities identifiers (ISO 6166) |
| AbaRoutingNumber | US bank routing numbers |
| Isbn10, Isbn13 | Book identifiers (ISBN-10 is alphanumeric - the check character may be X) |
| Sedol, Cusip | UK / US securities identifiers (alphanumeric) |
| Iban, Lei | Bank account and legal-entity identifiers (two-character ISO 7064 Mod 97-10 check) |
| Iso7064Mod11_2, Iso7064Mod97_10 | Generic ISO 7064 building blocks for custom alphanumeric schemes |
| Code39Mod43, Crockford32 | Code 39 barcode and Crockford base-32 check characters |
| CheckDigitInputAlphabet / CheckDigitOutputAlphabet | Character-set enums consumed by the alphanumeric check-digit algorithms |
| CheckValueAlgorithm | Abstract root of the check-digit hierarchy (Append / GetCurrentCheckValue / Reset) |
| CheckDigitAlgorithm, AlphanumericCheckDigitAlgorithm, MultiCharCheckDigitAlgorithm | Abstract base classes under CheckValueAlgorithm - extension points for decimal, alphanumeric, and multi-character schemes |
Bodu.IO.Hashing.Extensions
Extension methods over NonCryptographicHashAlgorithm for ergonomic one-shot computation, async streaming, and verification.
| Type | Provides |
|---|---|
| NonCryptographicHashAlgorithmExtensions | AppendData, AppendDataAsync, ComputeHash, ComputeHashAsync, VerifyHash, VerifyHashAsync, TryVerifyHash, TryVerifyHashAsync. |
Choosing a subfamily
All three subfamilies derive from the same base type, but they are tuned for different jobs - and the best algorithm for one job is a poor choice for another.
| Subfamily | Optimized for | Operates on | Adversary model |
|---|---|---|---|
| Fingerprint | Even distribution and speed | Binary buffer | None |
| Checksum | Detecting specific error patterns | Binary buffer | None |
| Check digit | Catching human transcription errors | Character sequence | None |
Fingerprints map an arbitrary byte sequence to a fixed-size integer that distributes evenly across the output range. They are judged on avalanche (a single input-bit change flips roughly half the output bits), distribution (hash-table buckets fill evenly), and streaming behaviour (FNV and Pearson are constant-memory; CityHash and MurmurHash3 buffer internally for SIMD throughput). Reach for them for hash-table keys, cache bucketing, deduplication, and content-addressable lookups inside a trust boundary - never for error-pattern detection or authentication.
Checksums produce a short tag engineered to catch the error patterns of a transmission or storage channel - single-bit flips, burst errors, adjacent transpositions. Two structural shapes: polynomial-remainder (CRC - divides the input as a polynomial over GF(2) by a generator polynomial) and twin-accumulator (Fletcher and Adler - two running sums whose cross-position coupling catches transpositions a simple sum misses).
The two shapes differ in the guarantees they offer, which is the axis to choose on:
| Property | CRC | Fletcher / Adler |
|---|---|---|
| Single-bit error | Always detected | Always detected |
| Adjacent transposition | Always detected | Always detected |
| Burst error of length ≤ width | Always detected | No per-position guarantee |
| Odd number of bit-flips | Always detected (most polynomials) | Not guaranteed |
| Per-byte cost | Higher (table lookup + XOR) | Lower (two adds + a fold) |
| Documented blind spots | None for accidental noise | Zero-byte runs (Fletcher); short inputs (Adler) |
Reach for CRC when you must match a wire format or need the published burst guarantee; reach for Fletcher or Adler when you control both endpoints and want the cheapest position-dependent checksum. The concepts page carries the full guarantee tables.
Check digits operate on a printed identifier - a short, human-readable string - and append one or two characters so a later reader can confirm it was not mis-typed. Five mathematical subfamilies trade off error coverage:
| Subfamily | Detects | Bodu types |
|---|---|---|
| Mod 10 (weighted sum) | All single-digit substitutions; most adjacent transpositions | Luhn, Ean8, Ean13, Gtin14, UpcA, AbaRoutingNumber, Isin |
| Quasigroup (Damm) | All single-digit substitutions and all adjacent transpositions | Damm |
| Dihedral group D₅ (Verhoeff) | The widest error coverage of any decimal scheme | Verhoeff |
| Mod 11 | All single-digit errors; most transpositions | Isbn10, Sedol, Cusip, Iso7064Mod11_2 |
| Mod 97-10 (ISO 7064) | Almost all transcription errors at scale | Iban, Lei, Iso7064Mod97_10 |
Picking between them. A checksum guards a binary payload that only software sees; a check digit guards a printed identifier a human copies by hand; a fingerprint just needs fast, even distribution across a table. CRC and Fletcher distribute poorly as hash functions, and FNV and CityHash give weaker burst-error guarantees than CRC - match the algorithm to the job.
Need an adversary model? Everything in this package is forgeable by an attacker who controls the input. For keyed and cryptographic hashes - SipHash, Poly1305, Tiger, ASCON, Merkle trees - that resist a deliberate attacker, see Bodu.Security.Cryptography.
Selecting a specific algorithm
Once the subfamily is chosen, this table compares the algorithms within each subfamily on the dimensions that matter most for picking one: output size, streaming behaviour, resumability, and the typical scenario the algorithm is tuned for.
| Algorithm | Output | Streaming | Resumable | Typical scenario |
|---|---|---|---|---|
Fnv1a32 / Fnv1a64 (and Fnv132 / Fnv164) |
32 / 64 bits | Constant memory | Yes (IResumableHashAlgorithm) |
Hash-table keys; the default fingerprint when in doubt. |
MurmurHash3_32 / MurmurHash3_128 |
32 / 128 bits | Constant memory | No | Database index keys; widely used in distributed systems. |
CityHash32 / CityHash64 / CityHash128 |
32 / 64 / 128 bits | Buffered (SIMD) | No | Fastest on long inputs; CDN and large-blob fingerprints. |
Pearson |
8 - 2048 bits | Constant memory | No | Configurable output width in 8-bit steps; embedded scenarios. |
Bernstein, BKDR, SDBM, JSHash, Elf64, ApHash, Pjw32, SuperFastHash |
32 / 64 bits | Constant memory | No | Compiler-style string hashing; legacy interop. |
Crc (any standard from CrcStandard) |
1 - 64 bits | Constant memory | Yes (IResumableHashAlgorithm) |
Error-detection checksum on transmission / storage channels; choice driven by published CrcStandard (e.g. CRC-32/ISO-HDLC for zlib / PNG / Ethernet). |
Fletcher16 / Fletcher32 / Fletcher64 |
16 / 32 / 64 bits | Constant memory | Yes (IResumableHashAlgorithm) |
Faster than CRC at comparable error coverage; protocol checksums. |
Adler32 / Adler32C / Adler64 |
32 / 32 / 64 bits | Constant memory | Yes (IResumableHashAlgorithm) |
Used by zlib; checksum for short, low-entropy payloads. |
Luhn, Damm, Verhoeff, Ean8, Ean13, UpcA, Gtin14, AbaRoutingNumber |
1 character | Constant memory | No | Single-character check digit for human-typed numeric identifiers. |
Isbn10, Sedol, Cusip, Isin, Iso7064Mod11_2 |
1 character | Constant memory | No | Single-character check digit for mixed numeric / alphanumeric identifiers. |
Iban, Lei, Iso7064Mod97_10 |
2 characters | Constant memory | No | Two-character check digit (ISO 7064 Mod 97-10) for high-coverage validation. |
Crc, the FNV family, the Fletcher family, and the Adler family implementIResumableHashAlgorithm- the ability to reverse-finalize a stored digest, append more bytes, and finalize again. The buffered fingerprints (CityHash, MurmurHash3) and the classic string hashes do not.
The
Bodu.IO.Hashing.Extensionsnamespace adds ergonomic one-shot and async helpers (ComputeHash,ComputeHashAsync,VerifyHash,TryVerifyHash) over every algorithm in the table.
Common lifecycle
using Bodu.IO.Hashing;
using Bodu.IO.Hashing.Checksums;
using var hash = new Crc(); // or Fletcher32, Adler32, Fnv1a64, CityHash64, …
hash.Append(chunk1);
hash.Append(chunk2);
byte[] partial = hash.GetCurrentHash(); // snapshot, non-destructive
hash.Append(chunk3);
byte[] full = hash.GetCurrentHash();
hash.Reset(); // back to the initial state
Crc, the FNV family, the Fletcher family, and the Adler family also implement IResumableHashAlgorithm (reverse-finalize a stored digest, append more bytes, finalize again).
Where to go next
- Core concepts - glossary the rest of the documentation assumes.
- Getting started - install + one minimal sample per subfamily.
- Bodu.IO.Hashing guides - recipe-style walk-throughs per algorithm.
- Bodu.IO.Hashing API reference - full type-by-type docs.
- For keyed and cryptographic hashes (SipHash, Poly1305, Tiger, ASCON, Merkle trees), see Bodu.Security.Cryptography.
- Hashing & Cryptography topic - this package and its sibling Bodu.Security.Cryptography side by side.