dryoc: Don't Roll Your Own Crypto™1
dryoc is a general-purpose cryptography library written in pure Rust. It implements many of the same algorithms and wire formats as libsodium, so supported operations can interoperate with libsodium.
The Classic API closely follows libsodium's functions and types, which makes it useful when porting existing code. The Rustaceous API provides typed Rust interfaces that make key, nonce, and output sizes explicit. Both APIs use the same implementations and can be used together.
dryoc does not implement every libsodium feature. See Project status for current coverage.
See the API documentation and integration tests for examples.
- Pure Rust, with no hidden C libraries
- Limited use of unsafe code2
- Classic and typed Rustaceous APIs for many libsodium operations
- WebAssembly support through the
wasm32-unknown-unknowntarget - Protected memory on Unix and Windows, enabled by default with the
protectedfeature - Password-hash string helpers, enabled by default with the
base64feature - Optional Serde and wincode serialization
- Optimized AArch64 and x86-64 implementations; those that need optional CPU extensions are selected at runtime, and CPUs without them use portable code
- Optional portable SIMD
implementations on nightly Rust with
features = ["simd_backend", "nightly"] - Curve25519 and Ed25519 group arithmetic implemented in dryoc; curve25519-dalek provides scalar arithmetic modulo the group order
- Portable SHA-256, SHA-512, and SHA-3 implementations from the RustCrypto project
On the optimized workloads shown below, dryoc is faster than libsodium 1.0.18
on both x86-64 and AArch64. Each result compares the two libraries in the same
process, using the same buffers, one thread, and -Ctarget-cpu=native:
| Workload | Intel Xeon 6975P-C (AVX-512) | Arm Neoverse V3 (NEON/SVE2) |
|---|---|---|
| Poly1305, 1 MiB | 5.85x faster |
3.28x faster |
| Poly1305, 16 KiB | 5.59x faster |
3.14x faster |
| XSalsa20-Poly1305 secretbox, 1 MiB | 3.07x faster |
2.84x faster |
| XSalsa20-Poly1305 secretbox, 1 KiB | 3.16x faster |
2.04x faster |
| BLAKE2b, 694,200 B | 1.19x faster |
1.43x faster |
These results do not require -Ctarget-cpu=native: the optimized Poly1305
and Salsa20 implementations, and the x86-64 BLAKE2b implementation, are
selected automatically at runtime, while the AArch64 BLAKE2b rounds use only
baseline instructions. Omitting the flag changes the results above by no more
than 6%. Argon2id results vary more with the machine and build flags. See
BENCHMARKS.md for the full results, test environment, builds
without CPU-specific flags, and workloads where libsodium is as fast or faster.
dryoc uses the Rust 2024 edition and requires Rust 1.89 or newer, as declared
by rust-version in Cargo.toml.
The optional portable SIMD implementations require nightly Rust and
--features simd_backend,nightly. The simd_backend feature selects those
implementations, while nightly enables Rust's unstable portable_simd API.
Optimized AArch64 and x86-64 implementations are built in and do not require
the simd_backend feature. Implementations that need optional CPU extensions,
such as NEON, SVE2, the SHA-2 and SHA-3 instructions, AVX2, AVX-512, and BMI2,
are selected at runtime when the CPU supports them. The AArch64 asm!
implementations of the BLAKE2b rounds, the scalar ChaCha20 rounds, and
Curve25519 field multiplication use only baseline instructions and are always
used on that architecture. Curve25519 and Ed25519 group operations are also
unaffected by the simd_backend feature.
Enable serde to derive serde::Serialize
and serde::Deserialize
for supported data structures.
Enable wincode to implement wincode::SchemaWrite
and wincode::SchemaRead
for the VecBox aliases in dryocbox and dryocsecretbox, and for the
VecBox and VecEnvelope aliases in dryocaead.
dryoc has not undergone a third-party security audit. Its compatibility tests, Rust types, and limited use of unsafe code reduce some classes of defects, but do not guarantee that an application is secure. Applications must still follow the documented key and nonce rules, protect secret material, handle errors, and choose primitives appropriate for their protocol.
The following features are implemented. Entries that mirror libsodium have been checked against libsodium 1.0.22:
- Public-key authenticated encryption (
crypto_box_*) libsodium link - Secret-key authenticated encryption (
crypto_secretbox_*) libsodium link - Curve25519 scalar multiplication (
crypto_scalarmult*) libsodium link - Zeroing memory (
sodium_memzero) with zeroize libsodium link - Generating random data (
randombytes_buf) libsodium link - Encrypted streams (
crypto_secretstream_*) libsodium link - XChaCha20-Poly1305-IETF AEAD (
crypto_aead_xchacha20poly1305_ietf_*) libsodium link - ChaCha20-Poly1305-IETF AEAD (
crypto_aead_chacha20poly1305_ietf_*) libsodium link - Memory locking (
sodium_mlock,sodium_munlock,sodium_mprotect_*) libsodium link - Encrypting related messages (
sodium_increment) libsodium link - Generic hashing (
crypto_generichash_*) libsodium link - Secret-key authentication (
crypto_auth*) libsodium link - One-time authentication (
crypto_onetimeauth_*) libsodium link - Sealed boxes (
crypto_box_seal*) libsodium link - Key derivation (
crypto_kdf_*) libsodium link - Key exchange (
crypto_kx_*) libsodium link - Public-key signatures (
crypto_sign_*) libsodium link - Ed25519 to Curve25519 (
crypto_sign_ed25519_*) libsodium link - Signature secret-key extraction helpers (
crypto_sign_ed25519_sk_to_seed,crypto_sign_ed25519_sk_to_pk) libsodium link - SHA-2 hashing (
crypto_hash_sha256_*,crypto_hash_sha512_*) libsodium link - SHA-3 hashing (
crypto_hash_sha3256_*,crypto_hash_sha3512_*; dryoc extension) NIST FIPS 202 link - Short-input hashing (
crypto_shorthash) libsodium link - Password hashing (
crypto_pwhash_*) libsodium link - HKDF key derivation variants (
crypto_kdf_hkdf_sha256_*,crypto_kdf_hkdf_sha512_*) libsodium link - Direct HMAC authentication variants (
crypto_auth_hmacsha256_*,crypto_auth_hmacsha512_*,crypto_auth_hmacsha512256_*) libsodium link
The following libsodium features are incomplete, internal only, or not implemented. Other crates may provide equivalent functionality:
- AEAD constructions beyond the ChaCha20-Poly1305-IETF variants, including AEGIS-128L/256, AES256-GCM, and the legacy 64-bit-nonce ChaCha20-Poly1305 construction
- XChaCha20-Poly1305 box and secretbox variants (
crypto_box_curve25519xchacha20poly1305_*,crypto_secretbox_xchacha20poly1305_*) - Extendable-output functions (
crypto_xof_shake*,crypto_xof_turboshake*), added in libsodium 1.0.21 - Key encapsulation (
crypto_kem_*,crypto_kem_mlkem768_*,crypto_kem_xwing_*), added in libsodium 1.0.22 - Deterministic random data for reproducible tests (
randombytes_buf_deterministic) - Short-input hash variants beyond SipHash-2-4 with 64-bit output (
crypto_shorthash_siphashx24_*) - IP address encryption (
crypto_ipcrypt_*,sodium_ip2bin,sodium_bin2ip), added in libsodium 1.0.21 - Helpers, padding, and constant-time verify utilities (
sodium_*,crypto_verify_*) - Standalone stream cipher APIs (
crypto_stream_*; use the salsa20 or chacha20 crates directly instead) - Advanced features:
- Keccak-f[1600] core permutation (
crypto_core_keccak1600_*) - Scrypt (
crypto_pwhash_scryptsalsa208sha256_*; use the scrypt crate directly instead) - Finite field and group arithmetic (
crypto_core_ed25519_*,crypto_core_ristretto255_*; try the curve25519-dalek crate) - Ed25519 and Ristretto255 scalar multiplication variants (
crypto_scalarmult_ed25519_*,crypto_scalarmult_ristretto255_*)
- Keccak-f[1600] core permutation (
Footnotes
-
Not actually trademarked. ↩
-
Protected memory is available on Unix and Windows with the default
protectedfeature. It requires custom allocation, system calls, and pointer arithmetic, which are unsafe in Rust. Some optimized implementations also use small, carefully bounded unsafe blocks. The in-crate unsafe inventory includes fixed-size byte views, wincode schema implementations for vector-backed boxes and AEAD envelopes, BLAKE2b parameter byte views, protected memory guarded heap buffers and OS protection calls, 16-byte volatile zeroization of secret buffers, the x86-64 backends (runtime-detected AVX2, AVX-512 and AVX-512 IFMA entry points for ChaCha20, XSalsa20, Poly1305, the Argon2 block compression and the BLAKE2b compression,asm!scalar ChaCha20 and Salsa20 double rounds that run beside the AVX-512 lane sets, an AVX-512 Ed25519 basepoint table lookup, and BMI2-compiled copies of the Curve25519 scalar multiplication, inversion and square-root loops), and the AArch64 backends: runtime-detected NEON entry points for Poly1305, XSalsa20, ChaCha20, and the Ed25519 basepoint table lookup, register-only SVE2asm!blocks for the ChaCha20 and XSalsa20 rounds, scalarasm!blocks for the ChaCha20 and BLAKE2b rounds and the Curve25519 field products, and runtime-detectedsha2/sha3instructionasm!loops for the SHA-256 and SHA-512 compression functions. The rustdoc unsafe code summary lists every non-test use of unsafe code in this crate. ↩
