tape-sha256 0.2.1

Pure-Rust, hardware-accelerated SHA-256: multi-buffer batches and iterated hash chains
Documentation
  • Coverage
  • 85.71%
    12 out of 14 items documented3 out of 10 items with examples
  • Size
  • Source code size: 371.77 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 659.68 kB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 3s Average build duration of successful builds.
  • all releases: 3s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • Repository
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • zfedoran

tape-sha256

Crates.io Documentation License

Pure-Rust, hardware-accelerated SHA-256 for batch hashing and iterated hash chains.

tape-sha256 provides two kinds of hashing:

  • Batch hashing processes many independent messages in parallel, one per SIMD lane. This is useful for Merkle trees, data verification, and other workloads that hash many inputs at once.
  • Hash chains repeatedly hash a 32-byte digest, either as one serial chain or as many independent chains in parallel. This is useful for workloads such as Solana proof-of-history verification.

The crate automatically selects the best implementation available on the running CPU, with portable fallbacks for unsupported targets.

Installation

[dependencies]
tape-sha256 = "0.2"

Batch hashing

Use hash_many to hash a group of independent messages:

use tape_sha256::hash_many;

let messages: Vec<&[u8]> = vec![b"one", b"two", b"three"];
let mut digests = vec![[0u8; 32]; messages.len()];

hash_many(&messages, &mut digests);

When every message shares a prefix, hash_many_prefixed hashes prefix || body without allocating or copying the concatenated inputs:

use tape_sha256::hash_many_prefixed;

let leaves: Vec<&[u8]> = vec![&[1u8; 4096], &[2u8; 4096]];
let mut digests = vec![[0u8; 32]; leaves.len()];

hash_many_prefixed(b"LEAF", &leaves, &mut digests);

For Merkle-tree parent nodes, hash_pairs similarly hashes prefix || left || right without constructing temporary buffers.

Hash chains

Use hash_chain when each digest becomes the input to the next hash:

use tape_sha256::hash_chain;

let seed = [0u8; 32];
let end = hash_chain(&seed, 62_500);

When several chains are independent, hash_chains runs them in parallel:

use tape_sha256::hash_chains;

let seeds = [[1u8; 32], [2u8; 32]];
let lengths = [62_500, 62_500];
let mut ends = [[0u8; 32]; 2];

hash_chains(&seeds, &lengths, &mut ends);

Hardware acceleration

At runtime, tape-sha256 selects an implementation for the current platform, including AVX-512, AVX2, SHA-NI, ARM SHA-2, NEON, WebAssembly SIMD, and portable Rust backends.

The scalar, avx2, avx512, and neon Cargo features pin a backend at compile time. A pinned backend must be supported by every CPU that runs the binary; the default runtime selection is safer for general-purpose builds.

Use backend() and lane_width() to inspect the selected batch backend, or chain_backend() to inspect the single-chain backend.

Performance and correctness

See BENCHMARKS.md for measurements, hardware-specific analysis, and methodology. WebAssembly results are documented in benches/wasm/README.md.

Every available backend is tested against the independent sha2 crate across message lengths covering block and padding boundaries. Run the test suite with:

cargo test --release

License

Apache-2.0