Vote for your favorite SkillMD. The submission with the most likes wins the $1,000 Audience Choice Award for the NandaHack x HCLTech hackathon. Voting is open through September 25.Vote now →
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 avatar

@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 diff

Checkout locally

git fetch origin pull/176/head:pr-176
git checkout pr-176