C · Hashing and Checksums

Hashing and Checksums

#include <stringzilla/capabilities.h>#include <stringzilla/hash.h>#include <stringzilla/cipher.h> 6.0.0-rc.1 · 91a27bdd

Hashing comes in three flavors: a byte checksum, a seeded single-shot hash, and an incremental streaming state. All produce identical output across every backend and platform, in both single-shot and incremental modes.

sz_status_t sz_bytesum_best(sz_cptr_t text, sz_size_t length, sz_u64_t *checksum, //
                            sz_capability_t capabilities, sz_stream_t stream);
sz_status_t sz_hash_best(sz_cptr_t text, sz_size_t length, sz_u64_t seed, sz_u64_t *hash, //
                         sz_capability_t capabilities, sz_stream_t stream);
sz_status_t sz_hash_multiseed_best(sz_cptr_t text, sz_size_t length, sz_u64_t const *seeds, sz_size_t seeds_count,
                                   sz_u64_t *hashes, sz_capability_t capabilities, sz_stream_t stream);

sz_hash_best is non-cryptographic, fast for both short and long inputs, passes the SMHasher --extra suite, and uses the AES extensions where present. sz_hash_multiseed_best hashes one input under many seeds at once — for feature hashing, Count-Min sketches, Bloom filters, and MinHash/LSH — by normalizing the input into AES blocks once and replaying cheap per-seed rounds.

Incremental hashing uses an opaque sz_hash_state_t, whose layout every capability shares, so each call may pass its own mask:

sz_status_t sz_hash_state_init_best(sz_hash_state_t *state, sz_u64_t seed, sz_capability_t capabilities, sz_stream_t stream);
sz_status_t sz_hash_state_update_best(sz_hash_state_t *state, sz_cptr_t text, sz_size_t length, //
                                      sz_capability_t capabilities, sz_stream_t stream);
sz_status_t sz_hash_state_digest_best(sz_hash_state_t const *state, sz_u64_t *hash, //
                                      sz_capability_t capabilities, sz_stream_t stream);
sz_bool_t sz_hash_state_equal(sz_hash_state_t const *lhs, sz_hash_state_t const *rhs);

A streaming SHA-256 is also provided, producing a 32-byte digest, with hardware backends on x86 SHA-NI, ARM NEON-SHA, and others:

sz_status_t sz_sha256_state_init_best(sz_sha256_state_t *state, sz_capability_t capabilities, sz_stream_t stream);
sz_status_t sz_sha256_state_update_best(sz_sha256_state_t *state, sz_cptr_t text, sz_size_t length, //
                                        sz_capability_t capabilities, sz_stream_t stream);
sz_status_t sz_sha256_state_digest_best(sz_sha256_state_t const *state, sz_u8_t digest[32], //
                                        sz_capability_t capabilities, sz_stream_t stream);

The same AES primitives back a reproducible pseudo-random fill, useful with sz_strings_lookup_best for generating random strings over a chosen alphabet:

sz_status_t sz_fill_random_best(sz_ptr_t target, sz_size_t length, sz_u64_t nonce, //
                                sz_capability_t capabilities, sz_stream_t stream);

Example combining a single-shot hash, a streamed hash, and a checksum:

#include <stringzilla/stringzilla.h>

int main(void) {
    sz_capability_t capabilities = sz_cap_serial_k;
    sz_capabilities_enabled_cpu(&capabilities);

    sz_u64_t single = 0;
    sz_hash_best("hello world", 11, 42, &single, capabilities, NULL);

    sz_hash_state_t state;
    sz_u64_t streamed = 0;
    sz_hash_state_init_best(&state, 42, capabilities, NULL);
    sz_hash_state_update_best(&state, "hello ", 6, capabilities, NULL);
    sz_hash_state_update_best(&state, "world", 5, capabilities, NULL);
    sz_hash_state_digest_best(&state, &streamed, capabilities, NULL);
    assert(streamed == single);

    sz_u64_t sum = 0;
    sz_bytesum_best("hi", 2, &sum, capabilities, NULL);
    assert(sum == 209);
    return 0;
}

API

Types

