# v1.0.0 — Stable Release

**Release date:** 2026-05-24
**Status:** **stable.** The 1.0 contract in
[`docs/STABILITY-1.0.md`](../STABILITY-1.0.md) takes effect at
this tag. Breaking changes from this point forward require a
2.0.

---

## What `crypt-io` is

A focused symmetric-crypto library for Rust. Algorithm-agile
AEAD encryption (ChaCha20-Poly1305, AES-256-GCM), hashing
(BLAKE3, SHA-256, SHA-512), MAC (HMAC-SHA256/512, BLAKE3
keyed), KDF (HKDF-SHA256/512, Argon2id), and streaming /
file encryption with a documented frame format.

No asymmetric crypto. No TLS. No PGP. No RNG surface. No key
storage. Those are different problems best solved by purpose-
built crates (`rustls`, `sequoia-openpgp`, `mod-rand`,
`key-vault`). `crypt-io` is the focused symmetric primitive
you compose with them.

---

## The 1.0 promise

What this tag commits to:

- **Frozen public surface.** Every item listed in
  [`docs/STABILITY-1.0.md`](../STABILITY-1.0.md) keeps its
  signature and behaviour for the lifetime of the 1.x series.
- **Frozen wire formats.** Single-shot AEAD output and the
  stream frame format (documented in
  [`docs/FILE_FORMAT.md`](../FILE_FORMAT.md)) are byte-stable
  for 1.x. A file encrypted by 1.0.0 decrypts cleanly with
  any 1.x.y.
- **Frozen MSRV** for the 1.x series. Rust 1.85 (edition
  2024). MSRV raises require a minor-version bump.
- **Additive-only minor releases.** New `Algorithm` /
  `Error` variants (both `#[non_exhaustive]`), new methods,
  new modules — never removals or renames.
- **No breaking changes without a 2.0** plus a documented
  migration guide. The 1.x line receives security patches
  for at least 12 months after any 2.0.

---

## What's in the box

### AEAD encryption — `crypt_io::aead`

```rust
use crypt_io::Crypt;

let key = [0u8; 32];
let crypt = Crypt::new();                     // ChaCha20-Poly1305 (default)
// let crypt = Crypt::aes_256_gcm();          // or AES-256-GCM
let ciphertext = crypt.encrypt(&key, b"hello world")?;
let recovered = crypt.decrypt(&key, &ciphertext)?;
# Ok::<(), crypt_io::Error>(())
```

Plus `encrypt_with_aad` / `decrypt_with_aad` for additional
authenticated data, and `_into` variants of all four for
zero-allocation hot loops (caller-supplied output buffer).
Fresh 96-bit nonce per call via OS CSPRNG — nonce reuse is
impossible through the public API.

### Hashing — `crypt_io::hash`

```rust
use crypt_io::hash;

let b3     = hash::blake3(b"data");           // [u8; 32]
let s256   = hash::sha256(b"data");           // [u8; 32]
let s512   = hash::sha512(b"data");           // [u8; 64]
let xof    = hash::blake3_long(b"data", 128); // Vec<u8>, 128 bytes
```

Streaming variants (`Blake3Hasher`, `Sha256Hasher`,
`Sha512Hasher`) for inputs that arrive in chunks. **Hash-only
by design** — no `with_key`. Keyed hashing lives in `mac` so
the "I used SHA-256 as a MAC" footgun can't happen.

### MAC — `crypt_io::mac`

```rust
use crypt_io::mac;

let tag = mac::hmac_sha256(b"key", b"message")?;
assert!(mac::hmac_sha256_verify(b"key", b"message", &tag)?);
# Ok::<(), crypt_io::Error>(())
```

Three MACs (HMAC-SHA256, HMAC-SHA512, BLAKE3 keyed) with the
same compute / verify / streaming triad. **Verification is
always constant-time** via upstream comparators. Module
documentation explicitly forbids `tag == expected` against
secret-equivalent values.

### KDF — `crypt_io::kdf`

```rust
use crypt_io::kdf;

// High-entropy input → derive subkeys.
let subkey = kdf::hkdf_sha256(&master, Some(b"salt"), b"app:v1", 32)?;

// Low-entropy input (password) → hash for storage.
let phc = kdf::argon2_hash(b"correct horse battery staple")?;
assert!(kdf::argon2_verify(&phc, b"correct horse battery staple")?);
# Ok::<(), crypt_io::Error>(())
```

