Conversation
…in update_out_len and a FINAL_LEN final buffer so a buffering cipher or an inline ciphertext||tag layout can be expressed; TaggedEncryptor/TaggedDecryptor adapt any FINAL_LEN=0 pair to the SimpleCipherEncryptor/SimpleCipherDecryptor ciphertext||tag shape; the block, simple-cipher and AEAD strength sweeps assert they are not vacuous, and the AEAD streaming suite gains a genuinely-buffering toy plus undersized-buffer and std-one-shot coverage
…XOF128/CXOF128) implementing AEADCipherEncryptor/AEADCipherDecryptor via AsconAead128Encryptor/AsconAead128Decryptor, with HashFactory/XOFFactory registration and CLI wiring including a TaggedDecryptor-based decrypt stream
…/officialfrancismendoza/119-core-aead-cipher
…CLI thread, and fix a broken intra-doc link (bcgit#119) Review follow-ups on the head of bcgit#120; no behaviour changes. - cli/src/main.rs, cli/src/ascon_cmd.rs: the ascon-aead128 command's help and module docs still described the pre-nonce-prefix format ("output = ciphertext||tag") after the command started generating a nonce and writing it as the first 16 bytes of the stream. They now spell the convention out in both directions, the way aes128-ctr's help does for its own nonce, and say what --nonce/--nonce-file turn off -- the part a user gets wrong, since feeding a prefixed ciphertext to "--decrypt --nonce ..." decrypts garbage and only then fails the tag check. The two encrypt paths each gain a line saying which API they drive and why the explicit-nonce one cannot use the AEADCipherEncryptor pair (do_encrypt_init generates the nonce by construction). - cli/src/main.rs: fn main's 8 MiB thread gains a comment for the constraint it exists for. It is load-bearing: with it removed and `ulimit -s 1024`, every subcommand -- sha3-256 as much as ascon-aead128 -- overflows during argument parsing in a debug build, before any algorithm runs. - crypto/ascon/src/lib.rs: [`ascon_aead128::AsconAead128Decryptor::do_decrypt_final`] does not resolve, because do_decrypt_final is an AEADCipherDecryptor method rather than an inherent one, so `cargo doc` warned and published a dead link. Points at the trait method instead. Assisted-by: Claude:claude-opus-5 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…#119) The entry carried the pre-remediation run, flagged as such ("20 missed before the XOF/CXOF boundary-test additions"). Re-measured on this head with `cargo mutants -p bouncycastle-ascon --test-package bouncycastle-ascon --jobs 3 --timeout 120`, with bc-test-data reachable from the copied tree and a config whose examine_globs block is removed: 735 mutants, 618 caught, 111 unviable, 6 missed. The six are the known equivalences already commented at their sites -- the sponge absorb/squeeze boundaries and the two disjoint-bit `|` -> `^` in set_state_byte -- so the 14 real survivors that run found in the XOF/CXOF Hash view are dead. Assisted-by: Claude:claude-opus-5 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…eded by the AEADCipherEncryptor/AEADCipherDecryptor split (bcgit#119) AEADCipher was the single-type AEAD trait this issue exists to split. It had no implementor on the base branch and its conformance suite had nothing to run against; this PR was about to give it its first and only implementor, on AsconAead128, in the same change that introduces the pair meant to replace it. That would have left the library with two parallel AEAD abstractions and Ascon-AEAD128 with four public one-shot encrypt surfaces. Deleted instead: - crypto/core/src/traits.rs: the trait itself (encrypt/encrypt_out/decrypt/decrypt_out, the aead_* pair, do_aead_encrypt_final/do_aead_decrypt_final). The AEADCipherEncryptor doc that contrasted its tag placement with this trait's now just points at tagged_aead. - crypto/core-test-framework/src/symmetric_ciphers.rs: TestFrameworkAEADCipher::test and ::test_plain_one_shots, the suites for it. The struct keeps test_encryptor_decryptor and test_buffering_toy, which exercise the pair. - crypto/ascon/src/ascon_aead128.rs: the impl, and the module-doc sentence that justified the newtype pair by pointing at it. Test coverage is kept where it was about Ascon rather than about the trait: the chunk-boundary sweep and the wrong-tag rejection now drive the inherent do_encrypt_final/do_decrypt_final (they only used the trait for its finalizers), and the undersized-buffer suite is rewritten against the inherent one-shots, whose own length checks -- including the 16-byte-ciphertext and oversized-buffer boundaries that must NOT be rejected -- were previously reached only through the trait. The three tests that were about the deleted code (the std Vec wrappers, the plain view's DecryptionFailed remapping, the AEADCipher framework conformance call) go with it. Assisted-by: Claude:claude-opus-5 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ion figures (bcgit#119) Deleting the trait and its suites takes bouncycastle-ascon from 735 mutants to 655: 558 caught, 91 unviable, 6 missed, the same six known equivalences as before, so the tests ported onto the inherent one-shots hold the coverage the deleted trait's tests had. Assisted-by: Claude:claude-opus-5 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ag layout on the AEAD traits, and address the remaining API-shape review points (bcgit#119) The `tagged_aead` adapter pair is gone; what it did belongs to the traits themselves. - crypto/core/src/traits.rs: AEADCipherEncryptor gains `tagged_encrypt` (one-shot into `ciphertext || tag`), `tagged_do_aead_encrypt_final` (streaming: flush, then append the tag) and `tagged_encrypt_out_len`; AEADCipherDecryptor gains `tagged_decrypt`, `tagged_do_aead_decrypt_final` (streaming: the tail is leftover ciphertext followed by the tag) and `tagged_decrypt_out_max_len`. All are defaults over the existing methods, so every implementor gets both layouts and neither has to be bolted on by a wrapper type that cannot express a buffering cipher's lengths (the `FINAL_LEN = 0` restriction TaggedEncryptor and TaggedDecryptor carried). - crypto/core/src/tagged_aead.rs is deleted, with its module declaration and every use of it. crypto/core/tests/aead_tagged_tests.rs keeps the toy AEAD the deleted module's in-`src` tests used and points it at the new methods: round trip at every length crossing `TAG_LEN`, every chunking, tampering, a stream that ends before a whole tag, and every undersized buffer. - crypto/core-test-framework: the AEAD suite now checks the inline layout for every implementor (one-shot against streaming, and a too-short tail as DecryptionFailed), and the buffering toy checks it where FINAL_LEN > 0, which is where `tagged_do_aead_encrypt_final` has to flush and append in one call. Its short-buffer probe on the decryptor now feeds the decryptor its own ciphertext rather than the plaintext, and uses the ciphertext's length. - crypto/ascon: `AsconAead128::new`'s `for_encryption: bool` is no longer public API -- `new_encrypting` / `new_decrypting` name the direction, and the bool constructor they share is private. The crate docs gain a `tagged_*` example. - cli/src/ascon_cmd.rs: both directions drive the trait pair, holding the tag back by hand on the way in, which is what the adapter did for it. A failed `do_encrypt_init`/`do_decrypt_init` -- the RNG or the key material -- now prints an error and exits rather than panicking, as block_mode_cmd.rs does for the same call, and the remaining unwraps carry their `infallible:` notes. - crypto/core/src/traits.rs also: the allocating one-shot's three-part return is now the named `AEADEncrypted<NONCE_LEN, TAG_LEN>` (clippy `type_complexity`), and `decrypt_out` / `encrypt_out_rng` get the same "an implementor with FINAL_LEN > 0 must override this" note `encrypt_out` already had. Assisted-by: Claude:claude-opus-5 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…nges (bcgit#119) 661 mutants, 558 caught, 97 unviable, 6 missed -- the same six known equivalences (the sponge absorb/squeeze boundaries and the two disjoint-bit `|` -> `^` in set_state_byte). The count moves from 655 with the new_encrypting/new_decrypting constructors. Assisted-by: Claude:claude-opus-5 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… in the tagged AEAD defaults (bcgit#119) `cargo mutants -p bouncycastle-core -f crypto/core/src/traits.rs --re 'AEADCipherEncryptor|AEADCipherDecryptor' --test-package bouncycastle-core --test-package bouncycastle-ascon` reported 116 mutants, 91 caught, 19 unviable, 6 missed. Four of the six were real: the buffer guards could be weakened without a test noticing, because a too-short buffer is rejected either by the guard or by the `do_update_out` behind it, and both report IncorrectOutputBufferLength with the same length -- so the probes could not tell which had fired. - crypto/core/tests/aead_tagged_tests.rs: `tagged_do_aead_decrypt_final` with a buffer of exactly `needed` must succeed. Kills `plaintext.len() < needed` -> `<=` and -> `==`. - crypto/core-test-framework: the buffering toy now finishes from a tail that still holds ciphertext (TAG_LEN + 4 bytes) into an exactly-sized buffer, which is what makes `update_out_len(..) + FINAL_LEN` observable -- with a generous buffer any arithmetic there would do. Kills `+ FINAL_LEN` -> `* FINAL_LEN`. The AEAD suite also feeds `encrypt_out_rng` a buffer with room to spare, so its own guard cannot be flipped to `>` unnoticed. The re-run is 116 mutants, 95 caught, 19 unviable, 2 missed; the two are `written + final_len` -> `written - final_len` in `encrypt_out_rng`, equivalent while every implementor has FINAL_LEN = 0. Assisted-by: Claude:claude-opus-5 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…/119-core-aead-cipher Two conflicts, both from the base branch's renames. In crypto/core/src/traits.rs the AEADCipher trait this PR deletes collided textually with the AEADCipherDecryptor docs that replaced it, resolved in favour of the deletion. In core-test-framework's symmetric_ciphers.rs the two import lists were unioned, minus the deleted AEADCipher. The PR's own code follows the base branch's API renames: SimpleCipherEncryptor / SimpleCipherDecryptor are SymmetricCipherEncryptor / SymmetricCipherDecryptor, TestFrameworkSimpleCipher is TestFrameworkSymmetricCipher, and SymmetricCipherError::IncorrectOutputBufferLength(&'static str, usize) is OutputBufferTooSmall(usize) -- the dropped name field took a sentence in ascon's two one-shots, which is no loss since the error identifies the buffer by the call it came from. Assisted-by: Claude:claude-opus-5 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Assisted-by: Claude:claude-sonnet-5
Contributor
Author
|
@ounsworth PR #120, erm... slipped on the soap in the wash room..., this one replaces it. We think it's now ready for final review as CCM and GCM are also well on their way and they represent the other 2 distinct styles of AEAD ciphers. CCM #126 is now good to go as well. For reasons not readily explainable, it appears the commit try for this PR is also in CCM #126 and GCM #132... |
…ipherDecryptor extend SymmetricCipherEncryptor/SymmetricCipherDecryptor, with the detached-tag methods named *_detached and the inline one-shots with AAD named *_with_aad
The inherited SymmetricCipher{En,De}cryptor methods are the AEAD with no
associated data and the tag inline (ciphertext || tag), so an AEAD can be held
and used as a plain symmetric cipher. FINAL_LEN keeps one meaning across both
traits: the tag plus anything the cipher holds back. Every AEAD decryptor now
holds back the last TAG_LEN bytes it has seen, since do_update_out is shared
and cannot know which final will be called: SymmetricCipherDecryptor::do_final
checks those bytes as the tag, AEADCipherDecryptor::do_final_out_detached
decrypts them as ciphertext.
The AEAD traits keep do_update_aad and add, named for the base method they
mirror: do_final_detached / do_final_out_detached (the _out form is the
required one), encrypt_out_detached, encrypt_out_rng_detached,
encrypt_detached, decrypt_out_detached, decrypt_detached and the
*_len_detached sizing helpers; and encrypt_out_with_aad,
encrypt_out_rng_with_aad, encrypt_with_aad, decrypt_out_with_aad and
decrypt_with_aad for the inline layout with AAD. do_encrypt_init,
do_decrypt_init, update_out_len and do_update_out are now inherited, and
tagged_do_aead_{en,de}crypt_final and the tagged_*_len helpers are gone,
their jobs taken by the inherited do_final and length helpers.
SymmetricCipherDecryptor::decrypt_out now zeroizes what it wrote when
do_final fails, since an AEAD reaches it through this trait and the AEAD
one-shots always have.
AsconAead128Encryptor / AsconAead128Decryptor implement both layers with
FINAL_LEN = TAG_LEN; the decryptor carries the 16-byte hold-back. The CLI's
Ascon-AEAD128 decrypt stream drops its hand-rolled tag tail, which the
decryptor now does itself. TestFrameworkAEADCipher::test_encryptor_decryptor
runs the whole TestFrameworkSymmetricCipher suite first, then the AEAD
checks; the buffering toy implements both layers and drives every one-shot.
cargo mutants -p bouncycastle-core -f crypto/core/src/traits.rs --re
'AEADCipher|SymmetricCipherDecryptor::decrypt_out' --test-package
bouncycastle-core --test-package bouncycastle-ascon: 134 mutants, 107 caught,
27 unviable, 0 missed. cargo mutants -p bouncycastle-ascon -f
crypto/ascon/src/ascon_aead128.rs --re 'AsconAead128(En|De)cryptor'
--test-package bouncycastle-ascon --test-package cli: 76 mutants, 49 caught,
27 unviable, 0 missed.
Assisted-by: Claude:claude-opus-5-5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ascon_AEAD128<Encrypting> is AsconAead128Encryptor and Ascon_AEAD128<Decrypting> is AsconAead128Decryptor, spelled as SP 800-232 spells the algorithm. A plain type alias cannot choose between two distinct types, so it is written as a projection through AsconAead128Mode, which is implemented for the two bouncycastle-modes direction markers and nothing else; any other Dir is a compile error. bouncycastle-ascon now depends on bouncycastle-modes for those markers only. The alias is re-exported at the crate root, carries a doctest of the no-AAD inline-tag round trip, and aead128_tests.rs runs the AEAD conformance suite through it. Assisted-by: Claude:claude-opus-5-5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…/119-core-aead-cipher
…/119-core-aead-cipher Resolves the two import conflicts from 8823c7b, which moved SecurityStrength out of core::traits into core::security_strength: cli/src/helpers.rs and core-test-framework/src/symmetric_ciphers.rs take the base's new import path and this branch's AEADCipherEncryptor/AEADCipherDecryptor names. The ascon crate, core's aead_tagged_tests and cli/src/ascon_cmd.rs exist only on this side, so the base's mechanical import move is applied to them here; the result matches the resolution already carried by PR bcgit#126 file for file. Assisted-by: Claude:claude-fable-5-1 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Contributor
Author
|
Now merged into PR #133 |
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.
Replaces #120, which GitHub records as merged although the change is not in the base branch.
#120 was merged on the GitHub mirror rather than on
origin. The mirror is refreshed fromorigin, so the reset that followed took the merge commit (a777acdc) with it:feature/xof-cshakeis back at8a13369on both remotes and carries none of this work.GitHub will not reopen a merged pull request, hence this one. Same head branch, same base,
same commits — nothing has been rebased or squashed, and the head is still
62e6a2b.Original description, from #120:
Since #120 was approved, the head has gained two commits:
ac72292— a merge offeature/xof-cshake, bringing in the base branch's renames:SimpleCipherEncryptor/SimpleCipherDecryptorareSymmetricCipherEncryptor/SymmetricCipherDecryptoragain, andSymmetricCipherError::IncorrectOutputBufferLength(&'static str, usize)is now
OutputBufferTooSmall(usize). Two conflicts were resolved: incrypto/core/src/traits.rsthe
AEADCiphertrait this PR deletes collided textually with theAEADCipherDecryptordocs thatreplaced it, resolved in favour of the deletion; and the two import lists in
core-test-framework/src/symmetric_ciphers.rswere unioned, minus the deleted trait. The asconand cli code follows the renames.
62e6a2b— three typo fixes inCONTRIBUTING.md(@officialfrancismendoza).cargo build --workspace,cargo test --workspace(1085 passed, 0 failed, 1 ignored) andcargo fmt --all --checkare clean on62e6a2b.The review history, including the approvals and ounsworth's threads, stays on #120.
Assisted-by: Claude:claude-opus-5
🤖 Generated with Claude Code