Every secure connection in the Rust ecosystem still bottoms out in C or hand-written assembly. Today that floor gets a Pure Rust one underneath it.
Today we’re releasing OxiCrypto 0.2.0 — the COOLJAPAN Pure Rust cryptographic primitives layer: hashes, MACs, AEADs, signatures, key exchange, KDFs, password hashing, CSPRNGs, and a post-quantum preview, all behind one clean trait surface.
No OpenSSL. No BoringSSL. No ring, no aws-lc-rs in the default closure. No FFI. No -sys crates. OxiCrypto is the foundation layer of the COOLJAPAN stack, and its non-negotiable goal is simple: a fresh rust:slim container running cargo build --no-default-features succeeds with zero apt-get install and no C toolchain.
Why OxiCrypto
For as long as Rust has shipped TLS, “Pure Rust” has been a polite fiction at the bottom of the stack. The popular crypto providers — ring, aws-lc-rs, openssl, mbedtls, boringssl — all wrap C or assembly. That means a system OpenSSL on the host, a C compiler at build time, *-sys crates in your dependency tree, and a build that breaks differently on every distribution and cross-compilation target. It also means the memory-safety story Rust promises stops exactly where the cryptography starts.
That trade-off is the worst place in the stack to make it. Cryptographic code is precisely the code you most want to be memory-safe, auditable, and reproducible — and precisely the code that has historically been written in C.
OxiCrypto exists to remove the native dependency from the floor of the ecosystem. It is the primitives layer that OxiTLS, OxiStore, OxiSQL, oxify, oxionnx (model signing), and oxirag (content addressing) build on, so the whole COOLJAPAN stack can be sovereign all the way down. This is the NoFFI initiative applied to its hardest, most security-critical target: replacing every C/assembly crypto backend with a clean, memory-safe, 100% Pure Rust implementation, default-on.
A note on what this is and isn’t: OxiCrypto is a careful integration and façade layer over the new-generation RustCrypto, dalek, and FIPS post-quantum crates, unified behind a single trait surface and a single version. The default feature set pulls zero *-sys crates. It is not a from-scratch reimplementation of every cipher, and it makes no formal-audit or FIPS-validation claims for the Pure Rust path — if you need FIPS-validated or HSM-backed primitives, those live behind explicit, feature-gated adapter crates that you opt into (see Tips).
What we built
OxiCrypto is a 14-crate workspace. Every category of primitive lives in its own focused crate, and a single oxicrypto façade re-exports all of them so applications depend on one name.
1. The trait surface (oxicrypto-core)
One coherent set of traits every algorithm implements: Hasher, Mac, Aead, Signer, Verifier, Kex, Kem, Kdf, PasswordHasher, and CryptoRng. Pick an algorithm by type or by runtime factory; the trait surface stays the same.
2. Hashing & XOFs (oxicrypto-hash)
SHA-2, SHA-3, BLAKE2b/s, and BLAKE3, plus the SP 800-185 family: SHAKE/cSHAKE/KMAC XOFs, ParallelHash, and TupleHash.
3. AEADs (oxicrypto-aead)
AES-GCM, ChaCha20-Poly1305, AES-GCM-SIV, XChaCha20-Poly1305, AES-CCM, OCB3, Deoxys-II, and HPKE (RFC 9180).
4. Raw ciphers (oxicrypto-cipher)
AES single-block ECB and the ChaCha20 keystream — the low-level pieces needed for things like QUIC header protection.
5. MACs (oxicrypto-mac)
HMAC-SHA-{256,384,512}, HMAC-SHA3-{256,512}, CMAC-AES, Poly1305, and KMAC128/256.
6. Signatures (oxicrypto-sig)
Ed25519, Ed448, ECDSA (P-256/384/521), BIP-340 Schnorr, RSA PKCS#1v15/PSS, and FROST threshold signatures (RFC 9591). The Ed448 path ships RFC 8032 §7.4 known-answer tests for Ed448ph and Ed448ctx.
7. Key exchange (oxicrypto-kex)
X25519, X448, and ECDH (P-256/384/521).
8. KDFs & password hashing (oxicrypto-kdf)
HKDF, PBKDF2, Argon2id, scrypt, Balloon, and KBKDF.
9. Randomness (oxicrypto-rand)
A ChaCha20 CSPRNG, a fork-safe reseeding RNG, and a thread-local RNG — including the OsRng source used throughout the examples.
10. Post-quantum preview (oxicrypto-pq)
ML-KEM (FIPS 203), ML-DSA (FIPS 204), SLH-DSA (FIPS 205), and hybrid KEMs (X-Wing and ML-KEM + P-384). Off by default behind the pq-preview feature.
The remaining crates round out the workspace: oxicrypto (the unified façade), oxicrypto-bench (Criterion benchmarks against ring and aws-lc-rs, dev-only), and the two bounded-FFI adapters, oxicrypto-adapter-aws-lc and oxicrypto-adapter-pkcs11.
Getting Started
Add the façade:
cargo add oxicrypto
[dependencies]
oxicrypto = "0.2.0"
# Post-quantum primitives (off by default):
oxicrypto = { version = "0.2.0", features = ["pq-preview"] }
Hashing — one-shot helpers for the common algorithms:
use oxicrypto::hash::{sha256, sha3_256, blake3};
let digest = sha256(b"hello world");
let digest = sha3_256(b"hello world");
let digest = blake3(b"hello world");
Authenticated encryption with AES-256-GCM, keys and nonces drawn from the OS RNG:
use oxicrypto::aead::{AesGcm256, CryptoRng};
use oxicrypto_rand::OsRng;
let key = AesGcm256::generate_key(&mut OsRng);
let nonce = AesGcm256::generate_nonce(&mut OsRng);
let ct = AesGcm256::encrypt(&key, &nonce, b"plaintext", b"aad")?;
let pt = AesGcm256::decrypt(&key, &nonce, &ct, b"aad")?;
Ed25519 signatures:
use oxicrypto::sig::{Ed25519, Signer, Verifier};
use oxicrypto_rand::OsRng;
let (sk, vk) = Ed25519::generate(&mut OsRng);
let sig = sk.sign(b"message")?;
vk.verify(b"message", &sig)?;
A post-quantum KEM round-trip with ML-KEM-768 (requires pq-preview):
use oxicrypto::pq::mlkem::{MlKem768, SharedKey};
use oxicrypto_rand::OsRng;
let (dk, ek) = MlKem768::generate(&mut OsRng);
let (ct, ss_sender) = ek.encapsulate(&mut OsRng);
let ss_receiver = dk.decapsulate(&ct)?;
assert_eq!(ss_sender.as_bytes(), ss_receiver.as_bytes());
The repository ships runnable examples for each category under crates/oxicrypto/examples/ — hash, encrypt, sign, kex, and pq_kem:
cargo run -p oxicrypto --example kex
cargo run -p oxicrypto --example pq_kem --features pq-preview
What’s inside
- Hashes & XOFs — SHA-2, SHA-3, BLAKE2b/s, BLAKE3, SHAKE/cSHAKE/KMAC, ParallelHash, TupleHash
- AEADs — AES-GCM, ChaCha20-Poly1305, AES-GCM-SIV, XChaCha20-Poly1305, AES-CCM, OCB3, Deoxys-II, HPKE (RFC 9180)
- MACs — HMAC (SHA-2 & SHA-3), CMAC-AES, Poly1305, KMAC128/256
- Signatures — Ed25519, Ed448, ECDSA P-256/384/521, BIP-340 Schnorr, RSA PKCS#1v15/PSS, FROST (RFC 9591)
- Key exchange — X25519, X448, ECDH P-256/384/521
- KDFs & passwords — HKDF, PBKDF2, Argon2id, scrypt, Balloon, KBKDF
- Randomness — ChaCha20 CSPRNG, fork-safe reseeding RNG, thread-local RNG,
OsRng - Post-quantum — ML-KEM (FIPS 203), ML-DSA (FIPS 204), SLH-DSA (FIPS 205), hybrid X-Wing & ML-KEM + P-384
- One trait surface —
Hasher,Mac,Aead,Signer,Verifier,Kex,Kem,Kdf,PasswordHasher,CryptoRng - Pure Rust by default — zero
*-syscrates in the default closure; builds onrust:slimwith no C toolchain
Tips
-
Verify the Pure Rust guarantee yourself. The default feature set pulls zero
*-syscrates. Confirm it on your own machine:cargo tree -p oxicrypto --edges normal 2>&1 | grep -E '\-sys' # Should print nothing -
Post-quantum is opt-in. ML-KEM, ML-DSA, SLH-DSA, and the hybrid KEMs sit behind the
pq-previewfeature so you only pay for them when you ask. Enable withfeatures = ["pq-preview"], and remember thepq_kemexample needs that flag too. -
Turn on runtime SIMD dispatch. The
simdfeature enables CPU feature detection (AES-NI, SHA-NI, AVX2) viacpufeatures, selecting accelerated paths at runtime where the hardware supports them. -
Never use a raw DH secret directly. As the
kexexample shows, run the X25519/X448/ECDH output through a KDF (HkdfSha256) before using it as a session key — bind it to application-specific salt and info. -
AEAD nonces must be unique per (key, message). AES-GCM uses 12-byte nonces; generate them with
generate_nonce(&mut OsRng)(or useOxiCrypto’s CSPRNG) rather than reusing a fixed value. If misuse-resistance matters, reach for AES-GCM-SIV or XChaCha20-Poly1305. -
FIPS and HSM backends are bounded FFI, opt-in, and not Pure Rust. As of 0.2.0 the
aws-lcandpkcs11backends are no longer part of theoxicryptofaçade. Applications that need FIPS-validated (aws-lc-rs) or HSM-backed (cryptoki) primitives add the adapter crates directly — these are the only edges where C/FFI (aws-lc-sys,cryptoki-sys) appears, and never in the default closure:# FIPS / aws-lc-rs backend (C/FFI, not Pure Rust) oxicrypto-adapter-aws-lc = { version = "0.2.0", features = ["aws-lc"] } # PKCS#11 HSM backend (C/FFI, not Pure Rust) oxicrypto-adapter-pkcs11 = { version = "0.2.0", features = ["pkcs11"] } -
MSRV is Rust 1.89 (edition 2021).
Part of the COOLJAPAN ecosystem
OxiCrypto is part of NoFFI — the COOLJAPAN initiative to replace every C/C++/Fortran/-sys FFI dependency in the Rust ecosystem with a clean, memory-safe, 100% Pure Rust implementation. Default features are Pure Rust, a single static binary, no system libraries, no build-time C toolchain, WASM-friendly.
It is the foundation layer the rest of the stack stands on. OxiCrypto depends on nothing; it is depended on by OxiTLS, OxiStore, OxiSQL, oxify, oxionnx, and oxirag. Around it sit sibling oxi* projects — OxiBLAS, OxiFFT, OxiARC, Oxicode — each removing another native dependency from the floor of the ecosystem.
Repository: https://github.com/cool-japan/oxicrypto
Star the repo 🔐 if you want a Rust ecosystem whose cryptography is finally Pure Rust all the way down.
Pure Rust cryptography — sovereign, safe, and FFI-free.
— KitaSan at COOLJAPAN OÜ June 22, 2026