Skip to content

feat(sdk,wasm): wire WASM crypto backend into TS SDK#82

Open
bb-connor wants to merge 3 commits intomainfrom
feat/wasm-crypto-backend
Open

feat(sdk,wasm): wire WASM crypto backend into TS SDK#82
bb-connor wants to merge 3 commits intomainfrom
feat/wasm-crypto-backend

Conversation

@bb-connor
Copy link
Collaborator

@bb-connor bb-connor commented Feb 14, 2026

Summary

  • Pluggable CryptoBackend interface in the TS SDK — all crypto (hashing, signing, verification) now routes through a backend abstraction
  • Noble backend (default) wraps @noble/ed25519 + @noble/hashes — zero behavior change for existing consumers
  • WASM backend (opt-in via initWasm()) wraps @clawdstrike/wasm (hush-core compiled to WebAssembly) for cross-language determinism
  • 5 new WASM exports in hush-wasm: generate_keypair, sign_ed25519, public_key_from_private, hash_sha256_bytes, hash_keccak256_bytes
  • Zero @noble/* imports outside noble-backend.ts — eliminates drift risk between Rust and TS crypto paths
  • @clawdstrike/wasm added as optional peerDependency, externalized in tsup bundle

Consumer usage (no breaking changes)

// Works immediately — noble backend (default)
import { sha256, signMessage } from "@clawdstrike/sdk";

// Opt-in to WASM at startup:
import { initWasm } from "@clawdstrike/sdk";
const ok = await initWasm(); // true if @clawdstrike/wasm installed
// All subsequent crypto calls now use WASM

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/wasm stays external
  • grep -r "@noble" packages/sdk/hush-ts/src/ — only appears in noble-backend.ts
  • npm run test:wasm --workspace=packages/sdk/hush-ts — determinism tests with WASM (requires wasm-pack build artifact)

🤖 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 CryptoBackend abstraction (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-wasm exports 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.

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>
@bb-connor
Copy link
Collaborator Author

@codex

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>
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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>
@bb-connor
Copy link
Collaborator Author

@codex

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

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.

1 participant