Expand description
§dryoc: Don’t Roll Your Own Crypto™1
dryoc is a pure-Rust, general-purpose cryptography library. It implements many libsodium-compatible APIs and wire formats, so supported operations can interoperate with libsodium across languages.
Doing cryptography properly is hard. While no human is infallible, computers are pretty good at following instructions. Humans are bad at following instructions, but they do a decent job of giving instructions, provided they can effectively communicate intent. Thus, if the instructions humans give the computer are correct, we can be reasonably assured that the operations the computer does are correct too.
This library tries to make it easy to give the computer the correct instructions, and it does so by providing well-known implementations of general-purpose cryptography functions, in an API that’s relatively easy to use, type safe, and hard to use incorrectly.
As the name of this library implies, one should avoid trying to “roll their own crypto”, as it often results in avoidable mistakes. In the context of cryptography, mistakes can be very costly.
This crate uses the Rust 2024 edition. The minimum supported Rust version (MSRV) is Rust 1.89 or newer.
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 are
deprecated.
§Features
- 100% pure Rust, no hidden C libraries
- mostly free of unsafe code2
- 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) on stable Rust for Unix and Windows targets, enabled by default with theprotectedfeature - Password-hash string helpers enabled by default with the
base64feature - 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), except on AArch64 where dryoc keeps the soft backend because the portable-SIMD path is slower there
- 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
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.
Poly1305 is a special exception on AArch64: even with simd_backend and
nightly enabled, dryoc uses the soft Poly1305 backend because profiling
shows the portable-SIMD implementation is slower on that architecture.
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.
§APIs
This library includes both a Classic API, which is very similar to the original libsodium API, and Rustaceous API with Rust-specific features. Both APIs can be used together interchangeably, according to your preferences. The Rustaceous API is a wrapper around the underlying classic API.
It’s recommended that you use the Rustaceous API unless you have strong feelings about using the Classic API. The Classic API includes some pitfalls and traps that are also present in the original libsodium API, and unless you’re extra careful you could make mistakes. With the Rustaceous API, it’s harder to make mistakes thanks to strict type and safety features.
The Rustaceous API is, arguably, somewhat trickier to use, especially if you’re new to Rust. The Rustaceous API requires knowing and specifying the desired type in many cases. For your convenience, type aliases are provided for common types within each module. The Classic API only uses base types (fixed length byte arrays and byte slices).
| Feature | Rustaceous API | Classic API | Reference |
|---|---|---|---|
| Public-key authenticated boxes | DryocBox | crypto_box | Link |
| Secret-key authenticated boxes | DryocSecretBox | crypto_secretbox | Link |
| Authenticated encryption with additional data | DryocAead | crypto_aead_xchacha20poly1305_ietf | Link |
| Streaming encryption | DryocStream | crypto_secretstream_xchacha20poly1305 | Link |
| Generic hashing, HMAC | GenericHash | crypto_generichash | Link |
| SHA-3 hashing | Sha3256, Sha3512 | crypto_hash | Link |
| Secret-key authentication | Auth | crypto_auth | Link |
| Direct HMAC authentication | Hmac | crypto_auth_hmacsha256, crypto_auth_hmacsha512, crypto_auth_hmacsha512256 | Link |
| One-time authentication | OnetimeAuth | crypto_onetimeauth | Link |
| Key derivation | Kdf | crypto_kdf | Link |
| HKDF key derivation | Hkdf | crypto_kdf | Link |
| Key exchange | Session | crypto_kx | Link |
| Public-key signatures | SigningKeyPair | crypto_sign | Link |
| Password hashing | PwHash | crypto_pwhash | Link |
| Protected memory3 | protected | N/A | Link |
| Short-input hashing | N/A | crypto_shorthash | Link |
§Using Serde
This crate includes optional Serde support which can be
enabled with the serde feature flag. When enabled, the
Serialize and
Deserialize traits are provided for data
structures.
§Using wincode
This crate includes optional wincode
support which can be enabled with the wincode feature flag. When enabled,
wincode::SchemaWrite and wincode::SchemaRead are provided for
supported Rustaceous box types, including
DryocBox,
DryocSecretBox, and
AeadBox.
§Unsafe code
Non-test unsafe code is limited to these areas:
| Area | Feature gate | Why unsafe is required |
|---|---|---|
src/types.rs fixed-size byte views | Always available | Converts validated byte slices and vectors into [u8; N] references without copying. Each cast is guarded by a length check or an exact-size wrapper invariant. |
src/dryocbox.rs, src/dryocsecretbox.rs, and src/dryocaead.rs wincode impls | wincode | Implements unsafe wincode schema traits for the Rustaceous box wire formats. The implementations write and read initialized fields in the same order. |
src/blake2b/blake2b_soft.rs and src/blake2b/blake2b_simd.rs parameter blocks | Always available for the soft backend; simd_backend,nightly for SIMD | Views a repr(C, packed) BLAKE2b parameter block as bytes so the initialization vector is mixed exactly as specified. The parameter type contains only initialized byte fields. |
src/protected.rs protected memory | protected on Unix/Windows | Calls OS APIs such as mlock, mprotect, VirtualLock, and VirtualProtect, implements page-aligned guarded heap buffers, and exposes exact-size byte-array views over protected heap buffers. |
src/classic/salsa20_simd.rs Salsa20 SIMD backend | simd_backend,nightly | Performs little-endian unaligned in-place and buffer-to-buffer word XOR in 256-byte chunks, plus volatile zeroization of cached SIMD lanes containing derived key material. |
Test-only unsafe code is used for libsodium and Argon2 compatibility checks and protected-memory platform probes; it is not part of the runtime crate API.
§Security notes
This crate has not been audited by any 3rd parties. It uses well-known implementations of the underlying algorithms which have been previously verified as using constant-time operations.
With that out of the way, the deterministic nature of cryptography and extensive testing used in this crate means it’s relatively safe to use, provided the underlying algorithms remain safe. Arguably, this crate is incredibly safe (as far as cryptography libraries go) thanks to the features provided by the API of this crate, and those provided by the Rust language itself.
§Acknowledgements
Big ups to the authors and contributors of NaCl and libsodium for paving the way toward better cryptography libraries.
Not actually trademarked. ↩
The protected memory features described in the protected mod are available on Unix and Windows targets with the default
protectedfeature. Unsupported targets do not expose the protected-memory API. These features 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 unsafe code section above for the non-test unsafe inventory in this crate. ↩Available on Unix and Windows targets with the
protectedfeature flag enabled. Theprotectedfeature is enabled by default. ↩The Rustaceous API is designed to protect users of this library from making mistakes, however the Classic API allows one to do as one pleases. ↩
Modules§
- auth
- Secret-key message authentication
- classic
- Classic API
- constants
- Constant value definitions
- dryocaead
- Authenticated encryption with additional data
- dryocbox
- Public-key authenticated encryption
- dryocsecretbox
- Secret-key authenticated encryption
- dryocstream
- Encrypted streams
- generichash
- Generic hashing
- hkdf
- HKDF key derivation
- hmac
- HMAC authentication
- kdf
- Key derivation functions
- keypair
- Public/secret keypair tools
- kx
- Key exchange functions
- onetimeauth
- One-time authentication
- precalc
- Precalculated secret key for use with
precalc_*functions incrate::dryocbox::DryocBox - protected
protected - Memory protection utilities
- pwhash
- Password hashing functions
- rng
- Random number generation utilities
- sha3
- SHA-3 hash algorithms
- sha256
- SHA-256 hash algorithm
- sha512
- SHA-512 hash algorithm
- sign
- Public-key signatures
- types
- Base type definitions
- utils
- Various utility functions
Enums§
- Error
- Errors generated by Dryoc.