Repository navigation
Conversation
officialfrancismendoza
added a commit
to officialfrancismendoza/bc-rust
that referenced
this pull request
Oct 21, 2026
officialfrancismendoza
added a commit
that referenced
this pull request
Oct 22, 2026
Keeping a key to one algorithm is moving to compile-time key types (#167), so the opt-in runtime binding that 0de70ae added goes. Nothing outside the tests ever bound a key, so no cipher call outside them changes outcome; KeyMaterial's Display/Debug lose the `algorithm` field. Removed: - KeyMaterial's `algorithm` field and KeyMaterialTrait::algorithm, set_algorithm and check_algorithm. - The 26 check_algorithm calls: 24 in crypto/cipher, one in Ascon's checked_key, one in the ToyCbc test double. The cipher imports go back to KeyMaterial alone. - The framework's key_binding module and its four suite blocks, two tests in key_material_tests.rs, and aes/tests/key_binding_tests.rs, including the cross-size test 6994217 added there. This is not `git revert 0de70ae`: that commit also folded the two ToyBlockCipher copies into the cipher crate's, which stays, and a plain revert conflicts with 6994217. Files no later commit touched are back to 0de70ae~1 byte for byte. #172's from_key_material and #157's ChaCha20 keys still call check_algorithm, and need the same removal when they next merge this. cargo test --workspace --no-fail-fast: 1106 passed, 1 failed. The failure is ascon_wycheproof, whose vector file is missing from the local wycheproof checkout; it fails the same way without this change. Assisted-by: Claude:claude-opus-5-5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dghgit
force-pushed
the
feature/key-rework
branch
from
October 24, 2026 09:53
69e24ba to
a615121
Compare
hubot
force-pushed
the
feature/key-rework
branch
from
October 24, 2026 10:06
a615121 to
69e24ba
Compare
…airs (prototype) Three more key paths beside the AEAD, packet and MAC ones, so that every mode in the tree can be reached from a mode-bound key: SymmetricEncryptionKey / SymmetricDecryptionKey over a SymmetricCipherEncryptor / Decryptor worker (padded CBC, CFB, CFB8, CTR), BlockEncryptionKey / BlockDecryptionKey over the whole-block pair (CBC with no padding layer), and EcbEncryptionKey / EcbDecryptionKey in hazmat, whose constructors take no RNG since ECB draws nothing. Each has its hazmat mode pair (SymmetricEncryptMode and friends) for a mode type to implement. The one-shots are provided over create_* and the worker's streaming methods; the symmetric pair's in-place forms are gated on the worker being a stream cipher. The workers are bounded on the cipher traits themselves, so KEY_LEN rides along until the constructors leave those traits. Assisted-by: Claude:claude-mythos-5-1
…(prototype) test_key variants of the symmetric, stream, block, AEAD and tagged-layout runners and the MAC runner, each driving a role-trait key with a caller-supplied RNG, plus an ECB variant that takes none. The key-type, algorithm-binding and strength checks those runners made at every do_*_init move to TestFrameworkFromKeyMaterial and TestFrameworkFromAnyKeyMaterial, which check them once, where the key is made. The E/D-generic runners stay until the constructors leave the cipher traits. Assisted-by: Claude:claude-mythos-5-1
…me (prototype) CBC<X>, CFB, CFB8, CTR<NONCE_LEN, BLOCK_LEN> and hazmat::ECB<X> implement Mode<P> over any ModeNames permutation, and the role-side mode traits: CBC<Pad> and ECB<Pad> the symmetric pair through the padding adapters, CBC<Blocks> the block pair, ECB<Blocks> the ECB pair, the stream modes the symmetric pair with no final output. CCMFrame<N, T, A, D> puts the fixed-frame CCM pair on the AEAD mode traits. The worker types gain crate-private from_perm / from_inner constructors so the modes can build them from a key state; the trait constructors stay until the deletion step. Assisted-by: Claude:claude-mythos-5-1
A 16-byte key drawn from a 256-bit DRBG was tagged 256-bit, a figure set_security_strength refuses for that length, so retagging such a key (as a MAC mode's key does to hand it to the permutation) failed. The strength is now the lower of the RNG's and the one the length supports. Assisted-by: Claude:claude-mythos-5-1
tests/common/toy_key.rs is a ToyKey<P, M> with the AES key's shape: FromKeyMaterial over any 16-byte toy permutation, the role impls forwarded to M's mode traits, and ToyGCM / ToyGMAC / ToyCMAC standing in for the modes whose key state needs the key length. The mode, padding and suspend tests build their workers from it and the mode types, the conformance runs move to the test_key runners, and each key gets the construction suite in place of the per-test wrong-key-type checks. The padded_tests toy, an 8-byte XOR cipher with its own trait constructors, is replaced by CBC<PKCS7> / CBC<NoPadding> over the shared toy; the ECB RNG-panic tests go, since the ECB key path has no RNG-taking entry point. Assisted-by: Claude:claude-mythos-5-1
The module examples built their workers through the trait constructors. They now build the mode's key state and call the mode traits, which is what a mode-bound key does, with GCM and CMAC on their from_key_state routes; the one-shots are the key's and are shown in the key crate. The CcmEncryptor examples and compile_fail checks move to CCMFrame. Assisted-by: Claude:claude-mythos-5-1
The 128-bit key validated once, on FromKeyMaterial, with the AEAD role pair handing out Ascon_AEAD128<Encrypting> / <Decrypting> per message; the cipher's constructor splits into the key check and the per-message init so both routes share it. The workers get the temporary worker-trait forwarding the role traits are bounded on. Tests, the bench and the memory harness move onto the key, the key gets the construction suite, and the crate docs show the key. The stack-usage rows for the init and one-shot entry points are withdrawn until they are re-measured on the key path. Assisted-by: Claude:claude-mythos-5-1
KMACKeyInternal<PARAMS>, as KMAC128Key / KMAC256Key: the cSHAKE state after the key binding of SP 800-185 Sec 4.3 step 1, with the customization and output length that make it one KMAC function, on FromAnyKeyMaterial (nominal length, no customization) and with_params / with_params_allow_weak for the rest, handing out KMACInternal workers through the MAC role pair. KMACInternal::new_with_params becomes the crate's own, written over the key; MAC::new stays until the deletion. The tests move onto the key and gain the construction suite; the CLI's mac commands build KMACKey and HmacKey objects in place of the trait constructors. Assisted-by: Claude:claude-mythos-5-1
As KeyMaterial::from_rng now does: a 28-byte HMAC-SHA224 key drawn from a 256-bit DRBG was tagged 256-bit, which set_security_strength refuses for that length. Assisted-by: Claude:claude-mythos-5-1
MACFactory::new makes an HmacKey or KMACKey from the material and hands out its generator, in place of MAC::new on the worker; the trait's own new and new_allow_weak_key arms go with the deletion. Assisted-by: Claude:claude-mythos-5-1
…o the key path (prototype) AESKey<P, M> forwards the symmetric, block and hazmat ECB role pairs to M's mode traits, so AES128Key<CBC<PKCS7>>, <CBC<Blocks>>, <CFB>, <CFB8>, <CTR>, <ECB<Blocks>>, <ECB<PKCS7>> and <CCMFrame<..>> are keys. The tests, benches, the CCM memory harness and the module docs move off the trait constructors and static one-shots onto the keys: the known-answer suites pin their IVs through create_encryptor and a FixedSeedRNG as before, the generic helpers are generic over the key type, the construction suite replaces the per-test wrong-key checks, and mode_key_tests.rs runs the framework over every new mode key. Dropped with no key path equivalent: the CMAC new_allow_weak_key acceptances and the wrong-length KeyMaterial512 refusals (a cipher key's length is in its type); the fixed-frame CCM key's one-shots take the frame length, so the "any length" cases move to the CCM packet key. The modes benches draw IVs from a FixedSeedRNG outside the timed closure, where the trait constructors drew from an OS DRBG inside it. Assisted-by: Claude:claude-mythos-5-1
The block, stream and GCM helpers take the key, or the worker it made, in place of the key material: load_key_object builds the AES key type a command's mode wants, the encrypt side draws its IV or nonce from the OS DRBG through create_encryptor, and the decrypt side's create_decryptor is infallible. The Ascon command builds an AsconAEAD128Key the same way. Output is unchanged: every cli/tests script passes. Assisted-by: Claude:claude-mythos-5-1
…g one-shots (prototype) SymmetricCipherEncryptor / Decryptor, AEADCipherEncryptor / Decryptor, BlockCipher* and StreamCipher* now describe a worker that already exists: do_encrypt_init, do_encrypt_init_rng, do_encrypt_init_nonce, do_decrypt_init and every static one-shot over them are gone, and with them the KEY_LEN parameter, which was only ever the material's. MAC loses new and new_allow_weak_key. Construction is a key object's (create_encryptor / create_decryptor / create_generator) and the one-shots are the role traits' in core::symmetric_key; the temporary AeadEncryptWorker / AeadDecryptWorker traits fold back into the AEAD cipher traits, which the role and mode traits bound on directly. Downstream, the impls go from the cipher modes, the padding adapters, the stream wrapper, Ascon-AEAD128, HMAC, KMAC and CMAC; the CCM packet workers and GMAC's material route are rewritten over the key state; the test framework drops its E/D-generic runners and test_mac; the HMAC callers in the hmac, sha2, sha3 and sm3 crates (tests, benches, docs) move onto HmacKey; the last GCM and CCM test helpers in aes move onto the keys. Dropped with no key-path twin: GCM's verify-before-decrypt one-shot override (the provided one-shots zeroize on failure), and the comparisons against the worker constructors, which now compare against the key-state route or an RFC reference. QUALITY_AND_STYLE.md's API and naming rules say where construction lives, and CLAUDE.md records the lessons. quality_stats.sh, ./crypto, before and after the branch: unwraps in core code 827 -> 798, Err() in core code 474 -> 446, test ratio .95 -> .98. Assisted-by: Claude:claude-mythos-5-1
…ared-length side loses "packet" (prototype)
The fixed-frame mode type is CCM_Packet<N, T, AAD_LEN, DATA_LEN>, was CCMFrame,
spelled as the spec spells it with #[allow(non_camel_case_types)] like
Ascon_AEAD128. Its workers are CcmPacketEncryptor / CcmPacketDecryptor, taking
the names from the any-length pair, which becomes CcmEncryptor / CcmDecryptor
over the crate-private engine, now Ccm<P, Dir, ..>. The core traits that pair
implements go from AeadPacket{Encrypt,Decrypt}Mode and
AeadPacket{Encryption,Decryption}Key to AeadDeclared*, after the lengths they
take per message. The test and bench aliases (Frame, ToyCcmFrame,
Aes128CcmFrameKey) follow as Packet, ToyCcmPacket and Aes128CcmPacketKey, and
"packet" in the docs, test names and the CLI bound follows the same split. The
GCM packet bench keeps its word, which is the ordinary one.
Assisted-by: Claude:claude-mythos-5-1
…edule (prototype) The role traits in core::symmetric_key and the mode traits in core::hazmat hand out their workers through a generic associated type with a lifetime, `type Encryptor<'k>`, and `create_encryptor` takes `&'k self`; every worker in the cipher crate (Cbc, Cfb, Cfb8, CtrKeyStream, Ecb, Gcm, Gmac, Cmac, the CCM engine and both CCM pairs) holds `&'k` to the mode's key state, so making a worker copies the per-message state and nothing else, and a worker cannot outlive its key. The mode traits spell the bound `where P: 'k`: rustc rejects a generic impl whose key state is a struct over `P` under `Self::KeyState: 'k`. What that removes: `KeyStream::new` and its `KEY_LEN`, `Gmac::new` / `new_nonce` (the last material route), `Cmac::init`, and every `P::new` on resume. SuspendableKeyed and SuspendableComponent gain the lifetime and take the key by `&'k`; a cipher-mode worker's `Key` is now the mode's `KeyState`, which a key object exposes through the new `core::hazmat::ModeKey::state` (AESKey and the test ToyKey implement it), and the suspended layouts are unchanged. The test framework's keystream suite takes a constructor closure and leaves the key-policy checks to the construction suite. Ascon, HMAC, KMAC and HKDF keep owned workers (HKDF embeds an HMAC worker) and implement the traits for every `'k`. Sizes: the CCM workers go from 264/296/328 B to 96 B at every key length, the CCM_Packet pair from 344 B to 176 B, the CMAC workers from 248/280/312 B to 48 B; the CCM peak-stack table is re-measured with massif (in place 19 328 -> 18 608 B). Tests bind the key before the worker, since the worker borrows it. quality_stats.sh, ./crypto: unwraps in core code 798 -> 784, Err() 446 -> 440, test ratio .98 unchanged. Assisted-by: Claude:claude-mythos-5-1
…y length leaves the workers (prototype) `BlockPermutation<BLOCK_LEN>` now carries the block methods and `ElectronicCodeBook<KEY_LEN, BLOCK_LEN>` adds only `new`. Every worker in the cipher crate and every `Mode<P>` impl bound on the former and no longer name a key length, so the GCM, GMAC and CMAC impls that `aes` wrote three times over are written once in `cipher`, generic over the permutation, and the cipher crate's tests lose their ToyGCM / ToyGMAC / ToyCMAC stand-ins. CMAC takes the block length as a parameter, `CMAC<BLOCK_LEN = 16>`, as CTR does. The AES GMAC pair becomes one inherent impl over `AESParams`. With that, `KEY_LEN` goes from every worker type (Cbc, Cfb, Cfb8, Ecb, CtrKeyStream, Ctr, StreamCipher, the padding adapters, Gcm, Gmac, Cmac, Ccm and both CCM pairs) and from `GcmKeyState::new` / `CmacKeyState::new`; the AES aliases follow. It stays on the mode traits' worker-producing halves, where `P: ElectronicCodeBook<KEY_LEN, ..>` is the tie between a key's length and its permutation's and is what keeps a key object's role impls to the one length. No layout, vector or size changes. quality_stats.sh, ./crypto: code lines 29792 -> 29432; unwraps and Err() unchanged at 784 / 440. Assisted-by: Claude:claude-mythos-5-1
…es the key object (prototype) `HMAC<'k, H>` holds the inner hash and a reference to the `HmacKey` it came from, whose outer pad state it is finished through, so a worker is one hash state plus a pointer rather than two states: 224 -> 120 bytes for the SHA-256 family, 416 -> 216 for SHA-512, 880 -> 448 for SHA-3. The two halves of the worker are public on the key as `inner_state` and `finish_out`, which is how HKDF's extract phase now runs: a struct cannot own a key and a worker that borrows it, so HKDF keeps the salt key and the inner hash and finishes through the key. Its suspended layout is unchanged. The MAC factory becomes a key enum, `MACFactory`, that hands out a worker enum, `MACFactoryWorker<'k>`, through the MAC role traits; its one-shots are the role traits' and its streaming goes through `create_generator`. Resume takes the key object where there is one: `HMAC`'s `SuspendableKeyed::Key` is `HmacKey`, Ascon-AEAD128's is `AsconAEAD128Key`, with no re-validation on resume since the key object was validated when it was made. HKDF's stays the salt material. No suspended layout changes. quality_stats.sh, ./crypto: unwraps in core code 784 -> 782, Err() 440 unchanged. Assisted-by: Claude:claude-mythos-5-1
They exist for HKDF's extract phase and are not part of the key's documented API; the worker is the way onto HMAC. Assisted-by: Claude:claude-mythos-5-1
Every row of the Ascon-AEAD128 and sponge tables is re-read from the frame remarks and the assembly of the release build, with the same method as before, under one compiler (rustc 1.97.0-nightly): the key check, the constructors and the one-shots, which had been withdrawn when the key objects arrived, get their figures, and the rows that had stood since the direction moved into the type are brought up to date. The sponge rows come out 8 bytes lower than the old figures under this compiler. Assisted-by: Claude:claude-mythos-5-1
dghgit
force-pushed
the
feature/key-rework-memory
branch
from
October 24, 2026 10:17
af15bb9 to
6c5e223
Compare
dghgit
force-pushed
the
feature/key-rework
branch
from
October 24, 2026 10:19
69e24ba to
a615121
Compare
This was referenced Oct 24, 2026
This was referenced Oct 24, 2026
…type) Lifted from #167, whose SymmetricCipherKey bound every key on PartialEq + Eq: a caller that holds two keys can ask whether they are the same key without reaching the material, which the key objects never hand back. Equality is over the expanded state and decided in constant time at every layer. AESInternal compares its schedule through Secret's byte-wise equality, which inspects every byte (round key 0 is the key itself, so two schedules are equal exactly when the keys are); GcmKeyState and CmacKeyState compare the permutation and their derived values joined with `&` rather than `&&`, so the time taken does not say which field differed; AESKey<P, M> is equal when its mode state is, bounded on the state rather than on Mode::KeyState so that a permutation without the impl still has keys; AsconAEAD128Key compares its Secret words. Mode::KeyState's docs now say that a state implementing PartialEq must compare in constant time. Tests: equality follows the material, for a clone, the same bytes and a single differing byte, through the bare schedule (CTR), GCM at 128 and 256 bits, CMAC and Ascon. Assisted-by: Claude:claude-mythos-5-1
…warnings denied again (prototype) BlockEncryptionKey's one-shot doc linked BlockCipherEncryptor::do_encrypt_inplace, which left that trait with the rebase; it now names do_encrypt_blocks_inplace. The AEAD helper module's link to SymmetricCipherDecryptor carried an explicit target the label already resolves to, which rustdoc now reports as redundant. Assisted-by: Claude:claude-mythos-5-1
dghgit
force-pushed
the
feature/key-rework-memory
branch
2 times, most recently
from
October 25, 2026 07:54
44855df to
9c343a5
Compare
roy-basmacier
pushed a commit
to roy-basmacier/bc-rust
that referenced
this pull request
Oct 25, 2026
Adds the three BLAKE hashes requested in bcgit#123 for OpenSSL provider provisioning, on the key-object API of feature/key-rework-memory (bcgit#172): two new crates wired into the factories, the CLI and the stack-memory benches. Other BLAKE2 digest lengths, salt/personalisation, BLAKE2bp/sp/X and tree mode are out of scope. blake2 (new crate bouncycastle-blake2): - BLAKE2b_512 and BLAKE2s_256 implement Hash and Suspendable; G, F, the parameter block and the final-t rule are commented against RFC 7693 s. 3.1-3.3. blake2b.rs and blake2s.rs are kept structurally identical. - The native keyed mode (not HMAC): key objects BLAKE2b_512_MACKey and BLAKE2s_256_MACKey (FromAnyKeyMaterial, MacGenerationKey, MacVerificationKey) hand out BLAKE2b_512_MAC / BLAKE2s_256_MAC workers. Key checks run type, then strength, then length (1..=64 / 1..=32). - AlgorithmOID: id-blake2b512 and id-blake2s256 (RFC 7693 s. 4), on the hash and MAC types. blake3 (new crate bouncycastle-blake3): - BLAKE3 implements Hash and XOF in hash mode (new) and derive_key mode (new_derive_key); BLAKE3Squeezer streams the extended output. - keyed_hash: key object BLAKE3KeyedHashKey (exactly 32 bytes) hands out BLAKE3KeyedHash workers, which keep an inherent into_squeezer for extended output. BLAKE3KeyedSqueezer is deliberately not Suspendable. - The engine follows the reference implementation's chunk state and 54-entry CV stack (spec s. 2.4-2.6, 5.1). Both crates: - MAC output truncates to the caller's buffer with a 4-byte floor (MIN_MAC_OUTPUT_LEN); every _out function zeroizes the buffer before any error check. Partial-bit input: 0 bits is a whole-byte message, 1..=7 returns InvalidInput, more returns InvalidLength. - Keyed workers implement SuspendableKeyed with the key object as the key. Suspended states hold no key bytes, and resume rebuilds the key-derived fields from the key object. - Design note: a suspended keyed state still lets its holder compute tags for extensions of the absorbed prefix (BLAKE2 once the key block is compressed; BLAKE3 only within the first chunk). HMAC does not have this property. It is documented and pinned by tests. factory: HashFactory gains BLAKE2b-512, BLAKE2s-256 and BLAKE3; XOFFactory gains BLAKE3; MACFactory gains the three BLAKE MAC keys and workers. cli: blake2b-512, blake2s-256, blake2b-512-mac, blake2s-256-mac, blake3, blake3-keyed-hash and blake3-derive-key, all streaming. cli/tests/ test_blake.sh adds 16 tests on the shell harness. tests: RFC 7693 Appendix A/B, selections from the official BLAKE2 KAT, the bc-test-data Blake2KAT.txt sweep (512 + 512 records), all 35 official BLAKE3 vectors in all three modes, and the core-test-framework suites for Hash, XOF, MAC keys, key construction and suspend/resume. Wycheproof has no BLAKE vectors. cargo mutants: blake2 378 tested, 10 missed; blake3 384 tested, 9 missed, 8 timeouts (non-terminating loops); every miss is an equivalent rewrite with a "Mutants note:" at the site. #![no_std] remains a todo in both crates, as in every hash crate, blocked by the Vec return types in core::traits::Hash. Assisted-by: Claude:claude-mythos-5-1 Assisted-by: Claude:claude-fable-5-1 Assisted-by: Claude:claude-opus-5-5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
roy-basmacier
pushed a commit
to roy-basmacier/bc-rust
that referenced
this pull request
Oct 25, 2026
Adds the three BLAKE hashes requested in bcgit#123 for OpenSSL provider provisioning, on the key-object API of feature/key-rework-memory (bcgit#172): two new crates wired into the factories, the CLI and the stack-memory benches. Other BLAKE2 digest lengths, salt/personalisation, BLAKE2bp/sp/X and tree mode are out of scope. blake2 (new crate bouncycastle-blake2): - BLAKE2b_512 and BLAKE2s_256 implement Hash and Suspendable; G, F, the parameter block and the final-t rule are commented against RFC 7693 s. 3.1-3.3. blake2b.rs and blake2s.rs are kept structurally identical. - The native keyed mode (not HMAC): key objects BLAKE2b_512_MACKey and BLAKE2s_256_MACKey (FromAnyKeyMaterial, MacGenerationKey, MacVerificationKey) hand out BLAKE2b_512_MAC / BLAKE2s_256_MAC workers. Key checks run type, then strength, then length (1..=64 / 1..=32). - AlgorithmOID: id-blake2b512 and id-blake2s256 (RFC 7693 s. 4), on the hash and MAC types. blake3 (new crate bouncycastle-blake3): - BLAKE3 implements Hash and XOF in hash mode (new) and derive_key mode (new_derive_key); BLAKE3Squeezer streams the extended output. - keyed_hash: key object BLAKE3KeyedHashKey (exactly 32 bytes) hands out BLAKE3KeyedHash workers, which keep an inherent into_squeezer for extended output. BLAKE3KeyedSqueezer is deliberately not Suspendable. - The engine follows the reference implementation's chunk state and 54-entry CV stack (spec s. 2.4-2.6, 5.1). Both crates: - MAC output truncates to the caller's buffer with a 4-byte floor (MIN_MAC_OUTPUT_LEN); every _out function zeroizes the buffer before any error check. Partial-bit input: 0 bits is a whole-byte message, 1..=7 returns InvalidInput, more returns InvalidLength. - Keyed workers implement SuspendableKeyed with the key object as the key. Suspended states hold no key bytes, and resume rebuilds the key-derived fields from the key object. - Design note: a suspended keyed state still lets its holder compute tags for extensions of the absorbed prefix (BLAKE2 once the key block is compressed; BLAKE3 only within the first chunk). HMAC does not have this property. It is documented and pinned by tests. factory: HashFactory gains BLAKE2b-512, BLAKE2s-256 and BLAKE3; XOFFactory gains BLAKE3; MACFactory gains the three BLAKE MAC keys and workers. cli: blake2b-512, blake2s-256, blake2b-512-mac, blake2s-256-mac, blake3, blake3-keyed-hash and blake3-derive-key, all streaming. cli/tests/ test_blake.sh adds 16 tests on the shell harness. tests: RFC 7693 Appendix A/B, selections from the official BLAKE2 KAT, the bc-test-data Blake2KAT.txt sweep (512 + 512 records), all 35 official BLAKE3 vectors in all three modes, and the core-test-framework suites for Hash, XOF, MAC keys, key construction and suspend/resume. Wycheproof has no BLAKE vectors. cargo mutants: blake2 378 tested, 10 missed; blake3 384 tested, 9 missed, 8 timeouts (non-terminating loops); every miss is an equivalent rewrite with a "Mutants note:" at the site. #![no_std] remains a todo in both crates, as in every hash crate, blocked by the Vec return types in core::traits::Hash. Assisted-by: Claude:claude-mythos-5-1 Assisted-by: Claude:claude-fable-5-1 Assisted-by: Claude:claude-opus-5-5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # crypto/factory/src/mac_factory.rs
The call-state byte held only the phase, and the SuspendableKeyed impl is one impl generic over `Dir`, so a state suspended while encrypting resumed as a decryptor and the reverse. `Direction` gains `STATE_BITS` (0x10 encrypting, 0x20 decrypting), GCM writes them above the phase nibble and refuses a state whose bits are the other direction's. The layout and length are unchanged. Found by the PR #157 review follow-up; Ascon already refuses the other direction. Assisted-by: Claude:claude-mythos-5-1
…m binding Assisted-by: Claude:claude-mythos-5-1
…g instead of panicking A non-hex `--key`, a missing `--key-file` or a non-hex `-v` value each printed a panic from an unwrap; they now exit with the same messages the cipher commands use. Key-file bytes are still taken raw, as before. Assisted-by: Claude:claude-mythos-5-1
Assisted-by: Claude:claude-mythos-5-1
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Issue Link
No issue filed. This continues the key object rework prototype in #170, which it is based on, and takes it to the end of the document's plan: the trait constructors go, and the workers borrow their keys.
Summary
The symmetric cipher and MAC traits lose their constructors and key-taking one-shots; every mode, Ascon-AEAD128 and KMAC get key objects; and a worker borrows the key it is made from, so creating an encryptor, decryptor, generator or verifier copies the per-message state and nothing else.
Description
SymmetricCipher*,AEADCipher*,BlockCipher*,StreamCipher*andMACcarry only streaming methods and length helpers. Construction is a key'screate_*, and the one-shots are provided on the role traits incore::symmetric_keyover them.KEY_LENis on the role and mode traits, never on a worker.CBC<X>,CFB,CFB8,CTR<N, B>,hazmat::ECB<X>,CCM<N, T>,CCM_Packet<N, T, A, D>,GCM<T>,GMAC<T>andCMAC<B>are mode types a key is bound to;AsconAEAD128KeyandKMAC128Key/KMAC256KeyjoinAESKey<P, M>andHmacKey<H>. The MAC factory is a key enum that hands out a worker enum. The CLI, the test framework (test_keyrunners and the construction suites) and the memory benches run on keys.type Encryptor<'k>, andcreate_encryptortakes&'k self. Every cipher-crate worker holds&'kto the mode's key state;HMAC<'k, H>holds&'k HmacKey<H>. Ascon and KMAC keep owned workers, since their working state is the key-dependent sponge. A key must outlive its workers, which the compiler enforces.BlockPermutation<BLOCK_LEN>carries the block methods andElectronicCodeBook<KEY_LEN, BLOCK_LEN>addsnew, so a mode'sMode<P>impl never names a key length and the GCM, GMAC and CMAC impls are written once incipher.KEY_LENstays on the mode traits' worker halves as the tie between a key's length and its permutation's, which is what keeps a key object's role impls to the one length.SuspendableKeyed<'k, N>andSuspendableComponent<'k>take the key by&'k: a cipher-mode worker'sKeyis the mode'sKeyState, reached throughcore::hazmat::ModeKey::state; HMAC's isHmacKey; Ascon's isAsconAEAD128Key; HKDF's stays the salt. No suspended layout changed.where P: 'k, notwhere Self::KeyState: 'k: a generic impl whose key state is a struct overPis rejected under the latter (E0276). CLAUDE.md records this with the rest of the mechanics.SymmetricCipherKey: PartialEq + Eq:AESKey<P, M>, its mode states (AESInternal,GcmKeyState,CmacKeyState) andAsconAEAD128KeyimplementPartialEq/Eqover the expanded state, every byte inspected and the fields joined with&, so two keys can be compared without the material being reachable.AESKey's impl is bounded on the state, not onMode::KeyState, so a permutation without the impl still has keys.new_allow_weak_keyon cipher-based MACs,Gmac::new/new_nonceandKeyStream::new(the last material routes), GCM's verify-before-decrypt one-shot override, the ECB RNG-panic tests.Measured
Struct sizes, and massif for the stack row; HMAC from
size_of:The Ascon stack table is re-measured on the key path with the frame-remark method the bench documents.
Scope and Risk
core,utils,cipher,aes,ascon,sha2,sha3,sm3,hmac,hkdf,factory,core-test-framework,cli,mem_usage_benches, plus CLAUDE.md and QUALITY_AND_STYLE.md. 148 files, +8855 / -8976 againstfeature/key-rework, in 19 commits.Validation
AI Usage Statement
Did you use AI in creating this pull request:
Assisted-by: Claude:claude-mythos-5-1