Skip to content

dryoc v2.0.0

Latest

Choose a tag to compare

@github-actions github-actions released this 28 Sep 12:29
· 3 commits to main since this release
Immutable release. Only release title and notes can be modified.
e419986

dryoc v2.0.0

dryoc 2.0 is a backward-incompatible major release. It adds post-quantum key encapsulation (ML-KEM-768, X-Wing) and post-quantum sealed boxes, Python bindings on PyPI, no_std support with std/alloc features, in-crate cryptographic primitives with runtime-detected SIMD backends (plus WebAssembly simd128 kernels), and a more consistent Rust API. serde is now enabled by default.

The wire formats did not change: boxes, AEAD envelopes, signed messages, secret streams, password-hash strings, and serde and wincode encodings written by 1.x read the same in 2.0, and 2.0 writes the same bytes. The minimum supported Rust version is still 1.89.

Full Changelog: v1.0.0...v2.0.0

Upgrading: nearly every breaking change is a compile error. Bump the version, build, and look each error up in UPGRADING.md. A short list of changes that still compile is repeated below.

Breaking Changes

Cargo features

  • serde is now a default feature; remove it from features.
  • wincode is renamed to wincode_0_6 and moves to wincode 0.6. The encoded bytes are unchanged.
  • u64_backend is removed; it did nothing.
  • The crate is #![no_std] with new std (default, implies alloc) and alloc features. default-features = false now builds without allocation; add std (or alloc on targets without std) to keep 1.x behavior. Without alloc, Vec* types, *_to_vec/*_to_vecbox, randombytes_buf, pwhash and classic::crypto_pwhash are unavailable. Error::Io needs std. Without std, SIMD kernels are selected at compile time from target features instead of detected at runtime, and bare-metal targets need a custom getrandom backend.
  • nightly no longer enables protected; add it explicitly when needed.

API cleanup

  • gen/r#gen names are removed (generate); *_with_defaults constructors are replaced by Stack* type aliases with generate(). KeyPair::new(), SigningKeyPair::new(), their Default impls and new_locked_keypair() (all-zero secret keys) are removed.
  • ByteArray<N>/MutByteArray<N> (and NewByteArray) are no longer implemented for &[u8], [u8] or Vec<u8>; convert runtime-length bytes with TryFrom and handle Error::InvalidLength.
  • DryocBox::unseal/unseal_to_vec become open/open_to_vec; DryocBox::from_parts/into_parts switch to wire order (epk, tag, data); redundant new_with_*/with_* box constructors are replaced by from_parts/from_bytes; AeadEnvelope::seal_to_vec becomes seal_to_vecbox; SigningKeyPair::sign returns SignedMessage infallibly; IncrementalSigner is renamed Ed25519phSigner with infallible finalize; Hmac/Auth/OnetimeAuth borrow the key; secret-stream Tag becomes a #[non_exhaustive] enum (Message/Push/Rekey/Final, try_from, &[u8] associated data, pull::<Out, _> order); KX moves to kx::StackSession::new_client/new_server; HKDF extract/expand argument order changes; GenericHash/PwHash default constructors are replaced by DefaultGenericHash/VecPwHash/Config::interactive(); output-first generic parameter order everywhere (Auth::compute::<Mac, _, _>, Sha256::compute::<Out, _>, push::<Out, _>, ...); several traits are now sealed (HmacVariant, HkdfVariant, Mode, ProtectMode, LockMode).
  • Classic crypto_secretbox_open_detached, crypto_box_open_detached and crypto_box_open_detached_afternm take ciphertext before MAC, like libsodium.
  • Algorithm modules no longer re-export dryoc::types; import dryoc::types::* where glob imports previously supplied the traits.

Changes that still compile

Check by hand; the compiler will not flag these. See UPGRADING.md for details.

  • Detached open with a 16-byte ciphertext: an old-order call compiles but fails authentication at runtime.
  • crypto_generichash/GenericHash accept libsodium's full ranges (1-64 byte output, 0-64 byte key); Some(&[]) now means no key.
  • Protected-memory deserialization returns an error on allocation/locking failure instead of panicking.
  • New #[must_use] on constructors, digests and MACs warns under -D warnings.
  • CPU detection without std is compile-time (see above).

Highlights

  • Post-quantum: ML-KEM-768 and X-Wing KEMs (Classic + Rustaceous), SHAKE and TurboSHAKE XOFs, and HPKE/X-Wing sealed boxes with an approved, documented format and profile.
  • Python: PyO3 abi3 bindings shipped as dryoc on PyPI (manylinux, musllinux, macOS, Windows wheels, free-threaded builds, sdist), with stub docs and a PyNaCl-oracle test suite.
  • Performance: in-crate primitives with runtime-detected SIMD (AVX2/AVX-512, NEON/SVE2, SHA2/SHA3 extensions) entered through CPU feature tokens, faster AArch64 kernels across ML-KEM, X25519/Ed25519, AEADs, Keccak and Argon2, WASM simd128 backends, and refreshed Xeon 6975P-C benchmarks against libsodium 1.0.22.
  • no_std + alloc/std split with getrandom directly (the rand dependency is gone); serde on by default; protected hardened (serde, soundness) and decoupled from nightly.
  • Security hardening: kernel secret-residue wiping sweeps at every opt level, wiped verify/box/kx/signing-key paths, full-range generichash lengths, Argon2 limits and secret handling, low-order key rejection paths kept intact.
  • Docs: new UPGRADING.md (1.x -> 2.0) and COMPATIBILITY.md, streamlined README and crate docs, unsafe-code inventory on its own rustdoc page, sealed-box format approval record, kernel wiping policy.
  • Tooling: release.py tags releases and bumps versions with lockfile refresh; nextest suites, focused Miri checks, fuzz smoke runs, SemVer checks, and faster/slimmer CI jobs.

