Repository navigation
Conversation
…into feature/stream-cipher
…ems like a personal workflow rather than a general thing.
…Added a note about this to QUALITY_AND_STYLE.md.
…so the lib target the src/ move introduced does not compile them as failing Rust doctests
…ding, and the SHA-512/t sealing trait is now named SHA512InitValue
….6 prints it, with H(0)'' on the left of the XOR and as the IV of the final SHA-512 call
…enches sources moved under src/ and are now doctested, and integration tests are preferred per QUALITY_AND_STYLE.md
…, dropping the one- and two-digit branches of s. 5.3.6 that no approved-t caller or test could reach; of its 43 mutants none is now missed
…4 a comment claimed, and exceeding it truncates the 64-bit length field silently instead of panicking on the byte-count add, so do_update asserts it in debug builds; sha512t_h0's assertion stops crediting FIPS 180-4 s. 5.3.6 with the t >= 100 its own three-digit formatting imposes, and a new test pins the 128-bit length carry that exempts SHA-512
… l < 2^64 bits, and exceeding it truncates the 64-bit length field silently instead of panicking on the byte-count add, so do_update asserts it in debug builds
…tor bundled into a feature commit makes the diff unreviewable however correct it is, so a refactor that unblocks the task goes in its own commit ahead of it and one that unblocks nothing gets proposed rather than done
… whose per-hash instantiations live in the hash crates, so HMAC_SHA512_224 and HMAC_SHA512_256 move to sha2::hmac as HMACParams impls; HMAC-SM3 is dropped here and reinstated under the new layout in the following commit, which is the only way to keep both commits building
…ed, as a new sm3::hmac module holding the HMACParams impl, the HMAC_SM3 alias and the OSCCA OID, with its criterion bench, factory and CLI wiring and known-answer tests restored alongside it
…a parameter set can derive MAX_SECURITY_STRENGTH from a const generic instead of naming a variant by hand; no behaviour change, and the following commit is the first caller that needs it Assisted-by: Claude:claude-opus-5 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…a hash for, not just the two approved truncations, so the IV Generation Function regains the one- and two-digit decimal branches that b11f8f6 dropped as unreachable -- writing a fixed three digits gives the "0256" spelling the section forbids, and hence the wrong IV, for every t below 100; t is checked against the section's own rule (positive, below 512, not 384) plus this crate's multiple-of-8 requirement, which BC Java's SHA512tDigest also imposes, and the unapproved truncations carry SHA512tParams::FIPS_APPROVED = false which SHA512Internal::new asserts in an inline const, so reaching one takes new_allow_unapproved_t() the way an encrypting mode takes ENCRYPTION_APPROVED; ALG_NAME, OUTPUT_LEN and MAX_SECURITY_STRENGTH are now derived from t and pinned to their old values for t = 224 and t = 256; new sha512t_tests.rs cross-checks eight truncations spanning all three digit branches against BC Java, and of the file's 259 mutants 180 are caught, 5 die on timeout and the 5 missed are the XOR/OR equivalences already documented at their sites Assisted-by: Claude:claude-opus-5 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ueezing becomes its own type
…oFinal after doOutput
… encodings and cshake CLI subcommands
…tions and the commit message style in CLAUDE.md
…Dir> is a plain alias The two wrapper structs fold into the cipher type: the AEAD and symmetric-cipher trait impls, the in-place pair and `SuspendableKeyed` are written on `AsconAEAD128<Encrypting>` / `AsconAEAD128<Decrypting>` directly, and `Ascon_AEAD128<Dir>` aliases it the way `AES_GCM_128<Dir>` aliases `Gcm`, rather than projecting through `Direction::Select`. The private core methods take names that do not collide with the trait methods (`absorb_aad`, `encrypt_bytes`, `finish_tag`, `decrypt_bytes`, `verify_tag`). The decrypting side's held-back bytes live in the struct for both directions, unused when encrypting, so both are 96 bytes in memory; the suspended layouts and their two length constants are unchanged. Assisted-by: Claude:claude-mythos-5-1
The cipher type takes the spec spelling directly, `Ascon_AEAD128<Dir>`, in place of `AsconAEAD128<Dir>` plus an alias to it; the alias's usage example moves onto the struct. Assisted-by: Claude:claude-mythos-5-1
Assisted-by: Claude:claude-mythos-5-1
The CCM packet decryptor's streaming method transforms its buffer in place, which is what the stream-cipher traits and Ascon call `do_*_inplace`; `do_decrypt_update` read as the out-of-place form the AEAD traits provide. Two labels that named a `do_encrypt_update` which never existed now name `do_encrypt`. Assisted-by: Claude:claude-mythos-5-1
Assisted-by: Claude:claude-mythos-5-1
Assisted-by: Claude:claude-mythos-5-1
…, as required by the library fn contracts.
| @@ -1,3 +1,11 @@ | |||
| mod aes_cbc_cmd; | |||
| mod aes_ccm_cmd; | |||
There was a problem hiding this comment.
I have played with a few of the new CLIs:
- aes128-cbc
- aes128-gcm
- aes256-gcm
- ascon-aead128
- ascon-hash256
- ascon-xof128
I made a few adjustments, such as, we used to be exposing only CBC, which means that if you just tried to encrypt a file, then 15/16 of the time you would get an error about the input not being a multiple of 16 bytes. So I changed this so that the aes_cbc CLI options are CBC so that it just works and does something sane instead of leading to user frustration, or worse, encouraging users to invent their own broken / vulnerable padding schemes.
@dghgit , @officialfrancismendoza I'm less familiar with some of the more esoteric modes here -- like CCM and CFB8 -- can you guys build the cli and play with the new CLIs you're adding to make sure you're happy with the ergonomics? It's possible that some of these we should just remove from the CLI because they are too complicated / special-purpose to be worth exposing over the CLI.
…tructions for what to do for a permutation that does not impl all modes
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>
…since that's its only consumer
| /// behaviour -- returning 1 rather than 0 for the data length -- are caught. | ||
| pub fn stream_do_final() -> Result<([u8; 0], usize), SymmetricCipherError> { | ||
| Ok(([], 0)) | ||
| } |
There was a problem hiding this comment.
This is extremely bizzare.
It's not even attached to an object, so it's not even finishing the object. This is literally a public function that takes no parameters and does nothing.
What's the point of this?
| out.copy_from_slice(input); | ||
| in_place(out)?; | ||
| Ok(input.len()) | ||
| } |
There was a problem hiding this comment.
Why is this a standalone static function and not part of a stream trait or the StreamCipher struct?
Taking the in_place function to call as a parameter seems like an overly-complicated pattern. What problem are you trying to solve with this construction instead of impl'ing do_update and do_final as part of a trait like we do everywhere else?
There was a problem hiding this comment.
Also, this function won't work in a no_std env because it requires a .copy_from_slice on an array of indefinite length.
This seems like a worse version of the StreatCipherEncryptor / Decryptor that we already impl below. I suggest just deleting this. Unless there's a really compelling reason to keep it?
| @@ -28,16 +28,24 @@ | |||
|
|
|||
| use crate::{AlgorithmFactory, FactoryError}; | |||
There was a problem hiding this comment.
Please add factories for all the new algorithms. I think we need:
- aead_factory.rs
- block_cipher_factory.rs
- stream_cipher_factory.rs
- symmetric_cipher_factory.rs
| @@ -54,6 +54,69 @@ mod hash_factory_tests { | |||
| let sha2 = HashFactory::new(sha2::SHA512_NAME).unwrap(); | |||
| assert_eq!(sha2.output_len(), 64); | |||
| assert_eq!(sha2.hash(&DUMMY_SEED[..512]), b"\xed\xb9\xbe\xd7\x21\xaa\x6a\x5f\x6f\xbc\x66\x19\xd3\xa3\xc2\xbe\x3d\x04\x30\x43\xf0\x5a\x9a\xeb\xc7\xb1\x19\x7a\x2a\xa9\xc4\x9a\x57\xd5\xdd\xd4\x67\x4c\x17\x85\x78\x50\x88\xd9\xf1\xff\x42\xc7\x97\xa0\x2a\xdc\x9b\x81\x7a\x13\x9a\x50\x97\x0d\xa6\xc9\x95\x24"); | |||
|
|
|||
There was a problem hiding this comment.
Personally, I feel like we could just delete all of the factory test files.
Does the factory crate need tests? If so, what is meaningful to test? I suppose we could test that the factory wirings have exposed the right algorithm under the right name, but I think we could just do that against the ALG_NAME string; running KATs seems like overkill? (and is also hard to audit by eye that we're running the right KATs).
Is there a strong reason why I shouldn't delete the entire factory/tests dir?
Like, have you put any tests here that you think are valuable and should we should keep?
There was a problem hiding this comment.
Right now I think I'd even delete the factories! We'll need something like them for dealing with CMP/CRMF/CMS, but what shape they'll take in a Rust environment currently eludes me.
That said, with testing, we just need enough to confirm that the factory provides a service which can be validated somehow against the service name used.
| "cxof128_output" => bench_cxof128_output(), | ||
| "cxof128_oneshot" => bench_cxof128_oneshot(), | ||
| _ => print_struct_sizes(), | ||
| } |
There was a problem hiding this comment.
Please make this match the main() style of the other mem benches ... ie the style where all-but-one function is commented out, rather than this pattern of reading it off the command-line.
That pattern was intentional so that we're not measuring stack memory usage of the code that has to handle reading std::env and the switch.
| "oneshot" => bench_oneshot_encrypt_out_detached(), | ||
| "direct_stream" => bench_direct_streaming(), | ||
| _ => print_struct_sizes(), | ||
| } |
There was a problem hiding this comment.
Ditto the comment in bench_ascon_mem_usage.rs; please make this match the style of the existing files.
…cipher traits in favour of the _blocks_inplace ones (since the former were shallow wrappers around the second with a worse public API). Also added a new SymmetricCipherError::DataNotBlockAligned to handle runtime checks for misalignments. Assisted-by: Claude Opus 5.5
Consolidates the stacked pair #113 (
feature/stream-cipher→release/0.1.3alpha) and #115(
feature/symmetric-cipher→feature/stream-cipher) into a single branch off the releasebranch, and adds the SHA-512/t work on top.
feature/simple-cipherswas built by branching fromrelease/0.1.3alphaand mergingfeature/stream-cipherthenfeature/symmetric-cipher; both merges fast-forwarded, so thecontent below the two new commits is exactly what #113 and #115 already carried — this is a
re-packaging, not new review surface. #113 (+21,938) and #115 (+2,310) sum to roughly the
+23,499 here.
New in this PR, on top of those two
core:SecurityStrength::from_bits/from_bytesbecomeconst fn(3912434) — twokeywords, no behaviour change. Needed so an associated const can derive a strength from a const
generic; split out ahead of the feature per CLAUDE.md's scope-of-changes rule.
sha2:SHA512t<T>is usable for everytFIPS 180-4 s. 5.3.6 defines a hash for (785dbef).Previously only
T = 224andT = 256had parameter impls, so nothing else could be named.sha512t_h0to100 <= t < 512and emitted a fixed three digits, since only 224 and 256 were reachable. Witharbitrary
treachable that would produce the"0256"spelling s. 5.3.6 explicitly forbids —and hence the wrong IV — for every
tbelow 100. The one- and two-digit branches are restoredand
check_tasserts the section's own rule: positive,< 512, not 384.tmust be a multiple of 8, becauseHashis byte-oriented anda 100-bit digest has no representation here. BC Java's
SHA512tDigestimposes the identicalrestriction, so the two libraries accept the same set of truncations.
ElectronicCodeBook::ENCRYPTION_APPROVEDgatestwo-key TDEA:
SHA512tParams::<T>::FIPS_APPROVEDis public andSHA512Internal::newasserts itin an inline
const, so an unapprovedtis a compile error at the call site andnew_allow_unapproved_t()is the deliberate way in. That also blocksDefault, which keeps anunapproved truncation out of generic code by accident.
ALG_NAME,OUTPUT_LENandMAX_SECURITY_STRENGTHare derived fromt, withconstassertions pinning them to the values 224 and 256 previously had by hand.
Verification
cargo test --workspace: 943 passed, 0 failed (was 923).cargo fmt --checkclean; no newclippy warnings. Both new commits build independently.
SHA512tDigest, an independent implementation:eight truncations (8, 16, 24, 88, 96, 104, 264, 504) spanning all three decimal branches, over
the FIPS 180-4 Appendix C messages plus the one-million-'a' case. The 224/256 rows in the same
table match the NIST-published values.
cargo mutantson the changed files: 259 mutants — 180 caught, 5 timeout-kills, 69 unviable,5 missed. All five missed are the pre-existing XOR/OR equivalences already annotated at their
sites in
ch,majanddo_final_internal; no new missed mutants.Note for reviewers
Adding
constto a publiccorefunction is a forward compatibility commitment, andSHA512tParamsis currently its only caller. The alternative was a private copy of the roundingladder inside
sha2, free to drift from the real one — happy to switch if the API-surface cost isthe greater worry.
🤖 Generated with Claude Code