# `hashes`

The `hashes` library provides portable implementations of several commonly used hashing algorithms. All hash objects implement the `hash_protocol` protocol by providing a `hash/2` predicate that takes a list of bytes and returns the computed hash as a lowercase hexadecimal atom.

The library implements the following hashing algorithms:

- DJB2 32-bit (`djb2_32`)

- DJB2 64-bit (`djb2_64`)

- SDBM 32-bit (`sdbm_32`)

- SDBM 64-bit (`sdbm_64`)

- FNV-1a 32-bit (`fnv1a_32`)

- FNV-1a 64-bit (`fnv1a_64`)

- SipHash (`siphash_2_4`)

- CRC-32 parametric reflected implementation (`crc32_reflected(Polynomial)`)

- CRC-32 parametric non-reflected implementation (`crc32_non_reflected(Polynomial, Initial, FinalXor, AppendLength)`)

- CRC-32/ISO-HDLC (`crc32b`)

- CRC-32C/Castagnoli (`crc32c`)

- CRC-32/POSIX (`crc32posix`)

- CRC-32/MPEG-2 (`crc32mpeg2`)

- CRC-32/BZIP2 (`crc32bzip2`)

- CRC-32Q (aka CRC-32/AIXM) (`crc32q`)

- MurmurHash3 x86 32-bit (`murmurhash3_x86_32`)

- MurmurHash3 x86 128-bit (`murmurhash3_x86_128`)

- MurmurHash3 x64 128-bit (`murmurhash3_x64_128`)

- SHA3-224 (`sha3_224`)

- SHA3-256 (`sha3_256`)

- SHA3-384 (`sha3_384`)

- SHA3-512 (`sha3_512`)

- SHAKE128 (`shake128(OutputBytes)`)

- SHAKE256 (`shake256(OutputBytes)`)

- MD5 (`md5`)

- SHA1 (`sha1`)

- SHA256 (`sha256`)

The `djb2_64`, `sdbm_64`, `fnv1a_64`, `siphash_2_4`, `murmurhash3_x86_128`, `murmurhash3_x64_128`, `sha3_224`, `sha3_256`, `sha3_384`, `sha3_512`, `shake128(OutputBytes)`, `shake256(OutputBytes)`, `sha1`, and `sha256` objects are only loaded on backend Prolog compilers supporting unbounded integer arithmetic.

The SHAKE objects are parametric extensible-output functions. Pass the number of output bytes to generate when constructing the object.

The `crc32_reflected(Polynomial)` object implements a reflected CRC-32 family using initial value `0xFFFFFFFF` and final xor value `0xFFFFFFFF`, where `Polynomial` is the reflected CRC-32 polynomial.

The `crc32_non_reflected(Polynomial, Initial, FinalXor, AppendLength)` object implements a non-reflected CRC-32 family using a canonical polynomial, configurable initial and final xor values, and an `AppendLength` flag that controls whether the message length is appended as little-endian bytes.

The `crc32b` object implements the CRC-32/ISO-HDLC variant, also widely used by Ethernet, gzip, and PKZip. It uses reflected input/output processing, the reflected polynomial `0xEDB88320` (equivalent to the canonical polynomial `0x04C11DB7`), initial value `0xFFFFFFFF`, and final xor value `0xFFFFFFFF`.

The `crc32c` object implements the CRC-32C/Castagnoli variant using reflected input/output processing, the reflected polynomial `0x82F63B78` (equivalent to the canonical polynomial `0x1EDC6F41`), initial value `0xFFFFFFFF`, and final xor value `0xFFFFFFFF`.

The `crc32posix` object implements the CRC-32/POSIX variant used by the standard `cksum` utility. It is an instance of the non-reflected `crc32_non_reflected(Polynomial, Initial, FinalXor, AppendLength)` family: it uses the canonical polynomial `0x04C11DB7`, initial value `0x00000000`, processes bits most-significant first, appends the message length as little-endian bytes, and applies a final xor value of `0xFFFFFFFF`.

The `crc32mpeg2` object implements the CRC-32/MPEG-2 variant using the canonical polynomial `0x04C11DB7`, initial value `0xFFFFFFFF`, no appended length bytes, and final xor value `0x00000000`.

The `crc32bzip2` object implements the CRC-32/BZIP2 variant using the canonical polynomial `0x04C11DB7`, initial value `0xFFFFFFFF`, no appended length bytes, and final xor value `0xFFFFFFFF`.

The `crc32q` object implements the CRC-32Q variant, also used by AIXM-style formats, using the canonical polynomial `0x814141AB`, initial value `0x00000000`, no appended length bytes, and final xor value `0x00000000`.

The `siphash_2_4` object uses the standard reference key `00 01 02 ... 0f`. For custom keys, use the parametric object `siphash_2_4(Key)` where `Key` is a list of 16 bytes.

The implementations of the hashing algorithms make no attempt to validate that the input is a list of bytes. When necessary, use the `types` library `type::check(list(byte), Input)` goal before calling the `hash/2` predicate.

## API documentation

Open the ../../apis/library_index.html#hashes link in a web browser.

## Loading

To load all entities in this library, load the `loader.lgt` file:

    | ?- logtalk_load(hashes(loader)).

## Testing

To test this library predicates, load the `tester.lgt` file:

    | ?- logtalk_load(hashes(tester)).

## Examples

Compute the SHA-256 hash of a text message:

    | ?- atom_codes('The quick brown fox jumps over the lazy dog', Bytes),
         sha256::hash(Bytes, Hash).
    Bytes = [84,104,101,32,113,117,105,99,107,32,98,114,111,119,110,32,102,111,120,32,106,117,109,112,115,32,111,118,101,114,32,116,104,101,32,108,97,122,121,32,100,111,103],
    Hash = 'd7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592'
    yes

Compute a 32-byte SHAKE128 digest:

    | ?- atom_codes('The quick brown fox jumps over the lazy dog', Bytes),
         shake128(32)::hash(Bytes, Hash).
    Bytes = [84,104,101,32,113,117,105,99,107,32,98,114,111,119,110,32,102,111,120,32,106,117,109,112,115,32,111,118,101,114,32,116,104,101,32,108,97,122,121,32,100,111,103],
    Hash = 'f4202e3c5852f9182a0430fd8144f0a74b95e7417ecae17db0f8cfeed0e3e66e'
    yes

Compute the CRC-32/ISO-HDLC checksum for the standard `123456789` test vector:

    | ?- atom_codes('123456789', Bytes), crc32b::hash(Bytes, Hash).
    Bytes = [49,50,51,52,53,54,55,56,57],
    Hash = 'cbf43926'
    yes

Compute the CRC-32C/Castagnoli checksum for the standard `123456789` test vector:

    | ?- atom_codes('123456789', Bytes), crc32c::hash(Bytes, Hash).
    Bytes = [49,50,51,52,53,54,55,56,57],
    Hash = 'e3069283'
    yes

Compute the CRC-32/POSIX checksum for the standard `123456789` test vector:

    | ?- atom_codes('123456789', Bytes), crc32posix::hash(Bytes, Hash).
    Bytes = [49,50,51,52,53,54,55,56,57],
    Hash = '377a6011'
    yes

Compute the CRC-32/MPEG-2 checksum for the standard `123456789` test vector:

    | ?- atom_codes('123456789', Bytes), crc32mpeg2::hash(Bytes, Hash).
    Bytes = [49,50,51,52,53,54,55,56,57],
    Hash = '0376e6e7'
    yes

Compute the CRC-32/BZIP2 checksum for the standard `123456789` test vector:

    | ?- atom_codes('123456789', Bytes), crc32bzip2::hash(Bytes, Hash).
    Bytes = [49,50,51,52,53,54,55,56,57],
    Hash = 'fc891918'
    yes

Compute the CRC-32Q checksum for the standard `123456789` test vector:

    | ?- atom_codes('123456789', Bytes), crc32q::hash(Bytes, Hash).
    Bytes = [49,50,51,52,53,54,55,56,57],
    Hash = '3010bf7f'
    yes

Use SipHash-2-4 with a custom key on a backend supporting unbounded integer arithmetic:

    | ?- siphash_2_4([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15])::hash([0,1,2,3], Hash).
    Hash = 'cf2794e0277187b7'
    yes