dryoc: Don't Roll Your Own Crypto™[^1]
dryoc is a pure-Rust, general-purpose cryptography library that's hard to misuse. It's based on the excellent libsodium library, but in pure Rust. It also includes protected memory features throughout, which makes it dead simple to build secure, robust, and safe cryptographic software. The original goal of this library was to provide a pure-Rust alternative to libsodium.

The purpose of this project is to provide a pure-Rust, mostly drop-in replacement for libsodium. This library has nearly the same ergonomics as libsodium (referred to in dryoc as the Classic API), such that people familiar with libsodium can use this library nearly interchangeably. While the API is not 100% identical to libsodium, most functions have the same or very similar signatures.
In addition to the Classic API, there's a Rustaceous API which aims to bring an idiomatic Rust implementation of libsodium's core features: public and secret key authenticated cryptography and general-purpose cryptography tools.
Not all features from libsodium are implemented here, either because there exist better implementations in other crates, or because they aren't necessary as part of this crate.
Additionally, this crate provides exceptionally safe cryptography thanks to Rust's safety features. The Rustaceous API is designed designed to make it difficult to shoot yourself in the foot. It's worth noting, however, you certainly can still shoot yourself if you choose (either by leaking private data, using insecure hardware, OPSEC issues, etc).
For example usage, refer to the official docs or the integration tests.
Features
- 100% pure Rust, no hidden C libraries
- mostly free of unsafe code[^2]
- Hard to misuse, helping you avoid common costly cryptography mistakes
- Many libsodium features implemented with both Classic and Rustaceous API
- Protected memory handling (
mprotect()+mlock(), along with Windows equivalents) - Serde support (with
features = ["serde"]) - wincode support for direct binary serialization of Rustaceous box types (with
features = ["wincode"]) - Portable SIMD implementations on nightly, with
features = ["simd_backend", "nightly"]:- Blake2b (used by generic hashing, password hashing, and key derivation)
- Argon2 block mixing (used by password hashing)
- Salsa20 (used by XSalsa20-Poly1305 secretbox)
- Poly1305 (used by one-time authentication and secret boxes)
- curve25519-dalek (used by public/private key functions) selects its own serial or x86_64 vector backend at build time
- SHA2 (used by sealed boxes) includes SIMD implementation for AVX2
- ChaCha20 (used by streaming interface) includes SIMD implementations for NEON, AVX2, and SSE2
Rust version
dryoc uses the Rust 2024 edition and requires Rust 1.89 or newer, as declared
by rust-version in Cargo.toml.
Rust 2024 reserves gen as a keyword. Prefer generation APIs such as
Key::generate(). Existing gen APIs remain available through raw identifier
syntax, such as Key::r#gen(), for compatibility and will be deprecated in a
future release.
The simd_backend and nightly features enable dryoc's portable SIMD
backends. CPU-specific dependency backends and local benchmarking may also
benefit from target-specific RUSTFLAGS:
- For AVX2 set
RUSTFLAGS=-Ctarget-cpu=haswell -Ctarget-feature=+avx2 - For SSE2 set
RUSTFLAGS=-Ctarget-feature=+sse2 - For NEON set
RUSTFLAGS=-Ctarget-feature=+neon - For local Apple Silicon benchmarks, use
RUSTFLAGS=-Ctarget-cpu=native. NEON is part of the AArch64 macOS baseline target, so adding-Ctarget-feature=+neonis not expected to change native results.
The Curve25519 backend is selected by curve25519-dalek, not by dryoc's
simd_backend feature.
Note that eventually this project will converge on portable SIMD implementations for all the core algos which will work across all platforms supported by LLVM, rather than relying on hand-coded assembly or intrinsics, but this is a work in progress.
See BENCHMARKS.md for side-by-side software and SIMD benchmark results.
Optional serialization
Enable serde to derive serde::Serialize
and serde::Deserialize
for supported data structures.
Enable wincode to derive wincode::SchemaWrite
and wincode::SchemaRead
for supported Rustaceous box types, including DryocBox and
DryocSecretBox.
Project status
The following libsodium features are currently implemented, or awaiting implementation:
- Public-key cryptography (
crypto_box_*) libsodium link - Secret-key cryptography (
crypto_secretbox_*) libsodium link - Point*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 - 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 - Short-input hashing (
crypto_shorthash) libsodium link - Password hashing (
crypto_pwhash_*) libsodium link
The following libsodium features are either incomplete, not exposed as public APIs, or not implemented; you may find equivalent functionality in other crates:
- Standalone stream cipher APIs (use the salsa20 crate directly instead)
- Helpers and padding utilities
- Advanced features:
- Scrypt (use scrypt crate directly instead)
- Finite field arithmetic (try the curve25519-dalek crate)
Stargazers over time
Other NaCl-related Rust implementations worth mentioning
[^1]: Not actually trademarked.
[^2]: The protected memory features described in the [protected] mod require custom memory allocation, system calls, and pointer arithmetic, which are unsafe in Rust. Some optional SIMD code, including dependency-provided SIMD implementations and small internal helpers, may contain unsafe code. In particular, many SIMD implementations are considered "unsafe" due to their use of assembly or intrinsics, however without SIMD-based cryptography you may be exposed to timing attacks. See the rustdoc unsafe code summary for the non-test unsafe inventory in this crate.