@soropass/core 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 (83) hide show
  1. package/dist/checkAuth-C2AcXqFe.d.cts +110 -0
  2. package/dist/checkAuth-C2AcXqFe.d.ts +110 -0
  3. package/dist/chunk-AHFGTIBY.js +36 -0
  4. package/dist/chunk-AHFGTIBY.js.map +1 -0
  5. package/dist/chunk-AMYFJQAC.js +29 -0
  6. package/dist/chunk-AMYFJQAC.js.map +1 -0
  7. package/dist/chunk-BIRF5I6I.js +265 -0
  8. package/dist/chunk-BIRF5I6I.js.map +1 -0
  9. package/dist/chunk-JNJ2FY45.js +209 -0
  10. package/dist/chunk-JNJ2FY45.js.map +1 -0
  11. package/dist/chunk-LB4HOTLV.js +135 -0
  12. package/dist/chunk-LB4HOTLV.js.map +1 -0
  13. package/dist/chunk-LM2AZXKZ.js +108 -0
  14. package/dist/chunk-LM2AZXKZ.js.map +1 -0
  15. package/dist/chunk-LUDXP56M.js +3 -0
  16. package/dist/chunk-LUDXP56M.js.map +1 -0
  17. package/dist/chunk-MMB4ZIW3.js +48 -0
  18. package/dist/chunk-MMB4ZIW3.js.map +1 -0
  19. package/dist/chunk-MOLZIRIH.js +22 -0
  20. package/dist/chunk-MOLZIRIH.js.map +1 -0
  21. package/dist/chunk-OGSUGATA.js +3 -0
  22. package/dist/chunk-OGSUGATA.js.map +1 -0
  23. package/dist/chunk-TPBBZNPP.js +30 -0
  24. package/dist/chunk-TPBBZNPP.js.map +1 -0
  25. package/dist/chunk-UQKNPO44.js +32 -0
  26. package/dist/chunk-UQKNPO44.js.map +1 -0
  27. package/dist/chunk-UV5HORMF.js +175 -0
  28. package/dist/chunk-UV5HORMF.js.map +1 -0
  29. package/dist/chunk-W75OQKHR.js +133 -0
  30. package/dist/chunk-W75OQKHR.js.map +1 -0
  31. package/dist/connect.cjs +166 -0
  32. package/dist/connect.cjs.map +1 -0
  33. package/dist/connect.d.cts +24 -0
  34. package/dist/connect.d.ts +24 -0
  35. package/dist/connect.js +6 -0
  36. package/dist/connect.js.map +1 -0
  37. package/dist/create.cjs +483 -0
  38. package/dist/create.cjs.map +1 -0
  39. package/dist/create.d.cts +106 -0
  40. package/dist/create.d.ts +106 -0
  41. package/dist/create.js +8 -0
  42. package/dist/create.js.map +1 -0
  43. package/dist/index.cjs +1542 -0
  44. package/dist/index.cjs.map +1 -0
  45. package/dist/index.d.cts +197 -0
  46. package/dist/index.d.ts +197 -0
  47. package/dist/index.js +354 -0
  48. package/dist/index.js.map +1 -0
  49. package/dist/recover-0wbOXDjR.d.cts +23 -0
  50. package/dist/recover-COnsxhYk.d.ts +23 -0
  51. package/dist/recover.cjs +802 -0
  52. package/dist/recover.cjs.map +1 -0
  53. package/dist/recover.d.cts +49 -0
  54. package/dist/recover.d.ts +49 -0
  55. package/dist/recover.js +10 -0
  56. package/dist/recover.js.map +1 -0
  57. package/dist/sign-Cfg0NM0T.d.cts +73 -0
  58. package/dist/sign-Cfg0NM0T.d.ts +73 -0
  59. package/dist/sign.cjs +883 -0
  60. package/dist/sign.cjs.map +1 -0
  61. package/dist/sign.d.cts +143 -0
  62. package/dist/sign.d.ts +143 -0
  63. package/dist/sign.js +8 -0
  64. package/dist/sign.js.map +1 -0
  65. package/dist/submit-BDKADQq0.d.cts +112 -0
  66. package/dist/submit-BO0Nh49I.d.ts +112 -0
  67. package/dist/testing.cjs +955 -0
  68. package/dist/testing.cjs.map +1 -0
  69. package/dist/testing.d.cts +86 -0
  70. package/dist/testing.d.ts +86 -0
  71. package/dist/testing.js +235 -0
  72. package/dist/testing.js.map +1 -0
  73. package/dist/types--WNl-Sda.d.cts +125 -0
  74. package/dist/types--WNl-Sda.d.ts +125 -0
  75. package/dist/types-dMRWEEo0.d.cts +73 -0
  76. package/dist/types-lW2h8Uxn.d.ts +73 -0
  77. package/dist/types.cjs +44 -0
  78. package/dist/types.cjs.map +1 -0
  79. package/dist/types.d.cts +5 -0
  80. package/dist/types.d.ts +5 -0
  81. package/dist/types.js +5 -0
  82. package/dist/types.js.map +1 -0
  83. package/package.json +117 -0
