in reviewhumanPR #176Privacy
rahulsharma-sys: sealedbox — nonce-misuse-resistant hybrid privacy (Problem 09)
Reworked sealedbox privacy plugin (Problem 09). This supersedes #36, which
Author
@rahulsharma-sys
github profile →- Status
- In review
- Opened on
- Jul 10
- Branch
- hackathon/rahulsharma-sys-privacy-sealedbox
Description
The pitch.
## Summary Reworked **`sealedbox`** privacy plugin (Problem 09). This supersedes #36, which GitHub auto-closed when its branch was renamed to match the charter's `hackathon/<handle>-<theme>` pattern (`rahul` → `rahulsharma-sys`); same author, same work, all review feedback addressed. The default `noop` privacy plugin is a passthrough. `sealedbox` provides a full Problem 09 solution — hybrid X25519 + ChaCha20-Poly1305 encryption, salted-Merkle selective disclosure, and epoch-based broadcast revocation — with one **load-bearing differentiator** vs the merged `hybrid_x25519`: deterministic mode is **nonce-misuse resistant (SIV-style)**. ### Why the differentiator matters Tier-1 traces must replay byte-for-byte, so a privacy plugin derives per-message keys/nonces deterministically. Every such scheme guards the derivation with a monotonic counter and concedes that a `(key, nonce)` collision would be catastrophic. But that counter lives in memory: reconstruct the plugin (restart, or two instances of one agent) and it resets to zero, re-deriving the same key and nonce for a different plaintext — a two-time pad. `hybrid_x25519`'s own docstring states its deterministic mode is safe *"only because the counter never repeats."* `sealedbox` folds a digest of `(plaintext, sorted audience)` into the HKDF `info` for the content key, content nonce, ephemeral scalars, and wrap nonces (the synthetic-IV construction behind AES-GCM-SIV). A counter collision then degrades to revealing *message equality* instead of a two-time pad. This is proven live: the adversarial validator `check_deterministic_reuse_safe` **fails** against `noop` and against `hybrid_x25519`'s reconstructed deterministic mode, and **passes** against `sealedbox`. ### Problem 09 surface - **Hybrid encryption**: fresh ChaCha20-Poly1305 content key per message, wrapped per recipient via X25519 ephemeral-static ECDH + HKDF-SHA256. The envelope header (version/sender/epoch/counter/sorted recipient key-ids) is bound as AEAD associated data, so redirection or header edits break authentication. - **Selective disclosure**: salted-Merkle `prove`/`verify_proof` (a `reveal` JSON array selects fields to disclose; the rest stay hidden behind the issuer root). - **Broadcast revocation**: `revoke` advances an epoch and excludes a member from future wraps; forward secrecy is explicitly future-only (documented). - **Replay rejection**: keyed on the envelope digest, so a reconstructed sender's distinct messages are not mistaken for replays of each other. - **Adversarial validators** (`validators/sealedbox_validators.py`): the four Problem 09 attacks (eavesdropper, replay, field-injection, stale-revocation) — each fails against `noop` and passes against `sealedbox` — plus the novel two-time-pad detector. - **Scenario** `scenarios/sealed_bid_sealedbox.yaml` (the canonical `sealed_bid_with_privacy.yaml` filename is owned by the merged `hybrid_x25519` PR, so this ships the parallel variant and does not modify it). Its prose is explicit that the Tier-1 auction task does not route payloads through the privacy layer, so the crypto is exercised in `tests/test_sealedbox.py`, not on the wire. Registered in both `_BUILTINS` and the `nest.plugins.privacy` entry point. ### Honesty notes Deterministic mode is protocol/trace-level confidentiality, **not** secrecy against a holder of the shared seed (who can re-derive any agent's key); `deterministic=False` gives per-agent random keys for genuine secrecy at the cost of reproducibility. This is stated in the docstrings. ## Test Plan `make ci-local` passes — ruff, ruff format --check, pyright (strict), pytest (**764 passed, 1 skipped**). 30 sealedbox tests cover encryption round-trips, multi-recipient, tamper + header-binding, malformed envelopes, replay, determinism, the nonce-misuse-resistance property (incl. a live comparison that the validator catches `hybrid_x25519` deterministic mode failing), random mode, selective discl …
Try it
Open PR on GitHubView diffCheckout locally
git fetch origin pull/176/head:pr-176
git checkout pr-176