The two halves of the harvest-now-decrypt-later defence (design.md §5.2),
each a standalone primitive; pqxdh combines them into a root key next.
- X25519 (x25519-dalek): secret/public keys, encode round-trip, diffie_hellman.
Secrets seeded from getrandom directly (no rng-trait plumbing, wasm-clean).
- ML-KEM-768 (ml-kem 0.3.2, FIPS 203): keygen, encapsulate/decapsulate, key
encode/parse via kem's KeyExport; system-RNG methods route through getrandom
0.4 (wasm_js in browser).
Tests: X25519 DH agreement + encoding round-trip; ML-KEM encapsulate↔decapsulate
agreement, public-key round-trip, and the implicit-rejection property (a wrong
decapsulation key yields a different, non-erroring secret — so transcript
binding, not a decap error, is what authenticates). Compiles to wasm32.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UMbqdSzDP4F7Y9AdK5LXaV
Closes the Phase-0 scaffold: buh-crypto now compiles to WebAssembly and the web
client exercises the whole crypto stack in the browser before any session code
depends on it.
buh-crypto:
- `wasm` feature gates a small wasm-bindgen FFI (src/ffi.rs): echo plus
wire/aead/identity self-tests. `#![forbid(unsafe_code)]` is kept for the
native core and relaxed only under `wasm` (bindgen's glue is the only unsafe).
- getrandom standardised on 0.4 (the version crypto-common under ml-dsa pulls)
with the `wasm_js` backend selected via .cargo/config.toml for
wasm32-unknown-unknown; chacha20poly1305 default features off to drop the old
getrandom-0.2 path.
- tests/wasm.rs runs the wire / XChaCha20-Poly1305 / ML-DSA-65 KATs under
wasm-bindgen-test — the deterministic-signature digest matches native
byte-for-byte, so every primitive is now gated native AND wasm.
web/: Vite + React + SWC + TS app wired with vite-plugin-wasm +
vite-plugin-top-level-await over a `--target bundler` wasm-pack build. On load
it round-trips a Uint8Array through echo and runs the three KATs in-browser;
verified in Firefox — all four checks green, zero console errors. All crypto is
imported through src/lib/crypto/, never from the generated pkg/ directly.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UMbqdSzDP4F7Y9AdK5LXaV
The user IS their key (design.md §4): identity is an ML-DSA-65 (FIPS 204)
keypair, hedged/randomized signing by default with a deterministic variant for
reproducible vectors. Fixed-size encode/parse for the public key (1952B) and
signature (3309B), verify-on-failure that leaks only that it failed.
AEAD: nonce-explicit XChaCha20-Poly1305 sealing primitive — the caller owns the
nonce (the ratchet will), so seal() is pure and KAT-pinnable; random_nonce() for
the one-off media-key cases. AAD is the place to bind the wire prelude+flags.
Tests gate the primitives:
- AEAD: the published draft-arciszewski-xchacha-03 A.1 vector (ciphertext+tag
byte-exact), plus tamper/ciphertext/tag/AAD-downgrade/wrong-key rejection.
- Identity: sign/verify round-trip, seed determinism, encode round-trip + length
checks, and a regression KAT pinning the seed=0 public key and deterministic
signature by SHA-256 digest (catches encoding / wasm divergence; upstream
ml-dsa carries the NIST ACVP vectors).
Adds ml-dsa (getrandom feature → hedged signing), chacha20poly1305, getrandom
0.3, sha2, hkdf to the workspace; only buh-crypto links them — the node never
does. CryptoError unifies wire/aead/signature/parse failures.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UMbqdSzDP4F7Y9AdK5LXaV
Establish the AGPL-3.0 cargo workspace per the org conventions, with the
crate layout for the anti-hub messenger: buh-entities (domain types/DTOs),
buh-crypto (client crypto core; compiles to WASM, never linked by the node),
and buh-core (business logic + MailboxRepo/BlobStore/SettlementBackend ports).
The settlement value types are deliberately chain- and money-free (design
§8.5); buh-core stays honestly thin, as a blind relay has little logic.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>