Pull Requests

Features

  • In-crate crypto primitives with runtime-detected SIMD backends (#152)
  • SHAKE and TurboSHAKE extendable-output functions (#160)
  • ML-KEM-768 and X-Wing key encapsulation (#161)
  • Post-quantum sealed boxes with HPKE and X-Wing (#163)
  • no_std support with std and alloc features (#178)
  • WASM simd128 backends (#186)
  • Enable serde by default (#189)
  • PyO3 bindings and PyPI release workflow (#191)
  • Release.py helper for tagging releases (#193)

Breaking API cleanup

  • Shared helpers, deduplicated impls, and removal of deprecated gen aliases (2.0.0) (#153)
  • Remove unused u64_backend feature (#172)
  • Remove all-zero keypair constructors and Default impls (#174)
  • Rename wincode feature to wincode_0_6 (#175)
  • Restrict ByteArray to fixed-size storage (#176)
  • Rename box open verbs and drop redundant box constructors (#201)
  • Match libsodium argument order in classic detached open (#203)
  • Make fallibility, input bounds and MAC key passing consistent (#204)
  • Simplify serde derives and protection modes (#200)
  • Generate every Vec box schema from one macro (#207)

Security and correctness

  • Serialize the fixed-size views of box fields (#167)
  • Stream-kernel wiping per the kernel wiping policy (#168)
  • Wipe Poly1305 hot-loop copies and document kernel wiping scope (#169)
  • Harden serde deserialization and protected-memory soundness (#180)
  • Wipe secret residue in verify, box, kx and signing-key paths (#181)
  • Accept libsodium's full output and key length ranges in generichash (#182)
  • Address Argon2 limits and secret handling in pwhash (#183)
  • Wipe kernel secret residue and require avx2 with avx512f (#184)
  • Enter target-feature kernels through CPU feature tokens (#185)
  • Keep kernel secrets out of helpers outlined at any opt-level (full sweep) (#188)
  • Copy bytearray inputs under their critical section (Python) (#192)
  • Correct the simd128 kernels' wiping notes (#209)
  • Use getrandom directly and drop rand (#179)
  • Safe StackByteArray views; sealed-box doc follow-ups (#177)
  • Build with nightly after allocator_api stabilization (#165)

Performance

  • Faster AArch64 kernels across ML-KEM, X25519/Ed25519, AEADs, Keccak and Argon2 (#194)
  • Refresh Xeon 6975P-C numbers against libsodium 1.0.22 (#195)

Tests

  • Expand known-answer coverage and differential fuzzing (#154)
  • Check native compatibility against libsodium 1.0.22 (#162)
  • Wasm known answers and serde coverage for XOF, KEM and sealed boxes (#170)
  • Secretstream limits and broader fuzz coverage (#171)
  • Route libsodium oracle calls through native_test_util (#202)
  • Share ChaCha20/Salsa20 kernel test helpers (#205)
  • Share Edwards fixtures, KAT parser, BLAKE2b loader and hex helpers (#214)

Documentation

  • Reword module and crate documentation (#156)
  • Nightly toolchain floor and kernel wiping policy (#166)
  • Record sealed-box format approval and HPKE profile (#173)
  • Tighten README, lib.rs, and BENCHMARKS prose (#196)
  • Gate alloc-only examples so doctests pass without alloc (#211)
  • Move the unsafe code inventory to its own rustdoc page (#216)
  • Shorten README unsafe code footnote to a link to the inventory (#217)
  • Streamline README and crate-level docs (#218)
  • Document every public API member in the .pyi stubs (#220)
  • Tone down README marketing copy to sentence case (#223)
  • Move dryoc-vs-libsodium differences to COMPATIBILITY.md (#224)
  • Add UPGRADING.md for moving from dryoc 1.x to 2.0 (#225)

CI and maintenance

  • Bump version (#149)
  • Use nextest for test suites (#150)
  • Bump deps (#155)
  • Replace Rust caching with mr boxington (#157)
  • Fuzz smoke run, kebab-case fuzz targets, all-jobs-pass gate (#158)
  • Add focused Miri memory-safety checks (#159)
  • Enable serde by default (#189)
  • Speed up wasm32 test jobs (#190)
  • Add --bump major|minor|patch to release.py (#197)
  • Dedupe nextest setup and Python helpers (#198)
  • Lint and type-check all Python code with ruff and ty (#199)
  • Publish musllinux wheels and fix the PyPI summary (#219)
  • Cut redundant jobs and speed up the slowest tests (#221)
  • Run fuzz targets in parallel, build CI test wheels without LTO (#222)