# Hashing and Checksums

> StringZilla for C

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.

```c
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:

```c
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:

```c
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:

```c
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:

```c
#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;
}
```

`#include <stringzilla/capabilities.h>`

`#include <stringzilla/hash.h>`

`#include <stringzilla/cipher.h>`

## sz_kernel_hash_t

Signature of the [`sz_hash_best`](#sz_hash_best) kernels.

```c
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_t

Signature of the [`sz_hash_multiseed_best`](#sz_hash_multiseed_best) kernels.

```c
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_t

Signature of the [`sz_hash_strings_best`](#sz_hash_strings_best) kernels.

```c
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_t

Signature of the [`sz_hash_state_init_best`](#sz_hash_state_init_best) kernels.

```c
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_t

Signature of the [`sz_hash_state_update_best`](#sz_hash_state_update_best) kernels.

```c
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_t

Signature of the [`sz_hash_state_digest_best`](#sz_hash_state_digest_best) kernels.

```c
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_t

Signature of the [`sz_bytesum_best`](#sz_bytesum_best) kernels.

```c
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_t

Signature of the [`sz_sha256_state_init_best`](#sz_sha256_state_init_best) kernels.

```c
typedef sz_status_t(*) sz_kernel_sha256_state_init_t(struct sz_sha256_state_t *, sz_stream_t);
```

## sz_kernel_sha256_state_update_t

Signature of the [`sz_sha256_state_update_best`](#sz_sha256_state_update_best) kernels.

```c
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_t

Signature of the [`sz_sha256_state_digest_best`](#sz_sha256_state_digest_best) kernels.

```c
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_t

Signature of the [`sz_sha256_multistate_update_best`](#sz_sha256_multistate_update_best) kernels.

```c
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_t

Signature of the [`sz_sha256_multistate_digest_best`](#sz_sha256_multistate_digest_best) kernels.

```c
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_t

Signature of the [`sz_aes256_key_init_best`](#sz_aes256_key_init_best) kernels.

```c
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_t

Signature of the [`sz_aes256_gcm_key_init_best`](#sz_aes256_gcm_key_init_best) kernels.

```c
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_t

Signature of the [`sz_aes256_ctr_xor_best`](#sz_aes256_ctr_xor_best) kernels.

```c
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_t

Signature of the [`sz_aes256_gcm_encrypt_best`](#sz_aes256_gcm_encrypt_best) kernels.

```c
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_t

Signature of the [`sz_aes256_gcm_decrypt_best`](#sz_aes256_gcm_decrypt_best) kernels.

```c
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_t

Signature of the [`sz_aes256_gcm_encryptor_init_best`](#sz_aes256_gcm_encryptor_init_best) kernels.

```c
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_t

Signature of the [`sz_aes256_gcm_encryptor_associate_best`](#sz_aes256_gcm_encryptor_associate_best) kernels.

```c
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_t

Signature of the [`sz_aes256_gcm_encryptor_update_best`](#sz_aes256_gcm_encryptor_update_best) kernels.

```c
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_t

Signature of the [`sz_aes256_gcm_encryptor_digest_best`](#sz_aes256_gcm_encryptor_digest_best) kernels.

```c
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_t

Signature of the [`sz_aes256_gcm_decryptor_init_best`](#sz_aes256_gcm_decryptor_init_best) kernels.

```c
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_t

Signature of the [`sz_aes256_gcm_decryptor_associate_best`](#sz_aes256_gcm_decryptor_associate_best) kernels.

```c
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_t

Signature of the [`sz_aes256_gcm_decryptor_update_unverified_best`](#sz_aes256_gcm_decryptor_update_unverified_best) kernels.

```c
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_t

Signature of the [`sz_aes256_gcm_decryptor_verify_best`](#sz_aes256_gcm_decryptor_verify_best) kernels.

```c
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);
```

## sz_bytesum_best

Computes the 64-bit check-sum of bytes in a string, similar to `std::ranges::accumulate`.

```c
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_bytesum` backends: serial, haswell, skylake, icelake, neon, sve, sve2, rvv, v128, v128relaxed, loongsonasx, powervsx

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

```
#include 
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;
}
```

- `text` (in): String to aggregate.
- `length` (in): Number of bytes in the text.
- `checksum` (out): The 64-bit unsigned sum.
- `capabilities` (in): One device's capabilities, like `sz_capabilities_enabled_cpu` reports.
- `stream` (in): Null 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_missing_kernel_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_kernel_k) No capability in `capabilities` has it.

## sz_hash_best

Computes the 64-bit unsigned hash of a string, similar to `std::hash` in C++.

```c
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_hash` backends: serial, westmere, skylake, icelake, neonaes, sve2aes, rvv, rvvcrypto, v128, v128relaxed, loongsonasx, powervsx

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 
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;
}
```

- `text` (in): String to hash.
- `length` (in): Number of bytes in the text.
- `seed` (in): 64-bit unsigned seed for the hash.
- `hash` (out): The 64-bit hash value.
- `capabilities` (in): One device's capabilities, like `sz_capabilities_enabled_cpu` reports.
- `stream` (in): Null 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: sz_hash_serial, sz_hash_westmere, sz_hash_skylake, sz_hash_icelake, sz_hash_neonaes, sz_hash_sve2aes, sz_hash_rvv, sz_hash_rvvcrypto, sz_hash_v128, sz_hash_v128relaxed, sz_hash_loongsonasx, sz_hash_powervsx

See also: [sz_hash_state_init_best](#sz_hash_state_init_best), [sz_hash_state_update_best](#sz_hash_state_update_best), [sz_hash_state_digest_best](#sz_hash_state_digest_best)

Statuses: - [`sz_missing_kernel_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_kernel_k) No capability in `capabilities` has it.

## sz_hash_strings_best

Hashes every one of `strings[order[i]]`, or of the first `count` strings, under one `seed`, each exactly as [`sz_hash_best`](#sz_hash_best) would, for group-by keys, joins and sharding.

```c
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);
```

- `sz_hash_strings` backends: serial, westmere, skylake, icelake, neonaes, rvvcrypto, v128, v128relaxed, loongsonasx, powervsx

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.

- `strings` (in): The strings to hash, in any layout.
- `order` (in): Indices into `strings`, possibly repeated, or null for the first `count`.
- `count` (in): Number of strings to hash.
- `seed` (in): The seed every string is hashed under.
- `hashes` (out): The `count` hashes, one per string.
- `capabilities` (in): One device's capabilities, like `sz_capabilities_enabled_cpu` reports.
- `stream` (in): Null on the CPU, or the GPU stream of that device to queue on.

Statuses: - [`sz_missing_kernel_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_kernel_k) No capability in `capabilities` has it.

## sz_hash_multiseed_best

Hashes one string under __many__ seeds at once, the "multi-seed" hash.

```c
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_multiseed` backends: serial, westmere, icelake, neonaes, rvvcrypto, v128, v128relaxed, powervsx

Equivalent to hashing with [`sz_hash_best`](#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`](#sz_hash_best) call:

```
#include 
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;
}
```

- `text` (in): String to hash.
- `length` (in): Number of bytes in the text.
- `seeds` (in): Array of `seeds_count` 64-bit seeds.
- `seeds_count` (in): Number of seeds, and the number of hashes written to `hashes`.
- `hashes` (out): Caller-allocated output buffer of `seeds_count` 64-bit hashes.
- `capabilities` (in): One device's capabilities, like `sz_capabilities_enabled_cpu` reports.
- `stream` (in): Null 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_missing_kernel_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_kernel_k) No capability in `capabilities` has it.

## sz_hash_state_init_best

Initializes the state for incremental construction of a hash.

```c
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_hash_state_init` backends: serial, westmere, skylake, icelake, neonaes, sve2aes, rvv, rvvcrypto, v128, v128relaxed, loongsonasx, powervsx

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

- `state` (out): The state to initialize.
- `seed` (in): The 64-bit unsigned seed for the hash.
- `capabilities` (in): One device's capabilities, like `sz_capabilities_enabled_cpu` reports.
- `stream` (in): Null on the CPU, or the GPU stream of that device to queue on.

Statuses: - [`sz_missing_kernel_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_kernel_k) No capability in `capabilities` has it.

## sz_hash_state_update_best

Updates the state with new data.

```c
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_hash_state_update` backends: serial, westmere, skylake, icelake, neonaes, sve2aes, rvv, rvvcrypto, v128, v128relaxed, loongsonasx, powervsx

- `state` (inout): The state to stream.
- `text` (in): The new data to include in the hash.
- `length` (in): The number of bytes in the new data.
- `capabilities` (in): One device's capabilities, like `sz_capabilities_enabled_cpu` reports.
- `stream` (in): Null on the CPU, or the GPU stream of that device to queue on.

Statuses: - [`sz_missing_kernel_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_kernel_k) No capability in `capabilities` has it.

## sz_hash_state_digest_best

Finalizes the immutable state into the hash.

```c
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_hash_state_digest` backends: serial, westmere, skylake, icelake, neonaes, sve2aes, rvv, rvvcrypto, v128, v128relaxed, loongsonasx, powervsx

- `state` (in): The state to fold.
- `hash` (out): The 64-bit hash value, as [`sz_hash_best`](#sz_hash_best) gives for the same bytes and seed.
- `capabilities` (in): One device's capabilities, like `sz_capabilities_enabled_cpu` reports.
- `stream` (in): Null on the CPU, or the GPU stream of that device to queue on.

Statuses: - [`sz_missing_kernel_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_kernel_k) No capability in `capabilities` has it.

## sz_sha256_state_init_best

Initializes the state for incremental SHA256 hashing.

```c
sz_status_t sz_sha256_state_init_best(
    sz_sha256_state_t *state,
    sz_capability_t capabilities,
    sz_stream_t stream);
```

- `sz_sha256_state_init` backends: serial, goldmont, neonsha, rvv, rvvcrypto, v128, loongsonasx, powervsx

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

- `state` (out): The state to initialize.
- `capabilities` (in): One device's capabilities, like `sz_capabilities_enabled_cpu` reports.
- `stream` (in): Null on the CPU, or the GPU stream of that device to queue on.

Statuses: - [`sz_missing_kernel_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_kernel_k) No capability in `capabilities` has it.

## sz_sha256_state_update_best

Updates the SHA256 state with new data.

```c
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_sha256_state_update` backends: serial, goldmont, neonsha, rvv, rvvcrypto, v128, loongsonasx, powervsx

- `state` (inout): The state to update.
- `text` (in): The new data to hash.
- `length` (in): The number of bytes in the new data.
- `capabilities` (in): One device's capabilities, like `sz_capabilities_enabled_cpu` reports.
- `stream` (in): Null on the CPU, or the GPU stream of that device to queue on.

Statuses: - [`sz_missing_kernel_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_kernel_k) No capability in `capabilities` has it.

## sz_sha256_state_digest_best

Finalizes the SHA256 state into the digest, leaving the state open to more data.

```c
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);
```

- `sz_sha256_state_digest` backends: serial, goldmont, neonsha, rvv, rvvcrypto, v128, loongsonasx, powervsx

- `state` (in): The state to finalize.
- `digest` (out): Output buffer for the 32-byte (256-bit) digest.
- `capabilities` (in): One device's capabilities, like `sz_capabilities_enabled_cpu` reports.
- `stream` (in): Null on the CPU, or the GPU stream of that device to queue on.

Statuses: - [`sz_missing_kernel_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_kernel_k) No capability in `capabilities` has it.

## sz_sha256_multistate_update_best

Advances many independent SHA256 states, one message per lane.

```c
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);
```

- `sz_sha256_multistate_update` backends: serial, goldmont, haswell, skylake, neonsha, rvvcrypto, cuda, rocm

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 
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`](https://www.unum.cloud/docs/stringzilla/c/sorting-and-sets.md#sz_sort_order_best) gives that ordering.

- `states` (inout): Array of at least `texts->count` states, each initialized with [`sz_sha256_state_init_best`](#sz_sha256_state_init_best).
- `texts` (in): Strings 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`](https://www.unum.cloud/docs/stringzilla/c/sorting-and-sets.md#sz_strings_to_tape_best) writes.
- `capabilities` (in): One device's capabilities, like `sz_capabilities_enabled_cpu` reports.
- `stream` (in): Null 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_missing_kernel_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_kernel_k) No capability in `capabilities` has it.

## sz_sha256_multistate_digest_best

Finalizes many independent SHA256 states, one digest per lane.

```c
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);
```

- `sz_sha256_multistate_digest` backends: serial, goldmont, haswell, skylake, neonsha, rvvcrypto, cuda, rocm

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

- `states` (in): Array of `states_count` states.
- `states_count` (in): Number of states to finalize, which is the lane count.
- `digests` (out): Output buffer of `states_count * STRINGZILLA_SHA256_DIGEST_LENGTH` bytes, one big-endian digest per lane, in lane order.
- `capabilities` (in): One device's capabilities, like `sz_capabilities_enabled_cpu` reports.
- `stream` (in): Null on the CPU, or the GPU stream of that device to queue on.

See also: [sz_sha256_state_digest_best](#sz_sha256_state_digest_best), [sz_sha256_multistate_update_best](#sz_sha256_multistate_update_best)

Statuses: - [`sz_missing_kernel_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_kernel_k) No capability in `capabilities` has it.

## sz_hash_find_kernel

Finds the hashing kernel of `kind`, from the best of `capabilities`.

```c
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);
```

- `kind` (in): The verb whose kernel to find.
- `capabilities` (in): The mask to pick the best capability from.
- `kernel` (out): The kernel, or null when none of `capabilities` has it.
- `capability` (out): The capability the kernel belongs to, or zero.

Statuses: - [`sz_missing_kernel_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_kernel_k)
- [`sz_missing_library_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_library_k) Header-only.

## sz_hash_state_equal

Compares the state of two running hashes.

```c
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_best

Expands a 32-byte secret into the AES-256 round-key schedule.

```c
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);
```

- `sz_aes256_key_init` backends: serial, westmere, icelake, neonaes, sve2aes, v128relaxed, v128, rvvcrypto, powervsx

Expanding an all-zero secret:

```
#include 
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;
}
```

- `key` (out): Receives the expanded schedule.
- `secret` (in): The 32 secret bytes.
- `capabilities` (in): One device's capabilities, like `sz_capabilities_enabled_cpu` reports.
- `stream` (in): Null 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_missing_kernel_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_kernel_k) No capability in `capabilities` has it.

## sz_aes256_ctr_xor_best

Exclusive-ors `length` bytes against the AES-256 counter-mode keystream.

```c
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);
```

- `sz_aes256_ctr_xor` backends: serial, westmere, icelake, neonaes, sve2aes, v128relaxed, v128, rvvcrypto, powervsx

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 
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;
}
```

- `key` (in): The expanded schedule.
- `nonce` (in): The 12 nonce bytes, which must never repeat under one key.
- `byte_offset` (in): Position of `text` within the stream, so a caller may start anywhere.
- `text` (in): The input bytes.
- `length` (in): Number of bytes to transform.
- `target` (out): Receives `length` bytes; may equal `text`, or must not overlap it at all.
- `capabilities` (in): One device's capabilities, like `sz_capabilities_enabled_cpu` reports.
- `stream` (in): Null 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_missing_kernel_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_kernel_k) No capability in `capabilities` has it.

## sz_aes256_gcm_key_init_best

Expands a 32-byte secret into a schedule and the Galois hash subkey powers.

```c
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);
```

- `sz_aes256_gcm_key_init` backends: serial, westmere, icelake, neonaes, sve2aes, v128relaxed, v128, rvvcrypto, powervsx

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.

- `key` (out): Receives the schedule and the powers.
- `secret` (in): The 32 secret bytes.
- `capabilities` (in): One device's capabilities, like `sz_capabilities_enabled_cpu` reports.
- `stream` (in): Null on the CPU, or the GPU stream of that device to queue on.

Statuses: - [`sz_missing_kernel_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_kernel_k) No capability in `capabilities` has it.

## sz_aes256_gcm_encrypt_best

Encrypts and authenticates a whole message in one call.

```c
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);
```

- `sz_aes256_gcm_encrypt` backends: serial, westmere, icelake, neonaes, sve2aes, v128relaxed, v128, rvvcrypto, powervsx

Sealing a short message and opening it again:

```
#include 
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;
}
```

- `key` (in): The expanded key.
- `nonce` (in): The 12 nonce bytes, which must never repeat under one key.
- `associated` (in): Authenticated, unencrypted bytes like a routing header, or [`STRINGZILLA_NULL`](https://www.unum.cloud/docs/stringzilla/c/types.md#STRINGZILLA_NULL).
- `associated_length` (in): Number of associated bytes, possibly zero.
- `text` (in): The plaintext.
- `length` (in): Number of plaintext bytes.
- `target` (out): Receives `length` ciphertext bytes, at `text` or not overlapping it at all.
- `tag` (out): Receives the 16-byte authentication tag.
- `capabilities` (in): One device's capabilities, like `sz_capabilities_enabled_cpu` reports.
- `stream` (in): Null 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_missing_kernel_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_kernel_k) No capability in `capabilities` has it.

## sz_aes256_gcm_decrypt_best

Verifies a tag and decrypts a whole message in one call.

```c
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);
```

- `sz_aes256_gcm_decrypt` backends: serial, westmere, icelake, neonaes, sve2aes, v128relaxed, v128, rvvcrypto, powervsx

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.

- `key` (in): The expanded key.
- `nonce` (in): The 12 nonce bytes used to encrypt.
- `associated` (in): Bytes authenticated but not encrypted, or [`STRINGZILLA_NULL`](https://www.unum.cloud/docs/stringzilla/c/types.md#STRINGZILLA_NULL).
- `associated_length` (in): Number of associated bytes, possibly zero.
- `text` (in): The ciphertext.
- `length` (in): Number of ciphertext bytes.
- `target` (out): Receives `length` plaintext bytes on success, and zeros on failure; may equal `text`, or must not overlap it at all.
- `tag` (in): The 16-byte tag to check.
- `capabilities` (in): One device's capabilities, like `sz_capabilities_enabled_cpu` reports.
- `stream` (in): Null 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_authentication_failed_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_authentication_failed_k) The tag did not match and `target` is zeroed.
- [`sz_missing_kernel_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_kernel_k) No capability in `capabilities` has it and nothing was written.

## sz_aes256_gcm_encryptor_init_best

Begins sealing a message delivered in chunks.

```c
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);
```

- `sz_aes256_gcm_encryptor_init` backends: serial, westmere, icelake, neonaes, sve2aes, v128relaxed, v128, rvvcrypto, powervsx

Sealing an eight-byte buffer in place:

```
#include 
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.

- `encryptor` (out): The encryptor to initialize.
- `key` (in): The expanded key, copied into `encryptor`.
- `nonce` (in): The 12 nonce bytes, which must never repeat under one key.
- `capabilities` (in): One device's capabilities, like `sz_capabilities_enabled_cpu` reports.
- `stream` (in): Null on the CPU, or the GPU stream of that device to queue on.

Statuses: - [`sz_missing_kernel_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_kernel_k) No capability in `capabilities` has it.

## sz_aes256_gcm_encryptor_associate_best

Absorbs associated data into a seal, authenticated but not encrypted.

```c
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);
```

- `sz_aes256_gcm_encryptor_associate` backends: serial, westmere, icelake, neonaes, sve2aes, v128relaxed, v128, rvvcrypto, powervsx

- `encryptor` (inout): The encryptor.
- `text` (in): The associated bytes.
- `length` (in): Number of associated bytes.
- `capabilities` (in): One device's capabilities, like `sz_capabilities_enabled_cpu` reports.
- `stream` (in): Null 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_missing_kernel_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_kernel_k) No capability in `capabilities` has it.

## sz_aes256_gcm_encryptor_update_best

Encrypts one chunk and absorbs its ciphertext into the running tag.

```c
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);
```

- `sz_aes256_gcm_encryptor_update` backends: serial, westmere, icelake, neonaes, sve2aes, v128relaxed, v128, rvvcrypto, powervsx

- `encryptor` (inout): The encryptor.
- `text` (in): The plaintext chunk.
- `length` (in): Number of bytes in the chunk.
- `target` (out): Receives `length` ciphertext bytes, at `text` or not overlapping it at all.
- `capabilities` (in): One device's capabilities, like `sz_capabilities_enabled_cpu` reports.
- `stream` (in): Null on the CPU, or the GPU stream of that device to queue on.

See also: sz_aes256_gcm_encryptor_update_serial

Statuses: - [`sz_missing_kernel_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_kernel_k) No capability in `capabilities` has it.

## sz_aes256_gcm_encryptor_digest_best

Finalizes a seal and emits its authentication tag.

```c
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);
```

- `sz_aes256_gcm_encryptor_digest` backends: serial, westmere, icelake, neonaes, sve2aes, v128relaxed, v128, rvvcrypto, powervsx

- `encryptor` (in): The encryptor, left unmodified so a caller may keep appending.
- `tag` (out): Receives the 16 tag bytes.
- `capabilities` (in): One device's capabilities, like `sz_capabilities_enabled_cpu` reports.
- `stream` (in): Null on the CPU, or the GPU stream of that device to queue on.

See also: sz_aes256_gcm_encryptor_digest_serial

Statuses: - [`sz_missing_kernel_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_kernel_k) No capability in `capabilities` has it.

## sz_aes256_gcm_decryptor_init_best

Begins opening a message delivered in chunks.

```c
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);
```

- `sz_aes256_gcm_decryptor_init` backends: serial, westmere, icelake, neonaes, sve2aes, v128relaxed, v128, rvvcrypto, powervsx

- `decryptor` (out): The decryptor to initialize.
- `key` (in): The expanded key, copied into `decryptor`.
- `nonce` (in): The 12 nonce bytes the message was sealed under.
- `capabilities` (in): One device's capabilities, like `sz_capabilities_enabled_cpu` reports.
- `stream` (in): Null on the CPU, or the GPU stream of that device to queue on.

See also: sz_aes256_gcm_decryptor_init_serial

Statuses: - [`sz_missing_kernel_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_kernel_k) No capability in `capabilities` has it.

## sz_aes256_gcm_decryptor_associate_best

Absorbs associated data into an open, authenticated but not encrypted.

```c
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);
```

- `sz_aes256_gcm_decryptor_associate` backends: serial, westmere, icelake, neonaes, sve2aes, v128relaxed, v128, rvvcrypto, powervsx

- `decryptor` (inout): The decryptor.
- `text` (in): The associated bytes.
- `length` (in): Number of associated bytes.
- `capabilities` (in): One device's capabilities, like `sz_capabilities_enabled_cpu` reports.
- `stream` (in): Null 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_missing_kernel_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_kernel_k) No capability in `capabilities` has it.

## sz_aes256_gcm_decryptor_update_unverified_best

Decrypts one chunk and absorbs its ciphertext into the running tag.

```c
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);
```

- `sz_aes256_gcm_decryptor_update_unverified` backends: serial, westmere, icelake, neonaes, sve2aes, v128relaxed, v128, rvvcrypto, powervsx

Nothing has verified that this ciphertext is genuine, and a caller that acts on the output before [`sz_aes256_gcm_decryptor_verify_best`](#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.

- `decryptor` (inout): The decryptor.
- `text` (in): The ciphertext chunk.
- `length` (in): Number of bytes in the chunk.
- `target` (out): Receives `length` plaintext bytes, at `text` or not overlapping it at all.
- `capabilities` (in): One device's capabilities, like `sz_capabilities_enabled_cpu` reports.
- `stream` (in): Null 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_missing_kernel_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_kernel_k) No capability in `capabilities` has it.

## sz_aes256_gcm_decryptor_verify_best

Finalizes an open and checks its authentication tag.

```c
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);
```

- `sz_aes256_gcm_decryptor_verify` backends: serial, westmere, icelake, neonaes, sve2aes, v128relaxed, v128, rvvcrypto, powervsx

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.

- `decryptor` (in): The decryptor, left unmodified.
- `tag` (in): The 16 tag bytes to check.
- `capabilities` (in): One device's capabilities, like `sz_capabilities_enabled_cpu` reports.
- `stream` (in): Null on the CPU, or the GPU stream of that device to queue on.

See also: sz_aes256_gcm_decryptor_verify_serial

Statuses: - [`sz_authentication_failed_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_authentication_failed_k) The tag did not match every byte the decryptor absorbed.
- [`sz_missing_kernel_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_kernel_k) No capability in `capabilities` has it.

## sz_cipher_find_kernel

Finds the cipher kernel of `kind`, from the best of `capabilities`.

```c
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);
```

- `kind` (in): The verb whose kernel to find.
- `capabilities` (in): The mask to pick the best capability from.
- `kernel` (out): The kernel, or null when none of `capabilities` has it.
- `capability` (out): The capability the kernel belongs to, or zero.

Statuses: - [`sz_missing_kernel_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_kernel_k)
- [`sz_missing_library_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_library_k) Header-only.

