Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
0a0e5f3
core: the symmetric, block and ECB key paths -- role pairs and mode p…
dghgit Oct 19, 2026
6772d72
core-test-framework: key-generic runners and the construction suites …
dghgit Oct 19, 2026
62f78a4
cipher: mode types for the symmetric, block and ECB paths, and CCMFra…
dghgit Oct 19, 2026
cb8188f
core: KeyMaterial::from_rng caps the strength at the key length
dghgit Oct 19, 2026
31dc205
cipher: tests onto the key path (prototype)
dghgit Oct 19, 2026
6216fe9
cipher: doc examples onto the mode-trait route (prototype)
dghgit Oct 19, 2026
3f4a7c6
ascon: AsconAEAD128Key (prototype)
dghgit Oct 19, 2026
6ea891e
sha3: KMACKey (prototype)
dghgit Oct 19, 2026
a21a586
hmac: HmacKey::generate caps the strength at the key length
dghgit Oct 19, 2026
3722b36
factory: MACFactory builds the MAC key objects (prototype)
dghgit Oct 19, 2026
1e192d1
aes: the symmetric, block and ECB roles on AESKey, and everything ont…
dghgit Oct 19, 2026
32d67f8
cli: the cipher commands build key objects (prototype)
dghgit Oct 19, 2026
16c3497
core: the cipher and MAC traits lose their constructors and key-takin…
dghgit Oct 19, 2026
8db1e8c
core, cipher: CCM_Packet names the fixed-frame CCM pair, and the decl…
dghgit Oct 20, 2026
2794490
core, cipher: workers borrow the key state instead of copying the sch…
dghgit Oct 19, 2026
bd97aeb
core, cipher: BlockPermutation splits from ElectronicCodeBook; the ke…
dghgit Oct 19, 2026
c13546e
hmac, ascon, factory: the HMAC worker borrows its key, and resume tak…
dghgit Oct 19, 2026
e389082
hmac: HmacKey::inner_state and finish_out are doc(hidden) (prototype)
dghgit Oct 20, 2026
6c5e223
ascon: the stack-usage table re-measured on the key path (prototype)
dghgit Oct 20, 2026
5607ba9
core, cipher, aes, ascon: key objects compare in constant time (proto…
dghgit Oct 25, 2026
9c343a5
core, cli: the two rustdoc lints the rebase left, so docs build with …
dghgit Oct 25, 2026
2a93fa7
Merge branch 'feature/key-rework' into feature/key-rework-memory
dghgit Oct 26, 2026
d9a7ddd
cipher: a GCM state resumes only in the direction it was suspended in
dghgit Oct 27, 2026
985a16a
ascon: the key constructor's doc no longer cites the dropped algorith…
dghgit Oct 27, 2026
4e52240
cli: the CTR doc admits --iv; the MAC commands report a bad key or ta…
dghgit Oct 27, 2026
5ad4643
CLAUDE.md: the CI section lists the five workflows
dghgit Oct 27, 2026
f25797d
From review REVIEW-2026-10-30-PR172-key-rework-memory-mythos.md: ciph…
dghgit Oct 30, 2026
e024c7a
From review REVIEW-2026-10-30-PR172-key-rework-memory-mythos.md: core…
dghgit Oct 30, 2026
8a82d76
From review REVIEW-2026-10-30-PR172-key-rework-memory-mythos.md: core…
dghgit Oct 30, 2026
84e0400
From review REVIEW-2026-10-30-PR172-key-rework-memory-mythos.md: hmac…
dghgit Oct 30, 2026
3a040e9
From review REVIEW-2026-10-30-PR172-key-rework-memory-mythos.md: sha2…
dghgit Oct 30, 2026
8855701
From review REVIEW-2026-10-30-PR172-key-rework-memory-mythos.md: sha3…
dghgit Oct 30, 2026
b360f07
From review REVIEW-2026-10-30-PR172-key-rework-memory-mythos.md: fact…
dghgit Oct 30, 2026
437b53b
From review REVIEW-2026-10-30-PR172-key-rework-memory-mythos.md: aes:…
dghgit Oct 30, 2026
5444ea3
From review REVIEW-2026-10-30-PR172-key-rework-memory-mythos.md: core…
dghgit Oct 30, 2026
2ceabe3
From review REVIEW-2026-10-30-PR172-key-rework-memory-mythos.md: core…
dghgit Oct 30, 2026
e6e8914
From review REVIEW-2026-10-30-PR172-key-rework-memory-mythos.md: ciph…
dghgit Oct 30, 2026
62ad79e
From review REVIEW-2026-10-30-PR172-key-rework-memory-mythos.md: aes:…
dghgit Oct 30, 2026
5a73ea5
From review REVIEW-2026-10-30-PR172-key-rework-memory-mythos.md: asco…
dghgit Oct 30, 2026
8d30219
From review REVIEW-2026-10-30-PR172-key-rework-memory-mythos.md: fact…
dghgit Oct 30, 2026
f6f3097
From review REVIEW-2026-10-30-PR172-key-rework-memory-mythos.md: hmac…
dghgit Oct 30, 2026
5f63075
From review REVIEW-2026-10-30-PR172-key-rework-memory-mythos.md: mem_…
dghgit Oct 30, 2026
2e5a183
From review REVIEW-2026-10-30-PR172-key-rework-memory-mythos.md: cli:…
dghgit Oct 30, 2026
234baab
From review REVIEW-2026-10-30-PR172-key-rework-memory-mythos.md: CLAU…
dghgit Oct 30, 2026
404d016
From review REVIEW-2026-10-30-PR172-correctness-mythos.md: sha3: KMAC…
dghgit Oct 30, 2026
496e3ad
From review REVIEW-2026-10-30-PR172-correctness-mythos.md: hkdf: the …
dghgit Oct 30, 2026
ee608a0
From review REVIEW-2026-10-30-PR172-correctness-mythos.md: cipher: CF…
dghgit Oct 30, 2026
778382d
From review REVIEW-2026-10-30-PR172-correctness-mythos.md: cli: the K…
dghgit Oct 30, 2026
8b71109
From review REVIEW-2026-10-31-PR172-fix-verification-mythos.md: cli: …
dghgit Oct 31, 2026
096bf63
From review REVIEW-2026-10-31-PR170-correctness-mythos.md: cipher: a …
dghgit Oct 31, 2026
0142fac
From review REVIEW-2026-10-31-PR170-correctness-mythos.md: cipher: GC…
dghgit Oct 31, 2026
bdd45b8
From review REVIEW-2026-10-31-PR170-correctness-mythos.md: core: a no…
dghgit Oct 31, 2026
534d182
From review REVIEW-2026-10-31-PR170-correctness-mythos.md: cipher: th…
dghgit Oct 31, 2026
4e8576b
QUALITY_AND_STYLE: cipher and MAC workers do not suspend; hashes, XOF…
dghgit Oct 31, 2026
12786cb
QUALITY_AND_STYLE: the suspend sentence says the remaining worker imp…
dghgit Oct 31, 2026
bb67b77
Merge branch 'feature/key-rework' into feature/key-rework-memory
dghgit Nov 2, 2026
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
76 changes: 69 additions & 7 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ The workspace has four top-level kinds of member:

- `crypto/core` defines the abstract traits (`Hash`, `KDF`, `MAC`, `KEM`, `Signature`, `RNG`, `Algorithm`, `HashAlgParams`, …), error enums (`HashError`, `KDFError`, `KEMError`, `MACError`, `RNGError`, `SignatureError`), and the `KeyMaterial` / `KeyType` wrapper that all sensitive byte buffers are required to use (see `Secret` super-trait requirement in QUALITY_AND_STYLE.md).
- `crypto/core-test-framework` contains the shared per-trait test suite (`hash.rs`, `kdf.rs`, `kem.rs`, `mac.rs`, `signature.rs`). New implementations of a core trait must be exercised through this framework — it's how trait conformance and error-condition coverage stay consistent across implementations.
- `crypto/factory` provides enum-based string-name factories (`HashFactory`, `KDFFactory`, `MACFactory`, `RNGFactory`, `XOFFactory`). Each factory enum impls the underlying trait so it can be used transparently as that primitive, and each impls `AlgorithmFactory` (`new(name)`, `default_128_bit()`, `default_256_bit()`). When adding a new primitive that fits an existing trait, register it in the corresponding factory.
- `crypto/factory` provides enum-based string-name factories (`HashFactory`, `KDFFactory`, `MACFactory`, `RNGFactory`, `XOFFactory`). Each factory enum impls the underlying trait so it can be used transparently as that primitive, except `MACFactory`, which is a key enum implementing the MAC role traits and handing out a `MACFactoryWorker` that impls `MAC`; and each impls `AlgorithmFactory` (`new(name)`, `default_128_bit()`, `default_256_bit()`). When adding a new primitive that fits an existing trait, register it in the corresponding factory.

Trait/factory/CLI is the standard layering: a new algorithm typically requires (a) the primitive crate, (b) implementing the relevant `core` trait, (c) wiring it into the matching factory, (d) a CLI subcommand in `cli/src/*_cmd.rs` registered in `cli/src/main.rs`.

Expand Down Expand Up @@ -173,10 +173,12 @@ taught, as mechanics to apply next time a cipher type is shaped or reshaped:
struct under the spec-spelled name (`Ascon_AEAD128<Dir>`, `#[allow(non_camel_case_types)]`)
is the whole public type, with no CamelCase twin and no alias to it.
- **The trait pair is the API.** Do not keep an inherent streaming or one-shot API beside the
`AEADCipher*` / `SymmetricCipher*` impls; everything a caller needs, including a supplied nonce
(`do_encrypt_init_nonce`, `encrypt_with_aad_nonce_out`), is on the traits. The only inherent
methods a cipher adds are for what the traits lack, in-place streaming (`do_*_inplace`), and
their decrypt form keeps the same tag hold-back as `do_decrypt_out` so the two interleave.
`AEADCipher*` / `SymmetricCipher*` impls; everything a caller needs is on the traits, and
everything that takes a key or draws a nonce, including a supplied nonce
(`create_encryptor_nonce`, `encrypt_with_aad_nonce_out`), is on the key object. The only
inherent methods a cipher adds are for what the traits lack, in-place streaming
(`do_*_inplace`), and their decrypt form keeps the same tag hold-back as `do_decrypt_out` so
the two interleave.
- **Private helpers must not share a trait method's name.** An inherent `do_encrypt_final` with a
different signature from the trait's is what forced the wrapper newtypes; name the core
helpers for what they do (`absorb_aad`, `encrypt_bytes`, `finish_tag`, `verify_tag`).
Expand All @@ -194,9 +196,57 @@ taught, as mechanics to apply next time a cipher type is shaped or reshaped:
a CLI path, run it against a known-answer vector (`--nonce` on `ascon-aead128` reproduces the
LWC KAT tag).
- **A rename stays in the crate it was asked for.** `do_*_update` to `do_*_inplace` was done for
Ascon; the CCM packet type still has its namesake. Note the follow-up rather than widening the
Ascon; the CCM type still has its namesake. Note the follow-up rather than widening the
change.

## Lessons from the key-object rework (October 2026)

The symmetric cipher and MAC traits lost their constructors and key-taking one-shots; keys took them.
What that taught, as mechanics for the next trait that sheds a constructor:

- **The trait describes a worker that exists.** `SymmetricCipherEncryptor`, `AEADCipherEncryptor`,
`BlockCipherEncryptor`, `StreamCipherEncryptor`, their decrypting halves and `MAC` carry only
streaming methods and length helpers. Construction is a key object's (`create_encryptor(rng)`,
`create_decryptor(init)`, `create_generator()`), and the one-shots are provided on the role
traits in `core::symmetric_key` over those. `KEY_LEN` is on the role and mode traits, never on
a worker trait.
- **Mode types carry the role.** A key is `AESKey<P, M>`; which role pairs it implements is
decided by `M`'s mode-trait impls in `core::hazmat::mode` (`SymmetricEncryptMode`,
`BlockEncryptMode`, `EcbEncryptMode`, `AeadEncryptMode`, `AeadDeclaredEncryptMode`, `MacMode`).
Padding and frame parameters live in the mode type (`CBC<PKCS7>`, `CBC<Blocks>`,
`ECB<Blocks>`, `CTR<12>`, `CCM_Packet<12, 16, 64, 1024>`), not on a worker alias.
- **The key length stops at the key.** `BlockPermutation<BLOCK_LEN>` carries the block methods
and `ElectronicCodeBook<KEY_LEN, BLOCK_LEN>` adds only `new`, so a worker and a mode's
`Mode<P>` impl bound on the former and never name a key length; the GCM, GMAC and CMAC impls
are generic in `cipher` for that reason. `KEY_LEN` stays on the mode traits' worker-producing
halves as the tie between a key's length and its permutation's, through
`P: ElectronicCodeBook<KEY_LEN, ..>`, which is what keeps a key object's role impls to the one
length. A mode that must know the block length (`CMAC<BLOCK_LEN>`, `CTR<N, BLOCK_LEN>`) takes
it as a parameter, since stable Rust cannot read it off the permutation inside the impl.
- **Test the key, not the worker pair.** The framework runners are `test_key` over a role pair
and the construction suites in `core_test_framework::from_key_material`; a test of "a key of the
wrong type is rejected" belongs to the construction suite, once, not to each mode's tests.
Known-answer suites keep pinning their IV through `create_encryptor` and a `FixedSeedRNG`.
- **Workers borrow the key.** The role and mode traits hand out workers through a generic
associated type with a lifetime, `type Encryptor<'k>`, and the cipher-crate workers hold
`&'k` to the mode's key state, so `create_encryptor` copies no schedule and a worker cannot
outlive its key. Spell the mode traits' GAT bound `where P: 'k`, not `where Self::KeyState: 'k`:
rustc rejects a generic impl whose key state is a struct over `P` (E0276) under the latter. A
function handed `key: &'k K` that names the worker is generic over `'k`; one that builds its
key locally bounds `for<'k> K::Encryptor<'k>: ..` with `K: 'static`. A test binds the key
before the worker, since `key_fn().create_encryptor(..)` borrows a temporary.
- **Resume takes the key object.** `SuspendableKeyed<'k, N>` and `SuspendableComponent<'k>` take
the key by `&'k`: a cipher-mode worker's `Key` is the mode's `KeyState`, reached through
`hazmat::ModeKey::state`, HMAC's is `HmacKey`, Ascon's is `AsconAEAD128Key`, and HKDF's stays
the salt material, since HKDF is not a key object. The suspended layouts did not change. A
worker that owns a copy of its key (Ascon, KMAC) implements the traits for every `'k` and
ignores it. A struct cannot hold a worker that borrows a key it also owns: HKDF runs its
extract-phase HMAC as the two halves `HmacKey::inner_state` / `finish_out`, and the MAC
factory is a key enum that hands out a worker enum.
- **What has no key-path twin is dropped, and said so.** `new_allow_weak_key` on a cipher-based
MAC, a wrong-length `KeyMaterial512` into a fixed-length key, GCM's verify-before-decrypt
one-shot override: each went with a line in the commit message rather than a shim.

