@oleary-labs/signet-sdk 0.1.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.
Files changed (95) hide show
  1. package/dist/admin.d.ts +38 -0
  2. package/dist/admin.d.ts.map +1 -0
  3. package/dist/admin.js +112 -0
  4. package/dist/admin.js.map +1 -0
  5. package/dist/authkey-session.d.ts +64 -0
  6. package/dist/authkey-session.d.ts.map +1 -0
  7. package/dist/authkey-session.js +164 -0
  8. package/dist/authkey-session.js.map +1 -0
  9. package/dist/bootstrap.d.ts +30 -0
  10. package/dist/bootstrap.d.ts.map +1 -0
  11. package/dist/bootstrap.js +60 -0
  12. package/dist/bootstrap.js.map +1 -0
  13. package/dist/bundler.d.ts +85 -0
  14. package/dist/bundler.d.ts.map +1 -0
  15. package/dist/bundler.js +160 -0
  16. package/dist/bundler.js.map +1 -0
  17. package/dist/delegate.d.ts +57 -0
  18. package/dist/delegate.d.ts.map +1 -0
  19. package/dist/delegate.js +111 -0
  20. package/dist/delegate.js.map +1 -0
  21. package/dist/frostVerify.d.ts +23 -0
  22. package/dist/frostVerify.d.ts.map +1 -0
  23. package/dist/frostVerify.js +69 -0
  24. package/dist/frostVerify.js.map +1 -0
  25. package/dist/index.d.ts +32 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +38 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/jwks.d.ts +28 -0
  30. package/dist/jwks.d.ts.map +1 -0
  31. package/dist/jwks.js +81 -0
  32. package/dist/jwks.js.map +1 -0
  33. package/dist/jwt.d.ts +27 -0
  34. package/dist/jwt.d.ts.map +1 -0
  35. package/dist/jwt.js +50 -0
  36. package/dist/jwt.js.map +1 -0
  37. package/dist/keygen.d.ts +26 -0
  38. package/dist/keygen.d.ts.map +1 -0
  39. package/dist/keygen.js +60 -0
  40. package/dist/keygen.js.map +1 -0
  41. package/dist/oauth.d.ts +34 -0
  42. package/dist/oauth.d.ts.map +1 -0
  43. package/dist/oauth.js +119 -0
  44. package/dist/oauth.js.map +1 -0
  45. package/dist/request.d.ts +42 -0
  46. package/dist/request.d.ts.map +1 -0
  47. package/dist/request.js +115 -0
  48. package/dist/request.js.map +1 -0
  49. package/dist/scopedSign.d.ts +82 -0
  50. package/dist/scopedSign.d.ts.map +1 -0
  51. package/dist/scopedSign.js +130 -0
  52. package/dist/scopedSign.js.map +1 -0
  53. package/dist/server-prover.d.ts +29 -0
  54. package/dist/server-prover.d.ts.map +1 -0
  55. package/dist/server-prover.js +54 -0
  56. package/dist/server-prover.js.map +1 -0
  57. package/dist/session.d.ts +14 -0
  58. package/dist/session.d.ts.map +1 -0
  59. package/dist/session.js +29 -0
  60. package/dist/session.js.map +1 -0
  61. package/dist/types.d.ts +56 -0
  62. package/dist/types.d.ts.map +1 -0
  63. package/dist/types.js +5 -0
  64. package/dist/types.js.map +1 -0
  65. package/dist/userop.d.ts +104 -0
  66. package/dist/userop.d.ts.map +1 -0
  67. package/dist/userop.js +212 -0
  68. package/dist/userop.js.map +1 -0
  69. package/dist/x402.d.ts +127 -0
  70. package/dist/x402.d.ts.map +1 -0
  71. package/dist/x402.js +167 -0
  72. package/dist/x402.js.map +1 -0
  73. package/package.json +64 -0
  74. package/src/admin.ts +178 -0
  75. package/src/authkey-session.ts +241 -0
  76. package/src/bootstrap.ts +106 -0
  77. package/src/bundler.ts +256 -0
  78. package/src/delegate.ts +163 -0
  79. package/src/frostVerify.ts +79 -0
  80. package/src/generate-inputs.ts +158 -0
  81. package/src/index.ts +43 -0
  82. package/src/jwks.ts +92 -0
  83. package/src/jwt.ts +74 -0
  84. package/src/keygen.ts +89 -0
  85. package/src/oauth.ts +157 -0
  86. package/src/partial-sha.ts +99 -0
  87. package/src/proof.ts +99 -0
  88. package/src/request.ts +174 -0
  89. package/src/scopedSign.ts +184 -0
  90. package/src/server-prover.ts +76 -0
  91. package/src/session.ts +33 -0
  92. package/src/types.ts +63 -0
  93. package/src/userop.ts +368 -0
  94. package/src/witness.ts +132 -0
  95. package/src/x402.ts +275 -0
