Skip to content

crypto-demo: exercise the rsa_oaep wrappers in an opt-in build - #377

Merged
lann merged 2 commits into
mainfrom
sdk-gate-rsa-oaep
Aug 12, 2026
Merged

crypto-demo: exercise the rsa_oaep wrappers in an opt-in build#377
lann merged 2 commits into
mainfrom
sdk-gate-rsa-oaep

Conversation

@lannbot

@lannbot lannbot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Premise check on #285

The issue lists six never-executed SDK modules, but five (aes_cbc, hmac_sha1, hkdf_sha1, pbkdf2_sha1, sha1_checked) gained demo checks in changes since it was filed. The remainder is rsa_oaep — and the issue's "cheapest close: extend crypto-demo's checks" runs into a structural constraint: a component's imports are derived from the calls it makes, and the in-guest provider withholds all four RSA op interfaces (class D, including rsa-oaep-encrypt — the class-d gate's own probe list). A demo that calls any OAEP constructor therefore stops composing at wac plug, killing demo::test-composed. This is #215's mechanism, encountered from the consumer side.

The shape

One crate, two artifacts — the class-D split the conformance architecture already uses (guest-ct vs signing-guest-ct), applied to the demo, with the gate's polarity matching the rest of the repository (the SDK's rsa-oaep-decrypt, the WIT gate, and add_to_linker all default off; serving is the deliberate act):

  • rsa-oaep cargo feature, off by default (forwards to the SDK's rsa-oaep-decrypt). The default build is the standard, composable artifact — crypto-demo.component.wasm, what demo::compose plugs.
  • build-component additionally produces crypto-demo-rsa-oaep.component.wasm (--features rsa-oaep), which adds the rsa-oaep-key-transport check and with it the withheld-by-default imports. Only the legs whose hosts deliberately serve those interfaces run it: the wasmtime-demo tests / demo::wasmtime (the standalone embedding opts into every gated interface) and the jco demo on Node. Verified structurally: 0 rsa-oaep mentions in the default artifact's WIT, 4 in the opt-in one.

The check covers every rsa_oaep constructor and both op wrappers: the Wycheproof known answer (rsa_oaep_2048_sha256_mgf1sha256, tcId 2 — the group key is the same 2048-bit modulus as the demo's existing RSA_SPKI) decrypts under both private-key imports (PKCS#8, full-CRT JWK); the public half imported as SPKI and as a public JWK encrypts back to the vector key; a ciphertext decrypts only under its label (mismatch fails AuthenticationFailed, per RFC 8017's indistinguishability rule); and a generated pair round-trips (OAEP is randomized — generation has no known-answer form).

Verification

  • just demo::test-composed: 21 checks pass (default build, no OAEP)
  • cargo test -p wasmtime-demo + just demo::wasmtime: 22 checks pass including rsa-oaep-key-transport (opt-in build); the summary self-consistency assertions hold
  • just demo::test-node (Node 24.19): 22 checks pass (opt-in build) — Node's WebCrypto serves the gated decrypt interfaces (the jco-node posture)
  • just fmt-check, just clippy (now --all-features on the demo, so the gated check stays linted) clean

Fixes #285

lann added 2 commits August 11, 2026 23:30
The rsa_oaep SDK module (every constructor plus the EncryptionKey/
DecryptionKey op wrappers) was the one guest-SDK surface no gate
executed. It cannot join the demo unconditionally: a component's
imports are derived from the calls it makes, and the in-guest provider
withholds all four RSA op interfaces (class D), so a demo calling OAEP
stops composing at wac plug.

The demo therefore gains an rsa-oaep cargo feature (default on) and
build-component produces two artifacts: the default build adds the
rsa-oaep-key-transport check — the Wycheproof known answer under both
private-key imports, both public-key imports encrypting back to it,
label binding, and a generated pair's round trip — and the
--no-default-features composable build keeps the OAEP interfaces out of
the call graph for the in-guest composition. The wasmtime and jco legs
run the full build (22 checks); the composed leg runs the composable one
(21).

Fixes #285 — the other five modules the issue lists gained checks in
earlier changes; rsa_oaep was the remainder.
Default-on read as an endorsement — as if enabling the withheld RSA op
interfaces were the normal choice a consumer opts out of. The posture
everywhere else is the reverse: the SDK's rsa-oaep-decrypt feature, the
WIT gate behind it, and add_to_linker all default off, and test builds
opt in deliberately. The demo now matches: the default build is the
composable artifact (crypto-demo.component.wasm, what the in-guest
composition plugs), and the --features rsa-oaep build exists as the
separate crypto-demo-rsa-oaep.component.wasm, run only by the legs whose
hosts deliberately serve those interfaces (the wasmtime-demo tests, the
jco demo on Node). The clippy line lints the demo --all-features so the
gated check stays covered.
@lannbot lannbot changed the title crypto-demo: exercise the rsa_oaep wrappers; split a composable build crypto-demo: exercise the rsa_oaep wrappers in an opt-in build Aug 12, 2026
@lann
lann merged commit 96158da into main Aug 12, 2026
10 checks passed
@lann
lann deleted the sdk-gate-rsa-oaep branch August 12, 2026 12:56
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.

guest SDK: six modules are executed by no gate (including rsa_oaep)

2 participants