Conversation
… and CLI wiring (PR #89)
… bits in the MSBs, unused low bits ignored
…ke the other hashes
…ptor with multi-block and one-shot methods (PR #107)
…-free bit-sliced AES permutation (PR #105)
…nd aes*-cbc CLI subcommands (PR #106)
…ryptor/PaddedDecryptor) (PR #97)
…me lengths, AES_CBC_* aliases, simpler CLI (PR #109)
…mmands and shared block-mode CLI (PR #111)
…locks8, SymmetricCipherEncryptor/Decryptor (from feature/sm4); CFB follows suit
…cb CLI subcommands; block-mode CLI generic over INIT_DATA_LEN
…S_PADS; SymmetricCipherEncryptor::do_final reports its output length
…with API changes and per-commit summaries
…rams/HashMLDSAParams/MLKEMParams traits, one impl per parameter set (#117)
…eamCipherDecryptor pair, shaped like the block cipher pair (in place, any length, generated init data); TestFrameworkStreamCipher implemented in place of its todo!()
… and Cfb8 (SP 800-38A Sec 6.3, s = 8) is added, with AES_CFB8_* aliases, aes*-cfb8 CLI subcommands and a shared stream-mode CLI
…, CFB8 is added, and the StreamCipher trait is replaced by the split encryptor/decryptor pair; re-measured throughput and mutation figures
…inst real AES at all three key lengths, not only the toy permutation
…th picks the counter width (max 4 bytes) and which errors rather than repeat a counter, with AES_CTR_* aliases and aes*-ctr CLI subcommands
… the nonce-plus-counter construction, pinning the 1, 2 and 3-byte counter widths that the ACVP and OpenSSL vectors cannot reach
… their HMAC variants
… and CLI wiring (PR #89)
… bits in the MSBs, unused low bits ignored
…ke the other hashes
…ptor with multi-block and one-shot methods (PR #107)
ounsworth
reviewed
Sep 30, 2026
ounsworth
reviewed
Sep 30, 2026
| @@ -1,76 +1,267 @@ | |||
| //! Generic behaviour tests for the symmetric cipher traits. | |||
Contributor
There was a problem hiding this comment.
This, and key_stream.rs should move to the bouncycastle-cipher crate, once that refactor has been done to create it.
ounsworth
reviewed
Sep 30, 2026
| @@ -8,5 +8,7 @@ | |||
|
|
|||
| pub mod errors; | |||
| pub mod key_material; | |||
| pub mod security_strength; | |||
| pub mod stream_cipher; | |||
…symmetric_ciphers.rs into aead.rs and block_cipher.rs, turn core's aead_tagged_tests into a runner driven by AES-GCM, and move the buffering-toy test of core's default one-shots back to core/tests Assisted-by: Claude:claude-fable-5-1
Note: crypto/aes/src/padded_mode.rs's PaddedMode is the same unsealed projection pattern this replaces in ascon; it can be de-duplicated onto core's Direction::Select in a follow-up, which is deliberately not bundled here. Assisted-by: Claude:claude-fable-5-1 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…and the byte-slice helpers) into feature/simple-ciphers Replaces core::hint::black_box with a volatile store/load barrier used by Condition::select/negate/swap/is_in_list, ct_eq_bytes, ct_eq_zero_bytes and conditional_copy_bytes. Adds ct_eq_bytes_mask and has conditional_copy_bytes take a Condition<u32> so ML-KEM implicit rejection never passes the secret through a bool. Sets rust-version = "1.88". Closes #128. Assisted-by: Claude Code:claude-fable-5-1 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…a backslash -- a backslash that is not the of an escaped byte is reported as InvalidHexCharacter at its own index, with regression tests for the trailing, lone and mid-input cases. Assisted-by: Claude:claude-fable-5-1
… into feature/simple-ciphers
… > file` is now exactly N bytes. Newline preserved for -x Assisted-by: Claude:claude-fable-5-1
ounsworth
reviewed
Oct 1, 2026
| @@ -2,6 +2,7 @@ | |||
| name = "bouncycastle-utils" | |||
| version.workspace = true | |||
| edition.workspace = true | |||
| rust-version.workspace = true | |||
ounsworth
reviewed
Oct 1, 2026
| // msp430 and avr; another backend gets no such promise. `core::hint::black_box`, used | ||
| // previously, is weaker still: its documentation calls it "best-effort" and says it "does not | ||
| // offer any guarantees for cryptographic or security purposes". | ||
| // --------------------------------------------------------------------------------------------- |
Contributor
There was a problem hiding this comment.
Note-to-self: read and make sure it makes sense.
ounsworth
reviewed
Oct 1, 2026
| @@ -1,3 +1,11 @@ | |||
| mod aes_cbc_cmd; | |||
Contributor
There was a problem hiding this comment.
Note-to-self: leaving un-viewed until I check the ascon bits
…ith the CLAUDE.md pointer updated to match Assisted-by: Claude Code:claude-fable-5-1 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
bouncycastle_core::hazmat defines the term; each crate with hazmat items declares pub mod hazmat and never re-exports out of it. Moved, paths only: ElectronicCodeBook, KeyStream and do_hazardous_operations in core; AESInternal and AES_ECB_* in aes; CtrKeyStream and Ecb in modes. ML-KEM's encaps_internal becomes hazmat::EncapsWithRandomness and HashDRBG80090A::new_unititialized becomes hazmat::NewUninitialized (typo fixed), as extension traits so the call needs the hazmat import. No logic change, no mutation run owed; test count 1040 before and after. Assisted-by: Claude Code:claude-fable-5-1 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
AES_CBC_* and AES_ECB_* were written through aes's own PaddedMode trait, the same unsealed direction projection that 64f3923 replaced in ascon; they now use Direction::Select and the trait and its module go. Type aliases only, no behaviour change, no mutation run owed; test count 1040 before and after. Assisted-by: Claude Code:claude-fable-5-1 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…make unbuffered the default
…ng to be sub-modules of a new crate bouncycastle-cipher. Assisted-by: claude-fable-5.1
StreamCipher loses its R: RNG type parameter (which it had to have because bouncycastle-core couldn't depend on bouncycastle-rng): do_encrypt_init now draws from HashDRBG_SHA512::new_from_os(), as Cbc, Gcm and Ccm do. Assisted-by: claude-opus-5-5
…al contract tests move to tests/ No behaviour change. Assisted-by: Claude:claude-fable-5-1
…-utils, with the component layer for composing suspended states Assised-by:claude-fable-5-1
ounsworth
reviewed
Oct 2, 2026
| /// that has to see the whole message before it can process any of it (see | ||
| /// [`AEADCipherEncryptor`]), may also return [`SymmetricCipherError::GenericError`] if the | ||
| /// input would exceed it. | ||
| fn do_encrypt_out( |
Contributor
There was a problem hiding this comment.
We have provided a do_encrypt_out, but not a do_encrypt() -> Vec<u8>. Create one, wrapped in a #[cargo(alloc)]` that we can clean up later after Jason's pattern lands.
Contributor
There was a problem hiding this comment.
Ditto for the AEAD trait -- most of the things there needs to be twinned.
…nstead of buffering the message (PR #164) CcmEncryptor / CcmDecryptor no longer hold a copy of the payload, which gave them a stack footprint that grew with the message. DATA_LEN is now the exact payload length, committed to B0 at init, so the streaming methods release every byte as it arrives, FINAL_LEN is the tag, and the decryptor holds back only the bytes past the frame as the possible inline tag. More than DATA_LEN is refused at the update and less at the final, on both sides. The AES aliases are renamed AES_CCM_*_Packet, CCM_MAX_BUFFER_LEN is gone, and a value is now the Ccm state plus the AAD capacity at any DATA_LEN. The inherent Ccm API, which takes the lengths per message, is unchanged. The AEAD one-shots and finals follow the library's trailing `_out` convention (encrypt_detached_out, decrypt_with_aad_out, do_final_detached_out and so on) across core, cipher, aes and ascon, and the AEADCipherEncryptor trait docs are rewritten for a calling application. QUALITY_AND_STYLE gains the rule that public API docs carry no implementation detail. Suspend-and-resume round-trip tests cover every mode, adapter and AES alias, and the shared test framework takes a fixed message length so it can drive the fixed-frame pair. Review fixes folded in: CcmDecryptor::decrypt_out_max_len is `ciphertext_len.min(DATA_LEN)`, so a short inline C through the one-shots reaches the final and is DecryptionFailed rather than OutputBufferTooSmall, with a test at DATA_LEN = 32; the adapters' update docs say a refused non-empty call still ends the AAD phase; and three wording errors in the rewritten trait docs are fixed. cargo mutants over crypto/cipher/src/modes/ccm.rs with the cipher and aes tests: 313 mutants, 231 caught, 78 unviable, 2 timeouts that are real kills, 2 missed (the OR/XOR equivalence in format_b0's flags octet). Assisted-by: Claude:claude-fable-5-1 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
ounsworth
reviewed
Oct 2, 2026
| //! root: this crate holds the traits, and `bouncycastle-aes` and `bouncycastle_cipher::modes` hold their | ||
| //! implementors. The safe adapters that wrap them -- `bouncycastle_cipher::stream::StreamCipher` | ||
| //! over a [`KeyStream`], the modes over an [`ElectronicCodeBook`] -- are not hazmat and stay where | ||
| //! they are. |
ounsworth
reviewed
Oct 2, 2026
| /// Errors from [`Suspendable`](crate::traits::Suspendable) and | ||
| /// [`SuspendableKeyed`](crate::traits::SuspendableKeyed). Defined in `bouncycastle-utils` next to | ||
| /// the version-header helpers that raise it, and re-exported here with the other error types. | ||
| pub use bouncycastle_utils::suspendable_state::SuspendableError; |
Contributor
There was a problem hiding this comment.
This should be moved here, not re-imported.
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.
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