Skip to content

Repository files navigation

Docs Crates.io Build & test Codecov

💬 Join the Matrix chat

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.

Granny says no

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.

Features

  • 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-unknown target
  • Protected memory on Unix and Windows, enabled by default with the protected feature
  • Password-hash string helpers, enabled by default with the base64 feature
  • 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

Performance

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

dryoc speedup over libsodium by workload

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.

Rust version

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.

Optional serialization

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.

Security

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.

Project status

The following features are implemented. Entries that mirror libsodium have been checked against libsodium 1.0.22:

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_*)

Other NaCl-related Rust implementations

Footnotes

  1. Not actually trademarked.

  2. Protected memory is available on Unix and Windows with the default protected feature. 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 SVE2 asm! blocks for the ChaCha20 and XSalsa20 rounds, scalar asm! blocks for the ChaCha20 and BLAKE2b rounds and the Curve25519 field products, and runtime-detected sha2/sha3 instruction asm! 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.

About

Don't Roll Your Own Crypto: pure-Rust, hard to misuse cryptography library

Topics

Resources

Stars

344 stars

Watchers

3 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages