Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changes/make-cryptographic-boundaries-mi-fba1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"rscrypto" = "minor"
---

Make cryptographic boundaries misuse-resistant: keyed BLAKE2 uses validated borrowed key types and variable outputs fail with typed errors, normal AEAD sealing owns nonce issuance while caller nonces require an expert import, entropy and platform override failures no longer panic, and diagnostic or dangerous capabilities no longer clutter the crate root.
1 change: 1 addition & 0 deletions benches/aead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use core::hint::black_box;
use aes_gcm::aead::{AeadInOut as _, KeyInit as _};
use aes_gcm_siv::aead::{AeadInPlace as _, KeyInit as _};
use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
use rscrypto::aead::expert::AeadWithNonce;

#[cfg(all(
any(unix, windows),
Expand Down
6 changes: 3 additions & 3 deletions benches/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1042,7 +1042,7 @@ fn ecdsa_p384_sign(c: &mut Criterion) {

#[cfg(all(feature = "diag", feature = "ecdsa-p384"))]
fn ecdsa_p384_internal(c: &mut Criterion) {
use rscrypto::{
use rscrypto::auth::{
diag_ecdsa_p384_basepoint_blinded_limb_digest, diag_ecdsa_p384_basepoint_r_limb_digest,
diag_ecdsa_p384_final_multiply_limb_digest, diag_ecdsa_p384_nonce_inverse_limb_digest,
diag_ecdsa_p384_nonce_reduce_limb_digest, diag_ecdsa_p384_order_mul_fixed_r_limb_digest,
Expand Down Expand Up @@ -1281,7 +1281,7 @@ fn ed25519_verify(c: &mut Criterion) {

#[cfg(feature = "diag")]
fn ed25519_verify_phase(c: &mut Criterion) {
use rscrypto::{
use rscrypto::auth::{
diag_ed25519_verify_challenge_reduce_digest, diag_ed25519_verify_portable_double_scalar_digest,
diag_ed25519_verify_public_decode_digest, diag_ed25519_verify_r_decode_digest, diag_ed25519_verify_scalars,
};
Expand Down Expand Up @@ -1339,7 +1339,7 @@ fn ed25519_verify_phase(c: &mut Criterion) {
))]
g.bench_function(BenchmarkId::new("aarch64-asm-double-scalar", len), |b| {
b.iter(|| {
black_box(rscrypto::diag_ed25519_verify_aarch64_asm_double_scalar_digest(
black_box(rscrypto::auth::diag_ed25519_verify_aarch64_asm_double_scalar_digest(
black_box(&scalars.s_canonical),
black_box(&scalars.neg_challenge),
black_box(&scalars.public_key),
Expand Down
30 changes: 19 additions & 11 deletions benches/blake2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ use blake2::{
use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
use digest::typenum::{U16, U32, U64};
use hmac::{Mac as _, digest::KeyInit};
use rscrypto::{Blake2b256, Blake2b512, Blake2bParams, Blake2s128, Blake2s256, Blake2sParams, Digest};
use rscrypto::{
Blake2b256, Blake2b512, Blake2bKey, Blake2bParams, Blake2s128, Blake2s256, Blake2sKey, Blake2sParams, Digest,
};

type RustCryptoBlake2bMac256 = Blake2bMac<U32>;
type RustCryptoBlake2bMac512 = Blake2bMac<U64>;
Expand Down Expand Up @@ -84,6 +86,8 @@ fn host_overhead(c: &mut Criterion) {
let inputs = tiny_inputs();
let key_b = [0x42u8; 64];
let key_s = [0x24u8; 32];
let key_b_typed = Blake2bKey::new(black_box(&key_b[..32])).unwrap();
let key_s_typed = Blake2sKey::new(black_box(&key_s)).unwrap();

let mut oneshot = c.benchmark_group("blake2/host-overhead");
for (len, data) in &inputs {
Expand All @@ -110,7 +114,7 @@ fn host_overhead(c: &mut Criterion) {
common::set_throughput(&mut keyed, *len);

keyed.bench_with_input(BenchmarkId::new("rscrypto/blake2b256", len), data, |b, d| {
b.iter(|| black_box(Blake2b256::keyed_digest(black_box(&key_b[..32]), black_box(d))))
b.iter(|| black_box(Blake2b256::keyed_digest(key_b_typed, black_box(d))))
});
keyed.bench_with_input(BenchmarkId::new("rustcrypto/blake2b256", len), data, |b, d| {
b.iter(|| {
Expand All @@ -121,7 +125,7 @@ fn host_overhead(c: &mut Criterion) {
});

keyed.bench_with_input(BenchmarkId::new("rscrypto/blake2s256", len), data, |b, d| {
b.iter(|| black_box(Blake2s256::keyed_digest(black_box(&key_s), black_box(d))))
b.iter(|| black_box(Blake2s256::keyed_digest(key_s_typed, black_box(d))))
});
keyed.bench_with_input(BenchmarkId::new("rustcrypto/blake2s256", len), data, |b, d| {
b.iter(|| {
Expand Down Expand Up @@ -176,13 +180,17 @@ fn keyed(c: &mut Criterion) {
let inputs = common::comp_sizes();
let key_b = [0x42u8; 64];
let key_s = [0x24u8; 32];
let key_b_256 = Blake2bKey::new(black_box(&key_b[..32])).unwrap();
let key_b_512 = Blake2bKey::new(black_box(&key_b)).unwrap();
let key_s_128 = Blake2sKey::new(black_box(&key_s[..16])).unwrap();
let key_s_256 = Blake2sKey::new(black_box(&key_s)).unwrap();
let mut g = c.benchmark_group("blake2/keyed");

for (len, data) in &inputs {
common::set_throughput(&mut g, *len);

g.bench_with_input(BenchmarkId::new("rscrypto/blake2b256", len), data, |b, d| {
b.iter(|| black_box(Blake2b256::keyed_digest(black_box(&key_b[..32]), black_box(d))))
b.iter(|| black_box(Blake2b256::keyed_digest(key_b_256, black_box(d))))
});
g.bench_with_input(BenchmarkId::new("rustcrypto/blake2b256", len), data, |b, d| {
b.iter(|| {
Expand All @@ -200,7 +208,7 @@ fn keyed(c: &mut Criterion) {
});

g.bench_with_input(BenchmarkId::new("rscrypto/blake2b512", len), data, |b, d| {
b.iter(|| black_box(Blake2b512::keyed_digest(black_box(&key_b), black_box(d))))
b.iter(|| black_box(Blake2b512::keyed_digest(key_b_512, black_box(d))))
});
g.bench_with_input(BenchmarkId::new("rustcrypto/blake2b512", len), data, |b, d| {
b.iter(|| {
Expand All @@ -218,7 +226,7 @@ fn keyed(c: &mut Criterion) {
});

g.bench_with_input(BenchmarkId::new("rscrypto/blake2s128", len), data, |b, d| {
b.iter(|| black_box(Blake2s128::keyed_digest(black_box(&key_s[..16]), black_box(d))))
b.iter(|| black_box(Blake2s128::keyed_digest(key_s_128, black_box(d))))
});
g.bench_with_input(BenchmarkId::new("rustcrypto/blake2s128", len), data, |b, d| {
b.iter(|| {
Expand All @@ -229,7 +237,7 @@ fn keyed(c: &mut Criterion) {
});

g.bench_with_input(BenchmarkId::new("rscrypto/blake2s256", len), data, |b, d| {
b.iter(|| black_box(Blake2s256::keyed_digest(black_box(&key_s), black_box(d))))
b.iter(|| black_box(Blake2s256::keyed_digest(key_s_256, black_box(d))))
});
g.bench_with_input(BenchmarkId::new("rustcrypto/blake2s256", len), data, |b, d| {
b.iter(|| {
Expand Down Expand Up @@ -332,8 +340,8 @@ fn params(c: &mut Criterion) {
b.iter(|| {
black_box(
Blake2bParams::new()
.salt(black_box(&salt_b))
.personal(black_box(&personal_b))
.salt(black_box(salt_b))
.personal(black_box(personal_b))
.hash_256(black_box(d)),
)
})
Expand All @@ -350,8 +358,8 @@ fn params(c: &mut Criterion) {
b.iter(|| {
black_box(
Blake2sParams::new()
.salt(black_box(&salt_s))
.personal(black_box(&personal_s))
.salt(black_box(salt_s))
.personal(black_box(personal_s))
.hash_256(black_box(d)),
)
})
Expand Down
2 changes: 1 addition & 1 deletion docs/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ rscrypto = { version = "0.7.8", features = ["full", "portable-only"] }

| Feature | Effect |
|---|---|
| `getrandom` | Enables OS-RNG constructors such as `random()` / `try_random()`, `RapidRandomState::try_new()`, canonical Argon2id/scrypt password-record generation, `try_generate()` for Ed25519/X25519/ECDSA, `Poly1305OneTimeKey::try_generate()`, ML-KEM `try_generate_keypair()` / `try_encapsulate()`, AEAD random sealing helpers, RSA key generation, signing salt/blinding, encryption randomness, and private-operation blinding. Password-record salts are intentionally OS-owned; other APIs retain caller-supplied byte-filling closures where deterministic tests or constrained integrations need them. Deterministic ECDSA signing does not use OS randomness. RSA key generation uses OS entropy to seed its key-generation HMAC_DRBG; no separate DRBG feature is required. |
| `getrandom` | Enables fallible OS-RNG constructors such as `try_random()` / `try_generate()`, `RapidRandomState::try_new()`, canonical Argon2id/scrypt password-record generation, ML-KEM `try_generate_keypair()` / `try_encapsulate()`, AEAD random sealing helpers, RSA key generation, signing salt/blinding, encryption randomness, and private-operation blinding. Password-record salts are intentionally OS-owned; other APIs retain caller-supplied byte-filling closures where deterministic tests or constrained integrations need them. Deterministic ECDSA signing does not use OS randomness. RSA key generation uses OS entropy to seed its key-generation HMAC_DRBG; no separate DRBG feature is required. |
| `serde` | Serde for non-secret byte wrappers (nonces, tags, public keys, signatures). |
| `serde-secrets` | Serde for secret-key and shared-secret bytes. Implies `serde`. Use only for controlled key-material storage, not logs or DTOs. |
| `parallel` | Rayon-backed BLAKE3 and Argon2 lane parallelism. Requires `std`, `blake3`, `argon2`. |
Expand Down
6 changes: 5 additions & 1 deletion docs/migration/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Migration Guides

This index covers 35 migration guides for individual crates and larger stacks.
This index covers 36 migration guides for API revisions, individual crates,
and larger stacks.

Each guide identifies dependency, import, call-site, behavior, and unsupported
surface changes.
Expand All @@ -9,6 +10,9 @@ If you are evaluating `rscrypto`, start with the crate you already use.
The guide states whether the mapped surface is compatible and which upstream
APIs must remain.

For projects upgrading rscrypto itself, start with
[`misuse-resistant API boundaries`](api-boundaries.md).

## Checksums

| From | To | Status |
Expand Down
11 changes: 9 additions & 2 deletions docs/migration/RustCrypto/aes-gcm-siv.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Evidence: `tests/aes128gcmsiv_oracle.rs`, `tests/aes256gcmsiv_oracle.rs`, and `t
| | Before (`aes-gcm-siv` 0.11.x) | After (`rscrypto` 0.7.8) |
|---|---|---|
| Cargo dep | `aes-gcm-siv = "0.11"` | `rscrypto = { version = "0.7.8", features = ["aes-gcm-siv"] }` |
| Import | `use aes_gcm_siv::{Aes256GcmSiv, Key, Nonce, KeyInit, aead::{Aead, Payload}};` | `use rscrypto::{Aead, Aes256GcmSiv, Aes256GcmSivKey, aead::Nonce96};` |
| Import | `use aes_gcm_siv::{Aes256GcmSiv, Key, Nonce, KeyInit, aead::{Aead, Payload}};` | `use rscrypto::{Aead, Aes256GcmSiv, Aes256GcmSivKey, aead::{Nonce96, expert::AeadWithNonce}};` |
| Encrypt | `cipher.encrypt(nonce, Payload { msg, aad })?` | `cipher.encrypt(&nonce, aad, msg, &mut out)?` |

## Cargo.toml
Expand Down Expand Up @@ -56,7 +56,10 @@ let ct = cipher.encrypt(nonce, Payload { msg: plaintext, aad }).unwrap();

```rust
// After
use rscrypto::{Aead, Aes256GcmSiv, Aes256GcmSivKey, aead::Nonce96};
use rscrypto::{
Aead, Aes256GcmSiv, Aes256GcmSivKey,
aead::{Nonce96, expert::AeadWithNonce},
};

let key = Aes256GcmSivKey::from_bytes([0u8; 32]);
let cipher = Aes256GcmSiv::new(&key);
Expand All @@ -65,6 +68,10 @@ let mut ct = vec![0u8; plaintext.len() + 16];
cipher.encrypt(&nonce, aad, plaintext, &mut ct)?;
```

The expert trait import makes preservation of the upstream caller-nonce
protocol explicit. Prefer `seal_random` when the protocol does not already
define nonce derivation.

### Combined decrypt

```rust
Expand Down
12 changes: 9 additions & 3 deletions docs/migration/RustCrypto/aes-gcm.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Evidence: `tests/aes128gcm_oracle.rs`, `tests/aes256gcm_oracle.rs`, and `tests/a
| | Before (`aes-gcm` 0.11.x) | After (`rscrypto` 0.7.8) |
|---|---|---|
| Cargo dep | `aes-gcm = "0.11"` | `rscrypto = { version = "0.7.8", features = ["aes-gcm"] }` |
| Import | `use aes_gcm::{Aes256Gcm, Key, Nonce, KeyInit, aead::{Aead, Payload}};` | `use rscrypto::{Aead, Aes256Gcm, Aes256GcmKey, aead::Nonce96};` |
| Import | `use aes_gcm::{Aes256Gcm, Key, Nonce, KeyInit, aead::{Aead, Payload}};` | `use rscrypto::{Aead, Aes256Gcm, Aes256GcmKey, aead::{Nonce96, expert::AeadWithNonce}};` |
| Encrypt | `cipher.encrypt(nonce, Payload { msg, aad })?` (returns `Vec<u8>`) | `cipher.encrypt(&nonce, aad, msg, &mut out)?` (writes into caller buffer) |

## Cargo.toml
Expand Down Expand Up @@ -59,7 +59,10 @@ let ct = cipher.encrypt(nonce, Payload { msg: plaintext, aad }).unwrap();

```rust
// After
use rscrypto::{Aead, Aes256Gcm, Aes256GcmKey, aead::Nonce96};
use rscrypto::{
Aead, Aes256Gcm, Aes256GcmKey,
aead::{Nonce96, expert::AeadWithNonce},
};

let key = Aes256GcmKey::from_bytes([0u8; 32]);
let cipher = Aes256Gcm::new(&key);
Expand All @@ -70,6 +73,9 @@ cipher.encrypt(&nonce, aad, plaintext, &mut ct)?;
```

The output layout is identical (`[ciphertext || tag]`), so on-the-wire compatibility is preserved. The shape change is who owns the buffer: `aes-gcm` allocates a `Vec`, rscrypto writes into a buffer you pre-sized.
The expert trait import is required because this migration preserves the
upstream caller-supplied nonce. New protocols should use `seal_random` or
`NonceCounter<Aes256Gcm>` so nonce issuance is not a normal call-site choice.

### Combined decrypt

Expand Down Expand Up @@ -107,7 +113,7 @@ let tag = cipher.encrypt_in_place(&nonce, aad, &mut buffer)?;
// buffer is now the ciphertext; tag: Aes256GcmTag (Copy).
```

`encrypt_in_place` is the canonical name in rscrypto; `encrypt_in_place_detached` is also available as an alias matching RustCrypto's naming.
Both names require the explicit `AeadWithNonce` import.

### Detached (in-place) decrypt

Expand Down
10 changes: 8 additions & 2 deletions docs/migration/RustCrypto/ascon-aead.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Evidence: `tests/ascon_aead_oracle.rs`.
| | Before (`ascon-aead` 0.6.x) | After (`rscrypto` 0.7.8) |
|---|---|---|
| Cargo dep | `ascon-aead = "0.6"` | `rscrypto = { version = "0.7.8", features = ["ascon-aead"] }` |
| Import | `use ascon_aead::{AsconAead128, Key, Nonce, aead::{Aead, KeyInit, Payload}};` | `use rscrypto::{Aead, AsconAead128, AsconAead128Key, aead::Nonce128};` |
| Import | `use ascon_aead::{AsconAead128, Key, Nonce, aead::{Aead, KeyInit, Payload}};` | `use rscrypto::{Aead, AsconAead128, AsconAead128Key, aead::{Nonce128, expert::AeadWithNonce}};` |
| Encrypt | `cipher.encrypt(nonce, Payload { msg, aad })?` | `cipher.encrypt(&nonce, aad, msg, &mut out)?` |

## Cargo.toml
Expand Down Expand Up @@ -52,7 +52,10 @@ let ct = cipher.encrypt(nonce, Payload { msg: plaintext, aad }).unwrap();

```rust
// After
use rscrypto::{Aead, AsconAead128, AsconAead128Key, aead::Nonce128};
use rscrypto::{
Aead, AsconAead128, AsconAead128Key,
aead::{Nonce128, expert::AeadWithNonce},
};

let key = AsconAead128Key::from_bytes([0u8; 16]);
let cipher = AsconAead128::new(&key);
Expand All @@ -61,6 +64,9 @@ let mut ct = vec![0u8; plaintext.len() + 16];
cipher.encrypt(&nonce, aad, plaintext, &mut ct)?;
```

The expert trait import preserves an existing caller-nonce protocol. Prefer
`seal_random` when the protocol does not already define nonce derivation.

### Combined decrypt

```rust
Expand Down
24 changes: 19 additions & 5 deletions docs/migration/RustCrypto/blake2.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ use rscrypto::{Blake2b256, Digest};
let out: [u8; 32] = Blake2b256::digest(b"123456789");
```

For runtime-variable output, use `Blake2b::digest_into(out_len, data, &mut buf)`: see the `Blake2b` rustdoc.
For runtime-variable output, size the destination and call
`Blake2b::digest_into(data, &mut buf)?`. The buffer length selects the output
length and invalid empty or oversized buffers return `Blake2Error`.

### Streaming

Expand Down Expand Up @@ -113,17 +115,29 @@ let tag = mac.finalize().into_bytes(); // GenericArray<u8, U64>

```rust
// After
use rscrypto::Blake2b512;
use rscrypto::{Blake2b512, Blake2bKey};
let key = [0x42u8; 32];
let tag: [u8; 64] = Blake2b512::keyed_digest(&key, b"message");
let key = Blake2bKey::new(&key)?;
let tag: [u8; 64] = Blake2b512::keyed_digest(key, b"message");
```

For streaming keyed mode, use `Blake2b512::new_keyed(&key)`. The MAC type and the hash type are unified: no separate `Blake2bMac` import.
For streaming keyed mode, use `Blake2b512::new_keyed(key)`. `Blake2bKey::new`
rejects empty or oversized keys at the caller boundary; the borrowed validated
key can then be reused without allocation or copying. Omitting the keyed
constructor selects unkeyed hashing. The MAC type and the hash type are
unified: no separate `Blake2bMac` import.

## Notes

- **Generic constants gone.** `Blake2b<U32>` and `Blake2s<U16>` style generics are replaced with named convenience types per output length. `generic-array` is no longer in your dependency tree if rscrypto is your only consumer.
- **MAC unification.** RustCrypto separates `Blake2bMac` from `Blake2b` because the MAC and the hash use different parameter blocks. rscrypto exposes both modes from the same type via `keyed_digest` / `new_keyed`. Personalisation, salt, and tree-hashing parameters are reachable through `Blake2bParams` / `Blake2sParams`.
- **MAC unification.** RustCrypto separates `Blake2bMac` from `Blake2b`
because the MAC and the hash use different parameter blocks. rscrypto
exposes both modes from the same type via `keyed_digest` / `new_keyed`.
Personalization and salt are available through `Blake2bParams` /
`Blake2sParams`; tree hashing is not exposed.
- **Exact parameter fields.** `Blake2bParams` accepts `[u8; 16]` salt and
personalization fields; `Blake2sParams` accepts `[u8; 8]`. Pad deliberately
before the call when a protocol defines a shorter value.
- **`finalize` consumes vs. borrows.** Same as `sha2` / `sha3`: drop `.clone()`.
- **`Output<D>` → `[u8; N]`.** Same as `sha2` / `sha3`.
- **No generic keyed-output comparison.** rscrypto's Blake2 keyed digest
Expand Down
18 changes: 14 additions & 4 deletions docs/migration/RustCrypto/chacha20poly1305.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Evidence: `tests/chacha20poly1305.rs`, `tests/xchacha20poly1305.rs`, and `tests/
| | Before (`chacha20poly1305` 0.11.x) | After (`rscrypto` 0.7.8) |
|---|---|---|
| Cargo dep | `chacha20poly1305 = "0.11"` | `rscrypto = { version = "0.7.8", features = ["chacha20poly1305", "xchacha20poly1305"] }` |
| Import | `use chacha20poly1305::{ChaCha20Poly1305, Key, Nonce, KeyInit, aead::{Aead, Payload}};` | `use rscrypto::{Aead, ChaCha20Poly1305, ChaCha20Poly1305Key, aead::Nonce96};` |
| Import | `use chacha20poly1305::{ChaCha20Poly1305, Key, Nonce, KeyInit, aead::{Aead, Payload}};` | `use rscrypto::{Aead, ChaCha20Poly1305, ChaCha20Poly1305Key, aead::{Nonce96, expert::AeadWithNonce}};` |
| Encrypt | `cipher.encrypt(nonce, Payload { msg, aad })?` | `cipher.encrypt(&nonce, aad, msg, &mut out)?` |

Drop `xchacha20poly1305` from the feature list if you don't use the 192-bit-nonce variant.
Expand Down Expand Up @@ -54,7 +54,10 @@ let ct = cipher.encrypt(nonce, Payload { msg: plaintext, aad }).unwrap();

```rust
// After
use rscrypto::{Aead, ChaCha20Poly1305, ChaCha20Poly1305Key, aead::Nonce96};
use rscrypto::{
Aead, ChaCha20Poly1305, ChaCha20Poly1305Key,
aead::{Nonce96, expert::AeadWithNonce},
};

let key = ChaCha20Poly1305Key::from_bytes([0u8; 32]);
let cipher = ChaCha20Poly1305::new(&key);
Expand All @@ -78,7 +81,10 @@ let ct = cipher.encrypt(nonce, Payload { msg: plaintext, aad }).unwrap();

```rust
// After
use rscrypto::{Aead, XChaCha20Poly1305, XChaCha20Poly1305Key, aead::Nonce192};
use rscrypto::{
Aead, XChaCha20Poly1305, XChaCha20Poly1305Key,
aead::{Nonce192, expert::AeadWithNonce},
};

let key = XChaCha20Poly1305Key::from_bytes([0u8; 32]);
let cipher = XChaCha20Poly1305::new(&key);
Expand All @@ -88,6 +94,8 @@ cipher.encrypt(&nonce, aad, plaintext, &mut ct)?;
```

The XChaCha variant uses `Nonce192` (24 bytes). That is the only structural change from the IETF-nonce variant.
The expert trait import is required because these examples preserve an
existing caller-nonce protocol. Prefer `seal_random` for new protocols.

### Decrypt + tamper-detection

Expand Down Expand Up @@ -120,7 +128,9 @@ cipher.decrypt_in_place(&nonce, aad, &mut buffer, &tag)?;
the deployment must still define a message limit and acceptable error
probability.
- **No `Payload`.** Same simplification as `aes-gcm.md`: positional `aad` and `msg`/`buffer` args.
- **`AeadInPlace` import not needed.** rscrypto exposes both combined and in-place shapes through the single `Aead` trait.
- **Explicit-nonce sealing is expert-only.** Import `AeadWithNonce` for
protocols that already prove nonce uniqueness. Decryption and fresh-random
sealing remain on `Aead`.
- **Failed-open buffer semantics change.** RustCrypto keeps the in-place buffer
unchanged on error. rscrypto clears it on authentication failure. Combined
rscrypto decrypt also clears its output buffer on authentication failure.
Expand Down
Loading