sz_kernel_hash_tSignature of the sz_hash_best kernels.
capabilities.h:680 ↗
typedef sz_status_t(*) sz_kernel_hash_t(sz_cptr_t, sz_size_t, sz_u64_t, sz_u64_t *, sz_stream_t);
sz_kernel_hash_multiseed_tSignature of the sz_hash_multiseed_best kernels.
capabilities.h:683 ↗
typedef sz_status_t(*) sz_kernel_hash_multiseed_t(sz_cptr_t, sz_size_t, sz_u64_t const *, sz_size_t, sz_u64_t *, sz_stream_t);
sz_kernel_hash_strings_tSignature of the sz_hash_strings_best kernels.
capabilities.h:687 ↗
typedef sz_status_t(*) sz_kernel_hash_strings_t(sz_strings_view_t const *, sz_size_t const *, sz_size_t, sz_u64_t, sz_u64_t *, sz_stream_t);
sz_kernel_hash_state_init_tSignature of the sz_hash_state_init_best kernels.
capabilities.h:691 ↗
typedef sz_status_t(*) sz_kernel_hash_state_init_t(struct sz_hash_state_t *, sz_u64_t, sz_stream_t);
sz_kernel_hash_state_update_tSignature of the sz_hash_state_update_best kernels.
capabilities.h:694 ↗
typedef sz_status_t(*) sz_kernel_hash_state_update_t(struct sz_hash_state_t *, sz_cptr_t, sz_size_t, sz_stream_t);
sz_kernel_hash_state_digest_tSignature of the sz_hash_state_digest_best kernels.
capabilities.h:697 ↗
typedef sz_status_t(*) sz_kernel_hash_state_digest_t(struct sz_hash_state_t const *, sz_u64_t *, sz_stream_t);
sz_kernel_bytesum_tSignature of the sz_bytesum_best kernels.
capabilities.h:700 ↗
typedef sz_status_t(*) sz_kernel_bytesum_t(sz_cptr_t, sz_size_t, sz_u64_t *, sz_stream_t);
sz_kernel_sha256_state_init_tSignature of the sz_sha256_state_init_best kernels.
capabilities.h:759 ↗
typedef sz_status_t(*) sz_kernel_sha256_state_init_t(struct sz_sha256_state_t *, sz_stream_t);
sz_kernel_sha256_state_update_tSignature of the sz_sha256_state_update_best kernels.
capabilities.h:762 ↗
typedef sz_status_t(*) sz_kernel_sha256_state_update_t(struct sz_sha256_state_t *, sz_cptr_t, sz_size_t, sz_stream_t);
sz_kernel_sha256_state_digest_tSignature of the sz_sha256_state_digest_best kernels.
capabilities.h:765 ↗
typedef sz_status_t(*) sz_kernel_sha256_state_digest_t(struct sz_sha256_state_t const *, sz_u8_t *, sz_stream_t);
sz_kernel_sha256_multistate_update_tSignature of the sz_sha256_multistate_update_best kernels.
capabilities.h:768 ↗
typedef sz_status_t(*) sz_kernel_sha256_multistate_update_t(struct sz_sha256_state_t *, sz_strings_view_t const *, sz_stream_t);
sz_kernel_sha256_multistate_digest_tSignature of the sz_sha256_multistate_digest_best kernels.
capabilities.h:772 ↗
typedef sz_status_t(*) sz_kernel_sha256_multistate_digest_t(struct sz_sha256_state_t const *, sz_size_t, sz_u8_t *, sz_stream_t);
sz_kernel_aes256_key_init_tSignature of the sz_aes256_key_init_best kernels.
capabilities.h:776 ↗
typedef sz_status_t(*) sz_kernel_aes256_key_init_t(struct sz_aes256_key_t *, sz_u8_t const *, sz_stream_t);
sz_kernel_aes256_gcm_key_init_tSignature of the sz_aes256_gcm_key_init_best kernels.
capabilities.h:779 ↗
typedef sz_status_t(*) sz_kernel_aes256_gcm_key_init_t(struct sz_aes256_gcm_key_t *, sz_u8_t const *, sz_stream_t);
sz_kernel_aes256_ctr_xor_tSignature of the sz_aes256_ctr_xor_best kernels.
capabilities.h:782 ↗
typedef sz_status_t(*) sz_kernel_aes256_ctr_xor_t(struct sz_aes256_key_t const *, sz_u8_t const *, sz_u64_t, sz_cptr_t, sz_size_t, sz_ptr_t, sz_stream_t);
sz_kernel_aes256_gcm_encrypt_tSignature of the sz_aes256_gcm_encrypt_best kernels.
capabilities.h:786 ↗
typedef sz_status_t(*) sz_kernel_aes256_gcm_encrypt_t(struct sz_aes256_gcm_key_t const *, sz_u8_t const *, sz_cptr_t, sz_size_t, sz_cptr_t, sz_size_t, sz_ptr_t, sz_u8_t *, sz_stream_t);
sz_kernel_aes256_gcm_decrypt_tSignature of the sz_aes256_gcm_decrypt_best kernels.
capabilities.h:791 ↗
typedef sz_status_t(*) sz_kernel_aes256_gcm_decrypt_t(struct sz_aes256_gcm_key_t const *, sz_u8_t const *, sz_cptr_t, sz_size_t, sz_cptr_t, sz_size_t, sz_ptr_t, sz_u8_t const *, sz_stream_t);
sz_kernel_aes256_gcm_encryptor_init_tSignature of the sz_aes256_gcm_encryptor_init_best kernels.
capabilities.h:796 ↗
typedef sz_status_t(*) sz_kernel_aes256_gcm_encryptor_init_t(struct sz_aes256_gcm_encryptor_t *, struct sz_aes256_gcm_key_t const *, sz_u8_t const *, sz_stream_t);
sz_kernel_aes256_gcm_encryptor_associate_tSignature of the sz_aes256_gcm_encryptor_associate_best kernels.
capabilities.h:801 ↗
typedef sz_status_t(*) sz_kernel_aes256_gcm_encryptor_associate_t(struct sz_aes256_gcm_encryptor_t *, sz_cptr_t, sz_size_t, sz_stream_t);
sz_kernel_aes256_gcm_encryptor_update_tSignature of the sz_aes256_gcm_encryptor_update_best kernels.
capabilities.h:805 ↗
typedef sz_status_t(*) sz_kernel_aes256_gcm_encryptor_update_t(struct sz_aes256_gcm_encryptor_t *, sz_cptr_t, sz_size_t, sz_ptr_t, sz_stream_t);
sz_kernel_aes256_gcm_encryptor_digest_tSignature of the sz_aes256_gcm_encryptor_digest_best kernels.
capabilities.h:809 ↗
typedef sz_status_t(*) sz_kernel_aes256_gcm_encryptor_digest_t(struct sz_aes256_gcm_encryptor_t const *, sz_u8_t *, sz_stream_t);
sz_kernel_aes256_gcm_decryptor_init_tSignature of the sz_aes256_gcm_decryptor_init_best kernels.
capabilities.h:813 ↗
typedef sz_status_t(*) sz_kernel_aes256_gcm_decryptor_init_t(struct sz_aes256_gcm_decryptor_t *, struct sz_aes256_gcm_key_t const *, sz_u8_t const *, sz_stream_t);
sz_kernel_aes256_gcm_decryptor_associate_tSignature of the sz_aes256_gcm_decryptor_associate_best kernels.
capabilities.h:818 ↗
typedef sz_status_t(*) sz_kernel_aes256_gcm_decryptor_associate_t(struct sz_aes256_gcm_decryptor_t *, sz_cptr_t, sz_size_t, sz_stream_t);
sz_kernel_aes256_gcm_decryptor_update_unverified_tSignature of the sz_aes256_gcm_decryptor_update_unverified_best kernels.
capabilities.h:822 ↗
typedef sz_status_t(*) sz_kernel_aes256_gcm_decryptor_update_unverified_t(struct sz_aes256_gcm_decryptor_t *, sz_cptr_t, sz_size_t, sz_ptr_t, sz_stream_t);
sz_kernel_aes256_gcm_decryptor_verify_tSignature of the sz_aes256_gcm_decryptor_verify_best kernels.
capabilities.h:826 ↗
typedef sz_status_t(*) sz_kernel_aes256_gcm_decryptor_verify_t(struct sz_aes256_gcm_decryptor_t const *, sz_u8_t const *, sz_stream_t);

Functions

sz_bytesum_bestComputes the 64-bit check-sum of bytes in a string, similar to std::ranges::accumulate.
hash.h:127 ↗
sz_status_t sz_bytesum_best(
    sz_cptr_t text,
    sz_size_t length,
    sz_u64_t *checksum,
    sz_capability_t capabilities,
    sz_stream_t stream);

Backends

  • sz_bytesumserialhaswellskylakeicelakeneonsvesve2rvvv128v128relaxedloongsonasxpowervsx

Summing the bytes of "hi", 104 + 105:

#include <stringzilla/stringzilla.h>
int main() {
    sz_capability_t capabilities;
    sz_u64_t checksum;
    sz_capabilities_enabled_cpu(&capabilities);
    sz_bytesum_best("hi", 2, &checksum, capabilities, NULL);
    return checksum == 209 ? 0 : 1;
}

Parameters

textinString to aggregate.
lengthinNumber of bytes in the text.
checksumoutThe 64-bit unsigned sum.
capabilitiesinOne device's capabilities, like sz_capabilities_enabled_cpu reports.
streaminNull on the CPU, or the GPU stream of that device to queue on.

See also

sz_bytesum_serial, sz_bytesum_haswell, sz_bytesum_skylake, sz_bytesum_icelake, sz_bytesum_neon, sz_bytesum_sve, sz_bytesum_sve2, sz_bytesum_v128, sz_bytesum_v128relaxed, sz_bytesum_rvv, sz_bytesum_loongsonasx, sz_bytesum_powervsx

Statuses

sz_hash_bestComputes the 64-bit unsigned hash of a string, similar to std::hash in C++.
hash.h:167 ↗
sz_status_t sz_hash_best(
    sz_cptr_t text,
    sz_size_t length,
    sz_u64_t seed,
    sz_u64_t *hash,
    sz_capability_t capabilities,
    sz_stream_t stream);

Backends

  • sz_hashserialwestmereskylakeicelakeneonaessve2aesrvvrvvcryptov128v128relaxedloongsonasxpowervsx

It's not cryptographically secure, but it's fast and provides a good distribution. It passes the SMHasher suite by Austin Appleby with no collisions, even with the --extra flag. HASH.md explains the algorithm in detail.

Telling two different strings apart:

#include <stringzilla/stringzilla.h>
int main() {
    sz_capability_t capabilities;
    sz_u64_t first_hash, second_hash;
    sz_capabilities_enabled_cpu(&capabilities);
    sz_hash_best("hello", 5, 0, &first_hash, capabilities, NULL);
    sz_hash_best("world", 5, 0, &second_hash, capabilities, NULL);
    return first_hash != second_hash ? 0 : 1;
}

Parameters

textinString to hash.
lengthinNumber of bytes in the text.
seedin64-bit unsigned seed for the hash.
hashoutThe 64-bit hash value.
capabilitiesinOne device's capabilities, like sz_capabilities_enabled_cpu reports.
streaminNull on the CPU, or the GPU stream of that device to queue on.

Notes

The output is the same on all platforms, in both single-shot and incremental modes.

See also

Statuses

sz_hash_strings_bestHashes every one of strings[order[i]], or of the first count strings, under one seed, each exactly as sz_hash_best would, for group-by keys, joins and sharding.
hash.h:189 ↗
sz_status_t sz_hash_strings_best(
    sz_strings_view_t const *strings,
    sz_size_t const *order,
    sz_size_t count,
    sz_u64_t seed,
    sz_u64_t *hashes,
    sz_capability_t capabilities,
    sz_stream_t stream);

Backends

  • sz_hash_stringsserialwestmereskylakeicelakeneonaesrvvcryptov128v128relaxedloongsonasxpowervsx

A tape read in its own order loads each window of consecutive keys once and hashes the keys of up to 64 bytes in it from registers, their AES rounds interleaved, while longer keys, orders and the accessor layout hash one string at a time.

Parameters

stringsinThe strings to hash, in any layout.
orderinIndices into strings, possibly repeated, or null for the first count.
countinNumber of strings to hash.
seedinThe seed every string is hashed under.
hashesoutThe count hashes, one per string.
capabilitiesinOne device's capabilities, like sz_capabilities_enabled_cpu reports.
streaminNull on the CPU, or the GPU stream of that device to queue on.

Statuses

sz_hash_multiseed_bestHashes one string under many seeds at once, the "multi-seed" hash.
hash.h:235 ↗
sz_status_t sz_hash_multiseed_best(
    sz_cptr_t text,
    sz_size_t length,
    sz_u64_t const *seeds,
    sz_size_t seeds_count,
    sz_u64_t *hashes,
    sz_capability_t capabilities,
    sz_stream_t stream);

Backends

  • sz_hash_multiseedserialwestmereicelakeneonaesrvvcryptov128v128relaxedpowervsx

Equivalent to hashing with sz_hash_best under each of seeds, but normalizes the input into AES blocks once and replays the cheap per-seed rounds over that prepared form.

Designed for workloads that need several independent hashes of the same (often short) key: feature-hashing & Count-Min sketches for BM25/TF-IDF, Bloom filters, cuckoo hashing, MinHash / SimHash / LSH banding, and rendezvous (HRW) hashing. Two effects make it faster than a loop of sz_hash_best: the branch-heavy load & de-interleave of variable-length short strings is amortized across all seeds, and AES-capable backends advance several seed-lanes per instruction.

Three seeds, the first matching a plain sz_hash_best call:

#include <stringzilla/stringzilla.h>
int main() {
    sz_capability_t capabilities;
    sz_u64_t seeds[3] = {1, 2, 3}, hashes[3], hash;
    sz_capabilities_enabled_cpu(&capabilities);
    sz_hash_multiseed_best("token", 5, seeds, 3, hashes, capabilities, NULL);
    sz_hash_best("token", 5, 1, &hash, capabilities, NULL);
    return hashes[0] == hash ? 0 : 1;
}

Parameters

textinString to hash.
lengthinNumber of bytes in the text.
seedsinArray of seeds_count 64-bit seeds.
seeds_countinNumber of seeds, and the number of hashes written to hashes.
hashesoutCaller-allocated output buffer of seeds_count 64-bit hashes.
capabilitiesinOne device's capabilities, like sz_capabilities_enabled_cpu reports.
streaminNull on the CPU, or the GPU stream of that device to queue on.

Notes

Biggest speedups are for length ≤ 64; above that only the input load is shared.

See also

sz_hash_multiseed_serial, sz_hash_multiseed_westmere, sz_hash_multiseed_icelake, sz_hash_multiseed_neonaes, sz_hash_multiseed_rvvcrypto, sz_hash_multiseed_v128, sz_hash_multiseed_v128relaxed, sz_hash_multiseed_powervsx

Statuses

sz_hash_state_init_bestInitializes the state for incremental construction of a hash.
hash.h:301 ↗
sz_status_t sz_hash_state_init_best(
    sz_hash_state_t *state,
    sz_u64_t seed,
    sz_capability_t capabilities,
    sz_stream_t stream);

Backends

  • sz_hash_state_initserialwestmereskylakeicelakeneonaessve2aesrvvrvvcryptov128v128relaxedloongsonasxpowervsx

Every backend shares the state layout, so each call of a stream may pass other capabilities.

Parameters

stateoutThe state to initialize.
seedinThe 64-bit unsigned seed for the hash.
capabilitiesinOne device's capabilities, like sz_capabilities_enabled_cpu reports.
streaminNull on the CPU, or the GPU stream of that device to queue on.

Statuses

sz_hash_state_update_bestUpdates the state with new data.
hash.h:316 ↗
sz_status_t sz_hash_state_update_best(
    sz_hash_state_t *state,
    sz_cptr_t text,
    sz_size_t length,
    sz_capability_t capabilities,
    sz_stream_t stream);

Backends

  • sz_hash_state_updateserialwestmereskylakeicelakeneonaessve2aesrvvrvvcryptov128v128relaxedloongsonasxpowervsx

Parameters

stateinoutThe state to stream.
textinThe new data to include in the hash.
lengthinThe number of bytes in the new data.
capabilitiesinOne device's capabilities, like sz_capabilities_enabled_cpu reports.
streaminNull on the CPU, or the GPU stream of that device to queue on.

Statuses

sz_hash_state_digest_bestFinalizes the immutable state into the hash.
hash.h:330 ↗
sz_status_t sz_hash_state_digest_best(
    sz_hash_state_t const *state,
    sz_u64_t *hash,
    sz_capability_t capabilities,
    sz_stream_t stream);

Backends

  • sz_hash_state_digestserialwestmereskylakeicelakeneonaessve2aesrvvrvvcryptov128v128relaxedloongsonasxpowervsx

Parameters

stateinThe state to fold.
hashoutThe 64-bit hash value, as sz_hash_best gives for the same bytes and seed.
capabilitiesinOne device's capabilities, like sz_capabilities_enabled_cpu reports.
streaminNull on the CPU, or the GPU stream of that device to queue on.

Statuses

sz_sha256_state_init_bestInitializes the state for incremental SHA256 hashing.
hash.h:345 ↗
sz_status_t sz_sha256_state_init_best(
    sz_sha256_state_t *state,
    sz_capability_t capabilities,
    sz_stream_t stream);

Backends

  • sz_sha256_state_initserialgoldmontneonsharvvrvvcryptov128loongsonasxpowervsx

Every backend shares the state layout, so each call of a stream may pass other capabilities.

Parameters

stateoutThe state to initialize.
capabilitiesinOne device's capabilities, like sz_capabilities_enabled_cpu reports.
streaminNull on the CPU, or the GPU stream of that device to queue on.

Statuses

sz_sha256_state_update_bestUpdates the SHA256 state with new data.
hash.h:360 ↗
sz_status_t sz_sha256_state_update_best(
    sz_sha256_state_t *state,
    sz_cptr_t text,
    sz_size_t length,
    sz_capability_t capabilities,
    sz_stream_t stream);

Backends

  • sz_sha256_state_updateserialgoldmontneonsharvvrvvcryptov128loongsonasxpowervsx

Parameters

stateinoutThe state to update.
textinThe new data to hash.
lengthinThe number of bytes in the new data.
capabilitiesinOne device's capabilities, like sz_capabilities_enabled_cpu reports.
streaminNull on the CPU, or the GPU stream of that device to queue on.

Statuses

sz_sha256_state_digest_bestFinalizes the SHA256 state into the digest, leaving the state open to more data.
hash.h:374 ↗
sz_status_t sz_sha256_state_digest_best(
    sz_sha256_state_t const *state,
    sz_u8_t digest,
    sz_capability_t capabilities,
    sz_stream_t stream);

Backends

  • sz_sha256_state_digestserialgoldmontneonsharvvrvvcryptov128loongsonasxpowervsx

Parameters

stateinThe state to finalize.
digestoutOutput buffer for the 32-byte (256-bit) digest.
capabilitiesinOne device's capabilities, like sz_capabilities_enabled_cpu reports.
streaminNull on the CPU, or the GPU stream of that device to queue on.

Statuses

sz_sha256_multistate_update_bestAdvances many independent SHA256 states, one message per lane.
hash.h:427 ↗
sz_status_t sz_sha256_multistate_update_best(
    sz_sha256_state_t *states,
    sz_strings_view_t const *texts,
    sz_capability_t capabilities,
    sz_stream_t stream);

Backends

  • sz_sha256_multistate_updateserialgoldmonthaswellskylakeneonsharvvcryptocudarocm

