@ledgerhq/revault-sdk 0.28.10 → 0.28.13
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/lib/bake.cjs +3 -3
- package/lib/bake.cjs.map +1 -1
- package/lib/bake.d.cts +2 -2
- package/lib/bake.d.ts +2 -2
- package/lib/bake.js +3 -3
- package/lib/bake.js.map +1 -1
- package/lib/{crypto-BTN8FS8v.cjs → crypto-CKLQSwr3.cjs} +48 -12
- package/lib/crypto-CKLQSwr3.cjs.map +1 -0
- package/lib/{crypto-BcqzGi2f.js → crypto-hrnmToQa.js} +48 -11
- package/lib/crypto-hrnmToQa.js.map +1 -0
- package/lib/crypto.cjs +1 -1
- package/lib/crypto.js +1 -1
- package/lib/{device-DQyYUWPl.js → device-BnO26Hlr.js} +90 -34
- package/lib/device-BnO26Hlr.js.map +1 -0
- package/lib/{device-DQ32fSI-.cjs → device-CvgFoib2.cjs} +113 -33
- package/lib/device-CvgFoib2.cjs.map +1 -0
- package/lib/device.cjs +3 -1
- package/lib/device.d.cts +2 -2
- package/lib/device.d.ts +2 -2
- package/lib/device.js +2 -2
- package/lib/engine.cjs +93 -53
- package/lib/engine.cjs.map +1 -1
- package/lib/engine.d.cts +2 -2
- package/lib/engine.d.ts +2 -2
- package/lib/engine.js +94 -54
- package/lib/engine.js.map +1 -1
- package/lib/{index-xlQiIxlX.d.ts → index-16zV3onR.d.ts} +1 -1
- package/lib/{index-B3IUJM2r.d.cts → index-BAb2WCcL.d.cts} +25 -14
- package/lib/{index-Doiqe3tk.d.cts → index-CliA8Mh-.d.cts} +1 -1
- package/lib/{index-B1WQdM71.d.ts → index-DQgupTPR.d.ts} +25 -14
- package/lib/index.cjs +1 -1
- package/lib/index.cjs.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/onboarding.cjs +6 -2
- package/lib/onboarding.cjs.map +1 -1
- package/lib/onboarding.d.cts +2 -2
- package/lib/onboarding.d.ts +2 -2
- package/lib/onboarding.js +6 -2
- package/lib/onboarding.js.map +1 -1
- package/lib/{types-DzZQZPXO.d.cts → types-bfqkmpgo.d.cts} +2 -1
- package/lib/{types-DqjcDy4H.d.ts → types-tRODcWIL.d.ts} +2 -1
- package/package.json +4 -5
- package/lib/crypto-BTN8FS8v.cjs.map +0 -1
- package/lib/crypto-BcqzGi2f.js.map +0 -1
- package/lib/device-DQ32fSI-.cjs.map +0 -1
- package/lib/device-DQyYUWPl.js.map +0 -1
|
@@ -2,6 +2,17 @@ import { t as Logger } from "./logger-DHtgWA66.js";
|
|
|
2
2
|
import { HsmCertificate, PsdAuthChallengeResponse, PsdPairingData, PubKey, RefreshPskData } from "@ledgerhq/revault-api";
|
|
3
3
|
import Transport from "@ledgerhq/hw-transport";
|
|
4
4
|
import { Observable } from "rxjs";
|
|
5
|
+
//#region src/device/abort.d.ts
|
|
6
|
+
/** Error returned when the application aborts a device operation. */
|
|
7
|
+
declare class DeviceOperationAbortedError extends Error {
|
|
8
|
+
constructor();
|
|
9
|
+
}
|
|
10
|
+
type DeviceOperationOptions = {
|
|
11
|
+
/** Stops this operation when the application no longer owns the interaction. */
|
|
12
|
+
signal?: AbortSignal;
|
|
13
|
+
};
|
|
14
|
+
declare const isDeviceOperationAbortedError: (error: unknown) => error is DeviceOperationAbortedError;
|
|
15
|
+
//#endregion
|
|
5
16
|
//#region src/device/types.d.ts
|
|
6
17
|
/**
|
|
7
18
|
* Tri-state result of {@link Device.hasPairing}. Replaces the legacy boolean so callers can
|
|
@@ -36,7 +47,7 @@ type Device = {
|
|
|
36
47
|
/**
|
|
37
48
|
* Get device attestation
|
|
38
49
|
*/
|
|
39
|
-
getAttestation: () => Promise<{
|
|
50
|
+
getAttestation: (opts?: DeviceOperationOptions) => Promise<{
|
|
40
51
|
attestation: {
|
|
41
52
|
codeHash: string;
|
|
42
53
|
attestationPub: string;
|
|
@@ -47,7 +58,7 @@ type Device = {
|
|
|
47
58
|
/**
|
|
48
59
|
* Get device confidentiality key
|
|
49
60
|
*/
|
|
50
|
-
getConfidentialityKey: () => Promise<{
|
|
61
|
+
getConfidentialityKey: (opts?: DeviceOperationOptions) => Promise<{
|
|
51
62
|
confidentialityKeyCurve25519: string;
|
|
52
63
|
confidentialityKeySignature: string;
|
|
53
64
|
}>;
|
|
@@ -85,11 +96,11 @@ type Device = {
|
|
|
85
96
|
* sub-chain only (skip the full pairing flow).
|
|
86
97
|
* - `"NO_PAIRING"` — no pairing at all; run the full pairing chain followed by a refresh.
|
|
87
98
|
*/
|
|
88
|
-
hasPairing: () => Promise<PairingStatus>;
|
|
99
|
+
hasPairing: (opts?: DeviceOperationOptions) => Promise<PairingStatus>;
|
|
89
100
|
/**
|
|
90
101
|
* Initialize pairing handshake
|
|
91
102
|
*/
|
|
92
|
-
initPairingHandshake: () => Promise<{
|
|
103
|
+
initPairingHandshake: (opts?: DeviceOperationOptions) => Promise<{
|
|
93
104
|
pubKey: string;
|
|
94
105
|
signature: string;
|
|
95
106
|
}>;
|
|
@@ -127,7 +138,7 @@ type Device = {
|
|
|
127
138
|
*/
|
|
128
139
|
setPairing: (opts: {
|
|
129
140
|
pairing: PsdPairingData;
|
|
130
|
-
}) => Promise<void>;
|
|
141
|
+
} & DeviceOperationOptions) => Promise<void>;
|
|
131
142
|
/**
|
|
132
143
|
* Sign the PSK-refresh authentication challenge (`SIGN_REFRESH_PSK_AUTH`, INS `0x55`).
|
|
133
144
|
*
|
|
@@ -143,7 +154,7 @@ type Device = {
|
|
|
143
154
|
*/
|
|
144
155
|
signRefreshPskAuth: (opts: {
|
|
145
156
|
ephemeralKey: string;
|
|
146
|
-
}) => Promise<string>;
|
|
157
|
+
} & DeviceOperationOptions) => Promise<string>;
|
|
147
158
|
/**
|
|
148
159
|
* Finalize a PSK refresh (`FINALIZE_PSK_REFRESH`, INS `0x53`).
|
|
149
160
|
*
|
|
@@ -151,7 +162,7 @@ type Device = {
|
|
|
151
162
|
* stores the re-delivered (static) PSK in NVM. Throws when the device already holds a different
|
|
152
163
|
* PSK for the partition (`SW_PSK_MISMATCH`, `0x6067`).
|
|
153
164
|
*/
|
|
154
|
-
finalizePskRefresh: (opts: RefreshPskData) => Promise<void>;
|
|
165
|
+
finalizePskRefresh: (opts: RefreshPskData & DeviceOperationOptions) => Promise<void>;
|
|
155
166
|
/**
|
|
156
167
|
* Start KK pattern (related to noise channel)
|
|
157
168
|
*/
|
|
@@ -170,20 +181,20 @@ type Device = {
|
|
|
170
181
|
handshake: string;
|
|
171
182
|
handshakeAttestation: HsmCertificate;
|
|
172
183
|
partitionId: string;
|
|
173
|
-
}) => Promise<void>;
|
|
184
|
+
} & DeviceOperationOptions) => Promise<void>;
|
|
174
185
|
/**
|
|
175
186
|
* Start a PSK session (Secure channel)
|
|
176
187
|
*/
|
|
177
188
|
startPskSession(opts: {
|
|
178
189
|
nonce: string;
|
|
179
190
|
partitionId: string;
|
|
180
|
-
}): Promise<void>;
|
|
191
|
+
} & DeviceOperationOptions): Promise<void>;
|
|
181
192
|
/**
|
|
182
193
|
* Approve with device
|
|
183
194
|
*/
|
|
184
195
|
validateVaultOperation: (opts: {
|
|
185
196
|
actions: string[];
|
|
186
|
-
}) => Promise<string>;
|
|
197
|
+
} & DeviceOperationOptions) => Promise<string>;
|
|
187
198
|
/**
|
|
188
199
|
* Send arbitrary APDU
|
|
189
200
|
* apduCommand in HEX string format
|
|
@@ -193,21 +204,21 @@ type Device = {
|
|
|
193
204
|
* Get app version
|
|
194
205
|
*
|
|
195
206
|
*/
|
|
196
|
-
getVersion: () => Promise<string>;
|
|
207
|
+
getVersion: (opts?: DeviceOperationOptions) => Promise<string>;
|
|
197
208
|
/**
|
|
198
209
|
* Poll device until it's plugged-on
|
|
199
210
|
*
|
|
200
211
|
*/
|
|
201
212
|
poll: (opts?: {
|
|
202
213
|
retryOnError?: (err: Error) => boolean;
|
|
203
|
-
}) => Promise<{
|
|
214
|
+
} & DeviceOperationOptions) => Promise<{
|
|
204
215
|
isAppOpened: boolean;
|
|
205
216
|
}>;
|
|
206
217
|
/**
|
|
207
218
|
* Returned when app is opened
|
|
208
219
|
* appName in string format
|
|
209
220
|
*/
|
|
210
|
-
pollApp: (name: string) => Promise<string>;
|
|
221
|
+
pollApp: (name: string, opts?: DeviceOperationOptions) => Promise<string>;
|
|
211
222
|
};
|
|
212
223
|
//#endregion
|
|
213
224
|
//#region src/device/api-device.d.ts
|
|
@@ -278,4 +289,4 @@ declare const isLockedDeviceError: (error: unknown) => boolean;
|
|
|
278
289
|
declare const isPskMissingError: (error: unknown) => boolean;
|
|
279
290
|
declare const isPskMismatchError: (error: unknown) => boolean;
|
|
280
291
|
//#endregion
|
|
281
|
-
export { isPskMissingError as a, ApiDevice as c, PairingStatus as d, isPskMismatchError as i, createApiDevice as l, isDeviceCancelError as n, isTransportStatusError as o, isLockedDeviceError as r, registerTransportModule as s, isCantOpenDeviceError as t, Device as u };
|
|
292
|
+
export { isPskMissingError as a, ApiDevice as c, PairingStatus as d, DeviceOperationAbortedError as f, isPskMismatchError as i, createApiDevice as l, isDeviceOperationAbortedError as m, isDeviceCancelError as n, isTransportStatusError as o, DeviceOperationOptions as p, isLockedDeviceError as r, registerTransportModule as s, isCantOpenDeviceError as t, Device as u };
|
package/lib/index.cjs
CHANGED
|
@@ -16,9 +16,9 @@ async function waitForRequestChallengesReady(client, request) {
|
|
|
16
16
|
(0, invariant.default)(request.inflight !== void 0, "Request in INITIAL state should be inflight");
|
|
17
17
|
const deadline = Date.now() + POLL_TIMEOUT_MS;
|
|
18
18
|
while (Date.now() < deadline) {
|
|
19
|
-
await wait(POLL_INTERVAL_MS);
|
|
20
19
|
const updated = await client.requests.findById.query({ id: request.id });
|
|
21
20
|
if (updated.state !== "INITIAL") return updated;
|
|
21
|
+
await wait(POLL_INTERVAL_MS);
|
|
22
22
|
}
|
|
23
23
|
throw new Error(`Timed out waiting for request ${request.id} challenges to be ready`);
|
|
24
24
|
}
|
package/lib/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":[],"sources":["../src/escape-hatch.ts"],"sourcesContent":["import type { VaultRequestResponse } from \"@ledgerhq/revault-api\";\nimport invariant from \"invariant\";\n\nimport type { RevaultApiTRPCClient } from \"./trpc\";\n\nconst POLL_INTERVAL_MS = 250;\nconst POLL_TIMEOUT_MS = 60_000;\n\nconst wait = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\n/**\n * Busy-polls until a request leaves the INITIAL state (i.e. challenges are generated).\n *\n * **Escape hatch** — prefer server-sent events or webhooks where available.\n */\nexport async function waitForRequestChallengesReady(\n client: RevaultApiTRPCClient,\n request: VaultRequestResponse,\n): Promise<VaultRequestResponse> {\n if (request.state !== \"INITIAL\") {\n return request;\n }\n\n invariant(request.inflight !== undefined, \"Request in INITIAL state should be inflight\");\n\n const deadline = Date.now() + POLL_TIMEOUT_MS;\n\n while (Date.now() < deadline) {\n
|
|
1
|
+
{"version":3,"file":"index.cjs","names":[],"sources":["../src/escape-hatch.ts"],"sourcesContent":["import type { VaultRequestResponse } from \"@ledgerhq/revault-api\";\nimport invariant from \"invariant\";\n\nimport type { RevaultApiTRPCClient } from \"./trpc\";\n\nconst POLL_INTERVAL_MS = 250;\nconst POLL_TIMEOUT_MS = 60_000;\n\nconst wait = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\n/**\n * Busy-polls until a request leaves the INITIAL state (i.e. challenges are generated).\n *\n * **Escape hatch** — prefer server-sent events or webhooks where available.\n */\nexport async function waitForRequestChallengesReady(\n client: RevaultApiTRPCClient,\n request: VaultRequestResponse,\n): Promise<VaultRequestResponse> {\n if (request.state !== \"INITIAL\") {\n return request;\n }\n\n invariant(request.inflight !== undefined, \"Request in INITIAL state should be inflight\");\n\n const deadline = Date.now() + POLL_TIMEOUT_MS;\n\n while (Date.now() < deadline) {\n const updated = await client.requests.findById.query({ id: request.id });\n if (updated.state !== \"INITIAL\") {\n return updated;\n }\n await wait(POLL_INTERVAL_MS);\n }\n\n throw new Error(`Timed out waiting for request ${request.id} challenges to be ready`);\n}\n"],"mappings":";;;;;AAKA,MAAM,mBAAmB;AACzB,MAAM,kBAAkB;AAExB,MAAM,QAAQ,OAA8B,IAAI,SAAS,YAAY,WAAW,SAAS,EAAE,CAAC;;;;;;AAO5F,eAAsB,8BACpB,QACA,SAC+B;CAC/B,IAAI,QAAQ,UAAU,WACpB,OAAO;CAGT,CAAA,GAAA,UAAA,QAAA,CAAU,QAAQ,aAAa,KAAA,GAAW,6CAA6C;CAEvF,MAAM,WAAW,KAAK,IAAI,IAAI;CAE9B,OAAO,KAAK,IAAI,IAAI,UAAU;EAC5B,MAAM,UAAU,MAAM,OAAO,SAAS,SAAS,MAAM,EAAE,IAAI,QAAQ,GAAG,CAAC;EACvE,IAAI,QAAQ,UAAU,WACpB,OAAO;EAET,MAAM,KAAK,gBAAgB;CAC7B;CAEA,MAAM,IAAI,MAAM,iCAAiC,QAAQ,GAAG,wBAAwB;AACtF"}
|
package/lib/index.js
CHANGED
|
@@ -13,9 +13,9 @@ async function waitForRequestChallengesReady(client, request) {
|
|
|
13
13
|
invariant(request.inflight !== void 0, "Request in INITIAL state should be inflight");
|
|
14
14
|
const deadline = Date.now() + POLL_TIMEOUT_MS;
|
|
15
15
|
while (Date.now() < deadline) {
|
|
16
|
-
await wait(POLL_INTERVAL_MS);
|
|
17
16
|
const updated = await client.requests.findById.query({ id: request.id });
|
|
18
17
|
if (updated.state !== "INITIAL") return updated;
|
|
18
|
+
await wait(POLL_INTERVAL_MS);
|
|
19
19
|
}
|
|
20
20
|
throw new Error(`Timed out waiting for request ${request.id} challenges to be ready`);
|
|
21
21
|
}
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/escape-hatch.ts"],"sourcesContent":["import type { VaultRequestResponse } from \"@ledgerhq/revault-api\";\nimport invariant from \"invariant\";\n\nimport type { RevaultApiTRPCClient } from \"./trpc\";\n\nconst POLL_INTERVAL_MS = 250;\nconst POLL_TIMEOUT_MS = 60_000;\n\nconst wait = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\n/**\n * Busy-polls until a request leaves the INITIAL state (i.e. challenges are generated).\n *\n * **Escape hatch** — prefer server-sent events or webhooks where available.\n */\nexport async function waitForRequestChallengesReady(\n client: RevaultApiTRPCClient,\n request: VaultRequestResponse,\n): Promise<VaultRequestResponse> {\n if (request.state !== \"INITIAL\") {\n return request;\n }\n\n invariant(request.inflight !== undefined, \"Request in INITIAL state should be inflight\");\n\n const deadline = Date.now() + POLL_TIMEOUT_MS;\n\n while (Date.now() < deadline) {\n
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/escape-hatch.ts"],"sourcesContent":["import type { VaultRequestResponse } from \"@ledgerhq/revault-api\";\nimport invariant from \"invariant\";\n\nimport type { RevaultApiTRPCClient } from \"./trpc\";\n\nconst POLL_INTERVAL_MS = 250;\nconst POLL_TIMEOUT_MS = 60_000;\n\nconst wait = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\n/**\n * Busy-polls until a request leaves the INITIAL state (i.e. challenges are generated).\n *\n * **Escape hatch** — prefer server-sent events or webhooks where available.\n */\nexport async function waitForRequestChallengesReady(\n client: RevaultApiTRPCClient,\n request: VaultRequestResponse,\n): Promise<VaultRequestResponse> {\n if (request.state !== \"INITIAL\") {\n return request;\n }\n\n invariant(request.inflight !== undefined, \"Request in INITIAL state should be inflight\");\n\n const deadline = Date.now() + POLL_TIMEOUT_MS;\n\n while (Date.now() < deadline) {\n const updated = await client.requests.findById.query({ id: request.id });\n if (updated.state !== \"INITIAL\") {\n return updated;\n }\n await wait(POLL_INTERVAL_MS);\n }\n\n throw new Error(`Timed out waiting for request ${request.id} challenges to be ready`);\n}\n"],"mappings":";;AAKA,MAAM,mBAAmB;AACzB,MAAM,kBAAkB;AAExB,MAAM,QAAQ,OAA8B,IAAI,SAAS,YAAY,WAAW,SAAS,EAAE,CAAC;;;;;;AAO5F,eAAsB,8BACpB,QACA,SAC+B;CAC/B,IAAI,QAAQ,UAAU,WACpB,OAAO;CAGT,UAAU,QAAQ,aAAa,KAAA,GAAW,6CAA6C;CAEvF,MAAM,WAAW,KAAK,IAAI,IAAI;CAE9B,OAAO,KAAK,IAAI,IAAI,UAAU;EAC5B,MAAM,UAAU,MAAM,OAAO,SAAS,SAAS,MAAM,EAAE,IAAI,QAAQ,GAAG,CAAC;EACvE,IAAI,QAAQ,UAAU,WACpB,OAAO;EAET,MAAM,KAAK,gBAAgB;CAC7B;CAEA,MAAM,IAAI,MAAM,iCAAiC,QAAQ,GAAG,wBAAwB;AACtF"}
|
package/lib/onboarding.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_rolldown_runtime = require("./rolldown-runtime-y5ARvAq5.cjs");
|
|
3
|
-
const require_crypto = require("./crypto-
|
|
3
|
+
const require_crypto = require("./crypto-CKLQSwr3.cjs");
|
|
4
4
|
let invariant = require("invariant");
|
|
5
5
|
invariant = require_rolldown_runtime.__toESM(invariant, 1);
|
|
6
6
|
let ts_pattern = require("ts-pattern");
|
|
@@ -226,7 +226,11 @@ const STEPS = {
|
|
|
226
226
|
/**
|
|
227
227
|
* Workspace initialization
|
|
228
228
|
*/
|
|
229
|
-
PENDING_WORKSPACE_INITIALIZATION: async ({ state, engine }) =>
|
|
229
|
+
PENDING_WORKSPACE_INITIALIZATION: async ({ state, engine }, logger) => {
|
|
230
|
+
const result = await engine.client.onboarding.initializeWorkspace.mutate({ onboardingId: state.id });
|
|
231
|
+
logger.info("Workspace initialized");
|
|
232
|
+
return result;
|
|
233
|
+
}
|
|
230
234
|
};
|
|
231
235
|
async function onboard(opts, logger) {
|
|
232
236
|
const { engine, debugAuthToken, signerSeed, untilStep } = opts;
|
package/lib/onboarding.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"onboarding.cjs","names":["match","getMasterSeed"],"sources":["../src/onboarding.ts"],"sourcesContent":["import type {\n ClaimedRole,\n HsmHostingMode,\n OnboardingFullStateResponse,\n OnboardingStep,\n} from \"@ledgerhq/revault-api\";\nimport invariant from \"invariant\";\nimport { match } from \"ts-pattern\";\n\nimport { getMasterSeed } from \"@/crypto\";\nimport type { Logger } from \"@/logger\";\n\nimport type { Engine, WithOnboarding } from \"./engine/types\";\n\ntype StepAction = (\n options: {\n engine: Engine<WithOnboarding>;\n state: OnboardingFullStateResponse;\n debugAuthToken?: string;\n signerSeed?: string;\n },\n logger: Logger,\n) => Promise<OnboardingFullStateResponse>;\n\nconst roleLabels: Record<ClaimedRole, string> = {\n WRAPPING_KEY_OWNER: \"Wrapping Key\",\n MASTER_ADMIN: \"Admin\",\n SHARED_OWNER: \"Shared Owner\",\n};\n\nconst devices: { index: number; role: ClaimedRole; name: string }[] = [\n { index: 1, role: \"WRAPPING_KEY_OWNER\", name: `${roleLabels.WRAPPING_KEY_OWNER} 1` },\n { index: 2, role: \"WRAPPING_KEY_OWNER\", name: `${roleLabels.WRAPPING_KEY_OWNER} 2` },\n { index: 3, role: \"WRAPPING_KEY_OWNER\", name: `${roleLabels.WRAPPING_KEY_OWNER} 3` },\n { index: 4, role: \"MASTER_ADMIN\", name: `${roleLabels.MASTER_ADMIN} 1` },\n { index: 5, role: \"MASTER_ADMIN\", name: `${roleLabels.MASTER_ADMIN} 2` },\n { index: 6, role: \"MASTER_ADMIN\", name: `${roleLabels.MASTER_ADMIN} 3` },\n { index: 7, role: \"SHARED_OWNER\", name: `${roleLabels.SHARED_OWNER} 1` },\n { index: 8, role: \"SHARED_OWNER\", name: `${roleLabels.SHARED_OWNER} 2` },\n { index: 9, role: \"SHARED_OWNER\", name: `${roleLabels.SHARED_OWNER} 3` },\n];\n\nconst deviceNameToIndex = (name: string): number => {\n const index = devices.find((d) => d.name === name)?.index;\n invariant(index !== undefined, `Unknown device ${name}`);\n return index;\n};\n\nconst checkHsmHostingMode = (\n state: OnboardingFullStateResponse,\n expectedMode: HsmHostingMode,\n): void => {\n /* v8 ignore next -- @preserve */\n if (state.hsmHostingMode !== expectedMode) {\n throw new Error(`HSM hosting mode should be ${expectedMode} but is ${state.hsmHostingMode}`);\n }\n};\n\n/* v8 ignore next -- @preserve */\nconst checkExternalSigners = (\n state: OnboardingFullStateResponse,\n debugAuthToken: string | undefined,\n): void => {\n const errorMessage = match(state.hsmHostingMode)\n .with(\"HOSTED\", () => null)\n .with(\"ON_PREM\", () => (debugAuthToken ? null : \"On-premises HSM requires a debug auth token\"))\n .exhaustive();\n if (errorMessage !== null) {\n throw new Error(errorMessage);\n }\n};\n\nexport const STEPS = {\n /**\n * Devices claiming\n */\n PENDING_DEVICE_CLAIMS: async ({ state, engine }, logger) => {\n const promises: Promise<void>[] = [];\n for (const device of devices) {\n if (state.hsmHostingMode === \"ON_PREM\" && device.role === \"SHARED_OWNER\") {\n continue;\n }\n if (state.skipWrappingKey && device.role === \"WRAPPING_KEY_OWNER\") {\n continue;\n }\n /* v8 ignore else -- @preserve */\n if (\n state.claimedDevices.find(\n /* v8 ignore next -- @preserve */\n (c) => c.deviceName === device.name,\n ) === undefined\n ) {\n const promise = engine\n .withDeviceIndex(device.index)\n .claimDevice({ role: device.role, deviceName: device.name })\n .then(() => logger.info(`Claimed ${device.name}`));\n promises.push(promise);\n }\n }\n await Promise.all(promises);\n return engine.client.onboarding.commitDeviceClaims.mutate({ onboardingId: state.id });\n },\n\n /**\n * Wrapping Key provisioning\n */\n PENDING_WRAPPING_KEY_PROVISIONING: async ({ state, engine }, logger) => {\n const { id: onboardingId } = state;\n state = await engine.client.onboarding.startWrappingKeyProvisioning.mutate({ onboardingId });\n const wrappingKey = state.wrappingKey!;\n const toCollect = state.claimedDevices\n .filter((claimed) => {\n if (claimed.role !== \"WRAPPING_KEY_OWNER\") return false;\n const inFragment = !!state.wrappingKey?.fragments.find(\n /* v8 ignore next -- @preserve */\n (f) => f.pubKey === claimed.pubKey,\n );\n return !inFragment;\n })\n .map((c) => {\n const index = deviceNameToIndex(c.deviceName);\n return index;\n });\n await Promise.all(\n toCollect.map((index) =>\n engine\n .withDeviceIndex(index)\n .collectWrappingKeyFragment(wrappingKey)\n .then(() => logger.info(`Collected Wrapping Key ${index}`)),\n ),\n );\n return engine.client.onboarding.commitWrappingKey.mutate({ onboardingId });\n },\n\n /**\n * Init Master Admins registration\n */\n PENDING_MASTER_ADMINS_REGISTRATION_INIT: async ({ engine, state }) =>\n engine.client.onboarding.startMasterAdminsRegistration.mutate({ onboardingId: state.id }),\n\n /**\n * Master Admins registration\n */\n PENDING_MASTER_ADMINS_REGISTRATION: async ({ state, engine }, logger) => {\n const { id: onboardingId } = state;\n const toRegister = state.claimedDevices.filter((claimed) => {\n if (claimed.role !== \"MASTER_ADMIN\") return false;\n const hasRegistered = !!state.masterAdmins.find(\n /* v8 ignore next -- @preserve */\n (a) => a.pubKey === claimed.pubKey,\n );\n return !hasRegistered;\n });\n await Promise.all(\n toRegister.map(async ({ deviceName: name }) => {\n const index = deviceNameToIndex(name);\n await engine.withDeviceIndex(index).registerDevice({ role: \"ADMIN\", name });\n logger.info(`Registered ${name}`);\n }),\n );\n return engine.client.onboarding.createMasterAdminGroup.mutate({ onboardingId });\n },\n\n /**\n * Init Shared Owners registration\n */\n PENDING_SHARED_OWNERS_REGISTRATION_INIT: async ({ engine, state }) => {\n checkHsmHostingMode(state, \"HOSTED\");\n return engine.client.onboarding.startSharedOwnersRegistration.mutate({\n onboardingId: state.id,\n });\n },\n\n /**\n * Shared Owners registration\n */\n PENDING_SHARED_OWNERS_REGISTRATION: async ({ state, engine }, logger) => {\n checkHsmHostingMode(state, \"HOSTED\");\n const { id: onboardingId } = state;\n const toRegister = state.claimedDevices.filter((claimed) => {\n if (claimed.role !== \"SHARED_OWNER\") return false;\n const hasRegistered = !!state.sharedOwners.find(\n /* v8 ignore next -- @preserve */ (a) => a.pubKey === claimed.pubKey,\n );\n return !hasRegistered;\n });\n await Promise.all(\n toRegister.map(async ({ deviceName: name }) => {\n const index = deviceNameToIndex(name);\n await engine.withDeviceIndex(index).registerDevice({ role: \"SHARED_OWNER\", name });\n logger.info(`Registered ${name}`);\n }),\n );\n return engine.client.onboarding.commitSharedOwnersRegistration.mutate({ onboardingId });\n },\n\n /**\n * Review by master admins\n */\n PENDING_REVIEW_BY_MASTER_ADMINS: async ({ state, engine }, logger) => {\n const { id: onboardingId } = state;\n state = await engine.client.onboarding.startReviewByMasterAdmins.mutate({ onboardingId });\n const toCollect = state.masterAdmins.filter((admin) => !admin.review?.signature);\n await Promise.all(\n toCollect.map(async (admin) => {\n const index = deviceNameToIndex(admin.name);\n const challenge = admin.review?.challenge;\n await engine.withDeviceIndex(index).reviewSharedOwner(challenge!);\n logger.info(`Approved with ${admin.name}`);\n }),\n );\n return engine.client.onboarding.commitReviewByMasterAdmins.mutate({ onboardingId });\n },\n\n PENDING_EXTERNAL_SIGNERS_REGISTRATION: async (\n { state, engine, debugAuthToken, signerSeed },\n logger,\n ) => {\n checkHsmHostingMode(state, \"ON_PREM\");\n const { id: onboardingId } = state;\n if (debugAuthToken) {\n const debugClient = engine.createClient({ debugAuthToken });\n const seed =\n signerSeed ?? Buffer.from(await getMasterSeed(engine.__options.salt)).toString(\"base64\");\n await debugClient.debug.insertExternalSignerSeed.mutate({\n workspaceName: state.workspaceName,\n seed,\n });\n logger.info(\"Inserted external signer seed\");\n }\n state = await engine.client.onboarding.startExternalSignersRegistration.mutate({\n onboardingId,\n });\n const toCollect = state.masterAdmins.filter(\n (admin) => !admin.reviewOfExternalSigners?.signature,\n );\n await Promise.all(\n toCollect.map(async (admin) => {\n const index = deviceNameToIndex(admin.name);\n const challenge = admin.reviewOfExternalSigners?.challenge;\n await engine.withDeviceIndex(index).reviewExternalSigners(challenge!); // same as review for shared owner, but with different challenge\n logger.info(`Approved with ${admin.name}`);\n }),\n );\n return engine.client.onboarding.commitExternalSignersRegistration.mutate({ onboardingId });\n },\n\n /**\n * Seed provisioning\n */\n PENDING_SEED_PROVISIONING: async ({ state, engine }, logger) => {\n checkHsmHostingMode(state, \"HOSTED\");\n const { id: onboardingId } = state;\n state = await engine.client.onboarding.startSeedProvisioning.mutate({ onboardingId });\n const toCollect = state.sharedOwners.filter((so) => !so.review?.seedFragment);\n await Promise.all(\n toCollect.map(async (so) => {\n const index = deviceNameToIndex(so.name);\n const challenge = so.review?.seedChallenge;\n await engine.withDeviceIndex(index).collectSeedFragment(challenge!);\n logger.info(`Collected fragment for ${so.name}`);\n }),\n );\n return engine.client.onboarding.commitSeedProvisioning.mutate({ onboardingId });\n },\n\n /**\n * Workspace initialization\n */\n PENDING_WORKSPACE_INITIALIZATION: async ({ state, engine }) =>\n engine.client.onboarding.initializeWorkspace.mutate({ onboardingId: state.id }),\n} as const satisfies Record<Exclude<OnboardingStep, \"COMPLETED\">, StepAction>;\n\nexport async function onboard(\n opts: {\n engine: Engine<WithOnboarding>;\n debugAuthToken?: string;\n signerSeed?: string;\n untilStep?: OnboardingStep;\n },\n logger: Logger,\n): Promise<void> {\n const { engine, debugAuthToken, signerSeed, untilStep } = opts;\n\n const { __onboardingId } = engine;\n logger.info(`Joining onboarding ${__onboardingId}`);\n let state = await engine.client.onboarding.getOnboarding.query({\n onboardingId: __onboardingId,\n });\n\n checkExternalSigners(state, debugAuthToken);\n\n while (state.step !== \"COMPLETED\") {\n if (untilStep && state.step === untilStep) {\n logger.info(\"Skipping the rest of the onboarding\");\n break;\n }\n const step = STEPS[state.step];\n logger.info(step.name);\n state = await step({ engine, state, debugAuthToken, signerSeed }, logger);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"onboarding.cjs","names":["match","getMasterSeed"],"sources":["../src/onboarding.ts"],"sourcesContent":["import type {\n ClaimedRole,\n HsmHostingMode,\n OnboardingFullStateResponse,\n OnboardingStep,\n} from \"@ledgerhq/revault-api\";\nimport invariant from \"invariant\";\nimport { match } from \"ts-pattern\";\n\nimport { getMasterSeed } from \"@/crypto\";\nimport type { Logger } from \"@/logger\";\n\nimport type { Engine, WithOnboarding } from \"./engine/types\";\n\ntype StepAction = (\n options: {\n engine: Engine<WithOnboarding>;\n state: OnboardingFullStateResponse;\n debugAuthToken?: string;\n signerSeed?: string;\n },\n logger: Logger,\n) => Promise<OnboardingFullStateResponse>;\n\nconst roleLabels: Record<ClaimedRole, string> = {\n WRAPPING_KEY_OWNER: \"Wrapping Key\",\n MASTER_ADMIN: \"Admin\",\n SHARED_OWNER: \"Shared Owner\",\n};\n\nconst devices: { index: number; role: ClaimedRole; name: string }[] = [\n { index: 1, role: \"WRAPPING_KEY_OWNER\", name: `${roleLabels.WRAPPING_KEY_OWNER} 1` },\n { index: 2, role: \"WRAPPING_KEY_OWNER\", name: `${roleLabels.WRAPPING_KEY_OWNER} 2` },\n { index: 3, role: \"WRAPPING_KEY_OWNER\", name: `${roleLabels.WRAPPING_KEY_OWNER} 3` },\n { index: 4, role: \"MASTER_ADMIN\", name: `${roleLabels.MASTER_ADMIN} 1` },\n { index: 5, role: \"MASTER_ADMIN\", name: `${roleLabels.MASTER_ADMIN} 2` },\n { index: 6, role: \"MASTER_ADMIN\", name: `${roleLabels.MASTER_ADMIN} 3` },\n { index: 7, role: \"SHARED_OWNER\", name: `${roleLabels.SHARED_OWNER} 1` },\n { index: 8, role: \"SHARED_OWNER\", name: `${roleLabels.SHARED_OWNER} 2` },\n { index: 9, role: \"SHARED_OWNER\", name: `${roleLabels.SHARED_OWNER} 3` },\n];\n\nconst deviceNameToIndex = (name: string): number => {\n const index = devices.find((d) => d.name === name)?.index;\n invariant(index !== undefined, `Unknown device ${name}`);\n return index;\n};\n\nconst checkHsmHostingMode = (\n state: OnboardingFullStateResponse,\n expectedMode: HsmHostingMode,\n): void => {\n /* v8 ignore next -- @preserve */\n if (state.hsmHostingMode !== expectedMode) {\n throw new Error(`HSM hosting mode should be ${expectedMode} but is ${state.hsmHostingMode}`);\n }\n};\n\n/* v8 ignore next -- @preserve */\nconst checkExternalSigners = (\n state: OnboardingFullStateResponse,\n debugAuthToken: string | undefined,\n): void => {\n const errorMessage = match(state.hsmHostingMode)\n .with(\"HOSTED\", () => null)\n .with(\"ON_PREM\", () => (debugAuthToken ? null : \"On-premises HSM requires a debug auth token\"))\n .exhaustive();\n if (errorMessage !== null) {\n throw new Error(errorMessage);\n }\n};\n\nexport const STEPS = {\n /**\n * Devices claiming\n */\n PENDING_DEVICE_CLAIMS: async ({ state, engine }, logger) => {\n const promises: Promise<void>[] = [];\n for (const device of devices) {\n if (state.hsmHostingMode === \"ON_PREM\" && device.role === \"SHARED_OWNER\") {\n continue;\n }\n if (state.skipWrappingKey && device.role === \"WRAPPING_KEY_OWNER\") {\n continue;\n }\n /* v8 ignore else -- @preserve */\n if (\n state.claimedDevices.find(\n /* v8 ignore next -- @preserve */\n (c) => c.deviceName === device.name,\n ) === undefined\n ) {\n const promise = engine\n .withDeviceIndex(device.index)\n .claimDevice({ role: device.role, deviceName: device.name })\n .then(() => logger.info(`Claimed ${device.name}`));\n promises.push(promise);\n }\n }\n await Promise.all(promises);\n return engine.client.onboarding.commitDeviceClaims.mutate({ onboardingId: state.id });\n },\n\n /**\n * Wrapping Key provisioning\n */\n PENDING_WRAPPING_KEY_PROVISIONING: async ({ state, engine }, logger) => {\n const { id: onboardingId } = state;\n state = await engine.client.onboarding.startWrappingKeyProvisioning.mutate({ onboardingId });\n const wrappingKey = state.wrappingKey!;\n const toCollect = state.claimedDevices\n .filter((claimed) => {\n if (claimed.role !== \"WRAPPING_KEY_OWNER\") return false;\n const inFragment = !!state.wrappingKey?.fragments.find(\n /* v8 ignore next -- @preserve */\n (f) => f.pubKey === claimed.pubKey,\n );\n return !inFragment;\n })\n .map((c) => {\n const index = deviceNameToIndex(c.deviceName);\n return index;\n });\n await Promise.all(\n toCollect.map((index) =>\n engine\n .withDeviceIndex(index)\n .collectWrappingKeyFragment(wrappingKey)\n .then(() => logger.info(`Collected Wrapping Key ${index}`)),\n ),\n );\n return engine.client.onboarding.commitWrappingKey.mutate({ onboardingId });\n },\n\n /**\n * Init Master Admins registration\n */\n PENDING_MASTER_ADMINS_REGISTRATION_INIT: async ({ engine, state }) =>\n engine.client.onboarding.startMasterAdminsRegistration.mutate({ onboardingId: state.id }),\n\n /**\n * Master Admins registration\n */\n PENDING_MASTER_ADMINS_REGISTRATION: async ({ state, engine }, logger) => {\n const { id: onboardingId } = state;\n const toRegister = state.claimedDevices.filter((claimed) => {\n if (claimed.role !== \"MASTER_ADMIN\") return false;\n const hasRegistered = !!state.masterAdmins.find(\n /* v8 ignore next -- @preserve */\n (a) => a.pubKey === claimed.pubKey,\n );\n return !hasRegistered;\n });\n await Promise.all(\n toRegister.map(async ({ deviceName: name }) => {\n const index = deviceNameToIndex(name);\n await engine.withDeviceIndex(index).registerDevice({ role: \"ADMIN\", name });\n logger.info(`Registered ${name}`);\n }),\n );\n return engine.client.onboarding.createMasterAdminGroup.mutate({ onboardingId });\n },\n\n /**\n * Init Shared Owners registration\n */\n PENDING_SHARED_OWNERS_REGISTRATION_INIT: async ({ engine, state }) => {\n checkHsmHostingMode(state, \"HOSTED\");\n return engine.client.onboarding.startSharedOwnersRegistration.mutate({\n onboardingId: state.id,\n });\n },\n\n /**\n * Shared Owners registration\n */\n PENDING_SHARED_OWNERS_REGISTRATION: async ({ state, engine }, logger) => {\n checkHsmHostingMode(state, \"HOSTED\");\n const { id: onboardingId } = state;\n const toRegister = state.claimedDevices.filter((claimed) => {\n if (claimed.role !== \"SHARED_OWNER\") return false;\n const hasRegistered = !!state.sharedOwners.find(\n /* v8 ignore next -- @preserve */ (a) => a.pubKey === claimed.pubKey,\n );\n return !hasRegistered;\n });\n await Promise.all(\n toRegister.map(async ({ deviceName: name }) => {\n const index = deviceNameToIndex(name);\n await engine.withDeviceIndex(index).registerDevice({ role: \"SHARED_OWNER\", name });\n logger.info(`Registered ${name}`);\n }),\n );\n return engine.client.onboarding.commitSharedOwnersRegistration.mutate({ onboardingId });\n },\n\n /**\n * Review by master admins\n */\n PENDING_REVIEW_BY_MASTER_ADMINS: async ({ state, engine }, logger) => {\n const { id: onboardingId } = state;\n state = await engine.client.onboarding.startReviewByMasterAdmins.mutate({ onboardingId });\n const toCollect = state.masterAdmins.filter((admin) => !admin.review?.signature);\n await Promise.all(\n toCollect.map(async (admin) => {\n const index = deviceNameToIndex(admin.name);\n const challenge = admin.review?.challenge;\n await engine.withDeviceIndex(index).reviewSharedOwner(challenge!);\n logger.info(`Approved with ${admin.name}`);\n }),\n );\n return engine.client.onboarding.commitReviewByMasterAdmins.mutate({ onboardingId });\n },\n\n PENDING_EXTERNAL_SIGNERS_REGISTRATION: async (\n { state, engine, debugAuthToken, signerSeed },\n logger,\n ) => {\n checkHsmHostingMode(state, \"ON_PREM\");\n const { id: onboardingId } = state;\n if (debugAuthToken) {\n const debugClient = engine.createClient({ debugAuthToken });\n const seed =\n signerSeed ?? Buffer.from(await getMasterSeed(engine.__options.salt)).toString(\"base64\");\n await debugClient.debug.insertExternalSignerSeed.mutate({\n workspaceName: state.workspaceName,\n seed,\n });\n logger.info(\"Inserted external signer seed\");\n }\n state = await engine.client.onboarding.startExternalSignersRegistration.mutate({\n onboardingId,\n });\n const toCollect = state.masterAdmins.filter(\n (admin) => !admin.reviewOfExternalSigners?.signature,\n );\n await Promise.all(\n toCollect.map(async (admin) => {\n const index = deviceNameToIndex(admin.name);\n const challenge = admin.reviewOfExternalSigners?.challenge;\n await engine.withDeviceIndex(index).reviewExternalSigners(challenge!); // same as review for shared owner, but with different challenge\n logger.info(`Approved with ${admin.name}`);\n }),\n );\n return engine.client.onboarding.commitExternalSignersRegistration.mutate({ onboardingId });\n },\n\n /**\n * Seed provisioning\n */\n PENDING_SEED_PROVISIONING: async ({ state, engine }, logger) => {\n checkHsmHostingMode(state, \"HOSTED\");\n const { id: onboardingId } = state;\n state = await engine.client.onboarding.startSeedProvisioning.mutate({ onboardingId });\n const toCollect = state.sharedOwners.filter((so) => !so.review?.seedFragment);\n await Promise.all(\n toCollect.map(async (so) => {\n const index = deviceNameToIndex(so.name);\n const challenge = so.review?.seedChallenge;\n await engine.withDeviceIndex(index).collectSeedFragment(challenge!);\n logger.info(`Collected fragment for ${so.name}`);\n }),\n );\n return engine.client.onboarding.commitSeedProvisioning.mutate({ onboardingId });\n },\n\n /**\n * Workspace initialization\n */\n PENDING_WORKSPACE_INITIALIZATION: async ({ state, engine }, logger) => {\n const result = await engine.client.onboarding.initializeWorkspace.mutate({\n onboardingId: state.id,\n });\n logger.info(\"Workspace initialized\");\n return result;\n },\n} as const satisfies Record<Exclude<OnboardingStep, \"COMPLETED\">, StepAction>;\n\nexport async function onboard(\n opts: {\n engine: Engine<WithOnboarding>;\n debugAuthToken?: string;\n signerSeed?: string;\n untilStep?: OnboardingStep;\n },\n logger: Logger,\n): Promise<void> {\n const { engine, debugAuthToken, signerSeed, untilStep } = opts;\n\n const { __onboardingId } = engine;\n logger.info(`Joining onboarding ${__onboardingId}`);\n let state = await engine.client.onboarding.getOnboarding.query({\n onboardingId: __onboardingId,\n });\n\n checkExternalSigners(state, debugAuthToken);\n\n while (state.step !== \"COMPLETED\") {\n if (untilStep && state.step === untilStep) {\n logger.info(\"Skipping the rest of the onboarding\");\n break;\n }\n const step = STEPS[state.step];\n logger.info(step.name);\n state = await step({ engine, state, debugAuthToken, signerSeed }, logger);\n }\n}\n"],"mappings":"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"}
|
package/lib/onboarding.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as Logger } from "./logger-DHtgWA66.cjs";
|
|
2
|
-
import { d as Engine, y as WithOnboarding } from "./types-
|
|
2
|
+
import { d as Engine, y as WithOnboarding } from "./types-bfqkmpgo.cjs";
|
|
3
3
|
import { OnboardingFullStateResponse, OnboardingStep } from "@ledgerhq/revault-api";
|
|
4
4
|
//#region src/onboarding.d.ts
|
|
5
5
|
declare const STEPS: {
|
|
@@ -1097,7 +1097,7 @@ declare const STEPS: {
|
|
|
1097
1097
|
state: OnboardingFullStateResponse;
|
|
1098
1098
|
debugAuthToken?: string;
|
|
1099
1099
|
signerSeed?: string;
|
|
1100
|
-
}) => Promise<{
|
|
1100
|
+
}, logger: Logger) => Promise<{
|
|
1101
1101
|
id: string;
|
|
1102
1102
|
workspaceName: string;
|
|
1103
1103
|
hsmHostingMode: "HOSTED" | "ON_PREM";
|
package/lib/onboarding.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as Logger } from "./logger-DHtgWA66.js";
|
|
2
|
-
import { d as Engine, y as WithOnboarding } from "./types-
|
|
2
|
+
import { d as Engine, y as WithOnboarding } from "./types-tRODcWIL.js";
|
|
3
3
|
import { OnboardingFullStateResponse, OnboardingStep } from "@ledgerhq/revault-api";
|
|
4
4
|
//#region src/onboarding.d.ts
|
|
5
5
|
declare const STEPS: {
|
|
@@ -1097,7 +1097,7 @@ declare const STEPS: {
|
|
|
1097
1097
|
state: OnboardingFullStateResponse;
|
|
1098
1098
|
debugAuthToken?: string;
|
|
1099
1099
|
signerSeed?: string;
|
|
1100
|
-
}) => Promise<{
|
|
1100
|
+
}, logger: Logger) => Promise<{
|
|
1101
1101
|
id: string;
|
|
1102
1102
|
workspaceName: string;
|
|
1103
1103
|
hsmHostingMode: "HOSTED" | "ON_PREM";
|
package/lib/onboarding.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as getMasterSeed } from "./crypto-
|
|
1
|
+
import { i as getMasterSeed } from "./crypto-hrnmToQa.js";
|
|
2
2
|
import invariant from "invariant";
|
|
3
3
|
import { match } from "ts-pattern";
|
|
4
4
|
//#region src/onboarding.ts
|
|
@@ -223,7 +223,11 @@ const STEPS = {
|
|
|
223
223
|
/**
|
|
224
224
|
* Workspace initialization
|
|
225
225
|
*/
|
|
226
|
-
PENDING_WORKSPACE_INITIALIZATION: async ({ state, engine }) =>
|
|
226
|
+
PENDING_WORKSPACE_INITIALIZATION: async ({ state, engine }, logger) => {
|
|
227
|
+
const result = await engine.client.onboarding.initializeWorkspace.mutate({ onboardingId: state.id });
|
|
228
|
+
logger.info("Workspace initialized");
|
|
229
|
+
return result;
|
|
230
|
+
}
|
|
227
231
|
};
|
|
228
232
|
async function onboard(opts, logger) {
|
|
229
233
|
const { engine, debugAuthToken, signerSeed, untilStep } = opts;
|
package/lib/onboarding.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"onboarding.js","names":[],"sources":["../src/onboarding.ts"],"sourcesContent":["import type {\n ClaimedRole,\n HsmHostingMode,\n OnboardingFullStateResponse,\n OnboardingStep,\n} from \"@ledgerhq/revault-api\";\nimport invariant from \"invariant\";\nimport { match } from \"ts-pattern\";\n\nimport { getMasterSeed } from \"@/crypto\";\nimport type { Logger } from \"@/logger\";\n\nimport type { Engine, WithOnboarding } from \"./engine/types\";\n\ntype StepAction = (\n options: {\n engine: Engine<WithOnboarding>;\n state: OnboardingFullStateResponse;\n debugAuthToken?: string;\n signerSeed?: string;\n },\n logger: Logger,\n) => Promise<OnboardingFullStateResponse>;\n\nconst roleLabels: Record<ClaimedRole, string> = {\n WRAPPING_KEY_OWNER: \"Wrapping Key\",\n MASTER_ADMIN: \"Admin\",\n SHARED_OWNER: \"Shared Owner\",\n};\n\nconst devices: { index: number; role: ClaimedRole; name: string }[] = [\n { index: 1, role: \"WRAPPING_KEY_OWNER\", name: `${roleLabels.WRAPPING_KEY_OWNER} 1` },\n { index: 2, role: \"WRAPPING_KEY_OWNER\", name: `${roleLabels.WRAPPING_KEY_OWNER} 2` },\n { index: 3, role: \"WRAPPING_KEY_OWNER\", name: `${roleLabels.WRAPPING_KEY_OWNER} 3` },\n { index: 4, role: \"MASTER_ADMIN\", name: `${roleLabels.MASTER_ADMIN} 1` },\n { index: 5, role: \"MASTER_ADMIN\", name: `${roleLabels.MASTER_ADMIN} 2` },\n { index: 6, role: \"MASTER_ADMIN\", name: `${roleLabels.MASTER_ADMIN} 3` },\n { index: 7, role: \"SHARED_OWNER\", name: `${roleLabels.SHARED_OWNER} 1` },\n { index: 8, role: \"SHARED_OWNER\", name: `${roleLabels.SHARED_OWNER} 2` },\n { index: 9, role: \"SHARED_OWNER\", name: `${roleLabels.SHARED_OWNER} 3` },\n];\n\nconst deviceNameToIndex = (name: string): number => {\n const index = devices.find((d) => d.name === name)?.index;\n invariant(index !== undefined, `Unknown device ${name}`);\n return index;\n};\n\nconst checkHsmHostingMode = (\n state: OnboardingFullStateResponse,\n expectedMode: HsmHostingMode,\n): void => {\n /* v8 ignore next -- @preserve */\n if (state.hsmHostingMode !== expectedMode) {\n throw new Error(`HSM hosting mode should be ${expectedMode} but is ${state.hsmHostingMode}`);\n }\n};\n\n/* v8 ignore next -- @preserve */\nconst checkExternalSigners = (\n state: OnboardingFullStateResponse,\n debugAuthToken: string | undefined,\n): void => {\n const errorMessage = match(state.hsmHostingMode)\n .with(\"HOSTED\", () => null)\n .with(\"ON_PREM\", () => (debugAuthToken ? null : \"On-premises HSM requires a debug auth token\"))\n .exhaustive();\n if (errorMessage !== null) {\n throw new Error(errorMessage);\n }\n};\n\nexport const STEPS = {\n /**\n * Devices claiming\n */\n PENDING_DEVICE_CLAIMS: async ({ state, engine }, logger) => {\n const promises: Promise<void>[] = [];\n for (const device of devices) {\n if (state.hsmHostingMode === \"ON_PREM\" && device.role === \"SHARED_OWNER\") {\n continue;\n }\n if (state.skipWrappingKey && device.role === \"WRAPPING_KEY_OWNER\") {\n continue;\n }\n /* v8 ignore else -- @preserve */\n if (\n state.claimedDevices.find(\n /* v8 ignore next -- @preserve */\n (c) => c.deviceName === device.name,\n ) === undefined\n ) {\n const promise = engine\n .withDeviceIndex(device.index)\n .claimDevice({ role: device.role, deviceName: device.name })\n .then(() => logger.info(`Claimed ${device.name}`));\n promises.push(promise);\n }\n }\n await Promise.all(promises);\n return engine.client.onboarding.commitDeviceClaims.mutate({ onboardingId: state.id });\n },\n\n /**\n * Wrapping Key provisioning\n */\n PENDING_WRAPPING_KEY_PROVISIONING: async ({ state, engine }, logger) => {\n const { id: onboardingId } = state;\n state = await engine.client.onboarding.startWrappingKeyProvisioning.mutate({ onboardingId });\n const wrappingKey = state.wrappingKey!;\n const toCollect = state.claimedDevices\n .filter((claimed) => {\n if (claimed.role !== \"WRAPPING_KEY_OWNER\") return false;\n const inFragment = !!state.wrappingKey?.fragments.find(\n /* v8 ignore next -- @preserve */\n (f) => f.pubKey === claimed.pubKey,\n );\n return !inFragment;\n })\n .map((c) => {\n const index = deviceNameToIndex(c.deviceName);\n return index;\n });\n await Promise.all(\n toCollect.map((index) =>\n engine\n .withDeviceIndex(index)\n .collectWrappingKeyFragment(wrappingKey)\n .then(() => logger.info(`Collected Wrapping Key ${index}`)),\n ),\n );\n return engine.client.onboarding.commitWrappingKey.mutate({ onboardingId });\n },\n\n /**\n * Init Master Admins registration\n */\n PENDING_MASTER_ADMINS_REGISTRATION_INIT: async ({ engine, state }) =>\n engine.client.onboarding.startMasterAdminsRegistration.mutate({ onboardingId: state.id }),\n\n /**\n * Master Admins registration\n */\n PENDING_MASTER_ADMINS_REGISTRATION: async ({ state, engine }, logger) => {\n const { id: onboardingId } = state;\n const toRegister = state.claimedDevices.filter((claimed) => {\n if (claimed.role !== \"MASTER_ADMIN\") return false;\n const hasRegistered = !!state.masterAdmins.find(\n /* v8 ignore next -- @preserve */\n (a) => a.pubKey === claimed.pubKey,\n );\n return !hasRegistered;\n });\n await Promise.all(\n toRegister.map(async ({ deviceName: name }) => {\n const index = deviceNameToIndex(name);\n await engine.withDeviceIndex(index).registerDevice({ role: \"ADMIN\", name });\n logger.info(`Registered ${name}`);\n }),\n );\n return engine.client.onboarding.createMasterAdminGroup.mutate({ onboardingId });\n },\n\n /**\n * Init Shared Owners registration\n */\n PENDING_SHARED_OWNERS_REGISTRATION_INIT: async ({ engine, state }) => {\n checkHsmHostingMode(state, \"HOSTED\");\n return engine.client.onboarding.startSharedOwnersRegistration.mutate({\n onboardingId: state.id,\n });\n },\n\n /**\n * Shared Owners registration\n */\n PENDING_SHARED_OWNERS_REGISTRATION: async ({ state, engine }, logger) => {\n checkHsmHostingMode(state, \"HOSTED\");\n const { id: onboardingId } = state;\n const toRegister = state.claimedDevices.filter((claimed) => {\n if (claimed.role !== \"SHARED_OWNER\") return false;\n const hasRegistered = !!state.sharedOwners.find(\n /* v8 ignore next -- @preserve */ (a) => a.pubKey === claimed.pubKey,\n );\n return !hasRegistered;\n });\n await Promise.all(\n toRegister.map(async ({ deviceName: name }) => {\n const index = deviceNameToIndex(name);\n await engine.withDeviceIndex(index).registerDevice({ role: \"SHARED_OWNER\", name });\n logger.info(`Registered ${name}`);\n }),\n );\n return engine.client.onboarding.commitSharedOwnersRegistration.mutate({ onboardingId });\n },\n\n /**\n * Review by master admins\n */\n PENDING_REVIEW_BY_MASTER_ADMINS: async ({ state, engine }, logger) => {\n const { id: onboardingId } = state;\n state = await engine.client.onboarding.startReviewByMasterAdmins.mutate({ onboardingId });\n const toCollect = state.masterAdmins.filter((admin) => !admin.review?.signature);\n await Promise.all(\n toCollect.map(async (admin) => {\n const index = deviceNameToIndex(admin.name);\n const challenge = admin.review?.challenge;\n await engine.withDeviceIndex(index).reviewSharedOwner(challenge!);\n logger.info(`Approved with ${admin.name}`);\n }),\n );\n return engine.client.onboarding.commitReviewByMasterAdmins.mutate({ onboardingId });\n },\n\n PENDING_EXTERNAL_SIGNERS_REGISTRATION: async (\n { state, engine, debugAuthToken, signerSeed },\n logger,\n ) => {\n checkHsmHostingMode(state, \"ON_PREM\");\n const { id: onboardingId } = state;\n if (debugAuthToken) {\n const debugClient = engine.createClient({ debugAuthToken });\n const seed =\n signerSeed ?? Buffer.from(await getMasterSeed(engine.__options.salt)).toString(\"base64\");\n await debugClient.debug.insertExternalSignerSeed.mutate({\n workspaceName: state.workspaceName,\n seed,\n });\n logger.info(\"Inserted external signer seed\");\n }\n state = await engine.client.onboarding.startExternalSignersRegistration.mutate({\n onboardingId,\n });\n const toCollect = state.masterAdmins.filter(\n (admin) => !admin.reviewOfExternalSigners?.signature,\n );\n await Promise.all(\n toCollect.map(async (admin) => {\n const index = deviceNameToIndex(admin.name);\n const challenge = admin.reviewOfExternalSigners?.challenge;\n await engine.withDeviceIndex(index).reviewExternalSigners(challenge!); // same as review for shared owner, but with different challenge\n logger.info(`Approved with ${admin.name}`);\n }),\n );\n return engine.client.onboarding.commitExternalSignersRegistration.mutate({ onboardingId });\n },\n\n /**\n * Seed provisioning\n */\n PENDING_SEED_PROVISIONING: async ({ state, engine }, logger) => {\n checkHsmHostingMode(state, \"HOSTED\");\n const { id: onboardingId } = state;\n state = await engine.client.onboarding.startSeedProvisioning.mutate({ onboardingId });\n const toCollect = state.sharedOwners.filter((so) => !so.review?.seedFragment);\n await Promise.all(\n toCollect.map(async (so) => {\n const index = deviceNameToIndex(so.name);\n const challenge = so.review?.seedChallenge;\n await engine.withDeviceIndex(index).collectSeedFragment(challenge!);\n logger.info(`Collected fragment for ${so.name}`);\n }),\n );\n return engine.client.onboarding.commitSeedProvisioning.mutate({ onboardingId });\n },\n\n /**\n * Workspace initialization\n */\n PENDING_WORKSPACE_INITIALIZATION: async ({ state, engine }) =>\n engine.client.onboarding.initializeWorkspace.mutate({ onboardingId: state.id }),\n} as const satisfies Record<Exclude<OnboardingStep, \"COMPLETED\">, StepAction>;\n\nexport async function onboard(\n opts: {\n engine: Engine<WithOnboarding>;\n debugAuthToken?: string;\n signerSeed?: string;\n untilStep?: OnboardingStep;\n },\n logger: Logger,\n): Promise<void> {\n const { engine, debugAuthToken, signerSeed, untilStep } = opts;\n\n const { __onboardingId } = engine;\n logger.info(`Joining onboarding ${__onboardingId}`);\n let state = await engine.client.onboarding.getOnboarding.query({\n onboardingId: __onboardingId,\n });\n\n checkExternalSigners(state, debugAuthToken);\n\n while (state.step !== \"COMPLETED\") {\n if (untilStep && state.step === untilStep) {\n logger.info(\"Skipping the rest of the onboarding\");\n break;\n }\n const step = STEPS[state.step];\n logger.info(step.name);\n state = await step({ engine, state, debugAuthToken, signerSeed }, logger);\n }\n}\n"],"mappings":";;;;AAwBA,MAAM,aAA0C;CAC9C,oBAAoB;CACpB,cAAc;CACd,cAAc;AAChB;AAEA,MAAM,UAAgE;CACpE;EAAE,OAAO;EAAG,MAAM;EAAsB,MAAM,GAAG,WAAW,mBAAmB;CAAI;CACnF;EAAE,OAAO;EAAG,MAAM;EAAsB,MAAM,GAAG,WAAW,mBAAmB;CAAI;CACnF;EAAE,OAAO;EAAG,MAAM;EAAsB,MAAM,GAAG,WAAW,mBAAmB;CAAI;CACnF;EAAE,OAAO;EAAG,MAAM;EAAgB,MAAM,GAAG,WAAW,aAAa;CAAI;CACvE;EAAE,OAAO;EAAG,MAAM;EAAgB,MAAM,GAAG,WAAW,aAAa;CAAI;CACvE;EAAE,OAAO;EAAG,MAAM;EAAgB,MAAM,GAAG,WAAW,aAAa;CAAI;CACvE;EAAE,OAAO;EAAG,MAAM;EAAgB,MAAM,GAAG,WAAW,aAAa;CAAI;CACvE;EAAE,OAAO;EAAG,MAAM;EAAgB,MAAM,GAAG,WAAW,aAAa;CAAI;CACvE;EAAE,OAAO;EAAG,MAAM;EAAgB,MAAM,GAAG,WAAW,aAAa;CAAI;AACzE;AAEA,MAAM,qBAAqB,SAAyB;CAClD,MAAM,QAAQ,QAAQ,MAAM,MAAM,EAAE,SAAS,IAAI,CAAC,EAAE;CACpD,UAAU,UAAU,KAAA,GAAW,kBAAkB,MAAM;CACvD,OAAO;AACT;AAEA,MAAM,uBACJ,OACA,iBACS;;CAET,IAAI,MAAM,mBAAmB,cAC3B,MAAM,IAAI,MAAM,8BAA8B,aAAa,UAAU,MAAM,gBAAgB;AAE/F;;AAGA,MAAM,wBACJ,OACA,mBACS;CACT,MAAM,eAAe,MAAM,MAAM,cAAc,CAAC,CAC7C,KAAK,gBAAgB,IAAI,CAAC,CAC1B,KAAK,iBAAkB,iBAAiB,OAAO,6CAA8C,CAAC,CAC9F,WAAW;CACd,IAAI,iBAAiB,MACnB,MAAM,IAAI,MAAM,YAAY;AAEhC;AAEA,MAAa,QAAQ;;;;CAInB,uBAAuB,OAAO,EAAE,OAAO,UAAU,WAAW;EAC1D,MAAM,WAA4B,CAAC;EACnC,KAAK,MAAM,UAAU,SAAS;GAC5B,IAAI,MAAM,mBAAmB,aAAa,OAAO,SAAS,gBACxD;GAEF,IAAI,MAAM,mBAAmB,OAAO,SAAS,sBAC3C;;GAGF,IACE,MAAM,eAAe;;KAElB,MAAM,EAAE,eAAe,OAAO;GACjC,MAAM,KAAA,GACN;IACA,MAAM,UAAU,OACb,gBAAgB,OAAO,KAAK,CAAC,CAC7B,YAAY;KAAE,MAAM,OAAO;KAAM,YAAY,OAAO;IAAK,CAAC,CAAC,CAC3D,WAAW,OAAO,KAAK,WAAW,OAAO,MAAM,CAAC;IACnD,SAAS,KAAK,OAAO;GACvB;EACF;EACA,MAAM,QAAQ,IAAI,QAAQ;EAC1B,OAAO,OAAO,OAAO,WAAW,mBAAmB,OAAO,EAAE,cAAc,MAAM,GAAG,CAAC;CACtF;;;;CAKA,mCAAmC,OAAO,EAAE,OAAO,UAAU,WAAW;EACtE,MAAM,EAAE,IAAI,iBAAiB;EAC7B,QAAQ,MAAM,OAAO,OAAO,WAAW,6BAA6B,OAAO,EAAE,aAAa,CAAC;EAC3F,MAAM,cAAc,MAAM;EAC1B,MAAM,YAAY,MAAM,eACrB,QAAQ,YAAY;GACnB,IAAI,QAAQ,SAAS,sBAAsB,OAAO;GAKlD,OAAO,CAAC,CAJY,CAAC,MAAM,aAAa,UAAU;;KAE/C,MAAM,EAAE,WAAW,QAAQ;GAC9B;EAEF,CAAC,CAAC,CACD,KAAK,MAAM;GAEV,OADc,kBAAkB,EAAE,UACvB;EACb,CAAC;EACH,MAAM,QAAQ,IACZ,UAAU,KAAK,UACb,OACG,gBAAgB,KAAK,CAAC,CACtB,2BAA2B,WAAW,CAAC,CACvC,WAAW,OAAO,KAAK,0BAA0B,OAAO,CAAC,CAC9D,CACF;EACA,OAAO,OAAO,OAAO,WAAW,kBAAkB,OAAO,EAAE,aAAa,CAAC;CAC3E;;;;CAKA,yCAAyC,OAAO,EAAE,QAAQ,YACxD,OAAO,OAAO,WAAW,8BAA8B,OAAO,EAAE,cAAc,MAAM,GAAG,CAAC;;;;CAK1F,oCAAoC,OAAO,EAAE,OAAO,UAAU,WAAW;EACvE,MAAM,EAAE,IAAI,iBAAiB;EAC7B,MAAM,aAAa,MAAM,eAAe,QAAQ,YAAY;GAC1D,IAAI,QAAQ,SAAS,gBAAgB,OAAO;GAK5C,OAAO,CAAC,CAJe,CAAC,MAAM,aAAa;;KAExC,MAAM,EAAE,WAAW,QAAQ;GAC9B;EAEF,CAAC;EACD,MAAM,QAAQ,IACZ,WAAW,IAAI,OAAO,EAAE,YAAY,WAAW;GAC7C,MAAM,QAAQ,kBAAkB,IAAI;GACpC,MAAM,OAAO,gBAAgB,KAAK,CAAC,CAAC,eAAe;IAAE,MAAM;IAAS;GAAK,CAAC;GAC1E,OAAO,KAAK,cAAc,MAAM;EAClC,CAAC,CACH;EACA,OAAO,OAAO,OAAO,WAAW,uBAAuB,OAAO,EAAE,aAAa,CAAC;CAChF;;;;CAKA,yCAAyC,OAAO,EAAE,QAAQ,YAAY;EACpE,oBAAoB,OAAO,QAAQ;EACnC,OAAO,OAAO,OAAO,WAAW,8BAA8B,OAAO,EACnE,cAAc,MAAM,GACtB,CAAC;CACH;;;;CAKA,oCAAoC,OAAO,EAAE,OAAO,UAAU,WAAW;EACvE,oBAAoB,OAAO,QAAQ;EACnC,MAAM,EAAE,IAAI,iBAAiB;EAC7B,MAAM,aAAa,MAAM,eAAe,QAAQ,YAAY;GAC1D,IAAI,QAAQ,SAAS,gBAAgB,OAAO;GAI5C,OAAO,CAAC,CAHe,CAAC,MAAM,aAAa;;KACN,MAAM,EAAE,WAAW,QAAQ;GAChE;EAEF,CAAC;EACD,MAAM,QAAQ,IACZ,WAAW,IAAI,OAAO,EAAE,YAAY,WAAW;GAC7C,MAAM,QAAQ,kBAAkB,IAAI;GACpC,MAAM,OAAO,gBAAgB,KAAK,CAAC,CAAC,eAAe;IAAE,MAAM;IAAgB;GAAK,CAAC;GACjF,OAAO,KAAK,cAAc,MAAM;EAClC,CAAC,CACH;EACA,OAAO,OAAO,OAAO,WAAW,+BAA+B,OAAO,EAAE,aAAa,CAAC;CACxF;;;;CAKA,iCAAiC,OAAO,EAAE,OAAO,UAAU,WAAW;EACpE,MAAM,EAAE,IAAI,iBAAiB;EAC7B,QAAQ,MAAM,OAAO,OAAO,WAAW,0BAA0B,OAAO,EAAE,aAAa,CAAC;EACxF,MAAM,YAAY,MAAM,aAAa,QAAQ,UAAU,CAAC,MAAM,QAAQ,SAAS;EAC/E,MAAM,QAAQ,IACZ,UAAU,IAAI,OAAO,UAAU;GAC7B,MAAM,QAAQ,kBAAkB,MAAM,IAAI;GAC1C,MAAM,YAAY,MAAM,QAAQ;GAChC,MAAM,OAAO,gBAAgB,KAAK,CAAC,CAAC,kBAAkB,SAAU;GAChE,OAAO,KAAK,iBAAiB,MAAM,MAAM;EAC3C,CAAC,CACH;EACA,OAAO,OAAO,OAAO,WAAW,2BAA2B,OAAO,EAAE,aAAa,CAAC;CACpF;CAEA,uCAAuC,OACrC,EAAE,OAAO,QAAQ,gBAAgB,cACjC,WACG;EACH,oBAAoB,OAAO,SAAS;EACpC,MAAM,EAAE,IAAI,iBAAiB;EAC7B,IAAI,gBAAgB;GAClB,MAAM,cAAc,OAAO,aAAa,EAAE,eAAe,CAAC;GAC1D,MAAM,OACJ,cAAc,OAAO,KAAK,MAAM,cAAc,OAAO,UAAU,IAAI,CAAC,CAAC,CAAC,SAAS,QAAQ;GACzF,MAAM,YAAY,MAAM,yBAAyB,OAAO;IACtD,eAAe,MAAM;IACrB;GACF,CAAC;GACD,OAAO,KAAK,+BAA+B;EAC7C;EACA,QAAQ,MAAM,OAAO,OAAO,WAAW,iCAAiC,OAAO,EAC7E,aACF,CAAC;EACD,MAAM,YAAY,MAAM,aAAa,QAClC,UAAU,CAAC,MAAM,yBAAyB,SAC7C;EACA,MAAM,QAAQ,IACZ,UAAU,IAAI,OAAO,UAAU;GAC7B,MAAM,QAAQ,kBAAkB,MAAM,IAAI;GAC1C,MAAM,YAAY,MAAM,yBAAyB;GACjD,MAAM,OAAO,gBAAgB,KAAK,CAAC,CAAC,sBAAsB,SAAU;GACpE,OAAO,KAAK,iBAAiB,MAAM,MAAM;EAC3C,CAAC,CACH;EACA,OAAO,OAAO,OAAO,WAAW,kCAAkC,OAAO,EAAE,aAAa,CAAC;CAC3F;;;;CAKA,2BAA2B,OAAO,EAAE,OAAO,UAAU,WAAW;EAC9D,oBAAoB,OAAO,QAAQ;EACnC,MAAM,EAAE,IAAI,iBAAiB;EAC7B,QAAQ,MAAM,OAAO,OAAO,WAAW,sBAAsB,OAAO,EAAE,aAAa,CAAC;EACpF,MAAM,YAAY,MAAM,aAAa,QAAQ,OAAO,CAAC,GAAG,QAAQ,YAAY;EAC5E,MAAM,QAAQ,IACZ,UAAU,IAAI,OAAO,OAAO;GAC1B,MAAM,QAAQ,kBAAkB,GAAG,IAAI;GACvC,MAAM,YAAY,GAAG,QAAQ;GAC7B,MAAM,OAAO,gBAAgB,KAAK,CAAC,CAAC,oBAAoB,SAAU;GAClE,OAAO,KAAK,0BAA0B,GAAG,MAAM;EACjD,CAAC,CACH;EACA,OAAO,OAAO,OAAO,WAAW,uBAAuB,OAAO,EAAE,aAAa,CAAC;CAChF;;;;CAKA,kCAAkC,OAAO,EAAE,OAAO,aAChD,OAAO,OAAO,WAAW,oBAAoB,OAAO,EAAE,cAAc,MAAM,GAAG,CAAC;AAClF;AAEA,eAAsB,QACpB,MAMA,QACe;CACf,MAAM,EAAE,QAAQ,gBAAgB,YAAY,cAAc;CAE1D,MAAM,EAAE,mBAAmB;CAC3B,OAAO,KAAK,sBAAsB,gBAAgB;CAClD,IAAI,QAAQ,MAAM,OAAO,OAAO,WAAW,cAAc,MAAM,EAC7D,cAAc,eAChB,CAAC;CAED,qBAAqB,OAAO,cAAc;CAE1C,OAAO,MAAM,SAAS,aAAa;EACjC,IAAI,aAAa,MAAM,SAAS,WAAW;GACzC,OAAO,KAAK,qCAAqC;GACjD;EACF;EACA,MAAM,OAAO,MAAM,MAAM;EACzB,OAAO,KAAK,KAAK,IAAI;EACrB,QAAQ,MAAM,KAAK;GAAE;GAAQ;GAAO;GAAgB;EAAW,GAAG,MAAM;CAC1E;AACF"}
|
|
1
|
+
{"version":3,"file":"onboarding.js","names":[],"sources":["../src/onboarding.ts"],"sourcesContent":["import type {\n ClaimedRole,\n HsmHostingMode,\n OnboardingFullStateResponse,\n OnboardingStep,\n} from \"@ledgerhq/revault-api\";\nimport invariant from \"invariant\";\nimport { match } from \"ts-pattern\";\n\nimport { getMasterSeed } from \"@/crypto\";\nimport type { Logger } from \"@/logger\";\n\nimport type { Engine, WithOnboarding } from \"./engine/types\";\n\ntype StepAction = (\n options: {\n engine: Engine<WithOnboarding>;\n state: OnboardingFullStateResponse;\n debugAuthToken?: string;\n signerSeed?: string;\n },\n logger: Logger,\n) => Promise<OnboardingFullStateResponse>;\n\nconst roleLabels: Record<ClaimedRole, string> = {\n WRAPPING_KEY_OWNER: \"Wrapping Key\",\n MASTER_ADMIN: \"Admin\",\n SHARED_OWNER: \"Shared Owner\",\n};\n\nconst devices: { index: number; role: ClaimedRole; name: string }[] = [\n { index: 1, role: \"WRAPPING_KEY_OWNER\", name: `${roleLabels.WRAPPING_KEY_OWNER} 1` },\n { index: 2, role: \"WRAPPING_KEY_OWNER\", name: `${roleLabels.WRAPPING_KEY_OWNER} 2` },\n { index: 3, role: \"WRAPPING_KEY_OWNER\", name: `${roleLabels.WRAPPING_KEY_OWNER} 3` },\n { index: 4, role: \"MASTER_ADMIN\", name: `${roleLabels.MASTER_ADMIN} 1` },\n { index: 5, role: \"MASTER_ADMIN\", name: `${roleLabels.MASTER_ADMIN} 2` },\n { index: 6, role: \"MASTER_ADMIN\", name: `${roleLabels.MASTER_ADMIN} 3` },\n { index: 7, role: \"SHARED_OWNER\", name: `${roleLabels.SHARED_OWNER} 1` },\n { index: 8, role: \"SHARED_OWNER\", name: `${roleLabels.SHARED_OWNER} 2` },\n { index: 9, role: \"SHARED_OWNER\", name: `${roleLabels.SHARED_OWNER} 3` },\n];\n\nconst deviceNameToIndex = (name: string): number => {\n const index = devices.find((d) => d.name === name)?.index;\n invariant(index !== undefined, `Unknown device ${name}`);\n return index;\n};\n\nconst checkHsmHostingMode = (\n state: OnboardingFullStateResponse,\n expectedMode: HsmHostingMode,\n): void => {\n /* v8 ignore next -- @preserve */\n if (state.hsmHostingMode !== expectedMode) {\n throw new Error(`HSM hosting mode should be ${expectedMode} but is ${state.hsmHostingMode}`);\n }\n};\n\n/* v8 ignore next -- @preserve */\nconst checkExternalSigners = (\n state: OnboardingFullStateResponse,\n debugAuthToken: string | undefined,\n): void => {\n const errorMessage = match(state.hsmHostingMode)\n .with(\"HOSTED\", () => null)\n .with(\"ON_PREM\", () => (debugAuthToken ? null : \"On-premises HSM requires a debug auth token\"))\n .exhaustive();\n if (errorMessage !== null) {\n throw new Error(errorMessage);\n }\n};\n\nexport const STEPS = {\n /**\n * Devices claiming\n */\n PENDING_DEVICE_CLAIMS: async ({ state, engine }, logger) => {\n const promises: Promise<void>[] = [];\n for (const device of devices) {\n if (state.hsmHostingMode === \"ON_PREM\" && device.role === \"SHARED_OWNER\") {\n continue;\n }\n if (state.skipWrappingKey && device.role === \"WRAPPING_KEY_OWNER\") {\n continue;\n }\n /* v8 ignore else -- @preserve */\n if (\n state.claimedDevices.find(\n /* v8 ignore next -- @preserve */\n (c) => c.deviceName === device.name,\n ) === undefined\n ) {\n const promise = engine\n .withDeviceIndex(device.index)\n .claimDevice({ role: device.role, deviceName: device.name })\n .then(() => logger.info(`Claimed ${device.name}`));\n promises.push(promise);\n }\n }\n await Promise.all(promises);\n return engine.client.onboarding.commitDeviceClaims.mutate({ onboardingId: state.id });\n },\n\n /**\n * Wrapping Key provisioning\n */\n PENDING_WRAPPING_KEY_PROVISIONING: async ({ state, engine }, logger) => {\n const { id: onboardingId } = state;\n state = await engine.client.onboarding.startWrappingKeyProvisioning.mutate({ onboardingId });\n const wrappingKey = state.wrappingKey!;\n const toCollect = state.claimedDevices\n .filter((claimed) => {\n if (claimed.role !== \"WRAPPING_KEY_OWNER\") return false;\n const inFragment = !!state.wrappingKey?.fragments.find(\n /* v8 ignore next -- @preserve */\n (f) => f.pubKey === claimed.pubKey,\n );\n return !inFragment;\n })\n .map((c) => {\n const index = deviceNameToIndex(c.deviceName);\n return index;\n });\n await Promise.all(\n toCollect.map((index) =>\n engine\n .withDeviceIndex(index)\n .collectWrappingKeyFragment(wrappingKey)\n .then(() => logger.info(`Collected Wrapping Key ${index}`)),\n ),\n );\n return engine.client.onboarding.commitWrappingKey.mutate({ onboardingId });\n },\n\n /**\n * Init Master Admins registration\n */\n PENDING_MASTER_ADMINS_REGISTRATION_INIT: async ({ engine, state }) =>\n engine.client.onboarding.startMasterAdminsRegistration.mutate({ onboardingId: state.id }),\n\n /**\n * Master Admins registration\n */\n PENDING_MASTER_ADMINS_REGISTRATION: async ({ state, engine }, logger) => {\n const { id: onboardingId } = state;\n const toRegister = state.claimedDevices.filter((claimed) => {\n if (claimed.role !== \"MASTER_ADMIN\") return false;\n const hasRegistered = !!state.masterAdmins.find(\n /* v8 ignore next -- @preserve */\n (a) => a.pubKey === claimed.pubKey,\n );\n return !hasRegistered;\n });\n await Promise.all(\n toRegister.map(async ({ deviceName: name }) => {\n const index = deviceNameToIndex(name);\n await engine.withDeviceIndex(index).registerDevice({ role: \"ADMIN\", name });\n logger.info(`Registered ${name}`);\n }),\n );\n return engine.client.onboarding.createMasterAdminGroup.mutate({ onboardingId });\n },\n\n /**\n * Init Shared Owners registration\n */\n PENDING_SHARED_OWNERS_REGISTRATION_INIT: async ({ engine, state }) => {\n checkHsmHostingMode(state, \"HOSTED\");\n return engine.client.onboarding.startSharedOwnersRegistration.mutate({\n onboardingId: state.id,\n });\n },\n\n /**\n * Shared Owners registration\n */\n PENDING_SHARED_OWNERS_REGISTRATION: async ({ state, engine }, logger) => {\n checkHsmHostingMode(state, \"HOSTED\");\n const { id: onboardingId } = state;\n const toRegister = state.claimedDevices.filter((claimed) => {\n if (claimed.role !== \"SHARED_OWNER\") return false;\n const hasRegistered = !!state.sharedOwners.find(\n /* v8 ignore next -- @preserve */ (a) => a.pubKey === claimed.pubKey,\n );\n return !hasRegistered;\n });\n await Promise.all(\n toRegister.map(async ({ deviceName: name }) => {\n const index = deviceNameToIndex(name);\n await engine.withDeviceIndex(index).registerDevice({ role: \"SHARED_OWNER\", name });\n logger.info(`Registered ${name}`);\n }),\n );\n return engine.client.onboarding.commitSharedOwnersRegistration.mutate({ onboardingId });\n },\n\n /**\n * Review by master admins\n */\n PENDING_REVIEW_BY_MASTER_ADMINS: async ({ state, engine }, logger) => {\n const { id: onboardingId } = state;\n state = await engine.client.onboarding.startReviewByMasterAdmins.mutate({ onboardingId });\n const toCollect = state.masterAdmins.filter((admin) => !admin.review?.signature);\n await Promise.all(\n toCollect.map(async (admin) => {\n const index = deviceNameToIndex(admin.name);\n const challenge = admin.review?.challenge;\n await engine.withDeviceIndex(index).reviewSharedOwner(challenge!);\n logger.info(`Approved with ${admin.name}`);\n }),\n );\n return engine.client.onboarding.commitReviewByMasterAdmins.mutate({ onboardingId });\n },\n\n PENDING_EXTERNAL_SIGNERS_REGISTRATION: async (\n { state, engine, debugAuthToken, signerSeed },\n logger,\n ) => {\n checkHsmHostingMode(state, \"ON_PREM\");\n const { id: onboardingId } = state;\n if (debugAuthToken) {\n const debugClient = engine.createClient({ debugAuthToken });\n const seed =\n signerSeed ?? Buffer.from(await getMasterSeed(engine.__options.salt)).toString(\"base64\");\n await debugClient.debug.insertExternalSignerSeed.mutate({\n workspaceName: state.workspaceName,\n seed,\n });\n logger.info(\"Inserted external signer seed\");\n }\n state = await engine.client.onboarding.startExternalSignersRegistration.mutate({\n onboardingId,\n });\n const toCollect = state.masterAdmins.filter(\n (admin) => !admin.reviewOfExternalSigners?.signature,\n );\n await Promise.all(\n toCollect.map(async (admin) => {\n const index = deviceNameToIndex(admin.name);\n const challenge = admin.reviewOfExternalSigners?.challenge;\n await engine.withDeviceIndex(index).reviewExternalSigners(challenge!); // same as review for shared owner, but with different challenge\n logger.info(`Approved with ${admin.name}`);\n }),\n );\n return engine.client.onboarding.commitExternalSignersRegistration.mutate({ onboardingId });\n },\n\n /**\n * Seed provisioning\n */\n PENDING_SEED_PROVISIONING: async ({ state, engine }, logger) => {\n checkHsmHostingMode(state, \"HOSTED\");\n const { id: onboardingId } = state;\n state = await engine.client.onboarding.startSeedProvisioning.mutate({ onboardingId });\n const toCollect = state.sharedOwners.filter((so) => !so.review?.seedFragment);\n await Promise.all(\n toCollect.map(async (so) => {\n const index = deviceNameToIndex(so.name);\n const challenge = so.review?.seedChallenge;\n await engine.withDeviceIndex(index).collectSeedFragment(challenge!);\n logger.info(`Collected fragment for ${so.name}`);\n }),\n );\n return engine.client.onboarding.commitSeedProvisioning.mutate({ onboardingId });\n },\n\n /**\n * Workspace initialization\n */\n PENDING_WORKSPACE_INITIALIZATION: async ({ state, engine }, logger) => {\n const result = await engine.client.onboarding.initializeWorkspace.mutate({\n onboardingId: state.id,\n });\n logger.info(\"Workspace initialized\");\n return result;\n },\n} as const satisfies Record<Exclude<OnboardingStep, \"COMPLETED\">, StepAction>;\n\nexport async function onboard(\n opts: {\n engine: Engine<WithOnboarding>;\n debugAuthToken?: string;\n signerSeed?: string;\n untilStep?: OnboardingStep;\n },\n logger: Logger,\n): Promise<void> {\n const { engine, debugAuthToken, signerSeed, untilStep } = opts;\n\n const { __onboardingId } = engine;\n logger.info(`Joining onboarding ${__onboardingId}`);\n let state = await engine.client.onboarding.getOnboarding.query({\n onboardingId: __onboardingId,\n });\n\n checkExternalSigners(state, debugAuthToken);\n\n while (state.step !== \"COMPLETED\") {\n if (untilStep && state.step === untilStep) {\n logger.info(\"Skipping the rest of the onboarding\");\n break;\n }\n const step = STEPS[state.step];\n logger.info(step.name);\n state = await step({ engine, state, debugAuthToken, signerSeed }, logger);\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { u as Device } from "./index-
|
|
1
|
+
import { u as Device } from "./index-BAb2WCcL.cjs";
|
|
2
2
|
import { i as TRPCClientOptions, r as RouterOutputs, t as RevaultApiTRPCClient } from "./trpc-BCwyqVKi.cjs";
|
|
3
3
|
import { ApiChallenge, ClaimedRole, OnboardingSeedChallenge, PsdChallenge, UserRegistrationResponse, VaultRequestResponse, WrappingKeyResponse } from "@ledgerhq/revault-api";
|
|
4
4
|
//#region src/engine/types.d.ts
|
|
@@ -142,6 +142,7 @@ type CorrelationIdOpts = {
|
|
|
142
142
|
type ApproveRequestParams = {
|
|
143
143
|
onScreenDisplayed?: () => void | Promise<void>;
|
|
144
144
|
onPsdChallengeSigned?: () => void | Promise<void>;
|
|
145
|
+
signal?: AbortSignal;
|
|
145
146
|
} & CorrelationIdOpts;
|
|
146
147
|
type DecorateWithWorkspacePsdAuthenticated = {
|
|
147
148
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { u as Device } from "./index-
|
|
1
|
+
import { u as Device } from "./index-DQgupTPR.js";
|
|
2
2
|
import { i as TRPCClientOptions, r as RouterOutputs, t as RevaultApiTRPCClient } from "./trpc-BCwyqVKi.js";
|
|
3
3
|
import { ApiChallenge, ClaimedRole, OnboardingSeedChallenge, PsdChallenge, UserRegistrationResponse, VaultRequestResponse, WrappingKeyResponse } from "@ledgerhq/revault-api";
|
|
4
4
|
//#region src/engine/types.d.ts
|
|
@@ -142,6 +142,7 @@ type CorrelationIdOpts = {
|
|
|
142
142
|
type ApproveRequestParams = {
|
|
143
143
|
onScreenDisplayed?: () => void | Promise<void>;
|
|
144
144
|
onPsdChallengeSigned?: () => void | Promise<void>;
|
|
145
|
+
signal?: AbortSignal;
|
|
145
146
|
} & CorrelationIdOpts;
|
|
146
147
|
type DecorateWithWorkspacePsdAuthenticated = {
|
|
147
148
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ledgerhq/revault-sdk",
|
|
3
|
-
"version": "0.28.
|
|
3
|
+
"version": "0.28.13",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -46,7 +46,8 @@
|
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@ledgerhq/errors": "^6.36.0",
|
|
48
48
|
"@ledgerhq/hw-transport": "^6.35.4",
|
|
49
|
-
"@noble/
|
|
49
|
+
"@noble/curves": "^2.3.0",
|
|
50
|
+
"@noble/hashes": "^2.3.0",
|
|
50
51
|
"@scure/bip32": "^2.0.1",
|
|
51
52
|
"@scure/bip39": "^2.0.1",
|
|
52
53
|
"@trpc/client": "11.17.0",
|
|
@@ -55,7 +56,6 @@
|
|
|
55
56
|
"axios": "^1.19.0",
|
|
56
57
|
"axios-retry": "^4.5.0",
|
|
57
58
|
"bn.js": "^5.2.3",
|
|
58
|
-
"elliptic": "^6.6.1",
|
|
59
59
|
"invariant": "^2.2.4",
|
|
60
60
|
"jose": "^6.2.8",
|
|
61
61
|
"lodash": "^4.18.1",
|
|
@@ -64,13 +64,12 @@
|
|
|
64
64
|
"ts-pattern": "^5.9.0",
|
|
65
65
|
"uuid": "^14.0.0",
|
|
66
66
|
"zod": "^4.4.3",
|
|
67
|
-
"@ledgerhq/revault-api": "1.
|
|
67
|
+
"@ledgerhq/revault-api": "1.83.0"
|
|
68
68
|
},
|
|
69
69
|
"devDependencies": {
|
|
70
70
|
"@eslint/js": "^9.39.4",
|
|
71
71
|
"@microsoft/api-extractor": "^7.47.0",
|
|
72
72
|
"@types/bn.js": "^5.2.0",
|
|
73
|
-
"@types/elliptic": "^6.4.18",
|
|
74
73
|
"@types/invariant": "^2.2.37",
|
|
75
74
|
"@types/lodash": "^4.17.24",
|
|
76
75
|
"@types/node": "^25.9.3",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"crypto-BTN8FS8v.cjs","names":["sha256","entropyToMnemonic","wordlist","mnemonicToSeed","HDKey","asn1","BN","crypto"],"sources":["../src/crypto/gen-seed.ts","../src/crypto/key-encoder.ts","../src/crypto/utils.ts"],"sourcesContent":["import { sha256 } from \"@noble/hashes/sha2.js\";\nimport { HDKey } from \"@scure/bip32\";\nimport { entropyToMnemonic, mnemonicToSeed } from \"@scure/bip39\";\nimport { wordlist } from \"@scure/bip39/wordlists/english.js\";\n\n/**\n * Generate a deterministic BIP39 mnemonic from a salt and device index.\n *\n * Produces `entropyToMnemonic(SHA256(salt + \"_\" + index))`, matching\n * the behavior of `@ledgerhq/vault-common`'s `genSeed`.\n *\n * @param salt The workspace salt\n * @param index The device index (1-based)\n * @returns A 24-word BIP39 mnemonic string\n */\nexport function genSeed(salt: string, index: number): string {\n const input = new TextEncoder().encode(`${salt}_${index}`);\n const entropy = sha256(input);\n return entropyToMnemonic(entropy, wordlist);\n}\n\nconst getSeedFragment = async (salt: string, index: number): Promise<Uint8Array> => {\n const seed = await mnemonicToSeed(genSeed(salt, index));\n const secpKey = HDKey.fromMasterSeed(seed);\n const fragment = secpKey.derive(\"m/5655636'/4932953'\");\n return Buffer.concat([fragment.privateKey!, fragment.chainCode!]);\n};\n\nexport const getMasterSeed = async (salt: string): Promise<Uint8Array> => {\n const fragments = await Promise.all([\n getSeedFragment(salt, 7),\n getSeedFragment(salt, 8),\n getSeedFragment(salt, 9),\n ]);\n\n const masterSeed = new Uint8Array(fragments[0].length);\n for (let i = 0; i < fragments[0].length; i++) {\n masterSeed[i] = fragments[0][i]! ^ fragments[1][i]! ^ fragments[2][i]!;\n }\n\n return masterSeed;\n};\n","// ========================================================================== //\n// //\n// DISCLAIMER //\n// //\n// This code has been blindly copy-pasted from: //\n// https://github.com/LedgerHQ/pkey-ts //\n// //\n// ========================================================================== //\n//\n// @ts-expect-error this library does not ship types\nimport asn1 from \"asn1.js\";\nimport BN from \"bn.js\";\nimport elliptic from \"elliptic\";\n\n/* cspell:disable */\nconst ECPrivateKeyASN = asn1.define(\"ECPrivateKey\", function () {\n // @ts-expect-error pure black box\n // biome-ignore lint/suspicious/noExplicitAny: black box\n const self = this as any;\n self\n .seq()\n .obj(\n self.key(\"version\").int(),\n self.key(\"privateKey\").octstr(),\n self.key(\"parameters\").explicit(0).objid().optional(),\n self.key(\"publicKey\").explicit(1).bitstr().optional(),\n );\n});\n\nconst ECPrivateKey8ASN = asn1.define(\n \"ECPrivateKey\",\n /* v8 ignore next -- @preserve */\n function () {\n // @ts-expect-error pure black box\n // biome-ignore lint/suspicious/noExplicitAny: black box\n const self = this as any;\n self\n .seq()\n .obj(\n self.key(\"version\").int(),\n self\n .key(\"privateKeyAlgorithm\")\n .seq()\n .obj(self.key(\"ecPublicKey\").objid(), self.key(\"curve\").objid()),\n self.key(\"privateKey\").octstr().contains(ECPrivateKeyASN),\n self.key(\"attributes\").explicit(0).bitstr().optional(),\n );\n },\n);\n\nconst SubjectPublicKeyInfoASN = asn1.define(\"SubjectPublicKeyInfo\", function () {\n // @ts-expect-error pure black box\n // biome-ignore lint/suspicious/noExplicitAny: black box\n const self = this as any;\n self\n .seq()\n .obj(\n self.key(\"algorithm\").seq().obj(self.key(\"id\").objid(), self.key(\"curve\").objid()),\n self.key(\"pub\").bitstr(),\n );\n});\n\ntype CurveOptions = {\n curveParameters: number[];\n privatePEMOptions: { label: string };\n publicPEMOptions: { label: string };\n curve: elliptic.ec;\n};\n\nconst curves: Record<string, CurveOptions> = {\n secp256k1: {\n curveParameters: [1, 3, 132, 0, 10],\n privatePEMOptions: { label: \"EC PRIVATE KEY\" },\n publicPEMOptions: { label: \"PUBLIC KEY\" },\n curve: new elliptic.ec(\"secp256k1\"),\n },\n p256: {\n curveParameters: [1, 2, 840, 10045, 3, 1, 7], // OID for p256 curve\n privatePEMOptions: { label: \"EC PRIVATE KEY\" },\n publicPEMOptions: { label: \"PUBLIC KEY\" },\n curve: new elliptic.ec(\"p256\"),\n },\n};\n\ntype PrivateKeyPKCS1 = {\n version: BN;\n privateKey: Buffer;\n parameters: number[];\n publicKey?: {\n unused: number;\n data: Buffer;\n };\n};\n\ntype PrivateKeyPKCS8 = {\n version: BN;\n privateKey: PrivateKeyPKCS1;\n privateKeyAlgorithm: { ecPublicKey: number[]; curve: number[] };\n};\n\nexport type KeyFormat = \"raw\" | \"pem\" | \"der\";\n\nexport class KeyEncoder {\n algorithmID: number[];\n options: CurveOptions;\n\n constructor(options: string | CurveOptions) {\n /* v8 ignore else -- @preserve */\n if (typeof options === \"string\") {\n /* v8 ignore if -- @preserve */\n if (options !== \"secp256k1\" && options !== \"p256\") {\n throw new Error(`Unknown curve ${options}`);\n }\n options = curves[options]!;\n }\n this.options = options;\n this.algorithmID = [1, 2, 840, 10045, 2, 1];\n }\n\n /* v8 ignore next -- @preserve */\n private PKCS1toPKCS8(privateKey: PrivateKeyPKCS1): PrivateKeyPKCS8 {\n return {\n version: new BN(0),\n privateKey,\n privateKeyAlgorithm: {\n ecPublicKey: this.algorithmID,\n curve: privateKey.parameters,\n },\n };\n }\n\n privateKeyObject(rawPrivateKey: string, rawPublicKey: string): PrivateKeyPKCS1 {\n const privateKeyObject: PrivateKeyPKCS1 = {\n version: new BN(1),\n privateKey: Buffer.from(rawPrivateKey, \"hex\"),\n parameters: this.options.curveParameters,\n };\n\n /* v8 ignore else -- @preserve */\n if (rawPublicKey) {\n privateKeyObject.publicKey = {\n unused: 0,\n data: Buffer.from(rawPublicKey, \"hex\"),\n };\n }\n\n return privateKeyObject;\n }\n\n publicKeyObject(rawPublicKey: string): {\n algorithm: { id: number[]; curve: number[] };\n pub: { unused: number; data: Buffer };\n } {\n return {\n algorithm: {\n id: this.algorithmID,\n curve: this.options.curveParameters,\n },\n pub: {\n unused: 0,\n data: Buffer.from(rawPublicKey, \"hex\"),\n },\n };\n }\n\n encodePrivate(\n privateKey: string | Buffer,\n originalFormat: KeyFormat,\n destinationFormat: KeyFormat,\n destinationFormatType: \"pkcs8\" | \"pkcs1\" = \"pkcs1\",\n ): string {\n let privateKeyObject: PrivateKeyPKCS1;\n\n /* Parse the incoming private key and convert it to a private key object */\n switch (originalFormat) {\n case \"raw\": {\n if (typeof privateKey !== \"string\") {\n throw new Error(\"private key must be a string\");\n }\n const keyPair = this.options.curve.keyFromPrivate(privateKey, \"hex\");\n const rawPublicKey = keyPair.getPublic(\"hex\");\n privateKeyObject = this.privateKeyObject(privateKey, rawPublicKey);\n break;\n }\n /* v8 ignore next -- @preserve */\n case \"der\":\n if (typeof privateKey === \"string\") {\n privateKey = Buffer.from(privateKey, \"hex\");\n }\n privateKeyObject = ECPrivateKeyASN.decode(privateKey, \"der\");\n break;\n case \"pem\":\n if (typeof privateKey !== \"string\") {\n throw new Error(\"private key must be a string\");\n }\n privateKeyObject = ECPrivateKeyASN.decode(\n privateKey,\n \"pem\",\n this.options.privatePEMOptions,\n );\n break;\n /* v8 ignore next -- @preserve */\n default:\n throw new Error(\"invalid private key format\");\n }\n\n /* Export the private key object to the desired format */\n switch (destinationFormat) {\n case \"raw\":\n if (destinationFormatType === \"pkcs1\") {\n return privateKeyObject.privateKey.toString(\"hex\");\n } else if (destinationFormatType === \"pkcs8\") {\n return this.PKCS1toPKCS8(privateKeyObject).privateKey.privateKey.toString(\"hex\");\n }\n break;\n case \"der\":\n if (destinationFormatType === \"pkcs1\") {\n return ECPrivateKeyASN.encode(privateKeyObject, \"der\").toString(\"hex\");\n } else if (destinationFormatType === \"pkcs8\") {\n return ECPrivateKey8ASN.encode(this.PKCS1toPKCS8(privateKeyObject), \"der\").toString(\n \"hex\",\n );\n }\n break;\n case \"pem\":\n if (destinationFormatType === \"pkcs1\") {\n return ECPrivateKeyASN.encode(privateKeyObject, \"pem\", this.options.privatePEMOptions);\n } else if (destinationFormatType === \"pkcs8\") {\n return ECPrivateKey8ASN.encode(this.PKCS1toPKCS8(privateKeyObject), \"pem\", {\n ...this.options.privatePEMOptions,\n label: \"PRIVATE KEY\",\n });\n }\n break;\n /* v8 ignore next -- @preserve */\n default:\n throw new Error(\"invalid destination format for private key\");\n }\n\n throw new Error(\"unsupported destination format or type\");\n }\n\n encodePublic(\n publicKey: string | Buffer,\n originalFormat: KeyFormat,\n destinationFormat: KeyFormat,\n ): string {\n // biome-ignore lint/suspicious/noImplicitAnyLet: melting pot object\n let publicKeyObject;\n\n switch (originalFormat) {\n case \"raw\":\n if (typeof publicKey !== \"string\") {\n throw new Error(\"public key must be a string\");\n }\n publicKeyObject = this.publicKeyObject(publicKey);\n break;\n /* v8 ignore next -- @preserve */\n case \"der\":\n if (typeof publicKey === \"string\") {\n publicKey = Buffer.from(publicKey, \"hex\");\n }\n publicKeyObject = SubjectPublicKeyInfoASN.decode(publicKey, \"der\");\n break;\n case \"pem\":\n if (typeof publicKey !== \"string\") {\n throw new Error(\"public key must be a string\");\n }\n publicKeyObject = SubjectPublicKeyInfoASN.decode(\n publicKey,\n \"pem\",\n this.options.publicPEMOptions,\n );\n break;\n /* v8 ignore next -- @preserve */\n default:\n throw new Error(\"invalid public key format\");\n }\n\n /* Export the private key object to the desired format */\n switch (destinationFormat) {\n case \"raw\":\n return publicKeyObject.pub.data.toString(\"hex\");\n case \"der\":\n return SubjectPublicKeyInfoASN.encode(publicKeyObject, \"der\").toString(\"hex\");\n case \"pem\":\n return SubjectPublicKeyInfoASN.encode(\n publicKeyObject,\n \"pem\",\n this.options.publicPEMOptions,\n );\n /* v8 ignore next -- @preserve */\n default:\n throw new Error(\"invalid destination format for public key\");\n }\n }\n}\n/* cspell:enable */\n","import elliptic from \"elliptic\";\nimport * as jose from \"jose\";\n\nimport { KeyEncoder } from \"./key-encoder\";\nimport type { GeneratedKeys } from \"./types\";\nimport crypto from \"node:crypto\";\n\nfunction extractPublicKey(pemKey: string): string {\n // convert the PEM formatted public key to raw public key in X9.62 uncompressed format\n // this is an oversimplified method and may not work with different curves or PEM formats\n const pem = pemKey.split(\"\\n\");\n pem.shift(); // remove the first line (BEGIN PUBLIC KEY)\n pem.pop(); // remove the last line (END PUBLIC KEY)\n // convert base64 to buffer\n const keyBuffer = Buffer.from(pem.join(\"\"), \"base64\");\n // assuming the first 26 bytes are the header for the SPKI formatted key.\n // the actual key should begin after this header.\n const actualKeyBuffer = keyBuffer.slice(26);\n return actualKeyBuffer.toString(\"hex\").toUpperCase();\n}\n\nfunction hexToPem(hexString: string, { isPrivate = true } = {}): string {\n const keyEncoder = new KeyEncoder(\"p256\");\n if (isPrivate) {\n return keyEncoder.encodePrivate(hexString, \"raw\", \"pem\");\n }\n return keyEncoder.encodePublic(hexString, \"raw\", \"pem\");\n}\n\n/**\n * If `entropy` is passed, will generate keys pair deterministically\n * else, random keys pair generated\n */\nexport function genKeys(entropy?: string): GeneratedKeys {\n if (entropy) {\n const ec = new elliptic.ec(\"p256\");\n const hashedEntropy = crypto.createHash(\"sha256\").update(entropy).digest(\"hex\");\n const keyPair = ec.genKeyPair({\n entropy: Buffer.from(hashedEntropy, \"hex\"),\n });\n return {\n privateKey: String(hexToPem(keyPair.getPrivate(\"hex\"))),\n publicKey: String(hexToPem(keyPair.getPublic(\"hex\"), { isPrivate: false })),\n hexPubKey: extractPublicKey(String(hexToPem(keyPair.getPublic(\"hex\"), { isPrivate: false }))),\n };\n }\n const { publicKey, privateKey } = crypto.generateKeyPairSync(\"ec\", {\n namedCurve: \"P-256\",\n publicKeyEncoding: { type: \"spki\", format: \"pem\" },\n privateKeyEncoding: { type: \"sec1\", format: \"pem\" },\n });\n const hexPubKey = extractPublicKey(publicKey);\n return {\n privateKey,\n publicKey,\n hexPubKey,\n };\n}\n\nexport const sign = async (privateKeyPem: string, base64Challenge: string): Promise<string> => {\n // Decode base64url challenge to bytes\n const challengeDataBytes = jose.base64url.decode(base64Challenge);\n\n // For EC private key format, we need to use a different import method\n // Since jose doesn't support SEC1 format directly, let's use Node.js crypto\n // Create a KeyObject from the EC private key\n const privateKey = crypto.createPrivateKey(privateKeyPem);\n\n // Use jose with the KeyObject\n return new jose.CompactSign(challengeDataBytes)\n .setProtectedHeader({ alg: \"ES256\", typ: \"JWT\" })\n .sign(privateKey);\n};\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"crypto-BcqzGi2f.js","names":[],"sources":["../src/crypto/gen-seed.ts","../src/crypto/key-encoder.ts","../src/crypto/utils.ts"],"sourcesContent":["import { sha256 } from \"@noble/hashes/sha2.js\";\nimport { HDKey } from \"@scure/bip32\";\nimport { entropyToMnemonic, mnemonicToSeed } from \"@scure/bip39\";\nimport { wordlist } from \"@scure/bip39/wordlists/english.js\";\n\n/**\n * Generate a deterministic BIP39 mnemonic from a salt and device index.\n *\n * Produces `entropyToMnemonic(SHA256(salt + \"_\" + index))`, matching\n * the behavior of `@ledgerhq/vault-common`'s `genSeed`.\n *\n * @param salt The workspace salt\n * @param index The device index (1-based)\n * @returns A 24-word BIP39 mnemonic string\n */\nexport function genSeed(salt: string, index: number): string {\n const input = new TextEncoder().encode(`${salt}_${index}`);\n const entropy = sha256(input);\n return entropyToMnemonic(entropy, wordlist);\n}\n\nconst getSeedFragment = async (salt: string, index: number): Promise<Uint8Array> => {\n const seed = await mnemonicToSeed(genSeed(salt, index));\n const secpKey = HDKey.fromMasterSeed(seed);\n const fragment = secpKey.derive(\"m/5655636'/4932953'\");\n return Buffer.concat([fragment.privateKey!, fragment.chainCode!]);\n};\n\nexport const getMasterSeed = async (salt: string): Promise<Uint8Array> => {\n const fragments = await Promise.all([\n getSeedFragment(salt, 7),\n getSeedFragment(salt, 8),\n getSeedFragment(salt, 9),\n ]);\n\n const masterSeed = new Uint8Array(fragments[0].length);\n for (let i = 0; i < fragments[0].length; i++) {\n masterSeed[i] = fragments[0][i]! ^ fragments[1][i]! ^ fragments[2][i]!;\n }\n\n return masterSeed;\n};\n","// ========================================================================== //\n// //\n// DISCLAIMER //\n// //\n// This code has been blindly copy-pasted from: //\n// https://github.com/LedgerHQ/pkey-ts //\n// //\n// ========================================================================== //\n//\n// @ts-expect-error this library does not ship types\nimport asn1 from \"asn1.js\";\nimport BN from \"bn.js\";\nimport elliptic from \"elliptic\";\n\n/* cspell:disable */\nconst ECPrivateKeyASN = asn1.define(\"ECPrivateKey\", function () {\n // @ts-expect-error pure black box\n // biome-ignore lint/suspicious/noExplicitAny: black box\n const self = this as any;\n self\n .seq()\n .obj(\n self.key(\"version\").int(),\n self.key(\"privateKey\").octstr(),\n self.key(\"parameters\").explicit(0).objid().optional(),\n self.key(\"publicKey\").explicit(1).bitstr().optional(),\n );\n});\n\nconst ECPrivateKey8ASN = asn1.define(\n \"ECPrivateKey\",\n /* v8 ignore next -- @preserve */\n function () {\n // @ts-expect-error pure black box\n // biome-ignore lint/suspicious/noExplicitAny: black box\n const self = this as any;\n self\n .seq()\n .obj(\n self.key(\"version\").int(),\n self\n .key(\"privateKeyAlgorithm\")\n .seq()\n .obj(self.key(\"ecPublicKey\").objid(), self.key(\"curve\").objid()),\n self.key(\"privateKey\").octstr().contains(ECPrivateKeyASN),\n self.key(\"attributes\").explicit(0).bitstr().optional(),\n );\n },\n);\n\nconst SubjectPublicKeyInfoASN = asn1.define(\"SubjectPublicKeyInfo\", function () {\n // @ts-expect-error pure black box\n // biome-ignore lint/suspicious/noExplicitAny: black box\n const self = this as any;\n self\n .seq()\n .obj(\n self.key(\"algorithm\").seq().obj(self.key(\"id\").objid(), self.key(\"curve\").objid()),\n self.key(\"pub\").bitstr(),\n );\n});\n\ntype CurveOptions = {\n curveParameters: number[];\n privatePEMOptions: { label: string };\n publicPEMOptions: { label: string };\n curve: elliptic.ec;\n};\n\nconst curves: Record<string, CurveOptions> = {\n secp256k1: {\n curveParameters: [1, 3, 132, 0, 10],\n privatePEMOptions: { label: \"EC PRIVATE KEY\" },\n publicPEMOptions: { label: \"PUBLIC KEY\" },\n curve: new elliptic.ec(\"secp256k1\"),\n },\n p256: {\n curveParameters: [1, 2, 840, 10045, 3, 1, 7], // OID for p256 curve\n privatePEMOptions: { label: \"EC PRIVATE KEY\" },\n publicPEMOptions: { label: \"PUBLIC KEY\" },\n curve: new elliptic.ec(\"p256\"),\n },\n};\n\ntype PrivateKeyPKCS1 = {\n version: BN;\n privateKey: Buffer;\n parameters: number[];\n publicKey?: {\n unused: number;\n data: Buffer;\n };\n};\n\ntype PrivateKeyPKCS8 = {\n version: BN;\n privateKey: PrivateKeyPKCS1;\n privateKeyAlgorithm: { ecPublicKey: number[]; curve: number[] };\n};\n\nexport type KeyFormat = \"raw\" | \"pem\" | \"der\";\n\nexport class KeyEncoder {\n algorithmID: number[];\n options: CurveOptions;\n\n constructor(options: string | CurveOptions) {\n /* v8 ignore else -- @preserve */\n if (typeof options === \"string\") {\n /* v8 ignore if -- @preserve */\n if (options !== \"secp256k1\" && options !== \"p256\") {\n throw new Error(`Unknown curve ${options}`);\n }\n options = curves[options]!;\n }\n this.options = options;\n this.algorithmID = [1, 2, 840, 10045, 2, 1];\n }\n\n /* v8 ignore next -- @preserve */\n private PKCS1toPKCS8(privateKey: PrivateKeyPKCS1): PrivateKeyPKCS8 {\n return {\n version: new BN(0),\n privateKey,\n privateKeyAlgorithm: {\n ecPublicKey: this.algorithmID,\n curve: privateKey.parameters,\n },\n };\n }\n\n privateKeyObject(rawPrivateKey: string, rawPublicKey: string): PrivateKeyPKCS1 {\n const privateKeyObject: PrivateKeyPKCS1 = {\n version: new BN(1),\n privateKey: Buffer.from(rawPrivateKey, \"hex\"),\n parameters: this.options.curveParameters,\n };\n\n /* v8 ignore else -- @preserve */\n if (rawPublicKey) {\n privateKeyObject.publicKey = {\n unused: 0,\n data: Buffer.from(rawPublicKey, \"hex\"),\n };\n }\n\n return privateKeyObject;\n }\n\n publicKeyObject(rawPublicKey: string): {\n algorithm: { id: number[]; curve: number[] };\n pub: { unused: number; data: Buffer };\n } {\n return {\n algorithm: {\n id: this.algorithmID,\n curve: this.options.curveParameters,\n },\n pub: {\n unused: 0,\n data: Buffer.from(rawPublicKey, \"hex\"),\n },\n };\n }\n\n encodePrivate(\n privateKey: string | Buffer,\n originalFormat: KeyFormat,\n destinationFormat: KeyFormat,\n destinationFormatType: \"pkcs8\" | \"pkcs1\" = \"pkcs1\",\n ): string {\n let privateKeyObject: PrivateKeyPKCS1;\n\n /* Parse the incoming private key and convert it to a private key object */\n switch (originalFormat) {\n case \"raw\": {\n if (typeof privateKey !== \"string\") {\n throw new Error(\"private key must be a string\");\n }\n const keyPair = this.options.curve.keyFromPrivate(privateKey, \"hex\");\n const rawPublicKey = keyPair.getPublic(\"hex\");\n privateKeyObject = this.privateKeyObject(privateKey, rawPublicKey);\n break;\n }\n /* v8 ignore next -- @preserve */\n case \"der\":\n if (typeof privateKey === \"string\") {\n privateKey = Buffer.from(privateKey, \"hex\");\n }\n privateKeyObject = ECPrivateKeyASN.decode(privateKey, \"der\");\n break;\n case \"pem\":\n if (typeof privateKey !== \"string\") {\n throw new Error(\"private key must be a string\");\n }\n privateKeyObject = ECPrivateKeyASN.decode(\n privateKey,\n \"pem\",\n this.options.privatePEMOptions,\n );\n break;\n /* v8 ignore next -- @preserve */\n default:\n throw new Error(\"invalid private key format\");\n }\n\n /* Export the private key object to the desired format */\n switch (destinationFormat) {\n case \"raw\":\n if (destinationFormatType === \"pkcs1\") {\n return privateKeyObject.privateKey.toString(\"hex\");\n } else if (destinationFormatType === \"pkcs8\") {\n return this.PKCS1toPKCS8(privateKeyObject).privateKey.privateKey.toString(\"hex\");\n }\n break;\n case \"der\":\n if (destinationFormatType === \"pkcs1\") {\n return ECPrivateKeyASN.encode(privateKeyObject, \"der\").toString(\"hex\");\n } else if (destinationFormatType === \"pkcs8\") {\n return ECPrivateKey8ASN.encode(this.PKCS1toPKCS8(privateKeyObject), \"der\").toString(\n \"hex\",\n );\n }\n break;\n case \"pem\":\n if (destinationFormatType === \"pkcs1\") {\n return ECPrivateKeyASN.encode(privateKeyObject, \"pem\", this.options.privatePEMOptions);\n } else if (destinationFormatType === \"pkcs8\") {\n return ECPrivateKey8ASN.encode(this.PKCS1toPKCS8(privateKeyObject), \"pem\", {\n ...this.options.privatePEMOptions,\n label: \"PRIVATE KEY\",\n });\n }\n break;\n /* v8 ignore next -- @preserve */\n default:\n throw new Error(\"invalid destination format for private key\");\n }\n\n throw new Error(\"unsupported destination format or type\");\n }\n\n encodePublic(\n publicKey: string | Buffer,\n originalFormat: KeyFormat,\n destinationFormat: KeyFormat,\n ): string {\n // biome-ignore lint/suspicious/noImplicitAnyLet: melting pot object\n let publicKeyObject;\n\n switch (originalFormat) {\n case \"raw\":\n if (typeof publicKey !== \"string\") {\n throw new Error(\"public key must be a string\");\n }\n publicKeyObject = this.publicKeyObject(publicKey);\n break;\n /* v8 ignore next -- @preserve */\n case \"der\":\n if (typeof publicKey === \"string\") {\n publicKey = Buffer.from(publicKey, \"hex\");\n }\n publicKeyObject = SubjectPublicKeyInfoASN.decode(publicKey, \"der\");\n break;\n case \"pem\":\n if (typeof publicKey !== \"string\") {\n throw new Error(\"public key must be a string\");\n }\n publicKeyObject = SubjectPublicKeyInfoASN.decode(\n publicKey,\n \"pem\",\n this.options.publicPEMOptions,\n );\n break;\n /* v8 ignore next -- @preserve */\n default:\n throw new Error(\"invalid public key format\");\n }\n\n /* Export the private key object to the desired format */\n switch (destinationFormat) {\n case \"raw\":\n return publicKeyObject.pub.data.toString(\"hex\");\n case \"der\":\n return SubjectPublicKeyInfoASN.encode(publicKeyObject, \"der\").toString(\"hex\");\n case \"pem\":\n return SubjectPublicKeyInfoASN.encode(\n publicKeyObject,\n \"pem\",\n this.options.publicPEMOptions,\n );\n /* v8 ignore next -- @preserve */\n default:\n throw new Error(\"invalid destination format for public key\");\n }\n }\n}\n/* cspell:enable */\n","import elliptic from \"elliptic\";\nimport * as jose from \"jose\";\n\nimport { KeyEncoder } from \"./key-encoder\";\nimport type { GeneratedKeys } from \"./types\";\nimport crypto from \"node:crypto\";\n\nfunction extractPublicKey(pemKey: string): string {\n // convert the PEM formatted public key to raw public key in X9.62 uncompressed format\n // this is an oversimplified method and may not work with different curves or PEM formats\n const pem = pemKey.split(\"\\n\");\n pem.shift(); // remove the first line (BEGIN PUBLIC KEY)\n pem.pop(); // remove the last line (END PUBLIC KEY)\n // convert base64 to buffer\n const keyBuffer = Buffer.from(pem.join(\"\"), \"base64\");\n // assuming the first 26 bytes are the header for the SPKI formatted key.\n // the actual key should begin after this header.\n const actualKeyBuffer = keyBuffer.slice(26);\n return actualKeyBuffer.toString(\"hex\").toUpperCase();\n}\n\nfunction hexToPem(hexString: string, { isPrivate = true } = {}): string {\n const keyEncoder = new KeyEncoder(\"p256\");\n if (isPrivate) {\n return keyEncoder.encodePrivate(hexString, \"raw\", \"pem\");\n }\n return keyEncoder.encodePublic(hexString, \"raw\", \"pem\");\n}\n\n/**\n * If `entropy` is passed, will generate keys pair deterministically\n * else, random keys pair generated\n */\nexport function genKeys(entropy?: string): GeneratedKeys {\n if (entropy) {\n const ec = new elliptic.ec(\"p256\");\n const hashedEntropy = crypto.createHash(\"sha256\").update(entropy).digest(\"hex\");\n const keyPair = ec.genKeyPair({\n entropy: Buffer.from(hashedEntropy, \"hex\"),\n });\n return {\n privateKey: String(hexToPem(keyPair.getPrivate(\"hex\"))),\n publicKey: String(hexToPem(keyPair.getPublic(\"hex\"), { isPrivate: false })),\n hexPubKey: extractPublicKey(String(hexToPem(keyPair.getPublic(\"hex\"), { isPrivate: false }))),\n };\n }\n const { publicKey, privateKey } = crypto.generateKeyPairSync(\"ec\", {\n namedCurve: \"P-256\",\n publicKeyEncoding: { type: \"spki\", format: \"pem\" },\n privateKeyEncoding: { type: \"sec1\", format: \"pem\" },\n });\n const hexPubKey = extractPublicKey(publicKey);\n return {\n privateKey,\n publicKey,\n hexPubKey,\n };\n}\n\nexport const sign = async (privateKeyPem: string, base64Challenge: string): Promise<string> => {\n // Decode base64url challenge to bytes\n const challengeDataBytes = jose.base64url.decode(base64Challenge);\n\n // For EC private key format, we need to use a different import method\n // Since jose doesn't support SEC1 format directly, let's use Node.js crypto\n // Create a KeyObject from the EC private key\n const privateKey = crypto.createPrivateKey(privateKeyPem);\n\n // Use jose with the KeyObject\n return new jose.CompactSign(challengeDataBytes)\n .setProtectedHeader({ alg: \"ES256\", typ: \"JWT\" })\n .sign(privateKey);\n};\n"],"mappings":"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"}
|