UltrafastSecp256k1/wasm
shrec 7e4695d4e0
docs: update versions to v3.22.0 + binding READMEs + CHANGELOG
- Update stale v3.14.0 headers/footers to v3.22.0: BINDINGS.md,
  DIFFERENTIAL_TESTING.md, AUDIT_TRACEABILITY.md, BINDINGS_PACKAGING.md,
  INTERNAL_AUDIT.md, LTS_POLICY.md
- Fix SECURITY_CLAIMS.md footer v3.21.0 -> v3.22.0
- Update ARCHITECTURE.md, AUDIT_GUIDE.md, CT_VERIFICATION.md,
  CROSS_PLATFORM_TEST_MATRIX.md, TEST_MATRIX.md, USER_GUIDE.md
- Update API_REFERENCE.md: frost_verify_partial signature
- Add BIP-39, ZK, Wallet, Multi-coin, ECDH to CHANGELOG [Unreleased]
- Update all 12 binding READMEs + wasm/README.md with new API surface
- Refresh audit reports (clang-17, gcc-13)
2026-03-13 20:39:36 +00:00
..
bench_wasm.mjs fix(wasm): fix runtime crash in WASM benchmark 2026-02-16 08:34:04 +04:00
CMakeLists.txt fix(wasm): define SECP256K1_NO_INT128 + add s2*G golden vector 2026-02-27 02:57:08 +04:00
package.json fix: delta audit findings + GPU audit runners + docs (#126) 2026-03-09 10:59:58 +04:00
README.md docs: update versions to v3.22.0 + binding READMEs + CHANGELOG 2026-03-13 20:39:36 +00:00
secp256k1_wasm.cpp style: replace all Unicode with ASCII across entire codebase 2026-02-23 02:16:57 +04:00
secp256k1_wasm.h style: replace all Unicode with ASCII across entire codebase 2026-02-23 02:16:57 +04:00
secp256k1.d.ts chore: bump version to 3.0.0, update CHANGELOG, add testers-wanted notice 2026-02-15 05:43:00 +04:00
secp256k1.mjs feat: WebAssembly (Emscripten), Android/WASM CI, Doxygen, fix ROCm 2026-02-15 05:38:50 +04:00

@ultrafastsecp256k1/wasm

Ultra high-performance secp256k1 for the browser and Node.js via Emscripten/WebAssembly.

Powered by UltrafastSecp256k1.

Install

npm install @ultrafastsecp256k1/wasm

Features

  • ECDSA sign/verify (RFC 6979 deterministic nonce, low-S)
  • Schnorr BIP-340 sign/verify
  • SHA-256 hashing
  • Point arithmetic (scalar mul, add)
  • Public key derivation
  • Self-test
  • ES6 module output with TypeScript declarations
  • Key tweaking -- negate, add, multiply
  • Ethereum -- Keccak-256, EIP-55 addresses, EIP-155 sign, ecrecover
  • BIP-39 -- mnemonic generation, validation, seed derivation
  • Multi-coin wallet -- 7-coin address dispatch (BTC/LTC/DOGE/DASH/ETH/BCH/TRX)
  • Batch verification -- ECDSA + Schnorr batch verify with invalid identification
  • MuSig2 -- BIP-327 multi-signatures (key agg, nonce gen, partial sign, aggregate)
  • FROST -- threshold signatures (keygen, sign, aggregate, verify)
  • Adaptor signatures -- Schnorr + ECDSA adaptor pre-sign, adapt, extract
  • Pedersen commitments -- commit, verify, sum balance, switch commitments
  • ZK proofs -- knowledge proof, DLEQ proof, Bulletproof range proof
  • Multi-scalar multiplication -- Shamir's trick, MSM
  • Pubkey arithmetic -- add, negate, combine N keys
  • SHA-512 -- full SHA-512 hash
  • Message signing -- BIP-137 Bitcoin message sign/verify

Quick Start

Build

# Install Emscripten SDK
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk && ./emsdk install latest && ./emsdk activate latest
source emsdk_env.sh

# Build WASM module
cd UltrafastSecp256k1
./scripts/build_wasm.sh

Output in build/wasm/dist/:

File Description
secp256k1_wasm.wasm WebAssembly binary
secp256k1_wasm.js Emscripten loader (ES6)
secp256k1.mjs High-level JS wrapper
secp256k1.d.ts TypeScript declarations
package.json npm package metadata

Usage (Node.js)

import { Secp256k1 } from './dist/secp256k1.mjs';

const lib = await Secp256k1.create();
console.log('Version:', lib.version());
console.log('Self-test:', lib.selftest() ? 'PASS' : 'FAIL');

// Generate public key from private key
const privkey = new Uint8Array(32);
privkey[31] = 1;  // scalar = 1 (generator point)
const { x, y } = lib.pubkeyCreate(privkey);
console.log('G.x:', Buffer.from(x).toString('hex'));

// ECDSA sign
const msgHash = lib.sha256(new TextEncoder().encode('Hello secp256k1'));
const sig = lib.ecdsaSign(msgHash, privkey);
console.log('Signature:', Buffer.from(sig).toString('hex'));

// ECDSA verify
const valid = lib.ecdsaVerify(msgHash, x, y, sig);
console.log('Valid:', valid);  // true

Usage (Browser)

<script type="module">
  import { Secp256k1 } from './dist/secp256k1.mjs';

  const lib = await Secp256k1.create();
  console.log('secp256k1 WASM loaded, version:', lib.version());
  // ... use lib.ecdsaSign(), lib.schnorrSign(), etc.
</script>

API Reference

Secp256k1.create(options?): Promise<Secp256k1>

Initialize the WASM module.

selftest(): boolean

Run built-in self-test.

version(): string

Library version (e.g. "3.0.0").

pubkeyCreate(seckey: Uint8Array): { x, y }

Derive public key from 32-byte private key.

pointMul(pointX, pointY, scalar): { x, y }

Scalar x Point multiplication.

pointAdd(px, py, qx, qy): { x, y }

Point addition.

ecdsaSign(msgHash, seckey): Uint8Array

ECDSA sign (64-byte compact: r ‖ s).

ecdsaVerify(msgHash, pubX, pubY, sig): boolean

ECDSA verify.

schnorrSign(seckey, msg, auxRand?): Uint8Array

Schnorr BIP-340 sign (64-byte: R.x ‖ s).

schnorrVerify(pubkeyX, msg, sig): boolean

Schnorr BIP-340 verify.

schnorrPubkey(seckey): Uint8Array

Derive x-only public key for BIP-340.

sha256(data): Uint8Array

SHA-256 hash.

C API (Low-level)

For direct use from C/C++ or custom WASM bindings, see secp256k1_wasm.h.

Build Options

# Debug build (assertions, safe heap, stack overflow checks)
./scripts/build_wasm.sh debug

# Or manually:
emcmake cmake -S wasm -B build/wasm -DCMAKE_BUILD_TYPE=Debug
cmake --build build/wasm -j

GLV Window Width

WASM defaults to GLV window w=4 (smaller tables for constrained environments). Override with:

emcmake cmake -S wasm -B build/wasm -DSECP256K1_GLV_WINDOW_WIDTH=5
Window Tradeoff
w=4 Default for WASM -- smaller tables, more point additions
w=5 Fewer additions, beneficial if cache permits

See docs/PERFORMANCE_GUIDE.md for detailed benchmarks.

License

MIT