Hashing one message is a serial dependency chain, so a wider instruction set cannot accelerate it. Independent messages compress in parallel lanes, which is what this does: sixteen at a time on AVX-512, eight on AVX2. Supply at least a few kilobytes per lane per call so the lane transposition is amortized; below one 64-byte block per lane it degrades to the single-message path. A zero-length chunk is a no-op for that lane. The states must be distinct, while the chunks may overlap.

Advancing two lanes by one chunk each, then taking both digests:

#include <stringzilla/stringzilla.h>
int main() {
    sz_cptr_t chunks[2] = {"hello", "world"};
    sz_sha256_state_t states[2];
    sz_u8_t digests[2 * STRINGZILLA_SHA256_DIGEST_LENGTH];
    sz_strings_view_t texts;
    sz_capability_t capabilities;
    sz_capabilities_enabled_cpu(&capabilities);
    sz_strings_from_null_terminated_strings(chunks, 2, &texts);
    sz_sha256_state_init_best(&states[0], capabilities, NULL);
    sz_sha256_state_init_best(&states[1], capabilities, NULL);
    sz_sha256_multistate_update_best(states, &texts, capabilities, NULL);
    sz_sha256_multistate_digest_best(states, 2, digests, capabilities, NULL);
    return digests[0] == 0x2c ? 0 : 1;
}

Lanes are grouped by vector width and a group advances in lockstep, so it costs as much as its longest member. Inputs sorted by length put similar lengths in the same group, and sz_sort_order_best gives that ordering.

Parameters

statesinoutArray of at least texts->count states, each initialized with sz_sha256_state_init_best.
textsinStrings supplying the next chunk of each lane's message, with count lanes; on a GPU, a tape the device addresses, like sz_strings_to_tape_best writes.
capabilitiesinOne device's capabilities, like sz_capabilities_enabled_cpu reports.
streaminNull on the CPU, or the GPU stream of that device to queue on.

Notes

Every lane is correct whatever its length, but throughput is best sorted by length.

See also

sz_sha256_multistate_update_serial, sz_sha256_multistate_update_goldmont, sz_sha256_multistate_update_haswell, sz_sha256_multistate_update_skylake, sz_sha256_multistate_update_neonsha, sz_sha256_multistate_update_rvvcrypto

Statuses

sz_sha256_multistate_digest_bestFinalizes many independent SHA256 states, one digest per lane.
hash.h:447 ↗
sz_status_t sz_sha256_multistate_digest_best(
    sz_sha256_state_t const *states,
    sz_size_t states_count,
    sz_u8_t *digests,
    sz_capability_t capabilities,
    sz_stream_t stream);

Backends

  • sz_sha256_multistate_digestserialgoldmonthaswellskylakeneonsharvvcryptocudarocm

Leaves every state unmodified, so a streaming caller can take an interim digest and append more.

Parameters

statesinArray of states_count states.
states_countinNumber of states to finalize, which is the lane count.
digestsoutOutput buffer of states_count * STRINGZILLA_SHA256_DIGEST_LENGTH bytes, one big-endian digest per lane, in lane order.
capabilitiesinOne device's capabilities, like sz_capabilities_enabled_cpu reports.
streaminNull on the CPU, or the GPU stream of that device to queue on.

See also

Statuses

sz_hash_find_kernelFinds the hashing kernel of kind, from the best of capabilities.
hash.h:1051 ↗
sz_status_t sz_hash_find_kernel(
    sz_kernel_kind_t kind,
    sz_capability_t capabilities,
    sz_kernel_punned_t *kernel,
    sz_capability_t *capability);

Parameters

kindinThe verb whose kernel to find.
capabilitiesinThe mask to pick the best capability from.
kerneloutThe kernel, or null when none of capabilities has it.
capabilityoutThe capability the kernel belongs to, or zero.

Statuses

sz_hash_state_equalCompares the state of two running hashes.
hash.h:1062 ↗
sz_bool_t sz_hash_state_equal(
    sz_hash_state_t const *lhs,
    sz_hash_state_t const *rhs);

Notes

The current content of the ins buffer and its length is ignored.

sz_aes256_key_init_bestExpands a 32-byte secret into the AES-256 round-key schedule.
cipher.h:107 ↗
sz_status_t sz_aes256_key_init_best(
    sz_aes256_key_t *key,
    sz_u8_t const secret,
    sz_capability_t capabilities,
    sz_stream_t stream);

Backends

  • sz_aes256_key_initserialwestmereicelakeneonaessve2aesv128relaxedv128rvvcryptopowervsx

Expanding an all-zero secret:

#include <stringzilla/stringzilla.h>
int main() {
    sz_u8_t secret[32] = {0};
    sz_aes256_key_t key;
    sz_capability_t capabilities;
    sz_capabilities_enabled_cpu(&capabilities);
    return sz_aes256_key_init_best(&key, secret, capabilities, NULL) == sz_success_k ? 0 : 1;
}

Parameters

keyoutReceives the expanded schedule.
secretinThe 32 secret bytes.
capabilitiesinOne device's capabilities, like sz_capabilities_enabled_cpu reports.
streaminNull on the CPU, or the GPU stream of that device to queue on.

See also

sz_aes256_key_init_serial, sz_aes256_key_init_westmere, sz_aes256_key_init_icelake, sz_aes256_key_init_neonaes, sz_aes256_key_init_sve2aes, sz_aes256_key_init_rvvcrypto, sz_aes256_key_init_v128, sz_aes256_key_init_v128relaxed, sz_aes256_key_init_powervsx

Statuses

sz_aes256_ctr_xor_bestExclusive-ors length bytes against the AES-256 counter-mode keystream.
cipher.h:151 ↗
sz_status_t sz_aes256_ctr_xor_best(
    sz_aes256_key_t const *key,
    sz_u8_t const nonce,
    sz_u64_t byte_offset,
    sz_cptr_t text,
    sz_size_t length,
    sz_ptr_t target,
    sz_capability_t capabilities,
    sz_stream_t stream);

Backends

  • sz_aes256_ctr_xorserialwestmereicelakeneonaessve2aesv128relaxedv128rvvcryptopowervsx

Counter mode is its own inverse, so one call serves both directions. The counter block is the nonce followed by a big-endian 32-bit block index that starts at zero, so block n covers bytes [16n, 16n + 16) and a byte_offset that is not a multiple of 16 simply discards the leading bytes of its first keystream block.

Encrypting a message, then decrypting only its second half:

#include <stringzilla/stringzilla.h>
int main() {
    sz_u8_t secret[32] = {0}, nonce[12] = {0};
    char plain[64] = "the second half is decrypted on its own", cipher[64], back[64];
    sz_aes256_key_t key;
    sz_capability_t capabilities;
    sz_capabilities_enabled_cpu(&capabilities);
    sz_aes256_key_init_best(&key, secret, capabilities, NULL);
    sz_aes256_ctr_xor_best(&key, nonce, 0, plain, 64, cipher, capabilities, NULL);
    sz_aes256_ctr_xor_best(&key, nonce, 32, cipher + 32, 32, back + 32, capabilities, NULL); // ? Seeks
    return back[32] == plain[32] ? 0 : 1;
}

Parameters

keyinThe expanded schedule.
nonceinThe 12 nonce bytes, which must never repeat under one key.
byte_offsetinPosition of text within the stream, so a caller may start anywhere.
textinThe input bytes.
lengthinNumber of bytes to transform.
targetoutReceives length bytes; may equal text, or must not overlap it at all.
capabilitiesinOne device's capabilities, like sz_capabilities_enabled_cpu reports.
streaminNull on the CPU, or the GPU stream of that device to queue on.

See also

sz_aes256_ctr_xor_serial, sz_aes256_ctr_xor_westmere, sz_aes256_ctr_xor_icelake, sz_aes256_ctr_xor_neonaes, sz_aes256_ctr_xor_sve2aes, sz_aes256_ctr_xor_rvvcrypto, sz_aes256_ctr_xor_v128, sz_aes256_ctr_xor_v128relaxed, sz_aes256_ctr_xor_powervsx

Statuses

sz_aes256_gcm_key_init_bestExpands a 32-byte secret into a schedule and the Galois hash subkey powers.
cipher.h:174 ↗
sz_status_t sz_aes256_gcm_key_init_best(
    sz_aes256_gcm_key_t *key,
    sz_u8_t const secret,
    sz_capability_t capabilities,
    sz_stream_t stream);

Backends

  • sz_aes256_gcm_key_initserialwestmereicelakeneonaessve2aesv128relaxedv128rvvcryptopowervsx

The backends are sz_aes256_gcm_key_init_serial, sz_aes256_gcm_key_init_westmere, sz_aes256_gcm_key_init_icelake, sz_aes256_gcm_key_init_neonaes, sz_aes256_gcm_key_init_sve2aes, sz_aes256_gcm_key_init_rvvcrypto, sz_aes256_gcm_key_init_v128, sz_aes256_gcm_key_init_v128relaxed and sz_aes256_gcm_key_init_powervsx, one per target.

Parameters

keyoutReceives the schedule and the powers.
secretinThe 32 secret bytes.
capabilitiesinOne device's capabilities, like sz_capabilities_enabled_cpu reports.
streaminNull on the CPU, or the GPU stream of that device to queue on.

Statuses

sz_aes256_gcm_encrypt_bestEncrypts and authenticates a whole message in one call.
cipher.h:219 ↗
sz_status_t sz_aes256_gcm_encrypt_best(
    sz_aes256_gcm_key_t const *key,
    sz_u8_t const nonce,
    sz_cptr_t associated,
    sz_size_t associated_length,
    sz_cptr_t text,
    sz_size_t length,
    sz_ptr_t target,
    sz_u8_t tag,
    sz_capability_t capabilities,
    sz_stream_t stream);

Backends

  • sz_aes256_gcm_encryptserialwestmereicelakeneonaessve2aesv128relaxedv128rvvcryptopowervsx

Sealing a short message and opening it again:

#include <stringzilla/stringzilla.h>
int main() {
    sz_u8_t secret[32] = {0}, nonce[12] = {0}, tag[16];
    char plain[5] = "hello", cipher[5], back[5];
    sz_aes256_gcm_key_t key;
    sz_capability_t capabilities;
    sz_capabilities_enabled_cpu(&capabilities);
    sz_aes256_gcm_key_init_best(&key, secret, capabilities, NULL);
    sz_aes256_gcm_encrypt_best(&key, nonce, NULL, 0, plain, 5, cipher, tag, capabilities, NULL);
    sz_status_t status = sz_aes256_gcm_decrypt_best(&key, nonce, NULL, 0, cipher, 5, back, tag, capabilities,
        NULL);
    return status == sz_success_k ? 0 : 1;
}

Parameters

keyinThe expanded key.
nonceinThe 12 nonce bytes, which must never repeat under one key.
associatedinAuthenticated, unencrypted bytes like a routing header, or STRINGZILLA_NULL.
associated_lengthinNumber of associated bytes, possibly zero.
textinThe plaintext.
lengthinNumber of plaintext bytes.
targetoutReceives length ciphertext bytes, at text or not overlapping it at all.
tagoutReceives the 16-byte authentication tag.
capabilitiesinOne device's capabilities, like sz_capabilities_enabled_cpu reports.
streaminNull on the CPU, or the GPU stream of that device to queue on.

See also

sz_aes256_gcm_encrypt_serial, sz_aes256_gcm_encrypt_westmere, sz_aes256_gcm_encrypt_icelake, sz_aes256_gcm_encrypt_neonaes, sz_aes256_gcm_encrypt_sve2aes, sz_aes256_gcm_encrypt_rvvcrypto, sz_aes256_gcm_encrypt_v128, sz_aes256_gcm_encrypt_v128relaxed, sz_aes256_gcm_encrypt_powervsx

Statuses