Two algorithms for two different threat models — module docs
explicitly distinguish "HKDF for high-entropy input" from
"Argon2id for passwords" so callers don't reach for the wrong
one. Argon2id uses OWASP-recommended defaults; tuneable via
`Argon2Params` for higher-cost scenarios.

### Streaming / file encryption — `crypt_io::stream`

```rust
use crypt_io::Algorithm;
use crypt_io::stream;

let key = [0u8; 32];
stream::encrypt_file("input.bin", "output.enc", &key, Algorithm::ChaCha20Poly1305)?;
stream::decrypt_file("output.enc", "decrypted.bin", &key)?;
# Ok::<(), crypt_io::Error>(())
```

Chunked AEAD using the [STREAM construction](https://eprint.iacr.org/2015/189.pdf).
Defeats truncation, chunk reordering, and chunk duplication —
attacks single-shot AEAD doesn't address because it has no
concept of chunks. Full wire-format spec in
[`docs/FILE_FORMAT.md`](../FILE_FORMAT.md).

In-memory streaming via `StreamEncryptor` / `StreamDecryptor`
for the same API shape against network sockets, buffered I/O,
or anything else that isn't a file.

---

## Performance, measured

On AMD Ryzen 9 9950X3D + AVX-512 + SHA-NI (WSL2 Ubuntu, Rust
1.85). Full per-suite numbers + methodology + reproduction
instructions in [`docs/PERFORMANCE.md`](../PERFORMANCE.md).

| Operation @ 1 MiB / 64 KiB | Throughput |
|---|---:|
| `Crypt::encrypt_into` ChaCha20-Poly1305 | **1.45 GiB/s** / 1.51 GiB/s |
| `Crypt::encrypt_into` AES-256-GCM | **1.59 GiB/s** / 1.63 GiB/s |
| `StreamEncryptor::update_into` ChaCha20 | **1.40 GiB/s** |
| `StreamEncryptor::update_into` AES-256-GCM | **1.54 GiB/s** |
| `hash::blake3` 64 KiB | **11.24 GiB/s** |
| `hash::sha256` 64 KiB (SHA-NI) | 2.49 GiB/s |
| `mac::blake3_keyed` 64 KiB | **11.74 GiB/s** |
| `kdf::hkdf_sha256` 32-byte output | **304 ns** |
| `Crypt::encrypt_into` allocation count (steady-state) | **0** |

`crypt-io` is within measurement noise of upstream RustCrypto
for every algorithm — the `_into` API closes the per-call `Vec`
allocation that was the documented wrapping overhead in early
phases.

---

## Verification posture

| Layer | Count |
|---|---:|
| Unit tests | 126 |
| Integration tests (`tests/stream.rs`, `tests/into_apis.rs`) | 38 |
| Doctests (one per public item) | 33 |
| Spec-pinned KATs (RFC 8439 / NIST GCM / FIPS 180-4 / RFC 4231 / RFC 5869 / BLAKE3 official) | 17+ |
| `cargo-fuzz` targets | 8 |
| Smoke-fuzz iterations | 4.7 M (15 s × 8 targets, 0 findings) |
| Verification gate | `cargo fmt` + `cargo clippy --all-features -- -D warnings` + `cargo test --all-features` + `cargo doc --all-features` with `RUSTDOCFLAGS="-D warnings"`, on Linux + macOS + Windows × stable + MSRV |

---

## How `crypt-io` got here

Eleven focused pre-1.0 phases:

| Phase | Surface |
|---|---|
| 0.1 | Scaffold, REPS lint discipline, CI |
| 0.2 | AEAD foundation — ChaCha20-Poly1305 |
| 0.3 | AES-256-GCM + algorithm selection |
| 0.4 | Hashing — BLAKE3 (+ XOF), SHA-256, SHA-512 |
| 0.5 | MAC — HMAC-SHA256/512, BLAKE3 keyed |
| 0.6 | KDF — HKDF-SHA256/512, Argon2id |
| 0.7 | Stream / file encryption + STREAM construction |
| 0.8 | Performance verification (criterion benches + PERFORMANCE.md) |
| 0.9 | Fuzz testing (8 cargo-fuzz targets, 4.7 M iterations clean) |
| 0.10 | Allocation profile (mod-alloc) + zero-allocation `_into` paths (+38-55%) |
| 0.11 | 1.0 documentation set (STABILITY / ARCHITECTURE / SECURITY / PLATFORM-NOTES / FILE_FORMAT) |

Per-phase details in [`docs/release/`](.). The
[`CHANGELOG.md`](../../CHANGELOG.md) consolidates every
Added / Changed / Security entry across all eleven phases.

---

## Installation

```toml
[dependencies]
crypt-io = "1"
```

Or:

```bash
cargo add crypt-io
```

Defaults include both AEADs (ChaCha20-Poly1305 + AES-256-GCM),
both hash families (BLAKE3 + SHA-2), both MAC families, both
KDFs, and streaming. To slim the dep tree, set
`default-features = false` and pick what you need.

---

## Reading order if you're new

- **README** ([`README.md`](../../README.md)) — quick-start
  examples.
- **API reference** ([`docs/API.md`](../API.md)) — every public
  item with at least one example.
- **Stability contract** ([`docs/STABILITY-1.0.md`](../STABILITY-1.0.md))
  — what's frozen and what can change.
- **Security model** ([`docs/SECURITY.md`](../SECURITY.md)) —
  threat model, algorithm rationale, vulnerability reporting.
- **Architecture** ([`docs/ARCHITECTURE.md`](../ARCHITECTURE.md))
  — module layout, dispatch pattern, dependency rationale.
- **Platform notes** ([`docs/PLATFORM-NOTES.md`](../PLATFORM-NOTES.md))
  — hardware acceleration availability + cross-compile.
- **Performance** ([`docs/PERFORMANCE.md`](../PERFORMANCE.md)) —
  measured throughput on the reference machine.
- **Stream wire format** ([`docs/FILE_FORMAT.md`](../FILE_FORMAT.md))
  — normative spec, frozen for 1.x.

---

## Compatibility

- **MSRV:** Rust 1.85 (edition 2024). Frozen for 1.x.
- **OS:** Linux, macOS, Windows. CI matrix on stable + MSRV.
- **Architectures:** x86_64, aarch64. Cross-compile-friendly.
- **`no_std`:** the core surface (`aead`, `hash`, `mac`, `kdf`)
  works without `std` if you disable default features and skip
  `stream::encrypt_file` / `decrypt_file` (the file helpers
  need `std::fs`).
- **Wire format:** 1.x frozen. Files encrypted at 1.0.0
  decrypt cleanly with any 1.x.y.

---

## Acknowledgements

`crypt-io` is wrapper-only. The cryptographic primitives ship
via:

- **[RustCrypto](https://github.com/RustCrypto)** —
  `chacha20poly1305`, `aes-gcm`, `sha2`, `hmac`, `hkdf`,
  `argon2`, `password-hash`
- **[BLAKE3](https://github.com/BLAKE3-team/BLAKE3)** —
  the official `blake3` crate, including the keyed mode and
  AVX-512 / NEON SIMD paths

Portfolio dependencies:
- **[`mod-rand`](https://github.com/jamesgober/mod-rand)** —
  Tier 3 OS-backed CSPRNG (powers nonce + salt generation)
- **[`error-forge`](https://github.com/jamesgober/error-forge)** —
  declared dependency, minimally used in 1.0
- **[`mod-alloc`](https://github.com/jamesgober/mod-alloc)** —
  heap profiler used by `examples/profile_alloc.rs` (dev-only)

The [STREAM construction](https://eprint.iacr.org/2015/189.pdf)
in `crypt_io::stream` is from "Online Authenticated-Encryption
and its Nonce-Reuse Misuse-Resistance" by Hoang, Reyhanitabar,
Rogaway, and Vizár (2015).

---

## Reporting security issues

Email **security@hivedb.com** — see
[`docs/SECURITY.md`](../SECURITY.md) for the disclosure policy
and expected response timelines.

Please do not file security reports as public GitHub issues.

---

## What's next

`crypt-io` 1.0 is intended to be **quiet infrastructure**.
`cargo add crypt-io = "1"`, write your encrypt loop, never
think about it again.

Post-1.0 candidates (demand-driven, no commitment):

- **1.1.x:** XChaCha20-Poly1305 (longer nonce variant),
  AES-256-SIV (nonce-misuse-resistant), scrypt KDF, additional
  fuzz targets.
- **1.x:** async file helpers, TPM-backed key wrapping if a
  viable trait surface emerges.
- **2.0:** only if forced by an upstream RustCrypto major bump
  or a clearly-better algorithm replacement with spec backing.

Track in the [GitHub issues](https://github.com/jamesgober/crypt-io/issues)
or the [`.dev/ROADMAP.md`](../../.dev/ROADMAP.md).
