Repository navigation
feat(wrap): pad every 1:1 frame to whole 4096-byte blocks - #1
Merged
Merged
Conversation
The host could tell a rotation, a rebuild Welcome and ContactAccepted from a message by length alone: a rotation's announcement carries the whole signed bundle, about five times an ordinary message. The lane wrap now pads the frame with 0x80 and zeros so that nonce, ciphertext and tag fill the fewest whole blocks of WRAP_BLOCK = 4096 bytes. Every record that fits one block has the same length; a longer message shows only its block count. A sender whose bundle lists two or more devices still sends a multi-block announcement. unwrap_frame refuses any length that is not a whole number of blocks before decrypting, and examines the padding only after the AEAD has verified, so there is no padding oracle. No client is deployed, so the labels stay at v1 and unpadded frames are refused. WRAP_BLOCK equals the inbox's default MAX_INLINE_BYTES, so a one-block record is still stored inline. only_a_payloads_size_reaches_the_host now asserts that every wrapped payload is a whole number of blocks, that every record the script wraps (the rotation's commit and announcement included) is one block, and that a one-block payload's length is constant across the matrix. The ledger notes follow. Not compiled or tested locally: this machine has no Rust toolchain. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
only_a_payloads_size_reaches_the_host looked for Alice's message at `a_to_b`, but that step appends nothing: Alice holds the message until Bob's ContactAccepted reaches her and sends it on inside `a_fetch`. The guard now checks `a_rotate`, which sends the same varied body with nothing held. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Summary
The host could tell a 1:1 record's kind by its length. A rotation's announcement carries the whole signed bundle, about five times an ordinary message, and rebuild Welcomes and ContactAccepted each have a size of their own. The lane wrap now pads every frame so that nonce, ciphertext and tag fill the fewest whole blocks of
WRAP_BLOCK = 4096bytes.src/lane_wrap.rs:wrap_framepads asframe || 0x80 || 0x00*.unwrap_framerefuses any length that is not a whole number of blocks before decrypting, and looks at the padding only after the AEAD has verified, so there is no padding oracle.WRAP_BLOCKequals the inbox's defaultMAX_INLINE_BYTES, so a one-block record is still stored inline.src/leakage_corpus.rs:only_a_payloads_size_reaches_the_hostnow asserts that:contracts/leakage-ledger.json: theciphertext_length,commit_frequencyandenvelope.bytesnotes follow.Known limits
lane_wrapand are not padded.Test plan
cargo fmt --check, the whole test suite, and in particular thelane_wrap,leakage_ledgerandleakage_corpustests. Nothing was compiled locally; the record sizes above are estimates, and the corpus test measures them.🤖 Generated with Claude Code