sz_aes256_gcm_decrypt_bestVerifies a tag and decrypts a whole message in one call.
cipher.h:257 ↗
sz_status_t sz_aes256_gcm_decrypt_best(
    sz_aes256_gcm_key_t const *key,
    sz_u8_t const nonce,
    sz_cptr_t associated,
    sz_size_t associated_length,
    sz_cptr_t text,
    sz_size_t length,
    sz_ptr_t target,
    sz_u8_t const tag,
    sz_capability_t capabilities,
    sz_stream_t stream);

Backends

  • sz_aes256_gcm_decryptserialwestmereicelakeneonaessve2aesv128relaxedv128rvvcryptopowervsx

The comparison runs in time independent of where the tag first differs, and the output is cleared rather than left holding the unauthenticated plaintext, so a caller who ignores the status still cannot act on forged data. Decrypting in place therefore destroys the ciphertext when the tag is rejected, which suits a caller that drops the message anyway and rules out one that must retry.

Parameters

keyinThe expanded key.
nonceinThe 12 nonce bytes used to encrypt.
associatedinBytes authenticated but not encrypted, or STRINGZILLA_NULL.
associated_lengthinNumber of associated bytes, possibly zero.
textinThe ciphertext.
lengthinNumber of ciphertext bytes.
targetoutReceives length plaintext bytes on success, and zeros on failure; may equal text, or must not overlap it at all.
taginThe 16-byte tag to check.
capabilitiesinOne device's capabilities, like sz_capabilities_enabled_cpu reports.
streaminNull on the CPU, or the GPU stream of that device to queue on.

See also

sz_aes256_gcm_decrypt_serial, sz_aes256_gcm_decrypt_westmere, sz_aes256_gcm_decrypt_icelake, sz_aes256_gcm_decrypt_neonaes, sz_aes256_gcm_decrypt_sve2aes, sz_aes256_gcm_decrypt_rvvcrypto, sz_aes256_gcm_decrypt_v128, sz_aes256_gcm_decrypt_v128relaxed, sz_aes256_gcm_decrypt_powervsx

Statuses

sz_aes256_gcm_encryptor_init_bestBegins sealing a message delivered in chunks.
cipher.h:301 ↗
sz_status_t sz_aes256_gcm_encryptor_init_best(
    sz_aes256_gcm_encryptor_t *encryptor,
    sz_aes256_gcm_key_t const *key,
    sz_u8_t const nonce,
    sz_capability_t capabilities,
    sz_stream_t stream);

Backends

  • sz_aes256_gcm_encryptor_initserialwestmereicelakeneonaessve2aesv128relaxedv128rvvcryptopowervsx

Sealing an eight-byte buffer in place:

#include <stringzilla/stringzilla.h>
int main() {
    sz_u8_t secret[32] = {0}, nonce[12] = {0}, tag[16], buffer[8] = {0};
    sz_aes256_gcm_key_t key;
    sz_aes256_gcm_encryptor_t encryptor;
    sz_capability_t capabilities;
    sz_capabilities_enabled_cpu(&capabilities);
    sz_aes256_gcm_key_init_best(&key, secret, capabilities, NULL);
    sz_aes256_gcm_encryptor_init_best(&encryptor, &key, nonce, capabilities, NULL);
    sz_aes256_gcm_encryptor_update_best(&encryptor, (sz_cptr_t)buffer, 8, (sz_ptr_t)buffer, capabilities, NULL);
    sz_aes256_gcm_encryptor_digest_best(&encryptor, tag, capabilities, NULL);
    return 0;
}

The backends are sz_aes256_gcm_encryptor_init_serial, sz_aes256_gcm_encryptor_init_westmere, sz_aes256_gcm_encryptor_init_icelake, sz_aes256_gcm_encryptor_init_neonaes, sz_aes256_gcm_encryptor_init_sve2aes, sz_aes256_gcm_encryptor_init_rvvcrypto, sz_aes256_gcm_encryptor_init_v128, sz_aes256_gcm_encryptor_init_v128relaxed and sz_aes256_gcm_encryptor_init_powervsx.

Parameters

encryptoroutThe encryptor to initialize.
keyinThe expanded key, copied into encryptor.
nonceinThe 12 nonce bytes, which must never repeat under one key.
capabilitiesinOne device's capabilities, like sz_capabilities_enabled_cpu reports.
streaminNull on the CPU, or the GPU stream of that device to queue on.

Statuses

sz_aes256_gcm_encryptor_associate_bestAbsorbs associated data into a seal, authenticated but not encrypted.
cipher.h:320 ↗
sz_status_t sz_aes256_gcm_encryptor_associate_best(
    sz_aes256_gcm_encryptor_t *encryptor,
    sz_cptr_t text,
    sz_size_t length,
    sz_capability_t capabilities,
    sz_stream_t stream);

Backends

  • sz_aes256_gcm_encryptor_associateserialwestmereicelakeneonaessve2aesv128relaxedv128rvvcryptopowervsx

Parameters

encryptorinoutThe encryptor.
textinThe associated bytes.
lengthinNumber of associated bytes.
capabilitiesinOne device's capabilities, like sz_capabilities_enabled_cpu reports.
streaminNull on the CPU, or the GPU stream of that device to queue on.

Notes

All associated data must be absorbed before the first call transforming message bytes.

See also

sz_aes256_gcm_encryptor_associate_serial

Statuses

sz_aes256_gcm_encryptor_update_bestEncrypts one chunk and absorbs its ciphertext into the running tag.
cipher.h:338 ↗
sz_status_t sz_aes256_gcm_encryptor_update_best(
    sz_aes256_gcm_encryptor_t *encryptor,
    sz_cptr_t text,
    sz_size_t length,
    sz_ptr_t target,
    sz_capability_t capabilities,
    sz_stream_t stream);

Backends

  • sz_aes256_gcm_encryptor_updateserialwestmereicelakeneonaessve2aesv128relaxedv128rvvcryptopowervsx

Parameters

