dryoc v1.0.0
dryoc 1.0.0 hardens cryptographic boundary checks, replaces string-only errors with structured errors, and adds libsodium-compatible ChaCha20-Poly1305-IETF support. This is a backward-incompatible upgrade from v0.9.0: source APIs, accepted inputs, selected serde representations, and 32-bit/wasm secretstream framing changed.
Full Changelog: v0.9.0...v1.0.0
Breaking Changes
Errors and fallible APIs
Error::Message,Error::FromSlice,From<String>, andFrom<&str>were removed. Errors now use non-exhaustive, matchable variants such asAuthenticationFailed,InvalidLength,InvalidValue,InvalidKey, andIo; downstream matches must include a wildcard.crypto_scalarmult,crypto_box_beforenm,crypto_box_detached,crypto_box_detached_afternm,crypto_secretbox_detached,KeyPair::precalculate, andPrecalcSecretKey::precalculatenow returnResult. Low-order X25519 public keys are rejected through scalarmult, box, key-exchange, and precalculation APIs.- Protected-memory traits, constructors, keypair generation, and protected precalculation now return
dryoc::Errorinstead ofstd::io::Error. Tag::from(u8)andPasswordHashAlgorithm::from(u32)were replaced by fallibleTryFromconversions.
API contracts
crypto_core_ed25519_is_valid_point_relaxedwas removed; use the strictcrypto_core_ed25519_is_valid_point. Signature verification and Ed25519-to-Curve25519 conversion now reject non-canonical, small-order, and mixed-order inputs.crypto_box_seed_keypair,crypto_box_seed_keypair_inplace, andKeyPair::from_seednow require exactlyCRYPTO_BOX_SEEDBYTESbytes.Kdf::derive_subkeysupports a const-generic output length, whilederive_subkey_to_vecnow requires an explicit length. Custom KDF main-key and KX session-key storage types must implementZeroizeOnDrop.Config::with_salt_lengthwas removed; newly generated password hashes always use libsodium's 16-byte salt. UseConfig::with_algorithmto select Argon2i or Argon2id.PwHash::to_string() -> Stringwas replaced byPwHash::to_encoded_string() -> Result<String, Error>.- Protected-memory
.munlock()is available only for values in theLockedtypestate.
Data, wire, and behavior compatibility
- With
serde, theConfig/PwHashrepresentation replacessalt_lengthwithparallelism.StackByteArray<N>now rejects short or overlong sequences instead of padding or truncating them, and variable protected buffers no longer retain unused size-hint padding. - Secretstream now authenticates lengths as fixed-width little-endian
u64values. Streams produced by pre-1.0 builds on 32-bit or wasm targets are not wire-compatible and must be decrypted with the old version and re-encrypted with v1.0.0. The prior 64-bit little-endian encoding already used the same byte width. - Box, secretbox, AEAD, password-hash, KDF, and secretstream APIs enforce corrected size and encoding limits before allocation or output mutation. Code that depended on oversized buffers, malformed encodings, unknown stream-tag bits, or non-canonical keys/signatures will now receive an error.
- Secret-bearing
Debugoutput is redacted. Do not depend on previous debug strings or exact human-readable error text.
Migration Guide (v0.9.x -> v1.0.0)
1. Update and compile
Change the dependency requirement to dryoc = "1", then update and compile all targets and enabled features:
cargo update -p dryoc --precise 1.0.0
cargo check --all-targets2. Handle new results and structured errors
Add ?, match, or an explicit expect at newly fallible calls:
let shared_key = crypto_box_beforenm(&public_key, &secret_key)?;
crypto_box_detached(&mut ciphertext, &mut mac, message, &nonce, &public_key, &secret_key)?;
let precalculated = keypair.precalculate(&third_party_public_key)?;Replace string matching with structured matching and retain a wildcard because the enums are non-exhaustive:
match error {
dryoc::Error::AuthenticationFailed => handle_authentication_failure(),
dryoc::Error::InvalidLength { context, actual, constraint } => {
handle_invalid_length(context, actual, constraint)
}
dryoc::Error::Io(source) => handle_io_error(source),
other => handle_other_error(other),
}If an API must still expose std::io::Error, explicitly handle dryoc::Error::Io(source) and define how non-I/O variants are translated.
3. Apply API replacements
Tag::from(byte)->Tag::try_from(byte)?PasswordHashAlgorithm::from(value)->PasswordHashAlgorithm::try_from(value)?pwhash.to_string()->pwhash.to_encoded_string()?kdf.derive_subkey_to_vec(id)->kdf.derive_subkey_to_vec(id, length)- For fixed-size KDF output, let the destination type select the length:
let subkey: StackByteArray<32> = kdf.derive_subkey(id)?; - Convert dynamic box seeds to an exact-size array and handle the slice-conversion error in the application before calling the seed APIs:
let seed: &[u8; CRYPTO_BOX_SEEDBYTES] = seed_slice.try_into().expect("seed must be exactly 32 bytes"); - Replace
crypto_core_ed25519_is_valid_point_relaxedwithcrypto_core_ed25519_is_valid_pointand handle values that no longer pass strict validation.
4. Migrate persisted data
Back up persisted serde-encoded Config/PwHash values before rewriting them. Replace the salt_length field with parallelism: 1; do not copy the old salt-length number into parallelism. Existing salt bytes remain part of PwHash, while newly generated salts are always 16 bytes. Valid libsodium-compatible encoded Argon2 strings do not need to be rehashed.
On 32-bit or wasm systems, decrypt any retained pre-1.0 secretstream ciphertext with v0.9.x and re-encrypt it with v1.0.0. Active stream state cannot be upgraded in place.
5. Validate application behavior
cargo test --all-targets
cargo clippy --all-targets -- -D warningsIf the application enables dryoc's nightly-only features, also run its feature combination with the nightly toolchain; for example, cargo +nightly test --all-targets --all-features.
Add negative tests for invalid lengths, low-order keys, non-canonical signatures, malformed password hashes, and unknown stream tags where the application previously assumed those inputs were accepted.
Highlights
- Added Classic and Rustaceous ChaCha20-Poly1305-IETF APIs with RFC 8439 known-answer tests and libsodium interoperability coverage.
- Added structured, dependency-free error types with contextual length and value constraints.
- Hardened secret zeroization, protected-memory failure behavior, constant-time comparisons, output/state atomicity on authentication failure, and redaction of secret-bearing debug output.
- Expanded MSRV, feature-matrix, wasm, Windows, fuzz, documentation, package, and publish validation; added an early SemVer compatibility check.
- Documented WebAssembly support and the nightly feature requirements for the SIMD backend.
Pull Requests
Features
Security and Correctness
- Harden cryptographic safety invariants (#139)
- Harden cryptographic APIs and release validation (#142)
Documentation
- Overhaul public API documentation (#140)
- Document WebAssembly support (#146)
- Clarify SIMD build requirements (#148)