@@ -0,0 +1,209 @@
1
+ import { utf8ToBytes, bytesToBase64Url, base64UrlToBytes, bytesToUtf8 } from './chunk-LB4HOTLV.js';
2
+ import { KitError } from './chunk-AMYFJQAC.js';
3
+ import { sha256 } from '@noble/hashes/sha256';
4
+ export { sha256 } from '@noble/hashes/sha256';
5
+
6
+ // src/internal/cbor.ts
7
+ function byteAt(bytes, index) {
8
+ const value = bytes[index];
9
+ if (value === void 0) throw new Error(`CBOR: unexpected end of input at byte ${index}`);
10
+ return value;
11
+ }
12
+ var MAX_DEPTH = 16;
13
+ function decodeCbor(bytes, offset = 0, depth = 0) {
14
+ if (depth > MAX_DEPTH) throw new Error("CBOR: maximum nesting depth exceeded");
15
+ const first = byteAt(bytes, offset);
16
+ const major = first >> 5;
17
+ const info = first & 31;
18
+ let pos = offset + 1;
19
+ let argument;
20
+ if (info < 24) {
21
+ argument = info;
22
+ } else if (info === 24) {
23
+ argument = byteAt(bytes, pos);
24
+ pos += 1;
25
+ } else if (info === 25) {
26
+ argument = byteAt(bytes, pos) << 8 | byteAt(bytes, pos + 1);
27
+ pos += 2;
28
+ } else if (info === 26) {
29
+ argument = byteAt(bytes, pos) * 16777216 + (byteAt(bytes, pos + 1) << 16) + (byteAt(bytes, pos + 2) << 8) + byteAt(bytes, pos + 3);
30
+ pos += 4;
31
+ } else {
32
+ throw new Error(`CBOR: unsupported length encoding (additional info ${info})`);
33
+ }
34
+ switch (major) {
35
+ case 0:
36
+ return { value: argument, length: pos - offset };
37
+ case 1:
38
+ return { value: -1 - argument, length: pos - offset };
39
+ case 2: {
40
+ const end = pos + argument;
41
+ if (end > bytes.length) throw new Error("CBOR: byte string exceeds input");
42
+ return { value: bytes.slice(pos, end), length: end - offset };
43
+ }
44
+ case 3: {
45
+ const end = pos + argument;
46
+ if (end > bytes.length) throw new Error("CBOR: text string exceeds input");
47
+ return { value: new TextDecoder().decode(bytes.slice(pos, end)), length: end - offset };
48
+ }
49
+ case 4: {
50
+ const items = [];
51
+ let cursor = pos;
52
+ for (let i = 0; i < argument; i += 1) {
53
+ const item = decodeCbor(bytes, cursor, depth + 1);
54
+ items.push(item.value);
55
+ cursor += item.length;
56
+ }
57
+ return { value: items, length: cursor - offset };
58
+ }
59
+ case 5: {
60
+ const map = /* @__PURE__ */ new Map();
61
+ let cursor = pos;
62
+ for (let i = 0; i < argument; i += 1) {
63
+ const key = decodeCbor(bytes, cursor, depth + 1);
64
+ cursor += key.length;
65
+ const val = decodeCbor(bytes, cursor, depth + 1);
66
+ cursor += val.length;
67
+ if (typeof key.value !== "number" && typeof key.value !== "string") {
68
+ throw new Error("CBOR: unsupported map key type");
69
+ }
70
+ if (map.has(key.value)) {
71
+ throw new Error("CBOR: duplicate map key (non-canonical)");
72
+ }
73
+ map.set(key.value, val.value);
74
+ }
75
+ return { value: map, length: cursor - offset };
76
+ }
77
+ default:
78
+ throw new Error(`CBOR: unsupported major type ${major}`);
79
+ }
80
+ }
81
+ function decodeCborFirst(bytes) {
82
+ return decodeCbor(bytes, 0).value;
83
+ }
84
+
85
+ // src/internal/bytes.ts
86
+ function concatBytes(...arrays) {
87
+ const total = arrays.reduce((n, a) => n + a.length, 0);
88
+ const out = new Uint8Array(total);
89
+ let offset = 0;
90
+ for (const a of arrays) {
91
+ out.set(a, offset);
92
+ offset += a.length;
93
+ }
94
+ return out;
95
+ }
96
+ function equalBytes(a, b) {
97
+ if (a.length !== b.length) return false;
98
+ let diff = 0;
99
+ for (let i = 0; i < a.length; i += 1) diff |= (a[i] ?? 0) ^ (b[i] ?? 0);
100
+ return diff === 0;
101
+ }
102
+
103
+ // src/webauthn/authData.ts
104
+ var MIN_LENGTH = 37;
105
+ function parseAuthenticatorData(authData) {
106
+ if (authData.length < MIN_LENGTH) {
107
+ throw new KitError(
108
+ "UNSUPPORTED_AUTHENTICATOR",
109
+ `authenticatorData is ${authData.length} bytes, expected at least ${MIN_LENGTH}`
110
+ );
111
+ }
112
+ const view = new DataView(authData.buffer, authData.byteOffset, authData.byteLength);
113
+ const rpIdHash = authData.slice(0, 32);
114
+ const bits = authData[32] ?? 0;
115
+ const flags = {
116
+ up: (bits & 1) !== 0,
117
+ uv: (bits & 4) !== 0,
118
+ be: (bits & 8) !== 0,
119
+ bs: (bits & 16) !== 0,
120
+ at: (bits & 64) !== 0,
121
+ ed: (bits & 128) !== 0,
122
+ bits
123
+ };
124
+ const signCount = view.getUint32(33, false);
125
+ const result = { rpIdHash, flags, signCount };
126
+ if (flags.at) {
127
+ if (authData.length < 55) {
128
+ throw new KitError(
129
+ "UNSUPPORTED_AUTHENTICATOR",
130
+ "authenticatorData truncated in attested data"
131
+ );
132
+ }
133
+ result.aaguid = authData.slice(37, 53);
134
+ const credIdLength = view.getUint16(53, false);
135
+ const credIdEnd = 55 + credIdLength;
136
+ if (authData.length < credIdEnd) {
137
+ throw new KitError(
138
+ "UNSUPPORTED_AUTHENTICATOR",
139
+ "authenticatorData truncated in credentialId"
140
+ );
141
+ }
142
+ result.credentialId = authData.slice(55, credIdEnd);
143
+ const rest = authData.slice(credIdEnd);
144
+ const { length } = decodeCbor(rest, 0);
145
+ result.credentialPublicKey = rest.slice(0, length);
146
+ }
147
+ return result;
148
+ }
149
+ function verifyRpIdHash(authData, rpId) {
150
+ const actual = parseAuthenticatorData(authData).rpIdHash;
151
+ const expected = sha256(utf8ToBytes(rpId));
152
+ if (!equalBytes(actual, expected)) {
153
+ throw new KitError(
154
+ "RP_ID_MISMATCH",
155
+ `authenticatorData rpIdHash does not match SHA-256("${rpId}")`
156
+ );
157
+ }
158
+ }
159
+
160
+ // src/webauthn/clientData.ts
161
+ function encodeChallenge(challenge) {
162
+ return bytesToBase64Url(challenge);
163
+ }
164
+ function decodeChallenge(challenge) {
165
+ return base64UrlToBytes(challenge);
166
+ }
167
+ function parseClientDataJSON(clientDataJSON) {
168
+ let raw;
169
+ try {
170
+ raw = JSON.parse(bytesToUtf8(clientDataJSON));
171
+ } catch (cause) {
172
+ throw new KitError("UNSUPPORTED_AUTHENTICATOR", "clientDataJSON is not valid JSON", { cause });
173
+ }
174
+ if (typeof raw !== "object" || raw === null) {
175
+ throw new KitError("UNSUPPORTED_AUTHENTICATOR", "clientDataJSON is not a JSON object");
176
+ }
177
+ const obj = raw;
178
+ const { type, challenge, origin, crossOrigin } = obj;
179
+ if (typeof type !== "string" || typeof challenge !== "string" || typeof origin !== "string") {
180
+ throw new KitError("UNSUPPORTED_AUTHENTICATOR", "clientDataJSON is missing required fields");
181
+ }
182
+ return {
183
+ type,
184
+ challenge,
185
+ origin,
186
+ crossOrigin: typeof crossOrigin === "boolean" ? crossOrigin : void 0
187
+ };
188
+ }
189
+ function verifyClientDataJSON(clientDataJSON, expected) {
190
+ const data = parseClientDataJSON(clientDataJSON);
191
+ if (data.type !== "webauthn.get") {
192
+ throw new KitError(
193
+ "UNSUPPORTED_AUTHENTICATOR",
194
+ `clientDataJSON.type "${data.type}" is not "webauthn.get"`
195
+ );
196
+ }
197
+ const allowed = Array.isArray(expected.origin) ? expected.origin : [expected.origin];
198
+ if (!allowed.includes(data.origin)) {
199
+ throw new KitError("ORIGIN_MISMATCH", `origin "${data.origin}" not in [${allowed.join(", ")}]`);
200
+ }
201
+ if (data.challenge !== expected.challenge) {
202
+ throw new KitError("CHALLENGE_MISMATCH", "clientDataJSON challenge does not match expected");
203
+ }
204
+ return data;
205
+ }
206
+
207
+ export { concatBytes, decodeCborFirst, decodeChallenge, encodeChallenge, parseAuthenticatorData, parseClientDataJSON, verifyClientDataJSON, verifyRpIdHash };
208
+ //# sourceMappingURL=chunk-JNJ2FY45.js.map
209
+ //# sourceMappingURL=chunk-JNJ2FY45.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/internal/cbor.ts","../src/internal/bytes.ts","../src/webauthn/authData.ts","../src/webauthn/clientData.ts"],"names":[],"mappings":"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","file":"chunk-JNJ2FY45.js","sourcesContent":["/**\n * A minimal CBOR (RFC 8949) decoder — only the major types WebAuthn needs:\n * unsigned ints, negative ints, byte strings, text strings, arrays and maps,\n * with 1/2/4-byte length prefixes. Indefinite lengths, tags, floats and\n * 8-byte lengths are intentionally unsupported (COSE keys and attestation\n * objects never use them) and throw. This keeps the SDK dependency-free while\n * staying robust — it is fully fixture-tested. It replaces passkey-kit's\n * hardcoded byte-offset scanning, which had no bounds checks.\n */\nexport type CborValue = number | bigint | Uint8Array | string | CborValue[] | CborMap;\nexport type CborMap = Map<number | string, CborValue>;\n\ninterface Decoded {\n value: CborValue;\n /** Total bytes consumed starting at the requested offset. */\n length: number;\n}\n\nfunction byteAt(bytes: Uint8Array, index: number): number {\n const value = bytes[index];\n if (value === undefined) throw new Error(`CBOR: unexpected end of input at byte ${index}`);\n return value;\n}\n\n/** Decode the first CBOR item at `offset`, returning its value and byte length. */\nconst MAX_DEPTH = 16; // COSE keys / attestation objects nest at most ~3 levels.\n\nexport function decodeCbor(bytes: Uint8Array, offset = 0, depth = 0): Decoded {\n if (depth > MAX_DEPTH) throw new Error('CBOR: maximum nesting depth exceeded');\n const first = byteAt(bytes, offset);\n const major = first >> 5;\n const info = first & 0x1f;\n let pos = offset + 1;\n\n let argument: number;\n if (info < 24) {\n argument = info;\n } else if (info === 24) {\n argument = byteAt(bytes, pos);\n pos += 1;\n } else if (info === 25) {\n argument = (byteAt(bytes, pos) << 8) | byteAt(bytes, pos + 1);\n pos += 2;\n } else if (info === 26) {\n argument =\n byteAt(bytes, pos) * 0x1000000 +\n (byteAt(bytes, pos + 1) << 16) +\n (byteAt(bytes, pos + 2) << 8) +\n byteAt(bytes, pos + 3);\n pos += 4;\n } else {\n throw new Error(`CBOR: unsupported length encoding (additional info ${info})`);\n }\n\n switch (major) {\n case 0: // unsigned integer\n return { value: argument, length: pos - offset };\n case 1: // negative integer\n return { value: -1 - argument, length: pos - offset };\n case 2: {\n // byte string\n const end = pos + argument;\n if (end > bytes.length) throw new Error('CBOR: byte string exceeds input');\n return { value: bytes.slice(pos, end), length: end - offset };\n }\n case 3: {\n // text string (UTF-8)\n const end = pos + argument;\n if (end > bytes.length) throw new Error('CBOR: text string exceeds input');\n return { value: new TextDecoder().decode(bytes.slice(pos, end)), length: end - offset };\n }\n case 4: {\n // array\n const items: CborValue[] = [];\n let cursor = pos;\n for (let i = 0; i < argument; i += 1) {\n const item = decodeCbor(bytes, cursor, depth + 1);\n items.push(item.value);\n cursor += item.length;\n }\n return { value: items, length: cursor - offset };\n }\n case 5: {\n // map\n const map: CborMap = new Map();\n let cursor = pos;\n for (let i = 0; i < argument; i += 1) {\n const key = decodeCbor(bytes, cursor, depth + 1);\n cursor += key.length;\n const val = decodeCbor(bytes, cursor, depth + 1);\n cursor += val.length;\n if (typeof key.value !== 'number' && typeof key.value !== 'string') {\n throw new Error('CBOR: unsupported map key type');\n }\n if (map.has(key.value)) {\n throw new Error('CBOR: duplicate map key (non-canonical)');\n }\n map.set(key.value, val.value);\n }\n return { value: map, length: cursor - offset };\n }\n default:\n throw new Error(`CBOR: unsupported major type ${major}`);\n }\n}\n\nexport function decodeCborFirst(bytes: Uint8Array): CborValue {\n return decodeCbor(bytes, 0).value;\n}\n","/** Concatenate byte arrays into one. */\nexport function concatBytes(...arrays: Uint8Array[]): Uint8Array {\n const total = arrays.reduce((n, a) => n + a.length, 0);\n const out = new Uint8Array(total);\n let offset = 0;\n for (const a of arrays) {\n out.set(a, offset);\n offset += a.length;\n }\n return out;\n}\n\n/** Length-safe, constant-time-ish byte equality. */\nexport function equalBytes(a: Uint8Array, b: Uint8Array): boolean {\n if (a.length !== b.length) return false;\n let diff = 0;\n for (let i = 0; i < a.length; i += 1) diff |= (a[i] ?? 0) ^ (b[i] ?? 0);\n return diff === 0;\n}\n\nexport function bytesToHex(bytes: Uint8Array): string {\n let hex = '';\n for (const byte of bytes) hex += byte.toString(16).padStart(2, '0');\n return hex;\n}\n","import { KitError } from '../errors';\nimport { decodeCbor } from '../internal/cbor';\nimport { sha256 } from '../internal/sha256';\nimport { equalBytes } from '../internal/bytes';\nimport { utf8ToBytes } from '../internal/encoding';\n\nexport interface AuthenticatorDataFlags {\n /** User Present */\n up: boolean;\n /** User Verified */\n uv: boolean;\n /** Backup Eligible */\n be: boolean;\n /** Backup State */\n bs: boolean;\n /** Attested credential data present */\n at: boolean;\n /** Extension data present */\n ed: boolean;\n /** Raw flags byte. */\n bits: number;\n}\n\nexport interface ParsedAuthenticatorData {\n rpIdHash: Uint8Array;\n flags: AuthenticatorDataFlags;\n signCount: number;\n aaguid?: Uint8Array;\n credentialId?: Uint8Array;\n /** Raw CBOR-encoded COSE public key (exact bytes), if attested data present. */\n credentialPublicKey?: Uint8Array;\n}\n\nconst MIN_LENGTH = 37; // rpIdHash(32) + flags(1) + signCount(4)\n\n/** Parse the authenticatorData byte structure (WebAuthn §6.1). */\nexport function parseAuthenticatorData(authData: Uint8Array): ParsedAuthenticatorData {\n if (authData.length < MIN_LENGTH) {\n throw new KitError(\n 'UNSUPPORTED_AUTHENTICATOR',\n `authenticatorData is ${authData.length} bytes, expected at least ${MIN_LENGTH}`,\n );\n }\n const view = new DataView(authData.buffer, authData.byteOffset, authData.byteLength);\n const rpIdHash = authData.slice(0, 32);\n const bits = authData[32] ?? 0;\n const flags: AuthenticatorDataFlags = {\n up: (bits & 0x01) !== 0,\n uv: (bits & 0x04) !== 0,\n be: (bits & 0x08) !== 0,\n bs: (bits & 0x10) !== 0,\n at: (bits & 0x40) !== 0,\n ed: (bits & 0x80) !== 0,\n bits,\n };\n const signCount = view.getUint32(33, false);\n\n const result: ParsedAuthenticatorData = { rpIdHash, flags, signCount };\n\n if (flags.at) {\n if (authData.length < 55) {\n throw new KitError(\n 'UNSUPPORTED_AUTHENTICATOR',\n 'authenticatorData truncated in attested data',\n );\n }\n result.aaguid = authData.slice(37, 53);\n const credIdLength = view.getUint16(53, false);\n const credIdEnd = 55 + credIdLength;\n if (authData.length < credIdEnd) {\n throw new KitError(\n 'UNSUPPORTED_AUTHENTICATOR',\n 'authenticatorData truncated in credentialId',\n );\n }\n result.credentialId = authData.slice(55, credIdEnd);\n // The COSE public key is the next CBOR item; capture its exact bytes so we\n // stop cleanly before any extension data (when flags.ed is set).\n const rest = authData.slice(credIdEnd);\n const { length } = decodeCbor(rest, 0);\n result.credentialPublicKey = rest.slice(0, length);\n }\n\n return result;\n}\n\n/** Verify that authenticatorData's rpIdHash equals SHA-256(rpId). */\nexport function verifyRpIdHash(authData: Uint8Array, rpId: string): void {\n const actual = parseAuthenticatorData(authData).rpIdHash;\n const expected = sha256(utf8ToBytes(rpId));\n if (!equalBytes(actual, expected)) {\n throw new KitError(\n 'RP_ID_MISMATCH',\n `authenticatorData rpIdHash does not match SHA-256(\"${rpId}\")`,\n );\n }\n}\n","import { KitError } from '../errors';\nimport { base64UrlToBytes, bytesToBase64Url, bytesToUtf8 } from '../internal/encoding';\n\n/** The subset of clientDataJSON fields we rely on. */\nexport interface ClientData {\n type: string;\n /** base64url-encoded challenge as embedded by the client. */\n challenge: string;\n origin: string;\n crossOrigin?: boolean;\n}\n\n/** Encode a raw challenge as the base64url string embedded in clientDataJSON. */\nexport function encodeChallenge(challenge: Uint8Array): string {\n return bytesToBase64Url(challenge);\n}\n\n/** Decode the base64url challenge embedded in clientDataJSON back to bytes. */\nexport function decodeChallenge(challenge: string): Uint8Array {\n return base64UrlToBytes(challenge);\n}\n\n/** Parse clientDataJSON bytes into a typed, validated-shape object. */\nexport function parseClientDataJSON(clientDataJSON: Uint8Array): ClientData {\n let raw: unknown;\n try {\n raw = JSON.parse(bytesToUtf8(clientDataJSON));\n } catch (cause) {\n throw new KitError('UNSUPPORTED_AUTHENTICATOR', 'clientDataJSON is not valid JSON', { cause });\n }\n if (typeof raw !== 'object' || raw === null) {\n throw new KitError('UNSUPPORTED_AUTHENTICATOR', 'clientDataJSON is not a JSON object');\n }\n const obj = raw as Record<string, unknown>;\n const { type, challenge, origin, crossOrigin } = obj;\n if (typeof type !== 'string' || typeof challenge !== 'string' || typeof origin !== 'string') {\n throw new KitError('UNSUPPORTED_AUTHENTICATOR', 'clientDataJSON is missing required fields');\n }\n return {\n type,\n challenge,\n origin,\n crossOrigin: typeof crossOrigin === 'boolean' ? crossOrigin : undefined,\n };\n}\n\n/**\n * Parse and verify clientDataJSON for an authentication (`webauthn.get`)\n * assertion: the ceremony type, the origin (exact match against one or more\n * allowed origins), and the embedded challenge (base64url string).\n */\nexport function verifyClientDataJSON(\n clientDataJSON: Uint8Array,\n expected: { origin: string | string[]; challenge: string },\n): ClientData {\n const data = parseClientDataJSON(clientDataJSON);\n if (data.type !== 'webauthn.get') {\n throw new KitError(\n 'UNSUPPORTED_AUTHENTICATOR',\n `clientDataJSON.type \"${data.type}\" is not \"webauthn.get\"`,\n );\n }\n const allowed = Array.isArray(expected.origin) ? expected.origin : [expected.origin];\n if (!allowed.includes(data.origin)) {\n throw new KitError('ORIGIN_MISMATCH', `origin \"${data.origin}\" not in [${allowed.join(', ')}]`);\n }\n if (data.challenge !== expected.challenge) {\n throw new KitError('CHALLENGE_MISMATCH', 'clientDataJSON challenge does not match expected');\n }\n return data;\n}\n"]}
@@ -0,0 +1,135 @@
1
+ import { KitError } from './chunk-AMYFJQAC.js';
2
+
3
+ // src/internal/encoding.ts
4
+ function bytesToBase64Url(bytes) {
5
+ let binary = "";
6
+ for (const byte of bytes) binary += String.fromCharCode(byte);
7
+ return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
8
+ }
9
+ function base64UrlToBytes(input) {
10
+ const base64 = input.replace(/-/g, "+").replace(/_/g, "/");
11
+ const padded = base64 + "=".repeat((4 - base64.length % 4) % 4);
12
+ const binary = atob(padded);
13
+ const out = new Uint8Array(new ArrayBuffer(binary.length));
14
+ for (let i = 0; i < binary.length; i += 1) out[i] = binary.charCodeAt(i);
15
+ return out;
16
+ }
17
+ function utf8ToBytes(text) {
18
+ return new TextEncoder().encode(text);
19
+ }
20
+ function bytesToUtf8(bytes) {
21
+ return new TextDecoder().decode(bytes);
22
+ }
23
+
24
+ // src/ceremonies/random.ts
25
+ function randomBytes(length) {
26
+ const webcrypto = globalThis.crypto;
27
+ if (typeof webcrypto?.getRandomValues !== "function") {
28
+ throw new KitError(
29
+ "UNSUPPORTED_AUTHENTICATOR",
30
+ "no secure random source (globalThis.crypto.getRandomValues) is available in this environment"
31
+ );
32
+ }
33
+ const out = new Uint8Array(new ArrayBuffer(length));
34
+ webcrypto.getRandomValues(out);
35
+ return out;
36
+ }
37
+
38
+ // src/ceremonies/browserClient.ts
39
+ function asKitError(error) {
40
+ if (error instanceof KitError) return error;
41
+ const name = typeof error === "object" && error !== null && "name" in error ? error.name : void 0;
42
+ if (name === "NotAllowedError") {
43
+ return new KitError("USER_CANCELLED", "The passkey prompt was dismissed.", { cause: error });
44
+ }
45
+ const message = error instanceof Error ? error.message : "WebAuthn request failed";
46
+ const detail = typeof name === "string" ? `${name}: ${message}` : message;
47
+ return new KitError("UNSUPPORTED_AUTHENTICATOR", detail, { cause: error });
48
+ }
49
+ function browserWebAuthnClient() {
50
+ const credentials = globalThis.navigator?.credentials;
51
+ if (!credentials) {
52
+ throw new KitError("UNSUPPORTED_AUTHENTICATOR", "navigator.credentials is unavailable");
53
+ }
54
+ return {
55
+ async create(options) {
56
+ const publicKey = {
57
+ challenge: base64UrlToBytes(options.challenge),
58
+ rp: options.rp,
59
+ user: {
60
+ id: base64UrlToBytes(options.user.id),
61
+ name: options.user.name,
62
+ displayName: options.user.displayName
63
+ },
64
+ pubKeyCredParams: options.pubKeyCredParams,
65
+ authenticatorSelection: options.authenticatorSelection,
66
+ attestation: options.attestation,
67
+ timeout: options.timeout
68
+ };
69
+ let credential;
70
+ try {
71
+ credential = await credentials.create({ publicKey });
72
+ } catch (error) {
73
+ throw asKitError(error);
74
+ }
75
+ if (!credential) throw new KitError("USER_CANCELLED", "credential creation returned null");
76
+ const response = credential.response;
77
+ return {
78
+ id: credential.id,
79
+ rawId: new Uint8Array(credential.rawId),
80
+ attestationObject: new Uint8Array(response.attestationObject)
81
+ };
82
+ },
83
+ async get(options) {
84
+ const publicKey = {
85
+ rpId: options.rpId,
86
+ challenge: options.challenge ? new Uint8Array(options.challenge) : randomBytes(32),
87
+ allowCredentials: (options.allowCredentials ?? []).map((id) => ({
88
+ type: "public-key",
89
+ id: base64UrlToBytes(id)
90
+ })),
91
+ userVerification: options.userVerification
92
+ };
93
+ const request = { publicKey };
94
+ if (options.mediation) request.mediation = options.mediation;
95
+ let credential;
96
+ try {
97
+ credential = await credentials.get(request);
98
+ } catch (error) {
99
+ throw asKitError(error);
100
+ }
101
+ if (!credential) throw new KitError("USER_CANCELLED", "assertion returned null");
102
+ const response = credential.response;
103
+ return {
104
+ id: credential.id,
105
+ rawId: new Uint8Array(credential.rawId),
106
+ authenticatorData: new Uint8Array(response.authenticatorData),
107
+ clientDataJSON: new Uint8Array(response.clientDataJSON),
108
+ signature: new Uint8Array(response.signature)
109
+ };
110
+ }
111
+ };
112
+ }
113
+ function defaultCredentialStorage() {
114
+ const key = (rpId) => `stellar-passkey:${rpId}`;
115
+ const ls = globalThis.localStorage;
116
+ if (ls) {
117
+ return {
118
+ get: (rpId) => ls.getItem(key(rpId)),
119
+ set: (rpId, credentialId) => {
120
+ ls.setItem(key(rpId), credentialId);
121
+ }
122
+ };
123
+ }
124
+ const memory = /* @__PURE__ */ new Map();
125
+ return {
126
+ get: (rpId) => memory.get(rpId) ?? null,
127
+ set: (rpId, credentialId) => {
128
+ memory.set(rpId, credentialId);
129
+ }
130
+ };
131
+ }
132
+
133
+ export { base64UrlToBytes, browserWebAuthnClient, bytesToBase64Url, bytesToUtf8, defaultCredentialStorage, randomBytes, utf8ToBytes };
134
+ //# sourceMappingURL=chunk-LB4HOTLV.js.map
135
+ //# sourceMappingURL=chunk-LB4HOTLV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/internal/encoding.ts","../src/ceremonies/random.ts","../src/ceremonies/browserClient.ts"],"names":[],"mappings":"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","file":"chunk-LB4HOTLV.js","sourcesContent":["/**\n * Isomorphic base64url + UTF-8 codecs. `atob`/`btoa`/`TextEncoder`/`TextDecoder`\n * are globals in modern browsers and Node >= 16, so no platform branch is\n * needed and nothing is bundled.\n */\n\n/** Encode bytes as unpadded base64url. */\nexport function bytesToBase64Url(bytes: Uint8Array): string {\n let binary = '';\n for (const byte of bytes) binary += String.fromCharCode(byte);\n return btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\n/** Decode base64 or base64url (padding optional) to bytes. */\nexport function base64UrlToBytes(input: string): Uint8Array<ArrayBuffer> {\n const base64 = input.replace(/-/g, '+').replace(/_/g, '/');\n const padded = base64 + '='.repeat((4 - (base64.length % 4)) % 4);\n const binary = atob(padded);\n const out = new Uint8Array(new ArrayBuffer(binary.length));\n for (let i = 0; i < binary.length; i += 1) out[i] = binary.charCodeAt(i);\n return out;\n}\n\nexport function utf8ToBytes(text: string): Uint8Array {\n return new TextEncoder().encode(text);\n}\n\nexport function bytesToUtf8(bytes: Uint8Array): string {\n return new TextDecoder().decode(bytes);\n}\n","import { KitError } from '../errors';\n\n/**\n * Cryptographically-random bytes, isomorphic (browser + Node global crypto).\n * Throws instead of silently returning all-zero bytes when no secure RNG is\n * present — an all-zero challenge would be catastrophic, not a soft fallback.\n */\nexport function randomBytes(length: number): Uint8Array<ArrayBuffer> {\n const webcrypto = globalThis.crypto as Crypto | undefined;\n if (typeof webcrypto?.getRandomValues !== 'function') {\n throw new KitError(\n 'UNSUPPORTED_AUTHENTICATOR',\n 'no secure random source (globalThis.crypto.getRandomValues) is available in this environment',\n );\n }\n const out = new Uint8Array(new ArrayBuffer(length));\n webcrypto.getRandomValues(out);\n return out;\n}\n","import { KitError } from '../errors';\nimport { base64UrlToBytes } from '../internal/encoding';\nimport type { PublicKeyCredentialCreationOptionsJSON } from '../webauthn/createOptions';\nimport { randomBytes } from './random';\nimport type {\n CredentialStorage,\n WebAuthnClient,\n WebAuthnCreateResult,\n WebAuthnGetOptions,\n WebAuthnGetResult,\n} from './types';\n\n/**\n * Map a `navigator.credentials` rejection to a `KitError`. Dismissing the OS\n * passkey sheet rejects with a `NotAllowedError` (a DOMException) — surface that\n * as `USER_CANCELLED` so the UI shows the true \"you cancelled\" copy instead of\n * the generic unsupported-authenticator fallback (S20 / S04 polish).\n */\nfunction asKitError(error: unknown): KitError {\n if (error instanceof KitError) return error;\n const name =\n typeof error === 'object' && error !== null && 'name' in error\n ? (error as { name?: unknown }).name\n : undefined;\n if (name === 'NotAllowedError') {\n return new KitError('USER_CANCELLED', 'The passkey prompt was dismissed.', { cause: error });\n }\n const message = error instanceof Error ? error.message : 'WebAuthn request failed';\n // Preserve the original DOMException name (e.g. InvalidStateError / ConstraintError)\n // in the message so diagnostics show the true cause, not just the generic bucket.\n const detail = typeof name === 'string' ? `${name}: ${message}` : message;\n return new KitError('UNSUPPORTED_AUTHENTICATOR', detail, { cause: error });\n}\n\n/** The browser `WebAuthnClient` backed by `navigator.credentials`. */\nexport function browserWebAuthnClient(): WebAuthnClient {\n const credentials = (globalThis as { navigator?: Navigator }).navigator?.credentials;\n if (!credentials) {\n throw new KitError('UNSUPPORTED_AUTHENTICATOR', 'navigator.credentials is unavailable');\n }\n return {\n async create(options: PublicKeyCredentialCreationOptionsJSON): Promise<WebAuthnCreateResult> {\n const publicKey: PublicKeyCredentialCreationOptions = {\n challenge: base64UrlToBytes(options.challenge),\n rp: options.rp,\n user: {\n id: base64UrlToBytes(options.user.id),\n name: options.user.name,\n displayName: options.user.displayName,\n },\n pubKeyCredParams: options.pubKeyCredParams,\n authenticatorSelection: options.authenticatorSelection,\n attestation: options.attestation,\n timeout: options.timeout,\n };\n let credential: PublicKeyCredential | null;\n try {\n credential = (await credentials.create({ publicKey })) as PublicKeyCredential | null;\n } catch (error) {\n throw asKitError(error);\n }\n if (!credential) throw new KitError('USER_CANCELLED', 'credential creation returned null');\n const response = credential.response as AuthenticatorAttestationResponse;\n return {\n id: credential.id,\n rawId: new Uint8Array(credential.rawId),\n attestationObject: new Uint8Array(response.attestationObject),\n };\n },\n async get(options: WebAuthnGetOptions): Promise<WebAuthnGetResult> {\n const publicKey: PublicKeyCredentialRequestOptions = {\n rpId: options.rpId,\n challenge: options.challenge ? new Uint8Array(options.challenge) : randomBytes(32),\n allowCredentials: (options.allowCredentials ?? []).map((id) => ({\n type: 'public-key',\n id: base64UrlToBytes(id),\n })),\n userVerification: options.userVerification,\n };\n const request: CredentialRequestOptions = { publicKey };\n if (options.mediation) request.mediation = options.mediation;\n let credential: PublicKeyCredential | null;\n try {\n credential = (await credentials.get(request)) as PublicKeyCredential | null;\n } catch (error) {\n throw asKitError(error);\n }\n if (!credential) throw new KitError('USER_CANCELLED', 'assertion returned null');\n const response = credential.response as AuthenticatorAssertionResponse;\n return {\n id: credential.id,\n rawId: new Uint8Array(credential.rawId),\n authenticatorData: new Uint8Array(response.authenticatorData),\n clientDataJSON: new Uint8Array(response.clientDataJSON),\n signature: new Uint8Array(response.signature),\n };\n },\n };\n}\n\n/** localStorage-backed credential store, with an in-memory fallback (Node/SSR). */\nexport function defaultCredentialStorage(): CredentialStorage {\n const key = (rpId: string): string => `stellar-passkey:${rpId}`;\n const ls = (globalThis as { localStorage?: Storage }).localStorage;\n if (ls) {\n return {\n get: (rpId) => ls.getItem(key(rpId)),\n set: (rpId, credentialId) => {\n ls.setItem(key(rpId), credentialId);\n },\n };\n }\n const memory = new Map<string, string>();\n return {\n get: (rpId) => memory.get(rpId) ?? null,\n set: (rpId, credentialId) => {\n memory.set(rpId, credentialId);\n },\n };\n}\n"]}
@@ -0,0 +1,108 @@
1
+ import { authEntryChallengeBytes } from './chunk-BIRF5I6I.js';
2
+ import { sha256, concatBytes } from './chunk-JNJ2FY45.js';
3
+ import { browserWebAuthnClient, base64UrlToBytes, bytesToUtf8, bytesToBase64Url } from './chunk-LB4HOTLV.js';
4
+ import '@stellar/stellar-sdk';
5
+ import { p256 } from '@noble/curves/nist';
6
+
7
+ // src/ceremonies/browserSigner.ts
8
+ function browserPasskeySigner(options) {
9
+ const webauthn = options.webauthn ?? browserWebAuthnClient();
10
+ return async (challenge) => {
11
+ const assertion = await webauthn.get({
12
+ rpId: options.rpId,
13
+ challenge: base64UrlToBytes(challenge),
14
+ allowCredentials: options.allowCredentials ?? [],
15
+ userVerification: options.userVerification ?? "preferred"
16
+ });
17
+ return {
18
+ authenticatorData: assertion.authenticatorData,
19
+ clientDataJSON: assertion.clientDataJSON,
20
+ signature: assertion.signature,
21
+ credentialId: assertion.rawId
22
+ };
23
+ };
24
+ }
25
+ function fail(reason) {
26
+ return { success: false, challengeBound: false, signatureValid: false, reason };
27
+ }
28
+ function verifySecp256r1StructMap(structMap, publicKey, signaturePayload) {
29
+ const field = (name) => {
30
+ const e = structMap.find((x) => x.key().sym().toString() === name);
31
+ return e ? new Uint8Array(e.val().bytes()) : void 0;
32
+ };
33
+ const authenticatorData = field("authenticator_data");
34
+ const clientDataJSON = field("client_data_json");
35
+ const signature = field("signature");
36
+ if (!authenticatorData || !clientDataJSON || !signature) {
37
+ return { ok: false, challengeBound: false, signatureValid: false, reason: "missing fields" };
38
+ }
39
+ if (signature.length !== 64) {
40
+ return {
41
+ ok: false,
42
+ challengeBound: false,
43
+ signatureValid: false,
44
+ reason: "not 64-byte compact"
45
+ };
46
+ }
47
+ let challengeBound = false;
48
+ try {
49
+ const cdj = JSON.parse(bytesToUtf8(clientDataJSON));
50
+ challengeBound = cdj.challenge === bytesToBase64Url(signaturePayload);
51
+ } catch {
52
+ challengeBound = false;
53
+ }
54
+ const digest = sha256(concatBytes(authenticatorData, sha256(clientDataJSON)));
55
+ const signatureValid = p256.verify(signature, digest, publicKey, {
56
+ lowS: false,
57
+ format: "compact"
58
+ });
59
+ return { ok: challengeBound && signatureValid, challengeBound, signatureValid };
60
+ }
61
+ function referenceCheckAuth(entry, publicKey, networkPassphrase) {
62
+ if (entry.credentials().switch().name !== "sorobanCredentialsAddress") {
63
+ return fail("no address credentials");
64
+ }
65
+ const structMap = entry.credentials().address().signature().map();
66
+ if (!structMap) return fail("signature is not a Secp256r1Signature map");
67
+ const signaturePayload = authEntryChallengeBytes(entry, networkPassphrase);
68
+ const r = verifySecp256r1StructMap(structMap, publicKey, signaturePayload);
69
+ return { success: r.ok, challengeBound: r.challengeBound, signatureValid: r.signatureValid };
70
+ }
71
+ function referenceSmartWalletCheckAuth(entry, publicKeyFor, networkPassphrase) {
72
+ if (entry.credentials().switch().name !== "sorobanCredentialsAddress") {
73
+ return { success: false, signers: [], reason: "no address credentials" };
74
+ }
75
+ const sig = entry.credentials().address().signature();
76
+ const map = sig.switch().name === "scvVec" ? sig.vec()?.[0]?.map() : void 0;
77
+ if (!map) {
78
+ return { success: false, signers: [], reason: "signature is not a Signatures(Map) vec" };
79
+ }
80
+ if (map.length === 0) return { success: false, signers: [], reason: "empty signatures map" };
81
+ const signaturePayload = authEntryChallengeBytes(entry, networkPassphrase);
82
+ const signers = [];
83
+ let allOk = true;
84
+ for (const e of map) {
85
+ const keyVec = e.key().vec();
86
+ const idBytes = keyVec?.[1]?.bytes();
87
+ const credentialId = idBytes ? Buffer.from(idBytes).toString("hex") : "";
88
+ const structMap = e.val().vec()?.[1]?.map();
89
+ const publicKey = publicKeyFor(credentialId);
90
+ if (!structMap || !publicKey) {
91
+ allOk = false;
92
+ signers.push({ credentialId, challengeBound: false, signatureValid: false });
93
+ continue;
94
+ }
95
+ const r = verifySecp256r1StructMap(structMap, publicKey, signaturePayload);
96
+ if (!r.ok) allOk = false;
97
+ signers.push({
98
+ credentialId,
99
+ challengeBound: r.challengeBound,
100
+ signatureValid: r.signatureValid
101
+ });
102
+ }
103
+ return { success: allOk, signers };
104
+ }
105
+
106
+ export { browserPasskeySigner, referenceCheckAuth, referenceSmartWalletCheckAuth };
107
+ //# sourceMappingURL=chunk-LM2AZXKZ.js.map
108
+ //# sourceMappingURL=chunk-LM2AZXKZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/ceremonies/browserSigner.ts","../src/soroban/checkAuth.ts"],"names":[],"mappings":"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","file":"chunk-LM2AZXKZ.js","sourcesContent":["import { base64UrlToBytes } from '../internal/encoding';\nimport type { AssertionResult, WebAuthnSigner } from '../soroban/sign';\nimport { browserWebAuthnClient } from './browserClient';\nimport type { WebAuthnClient } from './types';\n\nexport interface BrowserPasskeySignerOptions {\n /** The Relying Party ID (your site's registrable domain). */\n rpId: string;\n /**\n * Restrict the prompt to specific credential ids (base64url) — pass the\n * `credentialId` from `create` / `connect` so the OS offers the right passkey.\n * Omit (or leave empty) for a discoverable prompt over any resident passkey.\n */\n allowCredentials?: string[];\n userVerification?: 'discouraged' | 'preferred' | 'required';\n /** Inject a custom client (tests / non-browser). Defaults to `browserWebAuthnClient()`. */\n webauthn?: WebAuthnClient;\n}\n\n/**\n * Adapt `navigator.credentials.get` into the `WebAuthnSigner` that\n * `signTransaction` / `signAuthEntry` expect — so wiring a passkey is one line:\n *\n * ```ts\n * const sign = browserPasskeySigner({ rpId, allowCredentials: [credentialId] });\n * const signedXdr = await signTransaction(txXdr, { networkPassphrase, sign });\n * ```\n *\n * The SDK hands the signer a base64url challenge (the Soroban auth preimage);\n * this decodes it to the raw bytes WebAuthn signs over, runs the assertion, and\n * returns the fields the auth assembler needs. The DER signature is low-S\n * normalized downstream (invariant #2) — nothing here weakens that.\n */\nexport function browserPasskeySigner(options: BrowserPasskeySignerOptions): WebAuthnSigner {\n const webauthn = options.webauthn ?? browserWebAuthnClient();\n return async (challenge: string): Promise<AssertionResult> => {\n const assertion = await webauthn.get({\n rpId: options.rpId,\n challenge: base64UrlToBytes(challenge),\n allowCredentials: options.allowCredentials ?? [],\n userVerification: options.userVerification ?? 'preferred',\n });\n return {\n authenticatorData: assertion.authenticatorData,\n clientDataJSON: assertion.clientDataJSON,\n signature: assertion.signature,\n credentialId: assertion.rawId,\n };\n };\n}\n","import { xdr } from '@stellar/stellar-sdk';\nimport { p256 } from '@noble/curves/nist';\nimport { sha256 } from '../internal/sha256';\nimport { concatBytes } from '../internal/bytes';\nimport { bytesToBase64Url, bytesToUtf8 } from '../internal/encoding';\nimport { authEntryChallengeBytes } from './preimage';\n\nexport interface CheckAuthResult {\n success: boolean;\n /** clientDataJSON.challenge === base64url(preimage hash). */\n challengeBound: boolean;\n /** secp256r1_verify over SHA256(authData ‖ SHA256(cdj)) passed. */\n signatureValid: boolean;\n reason?: string;\n}\n\nfunction fail(reason: string): CheckAuthResult {\n return { success: false, challengeBound: false, signatureValid: false, reason };\n}\n\n/**\n * Verify a bare `Secp256r1Signature` ScMap ({ authenticator_data,\n * client_data_json, signature }) against a public key + the expected signature\n * payload. Shared by the single-signer and smart-wallet reference verifiers.\n */\nfunction verifySecp256r1StructMap(\n structMap: xdr.ScMapEntry[],\n publicKey: Uint8Array,\n signaturePayload: Uint8Array,\n): { ok: boolean; challengeBound: boolean; signatureValid: boolean; reason?: string } {\n const field = (name: string): Uint8Array | undefined => {\n const e = structMap.find((x) => x.key().sym().toString() === name);\n return e ? new Uint8Array(e.val().bytes()) : undefined;\n };\n const authenticatorData = field('authenticator_data');\n const clientDataJSON = field('client_data_json');\n const signature = field('signature');\n if (!authenticatorData || !clientDataJSON || !signature) {\n return { ok: false, challengeBound: false, signatureValid: false, reason: 'missing fields' };\n }\n if (signature.length !== 64) {\n return {\n ok: false,\n challengeBound: false,\n signatureValid: false,\n reason: 'not 64-byte compact',\n };\n }\n let challengeBound = false;\n try {\n const cdj = JSON.parse(bytesToUtf8(clientDataJSON)) as { challenge?: string };\n challengeBound = cdj.challenge === bytesToBase64Url(signaturePayload);\n } catch {\n challengeBound = false;\n }\n // Host fn semantics: no low-S enforcement (lowS:false), compact format.\n const digest = sha256(concatBytes(authenticatorData, sha256(clientDataJSON)));\n const signatureValid = p256.verify(signature, digest, publicKey, {\n lowS: false,\n format: 'compact',\n });\n return { ok: challengeBound && signatureValid, challengeBound, signatureValid };\n}\n\n/**\n * A faithful JavaScript model of the on-chain `__check_auth` (kalepail\n * `webauthn-wallet` `verify.rs`): reconstruct `SHA256(authenticator_data ‖\n * SHA256(client_data_json))`, run `secp256r1_verify` (which does NOT enforce\n * low-S — hence the client-side normalization), and assert challenge-binding\n * (`clientDataJSON.challenge === base64url(signature_payload)`). Lets us prove\n * the assembly without a live Soroban RPC; the real on-chain run is exercised\n * by the kit integration (S17) and the demo (S21).\n */\nexport function referenceCheckAuth(\n entry: xdr.SorobanAuthorizationEntry,\n publicKey: Uint8Array,\n networkPassphrase: string,\n): CheckAuthResult {\n if (entry.credentials().switch().name !== 'sorobanCredentialsAddress') {\n return fail('no address credentials');\n }\n // The signature is the Secp256r1Signature struct directly: a sorted ScMap\n // { authenticator_data, client_data_json, signature } (see assemble.ts).\n const structMap = entry.credentials().address().signature().map();\n if (!structMap) return fail('signature is not a Secp256r1Signature map');\n\n const signaturePayload = authEntryChallengeBytes(entry, networkPassphrase);\n const r = verifySecp256r1StructMap(structMap, publicKey, signaturePayload);\n return { success: r.ok, challengeBound: r.challengeBound, signatureValid: r.signatureValid };\n}\n\nexport interface SmartWalletCheckAuthResult {\n success: boolean;\n signers: { credentialId: string; challengeBound: boolean; signatureValid: boolean }[];\n reason?: string;\n}\n\n/**\n * A reference model of passkey-kit's smart-wallet `__check_auth`: unwrap the\n * `Signatures(Map<SignerKey, Signature>)` value (`ScVal::Vec([ScVal::Map(...)])`),\n * and for each `SignerKey::Secp256r1(id) => Signature::Secp256r1(struct)` entry,\n * look up that credential id's SEC-1 public key and verify the struct. Succeeds\n * only when the map is non-empty and every signer verifies + is challenge-bound.\n * `publicKeyFor` receives the lowercase-hex credential id.\n */\nexport function referenceSmartWalletCheckAuth(\n entry: xdr.SorobanAuthorizationEntry,\n publicKeyFor: (credentialIdHex: string) => Uint8Array | undefined,\n networkPassphrase: string,\n): SmartWalletCheckAuthResult {\n if (entry.credentials().switch().name !== 'sorobanCredentialsAddress') {\n return { success: false, signers: [], reason: 'no address credentials' };\n }\n const sig = entry.credentials().address().signature();\n const map = sig.switch().name === 'scvVec' ? sig.vec()?.[0]?.map() : undefined;\n if (!map) {\n return { success: false, signers: [], reason: 'signature is not a Signatures(Map) vec' };\n }\n if (map.length === 0) return { success: false, signers: [], reason: 'empty signatures map' };\n\n const signaturePayload = authEntryChallengeBytes(entry, networkPassphrase);\n const signers: SmartWalletCheckAuthResult['signers'] = [];\n let allOk = true;\n\n for (const e of map) {\n const keyVec = e.key().vec();\n const idBytes = keyVec?.[1]?.bytes();\n const credentialId = idBytes ? Buffer.from(idBytes).toString('hex') : '';\n // Signature::Secp256r1(struct) → scvVec([Symbol, structMap]).\n const structMap = e.val().vec()?.[1]?.map();\n const publicKey = publicKeyFor(credentialId);\n if (!structMap || !publicKey) {\n allOk = false;\n signers.push({ credentialId, challengeBound: false, signatureValid: false });\n continue;\n }\n const r = verifySecp256r1StructMap(structMap, publicKey, signaturePayload);\n if (!r.ok) allOk = false;\n signers.push({\n credentialId,\n challengeBound: r.challengeBound,\n signatureValid: r.signatureValid,\n });\n }\n return { success: allOk, signers };\n}\n"]}
@@ -0,0 +1,3 @@
1
+
2
+ //# sourceMappingURL=chunk-LUDXP56M.js.map
3
+ //# sourceMappingURL=chunk-LUDXP56M.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-LUDXP56M.js"}
@@ -0,0 +1,48 @@
1
+ import { decodeChallenge } from './chunk-JNJ2FY45.js';
2
+ import { KitError } from './chunk-AMYFJQAC.js';
3
+ import { hash, Address, xdr, StrKey } from '@stellar/stellar-sdk';
4
+ import { sha256 } from '@noble/hashes/sha256';
5
+
6
+ function contractIdFromDeployerSalt(deployer, salt, networkPassphrase) {
7
+ let address;
8
+ try {
9
+ address = Address.fromString(deployer).toScAddress();
10
+ } catch (cause) {
11
+ throw new KitError("CONTRACT_AUTH_FAILED", `invalid deployer address "${deployer}"`, { cause });
12
+ }
13
+ const preimage = xdr.HashIdPreimage.envelopeTypeContractId(
14
+ new xdr.HashIdPreimageContractId({
15
+ networkId: hash(Buffer.from(networkPassphrase)),
16
+ contractIdPreimage: xdr.ContractIdPreimage.contractIdPreimageFromAddress(
17
+ new xdr.ContractIdPreimageFromAddress({
18
+ address,
19
+ salt: Buffer.from(salt)
20
+ })
21
+ )
22
+ })
23
+ );
24
+ return StrKey.encodeContract(hash(preimage.toXDR()));
25
+ }
26
+ function deriveAccountAddress(options) {
27
+ const { factoryContractId, credentialId, networkPassphrase } = options;
28
+ if (credentialId.length === 0) {
29
+ throw new KitError("CONTRACT_AUTH_FAILED", "deriveAccountAddress: empty credential id");
30
+ }
31
+ return contractIdFromDeployerSalt(
32
+ factoryContractId,
33
+ hash(Buffer.from(credentialId)),
34
+ // e.crypto().sha256(credential_id)
35
+ networkPassphrase
36
+ );
37
+ }
38
+ function deriveSmartWalletAddress(options) {
39
+ const raw = decodeChallenge(options.credentialId);
40
+ if (raw.length === 0) {
41
+ throw new KitError("CONTRACT_AUTH_FAILED", "deriveSmartWalletAddress: empty credential id");
42
+ }
43
+ return contractIdFromDeployerSalt(options.deployer, sha256(raw), options.networkPassphrase);
44
+ }
45
+
46
+ export { deriveAccountAddress, deriveSmartWalletAddress };
47
+ //# sourceMappingURL=chunk-MMB4ZIW3.js.map
48
+ //# sourceMappingURL=chunk-MMB4ZIW3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/soroban/address.ts"],"names":[],"mappings":";;;;;AAMA,SAAS,0BAAA,CACP,QAAA,EACA,IAAA,EACA,iBAAA,EACQ;AACR,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI;AACF,IAAA,OAAA,GAAU,OAAA,CAAQ,UAAA,CAAW,QAAQ,CAAA,CAAE,WAAA,EAAY;AAAA,EACrD,SAAS,KAAA,EAAO;AACd,IAAA,MAAM,IAAI,SAAS,sBAAA,EAAwB,CAAA,0BAAA,EAA6B,QAAQ,CAAA,CAAA,CAAA,EAAK,EAAE,OAAO,CAAA;AAAA,EAChG;AACA,EAAA,MAAM,QAAA,GAAW,IAAI,cAAA,CAAe,sBAAA;AAAA,IAClC,IAAI,IAAI,wBAAA,CAAyB;AAAA,MAC/B,SAAA,EAAW,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,iBAAiB,CAAC,CAAA;AAAA,MAC9C,kBAAA,EAAoB,IAAI,kBAAA,CAAmB,6BAAA;AAAA,QACzC,IAAI,IAAI,6BAAA,CAA8B;AAAA,UACpC,OAAA;AAAA,UACA,IAAA,EAAM,MAAA,CAAO,IAAA,CAAK,IAAI;AAAA,SACvB;AAAA;AACH,KACD;AAAA,GACH;AACA,EAAA,OAAO,OAAO,cAAA,CAAe,IAAA,CAAK,QAAA,CAAS,KAAA,EAAO,CAAC,CAAA;AACrD;AAkBO,SAAS,qBAAqB,OAAA,EAA8C;AACjF,EAAA,MAAM,EAAE,iBAAA,EAAmB,YAAA,EAAc,iBAAA,EAAkB,GAAI,OAAA;AAC/D,EAAA,IAAI,YAAA,CAAa,WAAW,CAAA,EAAG;AAC7B,IAAA,MAAM,IAAI,QAAA,CAAS,sBAAA,EAAwB,2CAA2C,CAAA;AAAA,EACxF;AACA,EAAA,OAAO,0BAAA;AAAA,IACL,iBAAA;AAAA,IACA,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,YAAY,CAAC,CAAA;AAAA;AAAA,IAC9B;AAAA,GACF;AACF;AAyBO,SAAS,yBAAyB,OAAA,EAAkD;AACzF,EAAA,MAAM,GAAA,GAAM,eAAA,CAAgB,OAAA,CAAQ,YAAY,CAAA;AAChD,EAAA,IAAI,GAAA,CAAI,WAAW,CAAA,EAAG;AACpB,IAAA,MAAM,IAAI,QAAA,CAAS,sBAAA,EAAwB,+CAA+C,CAAA;AAAA,EAC5F;AACA,EAAA,OAAO,2BAA2B,OAAA,CAAQ,QAAA,EAAU,OAAO,GAAG,CAAA,EAAG,QAAQ,iBAAiB,CAAA;AAC5F","file":"chunk-MMB4ZIW3.js","sourcesContent":["import { Address, StrKey, hash, xdr } from '@stellar/stellar-sdk';\nimport { sha256 } from '@noble/hashes/sha256';\nimport { KitError } from '../errors';\nimport { decodeChallenge } from '../webauthn/clientData';\n\n/** The createCustomContract C-address from a deployer address + 32-byte salt (no network round-trip). */\nfunction contractIdFromDeployerSalt(\n deployer: string,\n salt: Uint8Array,\n networkPassphrase: string,\n): string {\n let address: xdr.ScAddress;\n try {\n address = Address.fromString(deployer).toScAddress();\n } catch (cause) {\n throw new KitError('CONTRACT_AUTH_FAILED', `invalid deployer address \"${deployer}\"`, { cause });\n }\n const preimage = xdr.HashIdPreimage.envelopeTypeContractId(\n new xdr.HashIdPreimageContractId({\n networkId: hash(Buffer.from(networkPassphrase)),\n contractIdPreimage: xdr.ContractIdPreimage.contractIdPreimageFromAddress(\n new xdr.ContractIdPreimageFromAddress({\n address,\n salt: Buffer.from(salt),\n }),\n ),\n }),\n );\n return StrKey.encodeContract(hash(preimage.toXDR()));\n}\n\nexport interface DeriveAccountAddressOptions {\n /** The AccountFactory contract C-address — the deployer. */\n factoryContractId: string;\n /** The credential-id bytes the factory salts by SHA-256 (utf-8 of the base64url id in our factory). */\n credentialId: Uint8Array;\n networkPassphrase: string;\n}\n\n/**\n * Derive the deterministic C-address of the `webauthn-account` our AccountFactory\n * deploys for a passkey — with NO network round-trip. The factory salts by\n * `sha256(credential_id)` and deploys with `deployer().with_current_contract(salt)`.\n * Verified against the on-chain `factoryDeployProof` in `contracts/deployments.json`\n * (credential `democred` → `CAGWE36M…`). For the passkey-kit v1 smart-wallet, use\n * {@link deriveSmartWalletAddress} instead (different deployer + salt-input scheme).\n */\nexport function deriveAccountAddress(options: DeriveAccountAddressOptions): string {\n const { factoryContractId, credentialId, networkPassphrase } = options;\n if (credentialId.length === 0) {\n throw new KitError('CONTRACT_AUTH_FAILED', 'deriveAccountAddress: empty credential id');\n }\n return contractIdFromDeployerSalt(\n factoryContractId,\n hash(Buffer.from(credentialId)), // e.crypto().sha256(credential_id)\n networkPassphrase,\n );\n}\n\nexport interface DeriveSmartWalletAddressOptions {\n /**\n * The account that deploys the wallet via `createCustomContract` — a classic\n * G-address (or a factory C-address). MUST be stable for offline `getAddress`.\n */\n deployer: string;\n /** base64url WebAuthn credential id of the FOUNDING passkey — its RAW bytes are salted. */\n credentialId: string;\n networkPassphrase: string;\n}\n\n/**\n * Derive the deterministic C-address of a passkey-kit **v1 smart-wallet** — offline,\n * no network. Mirrors passkey-kit's scheme exactly: `salt = sha256(rawCredentialId)`\n * (the base64url-decoded credential-id bytes), deployed by a fixed `deployer`\n * account via `createCustomContract`. Proven on-chain (`scripts/v1-events-probe.ts`:\n * derived id === deployed id).\n *\n * This only recovers the address for the wallet's FOUNDING credential (the one used\n * as the deploy salt). Signers added later via `add_signer` do not change the\n * address and cannot be reversed into it — resolve those through the events indexer\n * ({@link smartWalletV1Indexer}).\n */\nexport function deriveSmartWalletAddress(options: DeriveSmartWalletAddressOptions): string {\n const raw = decodeChallenge(options.credentialId);\n if (raw.length === 0) {\n throw new KitError('CONTRACT_AUTH_FAILED', 'deriveSmartWalletAddress: empty credential id');\n }\n return contractIdFromDeployerSalt(options.deployer, sha256(raw), options.networkPassphrase);\n}\n"]}
@@ -0,0 +1,22 @@
1
+ import { browserWebAuthnClient, randomBytes } from './chunk-LB4HOTLV.js';
2
+ import { assertUserActivation } from './chunk-TPBBZNPP.js';
3
+
4
+ // src/ceremonies/recover.ts
5
+ async function recover(options) {
6
+ assertUserActivation(options.userActivation);
7
+ const webauthn = options.webauthn ?? browserWebAuthnClient();
8
+ const assertion = await webauthn.get({
9
+ rpId: options.rpId,
10
+ allowCredentials: [],
11
+ challenge: options.challenge ?? randomBytes(32)
12
+ });
13
+ const accounts = await options.indexer.resolveByCredential(assertion.id);
14
+ return accounts.map((account) => ({
15
+ contractId: account.contractId,
16
+ credentialId: assertion.id
17
+ }));
18
+ }
19
+
20
+ export { recover };
21
+ //# sourceMappingURL=chunk-MOLZIRIH.js.map
22
+ //# sourceMappingURL=chunk-MOLZIRIH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/ceremonies/recover.ts"],"names":[],"mappings":";;;;AAwBA,eAAsB,QAAQ,OAAA,EAAmD;AAC/E,EAAA,oBAAA,CAAqB,QAAQ,cAAc,CAAA;AAC3C,EAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,QAAA,IAAY,qBAAA,EAAsB;AAC3D,EAAA,MAAM,SAAA,GAAY,MAAM,QAAA,CAAS,GAAA,CAAI;AAAA,IACnC,MAAM,OAAA,CAAQ,IAAA;AAAA,IACd,kBAAkB,EAAC;AAAA,IACnB,SAAA,EAAW,OAAA,CAAQ,SAAA,IAAa,WAAA,CAAY,EAAE;AAAA,GAC/C,CAAA;AACD,EAAA,MAAM,WAAW,MAAM,OAAA,CAAQ,OAAA,CAAQ,mBAAA,CAAoB,UAAU,EAAE,CAAA;AACvE,EAAA,OAAO,QAAA,CAAS,GAAA,CAAI,CAAC,OAAA,MAAa;AAAA,IAChC,YAAY,OAAA,CAAQ,UAAA;AAAA,IACpB,cAAc,SAAA,CAAU;AAAA,GAC1B,CAAE,CAAA;AACJ","file":"chunk-MOLZIRIH.js","sourcesContent":["import { assertUserActivation } from '../anchors';\nimport type { IndexerAdapter } from '../adapters/types';\nimport { browserWebAuthnClient } from './browserClient';\nimport { randomBytes } from './random';\nimport type { WebAuthnClient } from './types';\n\nexport interface RecoverOptions {\n rpId: string;\n indexer: IndexerAdapter;\n webauthn?: WebAuthnClient;\n challenge?: Uint8Array;\n userActivation?: { isActive: boolean };\n}\n\nexport interface RecoverResult {\n contractId: string;\n credentialId: string;\n}\n\n/**\n * `recover` — the lost-localStorage / new-device path. Performs a\n * discoverable-credential `get()` (no allowCredentials), then resolves every\n * smart account controlled by that credential via the IndexerAdapter.\n */\nexport async function recover(options: RecoverOptions): Promise<RecoverResult[]> {\n assertUserActivation(options.userActivation); // anchor: apple-user-gesture (S04)\n const webauthn = options.webauthn ?? browserWebAuthnClient();\n const assertion = await webauthn.get({\n rpId: options.rpId,\n allowCredentials: [],\n challenge: options.challenge ?? randomBytes(32),\n });\n const accounts = await options.indexer.resolveByCredential(assertion.id);\n return accounts.map((account) => ({\n contractId: account.contractId,\n credentialId: assertion.id,\n }));\n}\n"]}