encryptorinoutThe encryptor.
textinThe plaintext chunk.
lengthinNumber of bytes in the chunk.
targetoutReceives length ciphertext bytes, at text or not overlapping it at all.
capabilitiesinOne device's capabilities, like sz_capabilities_enabled_cpu reports.
streaminNull on the CPU, or the GPU stream of that device to queue on.

See also

sz_aes256_gcm_encryptor_update_serial

Statuses

sz_aes256_gcm_encryptor_digest_bestFinalizes a seal and emits its authentication tag.
cipher.h:354 ↗
sz_status_t sz_aes256_gcm_encryptor_digest_best(
    sz_aes256_gcm_encryptor_t const *encryptor,
    sz_u8_t tag,
    sz_capability_t capabilities,
    sz_stream_t stream);

Backends

  • sz_aes256_gcm_encryptor_digestserialwestmereicelakeneonaessve2aesv128relaxedv128rvvcryptopowervsx

Parameters

encryptorinThe encryptor, left unmodified so a caller may keep appending.
tagoutReceives the 16 tag bytes.
capabilitiesinOne device's capabilities, like sz_capabilities_enabled_cpu reports.
streaminNull on the CPU, or the GPU stream of that device to queue on.

See also

sz_aes256_gcm_encryptor_digest_serial

Statuses

sz_aes256_gcm_decryptor_init_bestBegins opening a message delivered in chunks.
cipher.h:371 ↗
sz_status_t sz_aes256_gcm_decryptor_init_best(
    sz_aes256_gcm_decryptor_t *decryptor,
    sz_aes256_gcm_key_t const *key,
    sz_u8_t const nonce,
    sz_capability_t capabilities,
    sz_stream_t stream);

Backends

  • sz_aes256_gcm_decryptor_initserialwestmereicelakeneonaessve2aesv128relaxedv128rvvcryptopowervsx

Parameters

decryptoroutThe decryptor to initialize.
keyinThe expanded key, copied into decryptor.
nonceinThe 12 nonce bytes the message was sealed under.
capabilitiesinOne device's capabilities, like sz_capabilities_enabled_cpu reports.
streaminNull on the CPU, or the GPU stream of that device to queue on.

See also

sz_aes256_gcm_decryptor_init_serial

Statuses

sz_aes256_gcm_decryptor_associate_bestAbsorbs associated data into an open, authenticated but not encrypted.
cipher.h:390 ↗
sz_status_t sz_aes256_gcm_decryptor_associate_best(
    sz_aes256_gcm_decryptor_t *decryptor,
    sz_cptr_t text,
    sz_size_t length,
    sz_capability_t capabilities,
    sz_stream_t stream);

Backends

  • sz_aes256_gcm_decryptor_associateserialwestmereicelakeneonaessve2aesv128relaxedv128rvvcryptopowervsx

Parameters

decryptorinoutThe decryptor.
textinThe associated bytes.
lengthinNumber of associated bytes.
capabilitiesinOne device's capabilities, like sz_capabilities_enabled_cpu reports.
streaminNull on the CPU, or the GPU stream of that device to queue on.

Notes

All associated data must be absorbed before the first call transforming message bytes.

See also

sz_aes256_gcm_decryptor_associate_serial

Statuses

sz_aes256_gcm_decryptor_update_unverified_bestDecrypts one chunk and absorbs its ciphertext into the running tag.
cipher.h:413 ↗
sz_status_t sz_aes256_gcm_decryptor_update_unverified_best(
    sz_aes256_gcm_decryptor_t *decryptor,
    sz_cptr_t text,
    sz_size_t length,
    sz_ptr_t target,
    sz_capability_t capabilities,
    sz_stream_t stream);

Backends

  • sz_aes256_gcm_decryptor_update_unverifiedserialwestmereicelakeneonaessve2aesv128relaxedv128rvvcryptopowervsx

Nothing has verified that this ciphertext is genuine, and a caller that acts on the output before sz_aes256_gcm_decryptor_verify_best succeeds is trusting an attacker's data. Buffer it, or accept that risk knowingly: a streaming decryption cannot avoid it, so the name says so.

Parameters

decryptorinoutThe decryptor.
textinThe ciphertext chunk.
lengthinNumber of bytes in the chunk.
targetoutReceives length plaintext bytes, at text or not overlapping it at all.
capabilitiesinOne device's capabilities, like sz_capabilities_enabled_cpu reports.
streaminNull on the CPU, or the GPU stream of that device to queue on.

Warnings

The emitted bytes are not yet authenticated.

See also

sz_aes256_gcm_decryptor_update_unverified_serial

Statuses

sz_aes256_gcm_decryptor_verify_bestFinalizes an open and checks its authentication tag.
cipher.h:436 ↗
sz_status_t sz_aes256_gcm_decryptor_verify_best(
    sz_aes256_gcm_decryptor_t const *decryptor,
    sz_u8_t const tag,
    sz_capability_t capabilities,
    sz_stream_t stream);

Backends

  • sz_aes256_gcm_decryptor_verifyserialwestmereicelakeneonaessve2aesv128relaxedv128rvvcryptopowervsx

The comparison runs in time independent of where the tag first differs, so a caller cannot leak the expected tag by timing repeated attempts. Emitting the expected tag and letting the caller compare it would hand that guarantee to code this library does not own.

Parameters

decryptorinThe decryptor, left unmodified.
taginThe 16 tag bytes to check.
capabilitiesinOne device's capabilities, like sz_capabilities_enabled_cpu reports.
streaminNull on the CPU, or the GPU stream of that device to queue on.

See also

sz_aes256_gcm_decryptor_verify_serial

Statuses

sz_cipher_find_kernelFinds the cipher kernel of kind, from the best of capabilities.
cipher.h:1099 ↗
sz_status_t sz_cipher_find_kernel(
    sz_kernel_kind_t kind,
    sz_capability_t capabilities,
    sz_kernel_punned_t *kernel,
    sz_capability_t *capability);

Parameters

kindinThe verb whose kernel to find.
capabilitiesinThe mask to pick the best capability from.
kerneloutThe kernel, or null when none of capabilities has it.
capabilityoutThe capability the kernel belongs to, or zero.

Statuses