@oleary-labs/signet-sdk 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,210 @@
1
+ # @oleary-labs/signet-sdk
2
+
3
+ TypeScript client for the [Signet](https://github.com/oleary-labs/signet-protocol) threshold-signing protocol. Handles session keys, OAuth + ZK auth, threshold keygen, threshold signing across three signing schemes (FROST/secp256k1, FROST/Ed25519, threshold ECDSA/secp256k1), delegation tokens, scoped sub-keys, ERC-4337 user operations, and x402 payments.
4
+
5
+ Extracted from `signet-ui`; now consumed by `signet-ui` and `signet-better-mcp`.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ bun add @oleary-labs/signet-sdk
11
+ # or: npm install @oleary-labs/signet-sdk
12
+ ```
13
+
14
+ Optional peer dependencies (only needed if you call the corresponding subpaths):
15
+
16
+ | Peer dep | Required for | Default state |
17
+ |---|---|---|
18
+ | `viem` >=2.0.0 | `./userop`, `./bundler`, `./x402`, anything that touches EVM ABI encoding | strongly recommended for most consumers |
19
+ | `@noir-lang/noir_js` 1.0.0-beta.11 | `./proof`, `./witness` (in-browser ZK proving) | optional — only needed if you prove client-side |
20
+ | `@aztec/bb.js` 0.82.2 | `./proof`, `./witness` | optional — same as above |
21
+ | `@oleary-labs/signet-circuits` ^0.3.0 | `./proof`, `./witness` | optional — server-side proving via `signet-min-bundler`'s `POST /v1/prove` doesn't require this peer at all |
22
+
23
+ Most consumers delegate ZK proof generation to `signet-min-bundler`'s `POST /v1/prove` (see `./server-prover`) and don't install the Noir/bb peers at all.
24
+
25
+ ## Concept overview — what's where
26
+
27
+ Signet's protocol nodes accept a `curve` parameter on every signing endpoint and dispatch to one of three schemes:
28
+
29
+ | Curve string | Scheme | Where it's used |
30
+ |---|---|---|
31
+ | `frost_secp256k1` | FROST Schnorr / secp256k1 (RFC 9591) | Admin signing, ERC-4337 user-op signing, anything FROST-based |
32
+ | `frost_ed25519` | FROST Schnorr / Ed25519 | Solana and other Ed25519 chains |
33
+ | `ecdsa_secp256k1` | Threshold ECDSA / secp256k1 (DJNPO20, 4-round robust) | Scoped sub-keys, x402 agent payments, EIP-712 typed-data signing where the verifier expects raw ECDSA |
34
+
35
+ The SDK reflects this with a unified function-per-operation API rather than separate client classes — every signing function takes a `curve` argument (or hard-codes one where it makes sense). The HTTP responses for signing carry both `signature` (the scheme's native format) and `ecdsa_signature` (a 65-byte r‖s‖v variant) where applicable.
36
+
37
+ Session authentication and auth-key certificates always use ephemeral local ECDSA — that's universal and lives entirely in the client.
38
+
39
+ ## Subpath exports
40
+
41
+ The SDK ships with 19 subpath exports. Import the one you need; the entry point (`@oleary-labs/signet-sdk`) re-exports the most common identifiers.
42
+
43
+ ### Core
44
+
45
+ | Subpath | Purpose |
46
+ |---|---|
47
+ | `./session` | Generate/import an ephemeral secp256k1 session keypair; hex helpers |
48
+ | `./types` | `SessionKeypair`, `IdTokenClaims`, and shared types |
49
+ | `./request` | Build canonical request hashes; sign them with the session ECDSA key (used internally by most other modules) |
50
+
51
+ ### Auth
52
+
53
+ | Subpath | Purpose |
54
+ |---|---|
55
+ | `./oauth` | OAuth code exchange and JWT extraction (`handleOAuthCallback`, `getOAuthReturnTo`) |
56
+ | `./jwt` | JWT decode / validate |
57
+ | `./jwks` | JWKS fetch and key lookup |
58
+ | `./bootstrap` | Bootstrap-group authentication wrapper |
59
+ | `./authkey-session` | Auth-key certificate session — server-side flow that lets a backend authenticate with a long-lived ECDSA key instead of an OAuth bearer token |
60
+
61
+ ### Keygen and signing
62
+
63
+ | Subpath | Purpose |
64
+ |---|---|
65
+ | `./keygen` | Threshold keygen request (`keygen(config, keypair, claims, keySuffix?, identity?, curve?, scope?)`) |
66
+ | `./admin` | Admin API auth — bootstrap-group FROST signing for admin endpoints |
67
+ | `./delegate` | Mint and redeem delegation JWTs (`requestDelegation`, `authenticateWithDelegation`) for autonomous-agent flows |
68
+ | `./scopedSign` | EIP-712 structured signing with scoped sub-keys (`signTypedData(...)`; `buildEIP712ScopeForTypedData` / `buildEIP712Scope` / `eip712TypeHash`; `CHAIN_PRESETS`) |
69
+ | `./frostVerify` | Client-side FROST Schnorr verification (RFC 9591) — useful for tests and round-trip checks |
70
+
71
+ ### ERC-4337 and payments
72
+
73
+ | Subpath | Purpose |
74
+ |---|---|
75
+ | `./userop` | Build ERC-4337 v0.7 user operations and FROST-sign them |
76
+ | `./bundler` | JSON-RPC client for `signet-min-bundler` (send/estimate/receipt) |
77
+ | `./x402` | `x402Fetch` — performs the full x402 dance (request → 402 → sign → retry) |
78
+
79
+ ### ZK proofs
80
+
81
+ | Subpath | Purpose |
82
+ |---|---|
83
+ | `./witness` | Build the witness for the `jwt_auth` Noir circuit |
84
+ | `./proof` | Generate the proof in-browser using `@aztec/bb.js` + `@noir-lang/noir_js` |
85
+ | `./server-prover` | Delegate proof generation to `signet-min-bundler`'s `POST /v1/prove` (recommended for most apps) |
86
+
87
+ ## The `curve` parameter contract
88
+
89
+ Functions that hit a signing endpoint accept a curve string. Pass one of the three canonical values exactly:
90
+
91
+ ```ts
92
+ "frost_secp256k1" | "frost_ed25519" | "ecdsa_secp256k1"
93
+ ```
94
+
95
+ Mismatches between what you pass here and the key's actual scheme will fail at the node, not in the client.
96
+
97
+ The session itself (the ephemeral keypair from `./session`) and auth-key certificates always use local ECDSA — there's no curve parameter for those; only the threshold-signing operations take one.
98
+
99
+ For the canonical per-curve reference (algorithms, storage prefixes, response shapes, picking guidance), see [`signet-protocol/docs/CURVES.md`](https://github.com/oleary-labs/signet-protocol/blob/main/docs/CURVES.md).
100
+
101
+ ## Example flows
102
+
103
+ ### A. FROST keygen via OAuth (Console main flow)
104
+
105
+ ```ts
106
+ import { generateSessionKeypair } from "@oleary-labs/signet-sdk/session";
107
+ import { handleOAuthCallback } from "@oleary-labs/signet-sdk/oauth";
108
+ import { keygen } from "@oleary-labs/signet-sdk/keygen";
109
+
110
+ const keypair = await generateSessionKeypair();
111
+ const { claims } = await handleOAuthCallback(/* ... */);
112
+
113
+ const result = await keygen(
114
+ {
115
+ nodeUrls: ["https://node-1.example.com", "https://node-2.example.com", "https://node-3.example.com"],
116
+ groupId: "0xf0700...",
117
+ proxyEndpoint: "/api/node/proxy", // optional CORS proxy
118
+ },
119
+ keypair,
120
+ claims,
121
+ /* keySuffix */ undefined,
122
+ /* identity */ undefined,
123
+ /* curve */ "frost_secp256k1",
124
+ );
125
+
126
+ console.log(result.ethereumAddress, result.groupPublicKey);
127
+ ```
128
+
129
+ ### B. ECDSA scoped sub-key + EIP-712 signing (x402 agent flow)
130
+
131
+ ```ts
132
+ import { keygen } from "@oleary-labs/signet-sdk/keygen";
133
+ import { requestDelegation, authenticateWithDelegation } from "@oleary-labs/signet-sdk/delegate";
134
+ import { signTypedData, buildEIP712ScopeForTypedData, CHAIN_PRESETS } from "@oleary-labs/signet-sdk/scopedSign";
135
+ import { buildTransferAuthorization, x402Fetch } from "@oleary-labs/signet-sdk/x402";
136
+
137
+ // Operator side: mint a scoped sub-key bound to USDC on Base AND the
138
+ // TransferWithAuthorization method. A 0x03 scope binds chainId +
139
+ // verifyingContract + the EIP-712 primary type, so the key cannot sign a
140
+ // different method (e.g. an EIP-2612 permit) on the same token. Derive the
141
+ // scope from a sample typed-data payload (message values are irrelevant):
142
+ const preset = CHAIN_PRESETS[0]; // USDC on Base
143
+ const zero = "0x0000000000000000000000000000000000000000";
144
+ const sample = buildTransferAuthorization(
145
+ zero, zero, "0", preset.verifyingContract, preset.chainId, preset.eip712Name, preset.eip712Version,
146
+ );
147
+ const scope = buildEIP712ScopeForTypedData(sample);
148
+ const subkey = await keygen(config, keypair, claims, /* keySuffix */ "agent-1", /* identity */ undefined, "ecdsa_secp256k1", scope);
149
+
150
+ // Mint a delegation JWT for the agent
151
+ const delegation = await requestDelegation({ /* ... */ curve: "ecdsa_secp256k1" });
152
+
153
+ // Agent side: redeem the delegation and sign
154
+ const agentSession = await authenticateWithDelegation(delegation, /* ... */);
155
+ const signed = await signTypedData(
156
+ nodeUrl,
157
+ proxyEndpoint,
158
+ groupId,
159
+ subkey.keyId,
160
+ "ecdsa_secp256k1",
161
+ typedData,
162
+ agentSession.keypair,
163
+ agentSession.claims,
164
+ );
165
+
166
+ // Use it for an x402 invoice
167
+ const response = await x402Fetch("https://api.example.com/pay", { /* ... */ });
168
+ ```
169
+
170
+ ### C. Admin signing via bootstrap group (FROST)
171
+
172
+ ```ts
173
+ import { adminSign } from "@oleary-labs/signet-sdk/admin";
174
+
175
+ const adminSig = await adminSign({
176
+ groupId,
177
+ nodeUrl,
178
+ proxyEndpoint,
179
+ // ...
180
+ });
181
+ ```
182
+
183
+ See `signet-ui` (Console, x402 demo) and `signet-better-mcp` (MCP server) for full working examples.
184
+
185
+ ## Relation to other Signet repos
186
+
187
+ ```
188
+ signet-circuits ──► signet-protocol (embeds VK)
189
+ ──► signet-min-bundler (embeds circuit, runs `nargo` + `bb`)
190
+ ──► signet-sdk (peer dep, optional — for browser proving)
191
+
192
+ signet-protocol ◄── HTTP /v1/* ── signet-sdk ◄── signet-ui, signet-better-mcp
193
+ signet-min-bundler ◄── /v1/prove ── signet-sdk (./server-prover)
194
+ ```
195
+
196
+ The SDK has no opinion about hosting — caller supplies all URLs at runtime (no hardcoded endpoints). For local development point it at the signet-protocol devnet (`http://localhost:8080..8082`) and `signet-min-bundler` (`http://localhost:4337`).
197
+
198
+ ## Build
199
+
200
+ ```bash
201
+ bun install
202
+ bun run build # tsc to ./dist (ESM + .d.ts)
203
+ bun run typecheck # tsc --noEmit
204
+ ```
205
+
206
+ ESM-only. `prepublishOnly` runs the build so `bun publish` (or `npm publish`) ships a current `dist/`.
207
+
208
+ ## License
209
+
210
+ MIT.
@@ -0,0 +1,26 @@
1
+ type GenerateInputsParams = {
2
+ jwt: string;
3
+ pubkey: JsonWebKey;
4
+ shaPrecomputeTillKeys?: string[];
5
+ maxSignedDataLength: number;
6
+ };
7
+ type JWTCircuitInputs = {
8
+ data?: {
9
+ storage: number[];
10
+ len: number;
11
+ };
12
+ base64_decode_offset: number;
13
+ pubkey_modulus_limbs: string[];
14
+ redc_params_limbs: string[];
15
+ signature_limbs: string[];
16
+ partial_data?: {
17
+ storage: number[];
18
+ len: number;
19
+ };
20
+ partial_hash?: number[];
21
+ full_data_length?: number;
22
+ };
23
+ export declare function generateInputs({ jwt, pubkey, shaPrecomputeTillKeys, maxSignedDataLength, }: GenerateInputsParams): Promise<JWTCircuitInputs>;
24
+ export declare function splitBigIntToChunks(bigInt: bigint, chunkSize: number, numChunks: number): bigint[];
25
+ export {};
26
+ //# sourceMappingURL=generate-inputs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-inputs.d.ts","sourceRoot":"","sources":["../src/generate-inputs.ts"],"names":[],"mappings":"AAEA,KAAK,oBAAoB,GAAG;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,UAAU,CAAC;IACnB,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;IACjC,mBAAmB,EAAE,MAAM,CAAC;CAC7B,CAAA;AAED,KAAK,gBAAgB,GAAG;IACtB,IAAI,CAAC,EAAE;QACL,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;IACF,oBAAoB,EAAE,MAAM,CAAC;IAC7B,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,YAAY,CAAC,EAAE;QACb,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;IACF,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAA;AAUD,wBAAsB,cAAc,CAAC,EACnC,GAAG,EACH,MAAM,EACN,qBAAqB,EACrB,mBAAmB,GACpB,EAAE,oBAAoB,6BAgGtB;AAUD,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,YASlB"}
@@ -0,0 +1,106 @@
1
+ import { generatePartialSHA256 } from './partial-sha';
2
+ /*
3
+ * Generates circuit inputs required for the jwt lib
4
+ * @param {Object} params - The input parameters
5
+ * @param {string} params.jwt - The JWT token to process (string)
6
+ * @param {JsonWebKey} params.pubkey - The public key to verify the signature (JsonWebKey)
7
+ * @param {string[]} params.shaPrecomputeTillKeys - (optional) Key(s) in the payload until which SHA should be precomputed
8
+ * @param {number} params.maxSignedDataLength - Maximum length of signed data (with or without partial hash) allowed by the circuit
9
+ */
10
+ export async function generateInputs({ jwt, pubkey, shaPrecomputeTillKeys, maxSignedDataLength, // when using partial hash, this will be the length of data after partial hash
11
+ }) {
12
+ // Parse token
13
+ const [headerB64, payloadB64] = jwt.split(".");
14
+ // Extract signed data as byte array
15
+ const signedDataString = jwt.split(".").slice(0, 2).join("."); // $header.$payload
16
+ const signedData = new TextEncoder().encode(signedDataString);
17
+ // Extract signature as bigint
18
+ const signatureBase64Url = jwt.split(".")[2];
19
+ const signatureBase64 = signatureBase64Url
20
+ .replace(/-/g, "+")
21
+ .replace(/_/g, "/");
22
+ const signature = new Uint8Array(atob(signatureBase64)
23
+ .split("")
24
+ .map((c) => c.charCodeAt(0)));
25
+ const signatureBigInt = BigInt("0x" + Array.from(signature).map(b => b.toString(16).padStart(2, '0')).join(''));
26
+ // Extract pubkey modulus as bigint
27
+ const pubkeyBigInt = BigInt("0x" + atob(pubkey.n.replace(/-/g, "+").replace(/_/g, "/"))
28
+ .split("")
29
+ .map(c => c.charCodeAt(0).toString(16).padStart(2, "0"))
30
+ .join(""));
31
+ const redcParam = (1n << (2n * 2048n + 4n)) / pubkeyBigInt; // something needed by the noir big-num lib
32
+ const inputs = {
33
+ pubkey_modulus_limbs: splitBigIntToChunks(pubkeyBigInt, 120, 18).map(s => s.toString()),
34
+ redc_params_limbs: splitBigIntToChunks(redcParam, 120, 18).map(s => s.toString()),
35
+ signature_limbs: splitBigIntToChunks(signatureBigInt, 120, 18).map(s => s.toString()),
36
+ };
37
+ if (!shaPrecomputeTillKeys || shaPrecomputeTillKeys.length === 0) {
38
+ // No precompute selector - no need to precompute SHA256
39
+ if (signedData.length > maxSignedDataLength) {
40
+ throw new Error("Signed data length exceeds maxSignedDataLength");
41
+ }
42
+ const signedDataPadded = new Uint8Array(maxSignedDataLength);
43
+ signedDataPadded.set(signedData);
44
+ inputs.data = {
45
+ storage: Array.from(signedDataPadded),
46
+ len: signedData.length,
47
+ };
48
+ // entire payload is base64 decode-able when not using partial hash
49
+ // offset in signed data is the index of payload start
50
+ // this can be any multiple of 4 from payload start, if you want to skip some bytes from start
51
+ inputs.base64_decode_offset = headerB64.length + 1;
52
+ }
53
+ else {
54
+ // Precompute SHA256 of the signed data
55
+ // SHA256 is done in 64 byte chunks, so we can hash upto certain portion outside of circuit to save constraints
56
+ // Signed data is $headerB64.$payloadB64
57
+ // We need to find the index in B64 payload corresponding to min(hdIndex, nonceIndex) when decoded
58
+ // Then we find the 64 byte boundary before this index and precompute the SHA256 upto that
59
+ const payloadString = atob(payloadB64);
60
+ const indicesOfPrecomputeKeys = shaPrecomputeTillKeys.map((key) => payloadString.indexOf(`"${key}":`));
61
+ const smallerIndex = Math.min(...indicesOfPrecomputeKeys);
62
+ const smallerIndexInB64 = Math.floor((smallerIndex * 4) / 3); // 4 B64 chars = 3 bytes
63
+ const sliceStart = headerB64.length + smallerIndexInB64 + 1; // +1 for the '.'
64
+ // Precompute the SHA256 hash
65
+ const { partialHash, remainingData } = await generatePartialSHA256(signedData, sliceStart);
66
+ // Pad to the max length configured in the circuit
67
+ if (remainingData.length > maxSignedDataLength) {
68
+ throw new Error("remainingData after partial hash exceeds maxSignedDataLength");
69
+ }
70
+ const remainingDataPadded = new Uint8Array(maxSignedDataLength);
71
+ remainingDataPadded.set(remainingData);
72
+ inputs.partial_data = {
73
+ storage: Array.from(remainingDataPadded),
74
+ len: remainingData.length,
75
+ };
76
+ inputs.partial_hash = Array.from(partialHash);
77
+ inputs.full_data_length = signedData.length;
78
+ // when using partial hash, the data after the partial hash might not be a valid base64
79
+ // we need to find an offset (1, 2, or 3) such that the remaining payload is base64 decode-able
80
+ // this is the number that should be added to the "payload chunk that was included in SHA precompute"
81
+ // to make it a multiple of 4
82
+ // in other words, if you trim offset number of bytes from the remaining payload, it will be base64 decode-able
83
+ const shaCutoffIndex = signedData.length - remainingData.length;
84
+ const payloadBytesInShaPrecompute = shaCutoffIndex - (headerB64.length + 1);
85
+ const offsetToMakeIt4x = 4 - (payloadBytesInShaPrecompute % 4);
86
+ inputs.base64_decode_offset = offsetToMakeIt4x;
87
+ }
88
+ return inputs;
89
+ }
90
+ /*
91
+ * Splits a BigInt into fixed-size chunks
92
+ * @param {bigint} bigInt - The BigInt to split
93
+ * @param {number} chunkSize - Size of each chunk in bits
94
+ * @param {number} numChunks - Number of chunks to split into
95
+ * @returns {bigint[]} Array of BigInt chunks
96
+ */
97
+ export function splitBigIntToChunks(bigInt, chunkSize, numChunks) {
98
+ const chunks = [];
99
+ const mask = (1n << BigInt(chunkSize)) - 1n;
100
+ for (let i = 0; i < numChunks; i++) {
101
+ const chunk = (bigInt / (1n << (BigInt(i) * BigInt(chunkSize)))) & mask;
102
+ chunks.push(chunk);
103
+ }
104
+ return chunks;
105
+ }
106
+ //# sourceMappingURL=generate-inputs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-inputs.js","sourceRoot":"","sources":["../src/generate-inputs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export declare function generatePartialSHA256(data: Uint8Array, hashUntilIndex: number): Promise<{
2
+ partialHash: Uint32Array<ArrayBuffer>;
3
+ remainingData: Uint8Array<ArrayBuffer>;
4
+ }>;
5
+ //# sourceMappingURL=partial-sha.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"partial-sha.d.ts","sourceRoot":"","sources":["../src/partial-sha.ts"],"names":[],"mappings":"AACA,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM;;;GA4BnF"}
@@ -0,0 +1,89 @@
1
+ // Returns the intermediate SHA256 hash of the data
2
+ export async function generatePartialSHA256(data, hashUntilIndex) {
3
+ if (typeof data === 'string') {
4
+ const encoder = new TextEncoder();
5
+ data = encoder.encode(data); // Convert string to Uint8Array
6
+ }
7
+ const blockSize = 64; // 512 bits
8
+ const blockIndex = Math.floor(hashUntilIndex / blockSize);
9
+ const H = new Uint32Array([
10
+ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
11
+ 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
12
+ ]);
13
+ for (let i = 0; i < blockIndex; i++) {
14
+ if (i * blockSize >= data.length) {
15
+ throw new Error('Block index out of range.');
16
+ }
17
+ const block = new Uint8Array(blockSize);
18
+ block.set(data.slice(i * blockSize, (i + 1) * blockSize));
19
+ sha256Block(H, block);
20
+ }
21
+ // Get the intermediate digest (this is **not** the final hash)
22
+ return {
23
+ partialHash: H,
24
+ remainingData: data.slice(blockIndex * blockSize)
25
+ };
26
+ }
27
+ /**
28
+ * SHA-256 constants (first 32 bits of fractional parts of cube roots of primes)
29
+ */
30
+ const K = [
31
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
32
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
33
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
34
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
35
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
36
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
37
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
38
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
39
+ ];
40
+ /**
41
+ * Rotate right function (SHA-256 bitwise operations)
42
+ */
43
+ function rotr(n, x) {
44
+ return (x >>> n) | (x << (32 - n));
45
+ }
46
+ /**
47
+ * SHA-256 Compression Function (Processes 64-byte blocks)
48
+ */
49
+ function sha256Block(H, block) {
50
+ let w = new Uint32Array(64);
51
+ let a = H[0], b = H[1], c = H[2], d = H[3];
52
+ let e = H[4], f = H[5], g = H[6], h = H[7];
53
+ // Convert block into 32-bit words
54
+ for (let i = 0; i < 16; i++) {
55
+ w[i] = (block[i * 4] << 24) | (block[i * 4 + 1] << 16) | (block[i * 4 + 2] << 8) | block[i * 4 + 3];
56
+ }
57
+ for (let i = 16; i < 64; i++) {
58
+ const s0 = rotr(7, w[i - 15]) ^ rotr(18, w[i - 15]) ^ (w[i - 15] >>> 3);
59
+ const s1 = rotr(17, w[i - 2]) ^ rotr(19, w[i - 2]) ^ (w[i - 2] >>> 10);
60
+ w[i] = (w[i - 16] + s0 + w[i - 7] + s1) >>> 0;
61
+ }
62
+ // Main compression loop
63
+ for (let i = 0; i < 64; i++) {
64
+ const S1 = rotr(6, e) ^ rotr(11, e) ^ rotr(25, e);
65
+ const ch = (e & f) ^ (~e & g);
66
+ const temp1 = (h + S1 + ch + K[i] + w[i]) >>> 0;
67
+ const S0 = rotr(2, a) ^ rotr(13, a) ^ rotr(22, a);
68
+ const maj = (a & b) ^ (a & c) ^ (b & c);
69
+ const temp2 = (S0 + maj) >>> 0;
70
+ h = g;
71
+ g = f;
72
+ f = e;
73
+ e = (d + temp1) >>> 0;
74
+ d = c;
75
+ c = b;
76
+ b = a;
77
+ a = (temp1 + temp2) >>> 0;
78
+ }
79
+ // Update intermediate hash values
80
+ H[0] = (H[0] + a) >>> 0;
81
+ H[1] = (H[1] + b) >>> 0;
82
+ H[2] = (H[2] + c) >>> 0;
83
+ H[3] = (H[3] + d) >>> 0;
84
+ H[4] = (H[4] + e) >>> 0;
85
+ H[5] = (H[5] + f) >>> 0;
86
+ H[6] = (H[6] + g) >>> 0;
87
+ H[7] = (H[7] + h) >>> 0;
88
+ }
89
+ //# sourceMappingURL=partial-sha.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"partial-sha.js","sourceRoot":"","sources":["../src/partial-sha.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Client-side ZK proof generation for JWT authentication.
3
+ *
4
+ * Runs entirely in the browser:
5
+ * 1. Parse JWT + fetch JWKS → build circuit witness
6
+ * 2. @noir-lang/noir_js → generate ACIR witness from compiled circuit
7
+ * 3. @aztec/bb.js → generate UltraHonk proof via WASM
8
+ *
9
+ * Expected time: ~2-7 seconds in a modern browser.
10
+ */
11
+ import type { IdTokenClaims } from "./types";
12
+ /** Proof generation result. */
13
+ export interface ProofResult {
14
+ proof: Uint8Array;
15
+ publicInputs: string[];
16
+ claims: IdTokenClaims;
17
+ }
18
+ /**
19
+ * Generate a ZK proof that a JWT is valid — entirely client-side.
20
+ *
21
+ * @param jwt — raw JWT string (header.payload.signature)
22
+ * @param sessionPubHex — 33-byte compressed secp256k1 session public key (hex)
23
+ * @returns proof bytes, public inputs, and decoded claims
24
+ */
25
+ export declare function generateJWTProof(jwt: string, sessionPubHex: string): Promise<ProofResult>;
26
+ /**
27
+ * Get the RSA modulus bytes for a JWT (for the node auth request).
28
+ */
29
+ export declare function getJWTModulusBytes(jwt: string): Promise<Uint8Array>;
30
+ //# sourceMappingURL=proof.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proof.d.ts","sourceRoot":"","sources":["../src/proof.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AASH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,+BAA+B;AAC/B,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,UAAU,CAAC;IAClB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,MAAM,EAAE,aAAa,CAAC;CACvB;AAKD;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,MAAM,EACX,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,WAAW,CAAC,CA2CtB;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAUzE"}
package/dist/proof.js ADDED
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Client-side ZK proof generation for JWT authentication.
3
+ *
4
+ * Runs entirely in the browser:
5
+ * 1. Parse JWT + fetch JWKS → build circuit witness
6
+ * 2. @noir-lang/noir_js → generate ACIR witness from compiled circuit
7
+ * 3. @aztec/bb.js → generate UltraHonk proof via WASM
8
+ *
9
+ * Expected time: ~2-7 seconds in a modern browser.
10
+ */
11
+ import { Noir } from "@noir-lang/noir_js";
12
+ import { UltraHonkBackend } from "@aztec/bb.js";
13
+ import { jwt as jwtArtifacts, assertBbJsVersion } from "@oleary-labs/signet-circuits";
14
+ import { decodeIdToken } from "./oauth";
15
+ import { getJWKSKeyForKid, decodeModulusBytes } from "./jwks";
16
+ import { buildFullWitness } from "./witness";
17
+ import { hexToBytes } from "./session";
18
+ // Circuit artifact from @signet/circuits — embedded at build time.
19
+ const circuit = jwtArtifacts.circuit;
20
+ /**
21
+ * Generate a ZK proof that a JWT is valid — entirely client-side.
22
+ *
23
+ * @param jwt — raw JWT string (header.payload.signature)
24
+ * @param sessionPubHex — 33-byte compressed secp256k1 session public key (hex)
25
+ * @returns proof bytes, public inputs, and decoded claims
26
+ */
27
+ export async function generateJWTProof(jwt, sessionPubHex) {
28
+ // 1. Parse JWT and decode claims
29
+ const parts = jwt.split(".");
30
+ const headerB64 = parts[0];
31
+ const header = JSON.parse(atob(headerB64.replace(/-/g, "+").replace(/_/g, "/")));
32
+ const claims = decodeIdToken(jwt);
33
+ // 2. Fetch the RSA key from the issuer's JWKS
34
+ const jwksKey = await getJWKSKeyForKid(header.kid, claims.iss);
35
+ const jsonWebKey = {
36
+ kty: jwksKey.kty,
37
+ n: jwksKey.n,
38
+ e: jwksKey.e,
39
+ alg: jwksKey.alg,
40
+ };
41
+ // 3. Build full circuit witness
42
+ const sessionPubBytes = Array.from(hexToBytes(sessionPubHex));
43
+ const witness = await buildFullWitness(jwt, jsonWebKey, claims, sessionPubBytes);
44
+ // 4. Version check — fail fast if bb.js doesn't match the circuit artifacts.
45
+ await assertBbJsVersion();
46
+ // 5. Generate ACIR witness from compiled circuit
47
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
48
+ const noir = new Noir(circuit);
49
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
50
+ const { witness: acirWitness } = await noir.execute(witness);
51
+ // 6. Generate UltraHonk proof via bb.js WASM
52
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
53
+ const backend = new UltraHonkBackend(circuit.bytecode);
54
+ const proofData = await backend.generateProof(acirWitness);
55
+ await backend.destroy();
56
+ return {
57
+ proof: proofData.proof,
58
+ publicInputs: proofData.publicInputs,
59
+ claims,
60
+ };
61
+ }
62
+ /**
63
+ * Get the RSA modulus bytes for a JWT (for the node auth request).
64
+ */
65
+ export async function getJWTModulusBytes(jwt) {
66
+ const parts = jwt.split(".");
67
+ const header = JSON.parse(atob(parts[0].replace(/-/g, "+").replace(/_/g, "/")));
68
+ const claims = JSON.parse(atob(parts[1].replace(/-/g, "+").replace(/_/g, "/")));
69
+ const jwksKey = await getJWKSKeyForKid(header.kid, claims.iss);
70
+ return decodeModulusBytes(jwksKey.n);
71
+ }
72
+ //# sourceMappingURL=proof.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proof.js","sourceRoot":"","sources":["../src/proof.ts"],"names":[],"mappings":"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"}
@@ -5,6 +5,7 @@
5
5
  * structured payload that the node verifies against the key's scope
6
6
  * before computing the hash and signing.
7
7
  */
8
+ import type { Hex } from "viem";
8
9
  import type { SessionKeypair, IdTokenClaims } from "./types";
9
10
  export interface EIP712Domain {
10
11
  name?: string;
@@ -26,13 +27,35 @@ export interface ScopedSignResult {
26
27
  ecdsaSignature: string;
27
28
  curve: string;
28
29
  }
30
+ type EIP712Types = Record<string, ReadonlyArray<{
31
+ name: string;
32
+ type: string;
33
+ }>>;
29
34
  /**
30
- * Build an EIP-712 domain scope (scheme 0x03).
35
+ * EIP-712 typeHash: keccak256(encodeType(primaryType)). This is the value a
36
+ * 0x03 scope binds, and the same value the verifying contract uses — so a
37
+ * key scoped to one method (e.g. TransferWithAuthorization) cannot sign a
38
+ * different method on the same contract (e.g. permit).
39
+ */
40
+ export declare function eip712TypeHash(primaryType: string, types: EIP712Types): Hex;
41
+ /**
42
+ * Build an EIP-712 domain+type scope (scheme 0x03).
31
43
  *
32
44
  * Format: 0x03 | chainId (8 bytes, uint64 BE) | verifyingContract (20 bytes)
33
- * Total: 29 bytes.
45
+ * | typeHash (32 bytes). Total: 61 bytes.
46
+ *
47
+ * `typeHash` is keccak256(encodeType(primaryType)) — see {@link eip712TypeHash}.
48
+ * Binding the type (not just the domain) prevents a key authorized for one
49
+ * typed-data method from signing a different method on the same contract.
50
+ */
51
+ export declare function buildEIP712Scope(chainId: number, verifyingContract: string, typeHash: Hex): string;
52
+ /**
53
+ * Convenience: build a 0x03 scope directly from an EIP-712 typed-data sample,
54
+ * deriving chainId, verifyingContract, and typeHash from it. Any sample with
55
+ * the intended domain + primary type works (message values are irrelevant to
56
+ * the scope). This is the recommended way to scope a key for a given method.
34
57
  */
35
- export declare function buildEIP712Scope(chainId: number, verifyingContract: string): string;
58
+ export declare function buildEIP712ScopeForTypedData(typedData: Pick<EIP712TypedData, "domain" | "types" | "primaryType">): string;
36
59
  /**
37
60
  * Sign a structured EIP-712 payload with a scoped key.
38
61
  *
@@ -79,4 +102,5 @@ export declare const CHAIN_PRESETS: readonly [{
79
102
  readonly eip712Name: "USD Coin";
80
103
  readonly eip712Version: "2";
81
104
  }];
105
+ export {};
82
106
  //# sourceMappingURL=scopedSign.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"scopedSign.d.ts","sourceRoot":"","sources":["../src/scopedSign.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAO7D,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,YAAY,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;IAC7D,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;CACf;AAMD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAG,MAAM,CAiBnF;AAMD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,eAAe,EAC1B,cAAc,EAAE,cAAc,EAC9B,MAAM,EAAE,aAAa,EACrB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,gBAAgB,CAAC,CAkD3B;AAMD,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiChB,CAAC"}
1
+ {"version":3,"file":"scopedSign.d.ts","sourceRoot":"","sources":["../src/scopedSign.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AAChC,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAQ7D,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,YAAY,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;IAC7D,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;CACf;AAMD,KAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAAC;AAyBjF;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,GAAG,CAK3E;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,iBAAiB,EAAE,MAAM,EACzB,QAAQ,EAAE,GAAG,GACZ,MAAM,CA2BR;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAC1C,SAAS,EAAE,IAAI,CAAC,eAAe,EAAE,QAAQ,GAAG,OAAO,GAAG,aAAa,CAAC,GACnE,MAAM,CAOR;AAMD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,eAAe,EAC1B,cAAc,EAAE,cAAc,EAC9B,MAAM,EAAE,aAAa,EACrB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,gBAAgB,CAAC,CA0D3B;AAMD,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiChB,CAAC"}