feat(sdk,wasm): wire WASM crypto backend into TS SDK#82
feat(sdk,wasm): wire WASM crypto backend into TS SDK#82
Conversation
Introduce a pluggable CryptoBackend interface in the TS SDK so all cryptographic operations (hashing, signing, verification) can run through either the existing @noble/* pure-JS libraries or hush-core compiled to WebAssembly. The noble backend remains the default; consumers opt into WASM via `initWasm()` at startup. Rust (hush-wasm): - Add generate_keypair, sign_ed25519, public_key_from_private exports - Add hash_sha256_bytes, hash_keccak256_bytes returning Uint8Array - Update TypeScript type declarations - Add unit + wasm integration tests TypeScript (hush-ts): - New backend.ts with CryptoBackend interface, getBackend/setBackend/initWasm - New noble-backend.ts wrapping @noble/* into CryptoBackend shape - New wasm-backend.ts wrapping @clawdstrike/wasm (dynamic import only) - Rewire hash.ts, sign.ts, watermarking.ts to use getBackend() - Zero @noble/* imports outside noble-backend.ts - Add @clawdstrike/wasm as optional peerDependency - Add backend + determinism test suites Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The WASM verify_ed25519 binding throws on malformed key/signature input, while the noble backend normalizes errors to false. Wrap the call in try/catch so both backends have identical error semantics. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ad09d227d5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
The web target of @clawdstrike/wasm (built with wasm-pack --target web) requires calling the default export init() to instantiate the WASM module before any other exports are usable. Without this, initWasm() could return true while crypto calls fail at runtime. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5122ea736f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| "access": "public" | ||
| }, | ||
| "peerDependencies": { | ||
| "@clawdstrike/wasm": ">=0.1.0" |
There was a problem hiding this comment.
Tighten WASM peer dependency to compatible release
The SDK’s new WASM backend now depends on exports introduced in this change (hash_sha256_bytes, hash_keccak256_bytes, generate_keypair, sign_ed25519, public_key_from_private), but the peer range >=0.1.0 still accepts older @clawdstrike/wasm builds that do not provide that surface. In that allowed configuration initWasm() can still return true, and the first crypto call then fails at runtime when an expected export is missing, so the declared compatibility range is too broad and should be constrained (or validated at init time).
Useful? React with 👍 / 👎.
| "bench": "node benchmarks/guards.bench.mjs", | ||
| "bench:json": "OUTPUT_JSON=1 node benchmarks/guards.bench.mjs" | ||
| "bench:json": "OUTPUT_JSON=1 node benchmarks/guards.bench.mjs", | ||
| "test:wasm": "WASM_AVAILABLE=1 vitest run" |
There was a problem hiding this comment.
Make wasm test command initialize the WASM backend
The new test:wasm script only sets WASM_AVAILABLE=1 and runs the normal Vitest suite, but there is no test setup that reads this variable or calls initWasm(), while the backend defaults to noble. This means npm run test:wasm still primarily validates the JS path and can miss regressions in the newly added WASM backend integration, so the command should force WASM initialization (and fail if unavailable).
Useful? React with 👍 / 👎.
Summary
CryptoBackendinterface in the TS SDK — all crypto (hashing, signing, verification) now routes through a backend abstraction@noble/ed25519+@noble/hashes— zero behavior change for existing consumersinitWasm()) wraps@clawdstrike/wasm(hush-core compiled to WebAssembly) for cross-language determinismhush-wasm:generate_keypair,sign_ed25519,public_key_from_private,hash_sha256_bytes,hash_keccak256_bytes@noble/*imports outsidenoble-backend.ts— eliminates drift risk between Rust and TS crypto paths@clawdstrike/wasmadded as optionalpeerDependency, externalized in tsup bundleConsumer usage (no breaking changes)
Test plan
cargo test -p hush-wasm— 18 unit + 4 integration tests pass (new signing, bytes, keypair functions)npm test --workspace=packages/sdk/hush-ts— all 159 tests pass across 20 files (noble backend)npm run build --workspace=packages/sdk/hush-ts— tsup bundles ESM/CJS/DTS,@clawdstrike/wasmstays externalgrep -r "@noble" packages/sdk/hush-ts/src/— only appears innoble-backend.tsnpm run test:wasm --workspace=packages/sdk/hush-ts— determinism tests with WASM (requireswasm-pack buildartifact)🤖 Generated with Claude Code
Note
Medium Risk
Touches core cryptographic call paths and adds dynamic WASM loading, so regressions could affect hashing/signing correctness or runtime availability despite the noble default and added tests.
Overview
Adds a pluggable crypto layer to the TS SDK by routing hashing and Ed25519 operations through a new
CryptoBackendabstraction (defaulting to a noble-based implementation) and exposing backend controls (getBackend,setBackend,initWasm,isWasmBackend).Introduces an opt-in WASM backend loaded via dynamic import from
@clawdstrike/wasm(optional peer dependency and externalized from the bundle), and updates watermarking key derivation to use the active backend instead of direct noble calls.Extends
hush-wasmexports with raw-byte hash variants plus Ed25519 keypair generation, signing, and public-key derivation, along with updated TypeScript typings and expanded Rust/wasm tests to cover these new APIs and backend behavior.Written by Cursor Bugbot for commit 5122ea7. This will update automatically on new commits. Configure here.