## Working from specifications

QUALITY_AND_STYLE.md is where the requirement for spec-corresponding comments and justified deviations lives. This
Expand Down Expand Up @@ -243,4 +293,16 @@ external vector suites — is specified in QUALITY_AND_STYLE.md and CONTRIBUTING

## CI

The only workflow is `.github/workflows/publish_doc_benches_to_ghpages.yaml`: on every PR it builds rustdoc and runs `quality_stats.sh`; on `main` it additionally runs `cargo bench --all` and publishes docs, code stats, and benchmark results to GitHub Pages (`https://bcgit.github.io/bc-rust/`). There is no separate CI test/lint job — local `cargo test --workspace` is the gate, and nothing but a developer running it stands between a broken test and `main`.
Five workflows under `.github/workflows/`, all triggered by pull requests:

- `rust-build.yml`: `cargo build --workspace --all-targets --all-features` on stable.
- `rust-test.yml`: `cargo test --all` on stable.
- `rust-style.yml`: `cargo fmt --all --check` on **nightly** rustfmt, so format before every commit.
- `rust-docs.yml`: `cargo doc --all` on stable.
- `publish_doc_benches_to_ghpages.yaml`: builds rustdoc and runs `quality_stats.sh`; on `main` it also
publishes docs and code stats to GitHub Pages (`https://bcgit.github.io/bc-rust/`). Its bench step is
commented out because the benches are too slow on the hosted runner, so benchmark figures come from a
developer's machine, not CI.

`cargo test --all` is the workspace run, so a failing test does block a PR; what CI does not run is
`cargo mutants`, the CLI shell tests under `cli/tests/`, or rustdoc with warnings denied.
36 changes: 25 additions & 11 deletions QUALITY_AND_STYLE.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,13 @@ lib.rs for all crates needs to contain: `#![forbid(missing_docs)]`, `#![no_std]`

All primitives must be accompanied by a CLI in `/cli`.

All algorithms with a state that is exercised across multiple API calls -- typically through a `do_update()`,
`do_final()` pattern -- should implement SerializableState so that the user can pause the execution of this algorithm to
a cache and resume later.
Hashes, XOFs and the MACs and KDFs built on them (KMAC, HMAC, HKDF) implement `Suspendable` or `SuspendableKeyed`, so
that a computation in progress can be written to a cache and resumed later. Cipher and MAC workers -- the encryptors,
decryptors, generators and verifiers a key object hands out -- do not: a suspended or cloned worker is a second copy of
a nonce, counter or keystream position, and two copies that both go on to encrypt reuse keystream (#173). Those workers
implement neither suspend trait nor `Clone`; a message is paused by holding its worker, and the worker traits are kept
`dyn`-compatible so it can be held as `&mut dyn` or, where allocation is acceptable, `Box<dyn>`. The suspend and `Clone`
impls the cipher workers still carry come out in the #173 sweep.

# Quality

Expand Down Expand Up @@ -88,7 +92,13 @@ In addition, some library-specific naming conventions:
## APIs

Where possible, primitives should expose "one-shot APIs" that simply take data and return a result as a static member
function that does not require object instantiation.
function that does not require object instantiation. The exception is anything keyed: a symmetric cipher or MAC is
reached through a key object (`AES128Key<GCM>`, `HmacKey<SHA256>`, `KMAC128Key`, `AsconAEAD128Key`), built once from
`KeyMaterial` by `FromKeyMaterial` / `FromAnyKeyMaterial`, and its one-shots and `create_*` constructors are methods on
that key. The cipher and MAC traits in `core::traits` describe a worker that already exists and carry no constructor
and no key-taking method, so a key's validation and expansion happen once, where the key is made, rather than per call.
A worker borrows the key it came from, for the lifetime on the role trait's associated worker type, so making one
copies no schedule and a worker cannot outlive its key.

Other version of Bouncy Castle have a design pattern where stateful objects follow a pattern of new () -> init () ->
do_update () -> do_final (), and then optionally reset () that sets the object back to an unitialized state. Instead,
Expand Down Expand Up @@ -123,17 +133,21 @@ Take, for example a one-shot API `fn encrypt(plaintext: &[u8]) -> Result<Vec<u8>
The following prefixes can be applied:

* `do_`: this implies that it is part of a stateful streaming API, will typically take `&mut self`, and is likely
accompanied by a `do_encrypt_init()` and `do_encrypt_final()`.
accompanied by a `do_encrypt_final()`; the object comes from a key's `create_encryptor()`.
* `create_`: a key object's constructor for a worker -- `create_encryptor(&self, rng)`, `create_decryptor(&self,
init_data)`, `create_generator(&self)`, `create_verifier(&self)`. Whatever draws randomness takes a `&mut dyn RNG`
explicitly, so a key has no `_rng` twins and no method that reaches for a default RNG.

The following suffixes can be applied

* `_init / _update / _final`: indicates phase of a stateful streaming API. Other verbs can be used here as appropriate
to the primitive, such as `absorb / squeeze`, `encrypt / decrypt`, etc. `_init` is typically a static constructor
(though exceptions may exist), and `_final` indicates that this function call renders the object unusable afterwards
by consuming `self` via a move: `_final(self, ..)`.
* `_update / _final`: indicates phase of a stateful streaming API. Other verbs can be used here as appropriate to the
primitive, such as `absorb / squeeze`, `encrypt / decrypt`, etc. `_final` indicates that this function call renders
the object unusable afterwards by consuming `self` via a move: `_final(self, ..)`.
* `_rng`: indicates that this version of the function sources its random numbers from a provided `&mut dyn RNG` instead
of
from the default library RNG. `_rng(.., &mut dyn RNG)`.
of from the default library RNG. `_rng(.., &mut dyn RNG)`. Keyed primitives do not have it: their constructors and
one-shots take the RNG, full stop.
* `_nonce`: on an AEAD key, the twin that takes the nonce from the caller instead of drawing it from the RNG, and so
does not return one.
* `_out / _inplace`: indicates that the function works in the provided buffer. `_out` indicates that the function takes
an output buffer, which may be oversized, and returns the number of bytes written to it:
`_out(.., out: &mut [u8] -> Result<usize, SymmetricCipherError>`. `_inplace` indicates that the input and output are
Expand Down
37 changes: 19 additions & 18 deletions cli/src/aes_cbc_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@
//! separately.

use crate::helpers::block_mode_helpers::{
BLOCK_LEN, CipherDirection, decrypt_stream, encrypt_stream, load_iv, load_key,
BLOCK_LEN, CipherDirection, decrypt_stream, encrypt_stream, load_iv, load_key_object,
start_encryptor,
};
use bouncycastle::aes::{AES_CBC_128, AES_CBC_192, AES_CBC_256};
use bouncycastle::aes::{AES128Key, AES192Key, AES256Key};
use bouncycastle::cipher::modes::CBC;
use bouncycastle::cipher::padding::PKCS7;
use bouncycastle::cipher::{Decrypting, Encrypting};
use bouncycastle::core::key_material::KeyMaterial;
use bouncycastle::core::traits::{SymmetricCipherDecryptor, SymmetricCipherEncryptor};
use bouncycastle::core::symmetric_key::{SymmetricDecryptionKey, SymmetricEncryptionKey};

pub(crate) fn aes128_cbc_cmd(
action: &CipherDirection,
Expand All @@ -26,9 +26,9 @@ pub(crate) fn aes128_cbc_cmd(
iv_file: &Option<String>,
output_hex: bool,
) {
run::<AES_CBC_128<Encrypting, PKCS7>, AES_CBC_128<Decrypting, PKCS7>, 16>(
run::<_, 16>(
action,
&load_key::<16>(key, key_file, "AES-128"),
&load_key_object::<AES128Key<CBC<PKCS7>>, 16>(key, key_file, "AES-128"),
load_iv::<BLOCK_LEN>(iv, iv_file),
output_hex,
);
Expand All @@ -42,9 +42,9 @@ pub(crate) fn aes192_cbc_cmd(
iv_file: &Option<String>,
output_hex: bool,
) {
run::<AES_CBC_192<Encrypting, PKCS7>, AES_CBC_192<Decrypting, PKCS7>, 24>(
run::<_, 24>(
action,
&load_key::<24>(key, key_file, "AES-192"),
&load_key_object::<AES192Key<CBC<PKCS7>>, 24>(key, key_file, "AES-192"),
load_iv::<BLOCK_LEN>(iv, iv_file),
output_hex,
);
Expand All @@ -58,30 +58,31 @@ pub(crate) fn aes256_cbc_cmd(
iv_file: &Option<String>,
output_hex: bool,
) {
run::<AES_CBC_256<Encrypting, PKCS7>, AES_CBC_256<Decrypting, PKCS7>, 32>(
run::<_, 32>(
action,
&load_key::<32>(key, key_file, "AES-256"),
&load_key_object::<AES256Key<CBC<PKCS7>>, 32>(key, key_file, "AES-256"),
load_iv::<BLOCK_LEN>(iv, iv_file),
output_hex,
);
}

/// Dispatches to the shared streaming loops.
fn run<E, D, const KEY_LEN: usize>(
/// Dispatches to the shared streaming loops under the key's padded CBC mode.
fn run<K, const KEY_LEN: usize>(
action: &CipherDirection,
key: &KeyMaterial<KEY_LEN>,
key: &K,
iv: Option<[u8; BLOCK_LEN]>,
output_hex: bool,
) where
E: SymmetricCipherEncryptor<KEY_LEN, BLOCK_LEN, BLOCK_LEN>,
D: SymmetricCipherDecryptor<KEY_LEN, BLOCK_LEN, BLOCK_LEN>,
K: SymmetricEncryptionKey<KEY_LEN, BLOCK_LEN, BLOCK_LEN>
+ SymmetricDecryptionKey<KEY_LEN, BLOCK_LEN, BLOCK_LEN>,
{
match action {
CipherDirection::Encrypt => {
encrypt_stream::<E, KEY_LEN, BLOCK_LEN>(key, iv, output_hex, None)
let (enc, generated_iv) = start_encryptor(iv, |rng| key.create_encryptor(rng));
encrypt_stream::<_, BLOCK_LEN>(enc, generated_iv.as_ref(), output_hex, None)
}
CipherDirection::Decrypt => {
decrypt_stream::<D, KEY_LEN, BLOCK_LEN>(key, iv, output_hex, None)
decrypt_stream::<_, BLOCK_LEN>(iv, |iv| key.create_decryptor(iv), output_hex, None)
}
}
}
10 changes: 5 additions & 5 deletions cli/src/aes_ccm_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
//! `ascon-aead128`, are the streaming alternatives.
//!
//! The AAD is read whole too: the key's one-shot takes it as a slice. (A.2.2 needs its length
//! before its first byte, so streaming it would need the declared-length constructor the packet
//! type keeps for itself.)
//! before its first byte, so streaming it would need the declared-length constructor the type
//! keeps for itself.)
//!
//! # The nonce is supplied, not generated
//!
Expand Down Expand Up @@ -53,7 +53,7 @@ use bouncycastle::cipher::modes::CCM;
use bouncycastle::core::errors::SymmetricCipherError;
use bouncycastle::core::key_material::KeyMaterial;
use bouncycastle::core::symmetric_key::{
AeadPacketDecryptionKey, AeadPacketEncryptionKey, FromKeyMaterial,
AeadDeclaredDecryptionKey, AeadDeclaredEncryptionKey, FromKeyMaterial,
};
use bouncycastle::hex;

Expand All @@ -68,8 +68,8 @@ use crate::helpers::block_mode_helpers::{CipherDirection, load_key};
trait CcmKeys<const KEY_LEN: usize> {
/// The key type at nonce length `N` and tag length `T`.
type Key<const N: usize, const T: usize>: FromKeyMaterial<KEY_LEN>
+ AeadPacketEncryptionKey<KEY_LEN, N, T, T>
+ AeadPacketDecryptionKey<KEY_LEN, N, T, T>;
+ AeadDeclaredEncryptionKey<KEY_LEN, N, T, T>
+ AeadDeclaredDecryptionKey<KEY_LEN, N, T, T>;
}

struct Aes128;
Expand Down
Loading
Loading