Skip to content

Add c2sp.org/chunked-encryption (Cobblestone) test vectors - #265

Merged
cpu merged 1 commit into
mainfrom
push-nkskznqqunmy
Jul 21, 2026
Merged

Add c2sp.org/chunked-encryption (Cobblestone) test vectors#265
cpu merged 1 commit into
mainfrom
push-nkskznqqunmy

Conversation

@FiloSottile

Copy link
Copy Markdown
Member

@alex

alex commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Perfect, thanks! Our current PR uses the ones from your impl.

@FiloSottile

Copy link
Copy Markdown
Member Author

These are ported from those, and the Go implementation (now renamed to filippo.io/cobblestone) now uses these.

@cpu cpu left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's some initial feedback mainly focused on the new schema.

Comment thread schemas/c2sp_chunked_encryption_schema.json
Comment thread schemas/c2sp_chunked_encryption_schema.json Outdated
Comment thread schemas/c2sp_chunked_encryption_schema.json Outdated
Comment thread schemas/c2sp_chunked_encryption_schema.json
@reaperhulk

Copy link
Copy Markdown
Contributor

I'm very keen on getting this merged so we can get our own cobblestone release out, anything I can do to help Filippo?

@FiloSottile

Copy link
Copy Markdown
Member Author

I agree with all of @cpu's comments and just haven't gotten to it, so if you have the cycles, feel free to make a PR to the push-nkskznqqunmy branch addressing them and I or @cpu will turbomerge it :)

@cpu

cpu commented Jul 20, 2026

Copy link
Copy Markdown
Member

I'm away from a full keyboard atm but I can apply the feedback tomorrow morning if nobody beats me to it.

@cpu
cpu force-pushed the push-nkskznqqunmy branch from ea16ea1 to 7ebaa4d Compare July 21, 2026 13:48
@cpu
cpu merged commit b61843a into main Jul 21, 2026
15 of 16 checks passed
@cpu

cpu commented Jul 21, 2026

Copy link
Copy Markdown
Member

@reaperhulk All set!

@cpu
cpu deleted the push-nkskznqqunmy branch July 21, 2026 13:54
@reaperhulk

Copy link
Copy Markdown
Contributor

Thanks! Beat me to it 😄 very much appreciated

alex pushed a commit to pyca/cryptography that referenced this pull request Jul 21, 2026
Bumps the wycheproof ref to pick up the c2sp.org/chunked-encryption
(Cobblestone) test vectors added in C2SP/wycheproof#265.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uyk58oD6F8BJwKHE4qCMA8
alex pushed a commit to pyca/cryptography that referenced this pull request Jul 21, 2026
Bumps the wycheproof ref to pick up the c2sp.org/chunked-encryption
(Cobblestone) test vectors added in C2SP/wycheproof#265.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uyk58oD6F8BJwKHE4qCMA8
reaperhulk pushed a commit to pyca/cryptography that referenced this pull request Jul 21, 2026
…5144)

* Add a chunked encryption recipe implementing c2sp.org/chunked-encryption

