libsoliton/README.md
Kamal Tufekcic 793b00ff4b
Some checks failed
CI / lint (push) Successful in 1m37s
CI / test-python (push) Successful in 1m45s
CI / test-zig (push) Successful in 1m37s
CI / test-wasm (push) Successful in 1m52s
CI / test (push) Successful in 13m50s
CI / miri (push) Successful in 13m48s
CI / build (push) Successful in 1m10s
CI / fuzz-regression (push) Successful in 9m16s
CI / publish (push) Failing after 55s
CI / publish-python (push) Failing after 1m40s
CI / publish-wasm (push) Failing after 1m49s
Add paper, more minor doc updates
Signed-off-by: Kamal Tufekcic <kamal@lo.sh>
2026-04-23 08:03:02 +03:00

158 lines
9.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# libsoliton
Pure-Rust post-quantum cryptographic library. Provides composite identity keys (X-Wing + ML-DSA-65), hybrid signatures, KEM-based authentication, asynchronous key exchange, double-ratchet message encryption, and encrypted storage — all without a C toolchain.
**Use cases:** any application requiring two-party encrypted communication or authenticated key agreement — messaging, voice/video calls, peer-to-peer sessions, file transfer, encrypted storage, zero-knowledge authentication, password-protected key vaults. The library provides the complete primitive stack; the application layer decides the transport and session management.
## Documentation
| Document | Description |
|----------|-------------|
| [paper.tex](paper.tex) | Protocol paper — design, security analysis, formal verification, implementation |
| [Abstract.md](Abstract.md) | Security analysis specification — adversary model, theorems, and verification targets for formal modeling |
| [Specification.md](Specification.md) | Full cryptographic specification (v1) |
| [CHEATSHEET.md](CHEATSHEET.md) | API quick reference with types, sizes, and signatures |
| [tamarin/README.md](tamarin/README.md) | Symbolic formal verification — 8 Tamarin models, 55 lemmas (Theorems 113) |
| [cryptoverif/README.md](cryptoverif/README.md) | Computational formal verification — 5 CryptoVerif models with concrete security bounds |
## Crate Layout
| Package | Path | Purpose |
|---------|------|---------|
| `libsoliton` (crates.io) | `soliton/` | Core library — all cryptographic logic |
| `libsoliton_capi` (crates.io) | `soliton_capi/` | C ABI FFI layer (cbindgen-generated header) |
| `soliton-py` (PyPI) | `soliton_py/` | Python binding (PyO3/maturin, wraps core Rust API) |
| `soliton-wasm` (npm) | `soliton_wasm/` | WASM binding (wasm-bindgen, wraps core Rust API) |
| `soliton-cli` (cargo) | `soliton_cli/` | Native CLI (`cargo install soliton-cli`) |
| `soliton_zig` | `soliton_zig/` | Zig wrapper (consumes CAPI via `@cImport`) |
## Testing
**By location** (non-overlapping — these add up to the total):
| Location | Count | Description |
|----------|-------|-------------|
| Core unit tests | 488 | `soliton/src/**/` `#[cfg(test)]` — unit tests + proptests |
| Core integration tests | 61 | `soliton/tests/` — KEX → ratchet, storage round-trips, argon2, zeroization verification, Appendix F vectors |
| CAPI tests | 287 | `soliton_capi/tests/` — null pointers, invalid lengths, round-trips, error codes |
| Python tests | 49 | `soliton_py/tests/` — full KEX → ratchet round-trip, serialize, reset, call keys, storage, streaming (_at), auth, identity, primitives |
| Zig tests | 35 | `soliton_zig/src/soliton.zig` — full KEX → ratchet round-trip, serialize, reset, call keys, storage, streaming (_at), auth, AEAD, X-Wing, argon2id |
| WASM tests | 36 | `soliton_wasm/tests/` — full KEX → ratchet lifecycle, serialize/deserialize, call keys, storage, streaming (_at), auth, identity, primitives, argon2id (Node + Chromium) |
| Fuzz targets | 36 | `*/fuzz/fuzz_targets/` — 29 core + 7 CAPI (`cargo-fuzz` / libFuzzer) |
**Cross-cutting** (subsets of the above):
| Property | Count | Subset of | Description |
|----------|-------|-----------|-------------|
| MIRI-eligible | 455 | core + CAPI | PQ-free subset safe for instruction-level interpretation (`--profile miri`) |
| KAT vectors | 27 | core unit + integration | 17 in `src/**/` `#[cfg(test)]` — SHA3-256, HMAC-SHA3-256, HKDF-SHA3-256, Ed25519, X25519, X-Wing, AEAD, KDF, KEX, streaming, call; 10 in `tests/compute_vectors.rs` — Specification.md Appendix F vectors F.25-F.37 (HKDF, AEAD, HybridSign, streaming, Argon2, HMAC long-key, first-message AAD, SPK sig, session-init sig, LO-Auth) |
```bash
# Full test suite
cargo test -p libsoliton -p libsoliton_capi
# MIRI (requires nightly)
MIRIFLAGS="-Zmiri-disable-isolation" cargo +nightly miri nextest run \
-p libsoliton -p libsoliton_capi --profile miri -j$(nproc)
# Fuzzing — corpus regression (replays all seeds, no mutations, fast)
./ci_regression.sh
# Fuzzing — overnight campaign (all active targets in parallel)
./fuzz_overnight.sh 24 2 # 24 hours, 2 workers per target
./fuzz_stats.sh # Post-run summary
```
## Fuzzing
36 fuzz targets (29 core + 7 CAPI) with two corpora (core: `soliton/fuzz/corpus/`, CAPI: `soliton_capi/fuzz/corpus/`) totaling 165,540 entries (883 MB). All corpora are checked in via Git LFS; `ci_regression.sh` replays every seed with zero mutations as a CI regression gate.
**Excluded targets** — 5 of 36 are excluded from overnight campaigns after saturation analysis. All reachable edges were discovered; additional CPU time yields no new coverage. These targets retain their corpora and run in `ci_regression.sh`.
| Target | Corpus | Edges | Reason |
|---|---|---|---|
| `fuzz_identity_from_bytes` | 84 | 107 | 3 length checks only |
| `fuzz_auth_verify` | ~15 | 88 | Single `ct_eq` call |
| `fuzz_xwing_roundtrip` | 7 | 763 | No adversarial input (keygen→encap→decap) |
| `fuzz_verification_phrase` | 29 | 88 | SHA3→wordlist index, trivial surface |
| `fuzz_auth_respond` | 4 | 1573 | Single KEM decap→HMAC, no branching on input |
**Latest campaign** — 31 targets (24 core + 7 CAPI), 1 libFuzzer worker per target, Hetzner CCX53 (32 vCPUs, AMD EPYC, 128 GB RAM), 24 hours.
| Metric | Value |
|---|---|
| **Total targets** | 36 (29 core + 7 CAPI) |
| **Active in campaign** | 31 |
| **Total executions** | 574.6 billion |
| **Corpus** | 165,540 entries (883 MB) |
| **Crashes / Timeouts / OOM** | **0 / 0 / 0** |
The state-machine fuzzer (`fuzz_ratchet_state_machine`) performs full cryptographic sessions with up to 200 protocol actions per execution (KEM, AEAD, HKDF, HMAC per message) — 12,714 coverage features, the highest of any target.
```bash
./ci_regression.sh # Replay all seeds — fast, runs in CI
./fuzz_overnight.sh 24 1 # 31 active targets, 24 hours, 1 worker each
./fuzz_stats.sh # Per-target breakdown (edges, features, throughput, RSS)
```
## Benchmarks
Measured with `cargo +nightly bench` across three platforms. ML-DSA-65, SHA3-256, and Keccak do not have SIMD implementations in the current RustCrypto crates — expect these numbers to improve as upstream adds platform-specific optimizations. All operations are pure ARX or field arithmetic; no hardware acceleration is required.
**Platform support:** Tested on x86-64, aarch64, riscv64gc, and wasm32. 32-bit native platforms are untested and unsupported — the library uses `u64` extensively and the PQ primitives have non-trivial stack requirements.
| Platform | CPU | Arch | Clock |
|----------|-----|------|-------|
| **Desktop** | AMD Ryzen 7 7840HS | x86-64 (Zen 4) | ~5.1 GHz boost |
| **RPi 5** | Cortex-A76 | aarch64 | 2.4 GHz |
| **VisionFive 2** | SiFive U74 | riscv64gc | 1.5 GHz |
**Per-message hot paths** (what users feel on every send/receive):
| Operation | Desktop | RPi 5 | VisionFive 2 | Notes |
|-----------|---------|-------|-------------|-------|
| Ratchet encrypt (same epoch) | 4.3 µs | 7.2 µs | 47.6 µs | HMAC-SHA3-256 + XChaCha20-Poly1305 |
| Ratchet decrypt (same epoch) | 6.2 µs | 10.1 µs | 67.5 µs | Includes `from_bytes` deserialization |
| KDF root (isolated) | 5.7 µs | 9.2 µs | 59.5 µs | HKDF-SHA3-256, 64-byte output |
| Ratchet serialize | 1.6 µs | 6.1 µs | 38.1 µs | `to_bytes` |
| Ratchet deserialize | 0.7 µs | 2.7 µs | 17.8 µs | `from_bytes_with_min_epoch` |
**Direction-change paths** (one KEM round-trip per direction switch):
| Operation | Desktop | RPi 5 | VisionFive 2 | Notes |
|-----------|---------|-------|-------------|-------|
| Ratchet encrypt (direction change) | 182 µs | 651 µs | 2.46 ms | X-Wing keygen + encapsulate + KDF |
| Ratchet decrypt (direction change) | 127 µs | 473 µs | 1.76 ms | X-Wing decapsulate + KDF |
**Session establishment** (one-time per conversation):
| Operation | Desktop | RPi 5 | VisionFive 2 | Notes |
|-----------|---------|-------|-------------|-------|
| Identity keygen | 417 µs | 1.05 ms | 4.90 ms | X-Wing + Ed25519 + ML-DSA-65 |
| Hybrid sign | 988 µs | 2.85 ms | 10.6 ms | Ed25519 + ML-DSA-65 (no SIMD) |
| Hybrid verify | 254 µs | 794 µs | 3.31 ms | Ed25519 + ML-DSA-65 (no SIMD) |
| X-Wing encapsulate | 104 µs | 417 µs | 1.44 ms | X25519 + ML-KEM-768 |
| X-Wing decapsulate | 112 µs | 451 µs | 1.61 ms | X25519 + ML-KEM-768 |
| Initiate session (Alice) | 1.41 ms | 3.95 ms | 17.1 ms | Ephemeral keygen + 3 encaps + HKDF + sign |
| Receive session (Bob) | 585 µs | 1.88 ms | 7.70 ms | Verify + 3 decaps + HKDF |
**Streaming AEAD** (file/media encryption):
| Operation | Desktop | RPi 5 | VisionFive 2 | Notes |
|-----------|---------|-------|-------------|-------|
| Encrypt 1 MiB | 537 µs (1.95 GB/s) | 3.96 ms (265 MB/s) | 31.0 ms (33.8 MB/s) | XChaCha20-Poly1305, single chunk |
| Decrypt 1 MiB | 749 µs (1.40 GB/s) | 4.74 ms (221 MB/s) | 34.9 ms (30.0 MB/s) | Includes init overhead |
| Encrypt 4 MiB sequential | 2.58 ms (1.55 GB/s) | 15.8 ms (253 MB/s) | 124 ms (32.3 MB/s) | 4 chunks, sequential API |
| Encrypt 4 MiB parallel | 867 µs (4.61 GB/s) | 5.35 ms (748 MB/s) | 33.0 ms (121 MB/s) | 4 chunks via `encrypt_chunk_at`, rayon (4 cores) |
| Encrypt 8 MiB parallel | 1.29 ms (6.21 GB/s) | 10.7 ms (748 MB/s) | 67.8 ms (118 MB/s) | 8 chunks, 2 rounds on 4 cores |
**Password KDF** (key vault protection):
| Operation | Desktop | RPi 5 | VisionFive 2 | Notes |
|-----------|---------|-------|-------------|-------|
| Argon2id OWASP minimum | 10.9 ms | 42.0 ms | 256 ms | 19 MiB, 2 passes, 1 lane |
| Argon2id recommended | 65.0 ms | 227 ms | 1.35 s | 64 MiB, 3 passes, 4 lanes |
## License
[AGPL-3.0-only](LICENSE.md)