package/dist/jwt.d.ts ADDED
@@ -0,0 +1,27 @@
1
+ /**
2
+ * JWT parsing utilities for ZK proof witness construction.
3
+ *
4
+ * Extracts the components needed by the noir jwt_auth circuit:
5
+ * - Signed data (header.payload as raw bytes)
6
+ * - RSA signature (decoded from base64url)
7
+ * - Key ID (kid) from the header for JWKS lookup
8
+ */
9
+ import type { IdTokenClaims } from "./types";
10
+ /** Parsed JWT components needed for proof generation. */
11
+ export interface ParsedJWT {
12
+ /** Raw signed data: base64(header) + "." + base64(payload) as bytes */
13
+ signedData: Uint8Array;
14
+ /** Base64-decoded RSA signature bytes */
15
+ signatureBytes: Uint8Array;
16
+ /** Key ID from the JWT header — used to find the right JWKS key */
17
+ kid: string;
18
+ /** Decoded payload claims */
19
+ claims: IdTokenClaims;
20
+ /** Offset where base64-encoded payload starts (header length + 1 for the dot) */
21
+ base64DecodeOffset: number;
22
+ }
23
+ /**
24
+ * Parse a JWT into its components for ZK proof generation.
25
+ */
26
+ export declare function parseJWT(jwt: string): ParsedJWT;
27
+ //# sourceMappingURL=jwt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../src/jwt.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,yDAAyD;AACzD,MAAM,WAAW,SAAS;IACxB,uEAAuE;IACvE,UAAU,EAAE,UAAU,CAAC;IACvB,yCAAyC;IACzC,cAAc,EAAE,UAAU,CAAC;IAC3B,mEAAmE;IACnE,GAAG,EAAE,MAAM,CAAC;IACZ,6BAA6B;IAC7B,MAAM,EAAE,aAAa,CAAC;IACtB,iFAAiF;IACjF,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CA+B/C"}
package/dist/jwt.js ADDED
@@ -0,0 +1,50 @@
1
+ /**
2
+ * JWT parsing utilities for ZK proof witness construction.
3
+ *
4
+ * Extracts the components needed by the noir jwt_auth circuit:
5
+ * - Signed data (header.payload as raw bytes)
6
+ * - RSA signature (decoded from base64url)
7
+ * - Key ID (kid) from the header for JWKS lookup
8
+ */
9
+ /**
10
+ * Parse a JWT into its components for ZK proof generation.
11
+ */
12
+ export function parseJWT(jwt) {
13
+ const parts = jwt.split(".");
14
+ if (parts.length !== 3) {
15
+ throw new Error("Invalid JWT: expected 3 parts");
16
+ }
17
+ const [headerB64, payloadB64, signatureB64] = parts;
18
+ // Decode header to get kid
19
+ const header = JSON.parse(base64urlDecode(headerB64));
20
+ if (header.alg !== "RS256") {
21
+ throw new Error(`Unsupported JWT algorithm: ${header.alg}`);
22
+ }
23
+ // Signed data is the raw ASCII bytes of "header.payload"
24
+ const signedDataStr = `${headerB64}.${payloadB64}`;
25
+ const signedData = new TextEncoder().encode(signedDataStr);
26
+ // Decode the RSA signature
27
+ const signatureBytes = base64urlDecodeBytes(signatureB64);
28
+ // Decode claims
29
+ const claims = JSON.parse(base64urlDecode(payloadB64));
30
+ return {
31
+ signedData,
32
+ signatureBytes,
33
+ kid: header.kid,
34
+ claims,
35
+ base64DecodeOffset: headerB64.length + 1,
36
+ };
37
+ }
38
+ function base64urlDecode(s) {
39
+ const padded = s.replace(/-/g, "+").replace(/_/g, "/");
40
+ return atob(padded);
41
+ }
42
+ function base64urlDecodeBytes(s) {
43
+ const decoded = base64urlDecode(s);
44
+ const bytes = new Uint8Array(decoded.length);
45
+ for (let i = 0; i < decoded.length; i++) {
46
+ bytes[i] = decoded.charCodeAt(i);
47
+ }
48
+ return bytes;
49
+ }
50
+ //# sourceMappingURL=jwt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt.js","sourceRoot":"","sources":["../src/jwt.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAkBH;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,GAAW;IAClC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACnD,CAAC;IAED,MAAM,CAAC,SAAS,EAAE,UAAU,EAAE,YAAY,CAAC,GAAG,KAAK,CAAC;IAEpD,2BAA2B;IAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,CAAC;IACtD,IAAI,MAAM,CAAC,GAAG,KAAK,OAAO,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,8BAA8B,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,yDAAyD;IACzD,MAAM,aAAa,GAAG,GAAG,SAAS,IAAI,UAAU,EAAE,CAAC;IACnD,MAAM,UAAU,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IAE3D,2BAA2B;IAC3B,MAAM,cAAc,GAAG,oBAAoB,CAAC,YAAY,CAAC,CAAC;IAE1D,gBAAgB;IAChB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,UAAU,CAAC,CAAkB,CAAC;IAExE,OAAO;QACL,UAAU;QACV,cAAc;QACd,GAAG,EAAE,MAAM,CAAC,GAAG;QACf,MAAM;QACN,kBAAkB,EAAE,SAAS,CAAC,MAAM,GAAG,CAAC;KACzC,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,CAAS;IAChC,MAAM,MAAM,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACvD,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;AACtB,CAAC;AAED,SAAS,oBAAoB,CAAC,CAAS;IACrC,MAAM,OAAO,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,KAAK,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Distributed key generation via bootstrap nodes.
3
+ *
4
+ * After auth, call keygen to create a key shard for the session identity.
5
+ * 409 (key already exists) is treated as success — the key was already created
6
+ * in a previous session.
7
+ */
8
+ import type { SessionKeypair, IdTokenClaims } from "./types";
9
+ export interface KeygenConfig {
10
+ nodeUrls: string[];
11
+ groupId: string;
12
+ /** Proxy endpoint for CORS */
13
+ proxyEndpoint?: string;
14
+ }
15
+ export interface KeygenResult {
16
+ keyId: string;
17
+ ethereumAddress: string;
18
+ groupPublicKey: string;
19
+ alreadyExisted: boolean;
20
+ }
21
+ /**
22
+ * Trigger keygen on a bootstrap node.
23
+ * If the key already exists (409), returns success with alreadyExisted=true.
24
+ */
25
+ export declare function keygen(config: KeygenConfig, keypair: SessionKeypair, claims: IdTokenClaims, keySuffix?: string, identity?: string, curve?: string, scope?: string): Promise<KeygenResult>;
26
+ //# sourceMappingURL=keygen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keygen.d.ts","sourceRoot":"","sources":["../src/keygen.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAG7D,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,8BAA8B;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,OAAO,CAAC;CACzB;AAED;;;GAGG;AACH,wBAAsB,MAAM,CAC1B,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,aAAa,EACrB,SAAS,CAAC,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,MAAM,EACjB,KAAK,CAAC,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,YAAY,CAAC,CAmDvB"}
package/dist/keygen.js ADDED
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Distributed key generation via bootstrap nodes.
3
+ *
4
+ * After auth, call keygen to create a key shard for the session identity.
5
+ * 409 (key already exists) is treated as success — the key was already created
6
+ * in a previous session.
7
+ */
8
+ import { signKeygenRequest } from "./request";
9
+ /**
10
+ * Trigger keygen on a bootstrap node.
11
+ * If the key already exists (409), returns success with alreadyExisted=true.
12
+ */
13
+ export async function keygen(config, keypair, claims, keySuffix, identity, curve, scope) {
14
+ const req = await signKeygenRequest(keypair, claims, config.groupId, keySuffix, identity);
15
+ // Try the first node (keygen only needs to be initiated on one node)
16
+ const nodeUrl = config.nodeUrls[0];
17
+ const url = config.proxyEndpoint
18
+ ? config.proxyEndpoint
19
+ : `${nodeUrl}/v1/keygen`;
20
+ const headers = {
21
+ "Content-Type": "application/json",
22
+ };
23
+ if (config.proxyEndpoint) {
24
+ headers["x-node-url"] = nodeUrl;
25
+ headers["x-node-path"] = "/v1/keygen";
26
+ }
27
+ // Add optional curve and scope to the request body
28
+ const body = { ...req };
29
+ if (curve)
30
+ body.curve = curve;
31
+ if (scope)
32
+ body.scope = scope;
33
+ const res = await fetch(url, {
34
+ method: "POST",
35
+ headers,
36
+ body: JSON.stringify(body),
37
+ });
38
+ if (res.status === 409) {
39
+ // Key already exists — node now returns full key info on 409
40
+ const data = await res.json();
41
+ return {
42
+ keyId: data.key_id ?? `${claims.iss}:${claims.sub}${keySuffix ? `:${keySuffix}` : ""}`,
43
+ ethereumAddress: data.ethereum_address ?? "",
44
+ groupPublicKey: data.public_key ?? "",
45
+ alreadyExisted: true,
46
+ };
47
+ }
48
+ if (!res.ok) {
49
+ const body = await res.text();
50
+ throw new Error(`Keygen failed: ${res.status} — ${body}`);
51
+ }
52
+ const data = await res.json();
53
+ return {
54
+ keyId: data.key_id,
55
+ ethereumAddress: data.ethereum_address,
56
+ groupPublicKey: data.public_key,
57
+ alreadyExisted: false,
58
+ };
59
+ }
60
+ //# sourceMappingURL=keygen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keygen.js","sourceRoot":"","sources":["../src/keygen.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAgB9C;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,MAAoB,EACpB,OAAuB,EACvB,MAAqB,EACrB,SAAkB,EAClB,QAAiB,EACjB,KAAc,EACd,KAAc;IAEd,MAAM,GAAG,GAAG,MAAM,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;IAE1F,qEAAqE;IACrE,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,GAAG,GAAG,MAAM,CAAC,aAAa;QAC9B,CAAC,CAAC,MAAM,CAAC,aAAa;QACtB,CAAC,CAAC,GAAG,OAAO,YAAY,CAAC;IAE3B,MAAM,OAAO,GAA2B;QACtC,cAAc,EAAE,kBAAkB;KACnC,CAAC;IACF,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;QACzB,OAAO,CAAC,YAAY,CAAC,GAAG,OAAO,CAAC;QAChC,OAAO,CAAC,aAAa,CAAC,GAAG,YAAY,CAAC;IACxC,CAAC;IAED,mDAAmD;IACnD,MAAM,IAAI,GAA4B,EAAE,GAAG,GAAG,EAAE,CAAC;IACjD,IAAI,KAAK;QAAE,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IAC9B,IAAI,KAAK;QAAE,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IAE9B,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAC3B,MAAM,EAAE,MAAM;QACd,OAAO;QACP,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;KAC3B,CAAC,CAAC;IAEH,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QACvB,6DAA6D;QAC7D,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,OAAO;YACL,KAAK,EAAE,IAAI,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,GAAG,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE;YACtF,eAAe,EAAE,IAAI,CAAC,gBAAgB,IAAI,EAAE;YAC5C,cAAc,EAAE,IAAI,CAAC,UAAU,IAAI,EAAE;YACrC,cAAc,EAAE,IAAI;SACrB,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,kBAAkB,GAAG,CAAC,MAAM,MAAM,IAAI,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAC9B,OAAO;QACL,KAAK,EAAE,IAAI,CAAC,MAAM;QAClB,eAAe,EAAE,IAAI,CAAC,gBAAgB;QACtC,cAAc,EAAE,IAAI,CAAC,UAAU;QAC/B,cAAc,EAAE,KAAK;KACtB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Google OAuth PKCE flow.
3
+ *
4
+ * Framework-agnostic — uses browser APIs only (sessionStorage, crypto, location).
5
+ * The token exchange itself is delegated to a caller-provided endpoint
6
+ * so the client_secret stays server-side.
7
+ */
8
+ import type { IdTokenClaims } from "./types";
9
+ export interface OAuthConfig {
10
+ clientId: string;
11
+ callbackPath?: string;
12
+ }
13
+ /**
14
+ * Kick off the Google OAuth PKCE flow.
15
+ * Stores PKCE state in sessionStorage and redirects to Google.
16
+ */
17
+ export declare function startGoogleOAuth(config: OAuthConfig, returnTo?: string): Promise<void>;
18
+ /**
19
+ * Handle the OAuth callback: validate state, exchange code for tokens.
20
+ *
21
+ * @param tokenEndpoint — URL of the server-side token exchange endpoint
22
+ * @returns The raw JWT id_token string, or throws on error.
23
+ */
24
+ export declare function handleOAuthCallback(tokenEndpoint: string): Promise<string>;
25
+ /**
26
+ * Decode a JWT payload without verification.
27
+ * Signature verification happens via ZK proof.
28
+ */
29
+ export declare function decodeIdToken(jwt: string): IdTokenClaims;
30
+ /**
31
+ * Get the return-to path stored before the OAuth redirect.
32
+ */
33
+ export declare function getOAuthReturnTo(): string;
34
+ //# sourceMappingURL=oauth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAqB7C,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,WAAW,EACnB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAgCf;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACvC,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,MAAM,CAAC,CA+CjB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAWxD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAIzC"}
package/dist/oauth.js ADDED
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Google OAuth PKCE flow.
3
+ *
4
+ * Framework-agnostic — uses browser APIs only (sessionStorage, crypto, location).
5
+ * The token exchange itself is delegated to a caller-provided endpoint
6
+ * so the client_secret stays server-side.
7
+ */
8
+ function base64urlEncode(buf) {
9
+ return btoa(String.fromCharCode(...new Uint8Array(buf)))
10
+ .replace(/\+/g, "-")
11
+ .replace(/\//g, "_")
12
+ .replace(/=/g, "");
13
+ }
14
+ function generateVerifier() {
15
+ const buf = new Uint8Array(32);
16
+ crypto.getRandomValues(buf);
17
+ return base64urlEncode(buf);
18
+ }
19
+ async function generateChallenge(verifier) {
20
+ const data = new TextEncoder().encode(verifier);
21
+ const digest = await crypto.subtle.digest("SHA-256", data);
22
+ return base64urlEncode(digest);
23
+ }
24
+ /**
25
+ * Kick off the Google OAuth PKCE flow.
26
+ * Stores PKCE state in sessionStorage and redirects to Google.
27
+ */
28
+ export async function startGoogleOAuth(config, returnTo) {
29
+ if (!config.clientId) {
30
+ throw new Error("Google Client ID not configured");
31
+ }
32
+ const verifier = generateVerifier();
33
+ const challenge = await generateChallenge(verifier);
34
+ const state = base64urlEncode(crypto.getRandomValues(new Uint8Array(16)));
35
+ sessionStorage.setItem("signet_oauth_verifier", verifier);
36
+ sessionStorage.setItem("signet_oauth_state", state);
37
+ sessionStorage.setItem("signet_oauth_return_to", returnTo ?? window.location.pathname);
38
+ const callbackPath = config.callbackPath ?? "/auth/callback";
39
+ const redirectUri = `${window.location.origin}${callbackPath}`;
40
+ const params = new URLSearchParams({
41
+ client_id: config.clientId,
42
+ redirect_uri: redirectUri,
43
+ response_type: "code",
44
+ scope: "openid profile email",
45
+ code_challenge: challenge,
46
+ code_challenge_method: "S256",
47
+ state,
48
+ });
49
+ window.location.href = `https://accounts.google.com/o/oauth2/v2/auth?${params}`;
50
+ }
51
+ /**
52
+ * Handle the OAuth callback: validate state, exchange code for tokens.
53
+ *
54
+ * @param tokenEndpoint — URL of the server-side token exchange endpoint
55
+ * @returns The raw JWT id_token string, or throws on error.
56
+ */
57
+ export async function handleOAuthCallback(tokenEndpoint) {
58
+ const params = new URLSearchParams(window.location.search);
59
+ const code = params.get("code");
60
+ const state = params.get("state");
61
+ const error = params.get("error");
62
+ if (error) {
63
+ throw new Error(`Google OAuth error: ${error} — ${params.get("error_description") ?? ""}`);
64
+ }
65
+ if (!code) {
66
+ throw new Error("No authorization code received");
67
+ }
68
+ const savedState = sessionStorage.getItem("signet_oauth_state");
69
+ if (state !== savedState) {
70
+ throw new Error("State mismatch — possible CSRF attack");
71
+ }
72
+ const verifier = sessionStorage.getItem("signet_oauth_verifier");
73
+ const callbackUri = window.location.origin + window.location.pathname;
74
+ // Clean up PKCE state
75
+ sessionStorage.removeItem("signet_oauth_state");
76
+ sessionStorage.removeItem("signet_oauth_verifier");
77
+ const res = await fetch(tokenEndpoint, {
78
+ method: "POST",
79
+ headers: { "Content-Type": "application/json" },
80
+ body: JSON.stringify({
81
+ code,
82
+ code_verifier: verifier,
83
+ redirect_uri: callbackUri,
84
+ }),
85
+ });
86
+ const data = await res.json();
87
+ if (data.error) {
88
+ throw new Error(`Token exchange failed: ${data.error} — ${data.error_description ?? ""}`);
89
+ }
90
+ return data.id_token;
91
+ }
92
+ /**
93
+ * Decode a JWT payload without verification.
94
+ * Signature verification happens via ZK proof.
95
+ */
96
+ export function decodeIdToken(jwt) {
97
+ const payload = jwt.split(".")[1];
98
+ const decoded = atob(payload.replace(/-/g, "+").replace(/_/g, "/"));
99
+ const claims = JSON.parse(decoded);
100
+ // Preserve original aud/azp presence for ZK proof public input matching.
101
+ // If the JWT doesn't have aud or azp, keep them empty so the prover
102
+ // and verifier agree on the same (empty) public inputs.
103
+ if (claims.aud === undefined)
104
+ claims.aud = "";
105
+ if (claims.azp === undefined)
106
+ claims.azp = "";
107
+ if (claims.email === undefined)
108
+ claims.email = "";
109
+ return claims;
110
+ }
111
+ /**
112
+ * Get the return-to path stored before the OAuth redirect.
113
+ */
114
+ export function getOAuthReturnTo() {
115
+ const returnTo = sessionStorage.getItem("signet_oauth_return_to") ?? "/";
116
+ sessionStorage.removeItem("signet_oauth_return_to");
117
+ return returnTo;
118
+ }
119
+ //# sourceMappingURL=oauth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.js","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Session-authenticated request signing.
3
+ *
4
+ * After auth, every keygen/sign request must include a signature
5
+ * over the canonical request hash, produced with the session private key.
6
+ *
7
+ * Canonical hash: SHA256(groupID ":" keyID ":" nonce ":" timestamp_8BE [":" messageHash])
8
+ * Signature: 64-byte [R || S] secp256k1 ECDSA (no recovery byte)
9
+ */
10
+ import type { SessionKeypair, IdTokenClaims } from "./types";
11
+ /** Signed request ready to POST to a node. */
12
+ export interface SignedRequest {
13
+ group_id: string;
14
+ key_suffix?: string;
15
+ session_pub: string;
16
+ request_sig: string;
17
+ nonce: string;
18
+ timestamp: number;
19
+ }
20
+ /** Signed request with message_hash for /v1/sign. */
21
+ export interface SignedSignRequest extends SignedRequest {
22
+ message_hash: string;
23
+ }
24
+ /**
25
+ * Derive the key ID that the node will resolve for this session.
26
+ *
27
+ * For OAuth sessions: iss:sub or iss:sub:suffix
28
+ * e.g. https://accounts.google.com:114810956681671373980
29
+ */
30
+ export declare function deriveKeyId(claims: IdTokenClaims, keySuffix?: string, identity?: string): string;
31
+ /**
32
+ * Build and sign a keygen request.
33
+ *
34
+ * @param identity - For auth key cert sessions, pass the identity string.
35
+ * The key ID becomes `identity[:suffix]` instead of `iss:sub[:suffix]`.
36
+ */
37
+ export declare function signKeygenRequest(keypair: SessionKeypair, claims: IdTokenClaims, groupId: string, keySuffix?: string, identity?: string): Promise<SignedRequest>;
38
+ /**
39
+ * Build and sign a threshold signing request.
40
+ */
41
+ export declare function signSignRequest(keypair: SessionKeypair, claims: IdTokenClaims, groupId: string, messageHash: Uint8Array, keySuffix?: string, identity?: string): Promise<SignedSignRequest>;
42
+ //# sourceMappingURL=request.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../src/request.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAG7D,8CAA8C;AAC9C,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qDAAqD;AACrD,MAAM,WAAW,iBAAkB,SAAQ,aAAa;IACtD,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,aAAa,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAGhG;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,MAAM,EACf,SAAS,CAAC,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,aAAa,CAAC,CAiBxB;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,UAAU,EACvB,SAAS,CAAC,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,iBAAiB,CAAC,CAwB5B"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Session-authenticated request signing.
3
+ *
4
+ * After auth, every keygen/sign request must include a signature
5
+ * over the canonical request hash, produced with the session private key.
6
+ *
7
+ * Canonical hash: SHA256(groupID ":" keyID ":" nonce ":" timestamp_8BE [":" messageHash])
8
+ * Signature: 64-byte [R || S] secp256k1 ECDSA (no recovery byte)
9
+ */
10
+ import { bytesToHex } from "./session";
11
+ /**
12
+ * Derive the key ID that the node will resolve for this session.
13
+ *
14
+ * For OAuth sessions: iss:sub or iss:sub:suffix
15
+ * e.g. https://accounts.google.com:114810956681671373980
16
+ */
17
+ export function deriveKeyId(claims, keySuffix, identity) {
18
+ const base = identity ?? `${claims.iss}:${claims.sub}`;
19
+ return keySuffix ? `${base}:${keySuffix}` : base;
20
+ }
21
+ /**
22
+ * Build and sign a keygen request.
23
+ *
24
+ * @param identity - For auth key cert sessions, pass the identity string.
25
+ * The key ID becomes `identity[:suffix]` instead of `iss:sub[:suffix]`.
26
+ */
27
+ export async function signKeygenRequest(keypair, claims, groupId, keySuffix, identity) {
28
+ const normalizedGroupId = groupId.toLowerCase();
29
+ const keyId = deriveKeyId(claims, keySuffix, identity);
30
+ const nonce = generateNonce();
31
+ const timestamp = Math.floor(Date.now() / 1000);
32
+ const hash = await canonicalRequestHash(normalizedGroupId, keyId, nonce, timestamp);
33
+ const sig = await signHash(keypair.privateKey, hash);
34
+ return {
35
+ group_id: normalizedGroupId,
36
+ key_suffix: keySuffix,
37
+ session_pub: keypair.publicKeyHex,
38
+ request_sig: bytesToHex(sig),
39
+ nonce,
40
+ timestamp,
41
+ };
42
+ }
43
+ /**
44
+ * Build and sign a threshold signing request.
45
+ */
46
+ export async function signSignRequest(keypair, claims, groupId, messageHash, keySuffix, identity) {
47
+ const normalizedGroupId = groupId.toLowerCase();
48
+ const keyId = deriveKeyId(claims, keySuffix, identity);
49
+ const nonce = generateNonce();
50
+ const timestamp = Math.floor(Date.now() / 1000);
51
+ const hash = await canonicalRequestHash(normalizedGroupId, keyId, nonce, timestamp, messageHash);
52
+ const sig = await signHash(keypair.privateKey, hash);
53
+ return {
54
+ group_id: normalizedGroupId,
55
+ key_suffix: keySuffix,
56
+ session_pub: keypair.publicKeyHex,
57
+ request_sig: bytesToHex(sig),
58
+ nonce,
59
+ timestamp,
60
+ message_hash: bytesToHex(messageHash),
61
+ };
62
+ }
63
+ /**
64
+ * Compute the canonical request hash matching the Go node's format.
65
+ *
66
+ * SHA256(groupID ":" keyID ":" nonce ":" timestamp_8BE [":" messageHash])
67
+ */
68
+ async function canonicalRequestHash(groupId, keyId, nonce, timestamp, messageHash) {
69
+ const parts = [];
70
+ const enc = new TextEncoder();
71
+ parts.push(enc.encode(groupId));
72
+ parts.push(enc.encode(":"));
73
+ parts.push(enc.encode(keyId));
74
+ parts.push(enc.encode(":"));
75
+ parts.push(enc.encode(nonce));
76
+ parts.push(enc.encode(":"));
77
+ // timestamp as 8-byte big-endian
78
+ const tsBuf = new ArrayBuffer(8);
79
+ const view = new DataView(tsBuf);
80
+ view.setBigUint64(0, BigInt(timestamp));
81
+ parts.push(new Uint8Array(tsBuf));
82
+ if (messageHash && messageHash.length > 0) {
83
+ parts.push(enc.encode(":"));
84
+ parts.push(messageHash);
85
+ }
86
+ // Concatenate
87
+ const total = parts.reduce((n, p) => n + p.length, 0);
88
+ const buf = new Uint8Array(total);
89
+ let offset = 0;
90
+ for (const p of parts) {
91
+ buf.set(p, offset);
92
+ offset += p.length;
93
+ }
94
+ const digest = await crypto.subtle.digest("SHA-256", buf);
95
+ return new Uint8Array(digest);
96
+ }
97
+ /**
98
+ * Sign a 32-byte hash with the session private key.
99
+ * Returns 64-byte [R || S] signature (no recovery byte).
100
+ *
101
+ * Uses signAsync which works without configuring hashes.sha256.
102
+ * lowS: true to match go-ethereum's crypto.VerifySignature.
103
+ */
104
+ async function signHash(privateKey, hash) {
105
+ const { signAsync } = await import("@noble/secp256k1");
106
+ // prehash: false — our input is already SHA-256'd, don't hash again
107
+ const sig = await signAsync(hash, privateKey, { lowS: true, prehash: false });
108
+ return new Uint8Array(sig);
109
+ }
110
+ function generateNonce() {
111
+ const bytes = new Uint8Array(16);
112
+ crypto.getRandomValues(bytes);
113
+ return bytesToHex(bytes);
114
+ }
115
+ //# sourceMappingURL=request.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request.js","sourceRoot":"","sources":["../src/request.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Structured EIP-712 signing for scoped keys.
3
+ *
4
+ * Scoped keys reject raw hash signing — the caller must provide a
5
+ * structured payload that the node verifies against the key's scope
6
+ * before computing the hash and signing.
7
+ */
8
+ import type { SessionKeypair, IdTokenClaims } from "./types";
9
+ export interface EIP712Domain {
10
+ name?: string;
11
+ version?: string;
12
+ chainId: number;
13
+ verifyingContract: string;
14
+ }
15
+ export interface EIP712TypedData {
16
+ domain: EIP712Domain;
17
+ types: Record<string, Array<{
18
+ name: string;
19
+ type: string;
20
+ }>>;
21
+ primaryType: string;
22
+ message: Record<string, unknown>;
23
+ }
24
+ export interface ScopedSignResult {
25
+ signature: string;
26
+ ecdsaSignature: string;
27
+ curve: string;
28
+ }
29
+ /**
30
+ * Build an EIP-712 domain scope (scheme 0x03).
31
+ *
32
+ * Format: 0x03 | chainId (8 bytes, uint64 BE) | verifyingContract (20 bytes)
33
+ * Total: 29 bytes.
34
+ */
35
+ export declare function buildEIP712Scope(chainId: number, verifyingContract: string): string;
36
+ /**
37
+ * Sign a structured EIP-712 payload with a scoped key.
38
+ *
39
+ * The node extracts the domain from the typed data, verifies it matches
40
+ * the key's scope, computes hashTypedData, and threshold-signs.
41
+ *
42
+ * @param nodeUrl - Target group node URL
43
+ * @param proxyEndpoint - CORS proxy URL
44
+ * @param groupId - Group contract address
45
+ * @param keyId - The scoped sub-key to sign with
46
+ * @param curve - Key curve (e.g. "ecdsa_secp256k1")
47
+ * @param typedData - Full EIP-712 typed data structure
48
+ * @param sessionKeypair - Active session keypair
49
+ * @param claims - OAuth/identity claims for session auth
50
+ * @param identity - For auth key cert sessions
51
+ */
52
+ export declare function signTypedData(nodeUrl: string, proxyEndpoint: string, groupId: string, keyId: string, curve: string, typedData: EIP712TypedData, sessionKeypair: SessionKeypair, claims: IdTokenClaims, identity?: string): Promise<ScopedSignResult>;
53
+ export declare const CHAIN_PRESETS: readonly [{
54
+ readonly label: "USDC on Base";
55
+ readonly chainId: 8453;
56
+ readonly contractName: "USDC";
57
+ readonly verifyingContract: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
58
+ readonly eip712Name: "USD Coin";
59
+ readonly eip712Version: "2";
60
+ }, {
61
+ readonly label: "USDC on Base Sepolia";
62
+ readonly chainId: 84532;
63
+ readonly contractName: "USDC";
64
+ readonly verifyingContract: "0x036CbD53842c5426634e7929541eC2318f3dCF7e";
65
+ readonly eip712Name: "USD Coin";
66
+ readonly eip712Version: "2";
67
+ }, {
68
+ readonly label: "USDC on Ethereum";
69
+ readonly chainId: 1;
70
+ readonly contractName: "USDC";
71
+ readonly verifyingContract: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";
72
+ readonly eip712Name: "USD Coin";
73
+ readonly eip712Version: "2";
74
+ }, {
75
+ readonly label: "USDC on Sepolia";
76
+ readonly chainId: 11155111;
77
+ readonly contractName: "USDC";
78
+ readonly verifyingContract: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238";
79
+ readonly eip712Name: "USD Coin";
80
+ readonly eip712Version: "2";
81
+ }];
82
+ //# sourceMappingURL=scopedSign.d.ts.map
@@ -0,0 +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"}