This adds cryptography.chunked_encryption, a top-level recipe (like
Fernet) for streaming authenticated encryption of large messages,
implementing the C2SP chunked-encryption specification
(https://c2sp.org/chunked-encryption) instantiated with SHA-256 and
AES-128-GCM.

The core is implemented in Rust: for each message a fresh key, base
nonce, and key commitment are derived with HKDF-Expand-SHA-256 from the
input key, a random 24-byte salt, and a caller-provided context; the
message is encrypted in 16 KiB chunks with AES-128-GCM, with the chunk
counter XOR'd into the base nonce. Full chunks are encrypted/decrypted
directly from the caller's input, so only sub-chunk remainders are
buffered internally, and update_into variants allow callers to supply
output buffers.

The internals are parameterized over the AEAD so that additional AEADs
could be supported later, but the public API is AES-128-GCM only.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uyk58oD6F8BJwKHE4qCMA8

* Address review feedback on chunked encryption

- Use the existing AesGcm AEAD implementation for chunk
  encryption/decryption instead of using OpenSSL's EVP interface
  directly (AESGCM.decrypt_into is now pub(crate) for this).
- Use the existing HkdfExpand implementation for key derivation.
- Fold the error state into the finalized state: a context that hit an
  error raises AlreadyFinalized on further use.
- Replace the let-else in Decrypter::update_impl with a match that
  yields the cipher and buffer fields.
- Replace the in-test reference implementation with the test vectors
  from the chunked reference implementation
  (https://github.com/FiloSottile/chunked), vendored into
  cryptography_vectors.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uyk58oD6F8BJwKHE4qCMA8

* Add PiB to the docs spelling wordlist

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uyk58oD6F8BJwKHE4qCMA8

* Restructure chunked encryption for full test coverage

- Extract the chunk counter/nonce logic into a ChunkNonces struct with
  Rust unit tests covering the 2**38-chunk limit, which can't be
  reached from Python tests.
- Track the Decrypter state as Option<DecrypterState> and process both
  active states in a single exhaustive match, removing the
  unreachable!() arms; finalize() now consumes the state on all paths.
- Drop the Encrypter's error poisoning: the only errors it guarded
  against are the capacity check (which fails before any state is
  modified) and internal OpenSSL errors.
- Test that a Decrypter is unusable after update_into() raises
  InvalidTag.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uyk58oD6F8BJwKHE4qCMA8

* Address review feedback: drop overhead paragraph, document buffer invariant

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uyk58oD6F8BJwKHE4qCMA8

* Expose the Cobblestone-128 and Cobblestone-256 instantiations

C2SP/C2SP#296 names the chunked-encryption spec's two instantiations:
Cobblestone-128 (SHA-512 and AES-128-GCM, recommended) and
Cobblestone-256 (SHA-512 and AES-256-GCM, compliance-oriented). Replace
the Encrypter/Decrypter classes with Cobblestone128Encryptor,
Cobblestone128Decryptor, Cobblestone256Encryptor, and
Cobblestone256Decryptor, sharing the core implementation, and switch
the HKDF-Expand hash from SHA-256 to SHA-512 per the updated spec.

The vendored reference test vectors predate this spec change (they
were generated with HKDF-SHA-256), so the vector tests are removed
until the reference implementation regenerates them.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uyk58oD6F8BJwKHE4qCMA8

* Replace the variant macro with explicit class definitions

The four Cobblestone classes are now plain compositions over internal
ChunkedEncryptor/ChunkedDecryptor types.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uyk58oD6F8BJwKHE4qCMA8

* Address review feedback: trim docs, drop Decryptor.generate_key, prune Rust tests

- Simplify the docs per review: drop the intro properties paragraph,
  the os.urandom mention, and the redundant clauses in the update_into
  and finalize descriptions.
- Remove generate_key from the Decryptor classes; key generation is an
  encryption-side operation.
- Drop the nonce XOR unit test: that path is fully covered by the
  Python round-trip tests. The remaining Rust test covers only the
  chunk counter limit, which is unreachable from Python.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uyk58oD6F8BJwKHE4qCMA8

* Remove hasattr assert from test_generate_key

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uyk58oD6F8BJwKHE4qCMA8

* Rename the module to cryptography.cobblestone, trim docs

Per review: the module, docs page, stubs, and Rust module are renamed
from chunked_encryption to cobblestone (the classes were already named
for the Cobblestone instantiations), and the docs' Implementation
section is dropped since the page already states it implements the
C2SP chunked-encryption specification.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uyk58oD6F8BJwKHE4qCMA8

* Add Wycheproof tests for Cobblestone

Bumps the wycheproof ref to pick up the c2sp.org/chunked-encryption
(Cobblestone) test vectors added in C2SP/wycheproof#265.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uyk58oD6F8BJwKHE4qCMA8

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants