@ledgerhq/revault-sdk 0.26.5 → 0.26.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_chunk = require("./chunk-CKQMccvm.cjs");
3
3
  const require_utils = require("./utils-DbSFXp4c.cjs");
4
- const require_crypto = require("./crypto-BDBF_rfw.cjs");
4
+ const require_crypto = require("./crypto-rlKUKWhL.cjs");
5
5
  let invariant = require("invariant");
6
6
  invariant = require_chunk.__toESM(invariant);
7
7
  let ts_pattern = require("ts-pattern");
package/lib/bake.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { n as createDeviceIndexResolver, r as fetchAll } from "./utils-BGbdjOP9.js";
2
- import { t as genKeys } from "./crypto-CPCBrCSZ.js";
2
+ import { t as genKeys } from "./crypto-DdEUFJar.js";
3
3
  import invariant from "invariant";
4
4
  import { match } from "ts-pattern";
5
5
  import _ from "lodash";
@@ -1,5 +1,6 @@
1
1
  import { sha256 } from "@noble/hashes/sha2.js";
2
- import { entropyToMnemonic } from "@scure/bip39";
2
+ import { HDKey } from "@scure/bip32";
3
+ import { entropyToMnemonic, mnemonicToSeed } from "@scure/bip39";
3
4
  import { wordlist } from "@scure/bip39/wordlists/english.js";
4
5
  import elliptic from "elliptic";
5
6
  import * as jose from "jose";
@@ -20,6 +21,21 @@ import crypto from "node:crypto";
20
21
  function genSeed(salt, index) {
21
22
  return entropyToMnemonic(sha256(new TextEncoder().encode(`${salt}_${index}`)), wordlist);
22
23
  }
24
+ const getSeedFragment = async (salt, index) => {
25
+ const seed = await mnemonicToSeed(genSeed(salt, index));
26
+ const fragment = HDKey.fromMasterSeed(seed).derive("m/5655636'/4932953'");
27
+ return Buffer.concat([fragment.privateKey, fragment.chainCode]);
28
+ };
29
+ const getMasterSeed = async (salt) => {
30
+ const fragments = await Promise.all([
31
+ getSeedFragment(salt, 7),
32
+ getSeedFragment(salt, 8),
33
+ getSeedFragment(salt, 9)
34
+ ]);
35
+ const masterSeed = new Uint8Array(fragments[0].length);
36
+ for (let i = 0; i < fragments[0].length; i++) masterSeed[i] = fragments[0][i] ^ fragments[1][i] ^ fragments[2][i];
37
+ return masterSeed;
38
+ };
23
39
  //#endregion
24
40
  //#region src/crypto/key-encoder.ts
25
41
  const ECPrivateKeyASN = asn1.define("ECPrivateKey", function() {
@@ -240,6 +256,6 @@ const sign = async (privateKeyPem, base64Challenge) => {
240
256
  }).sign(privateKey);
241
257
  };
242
258
  //#endregion
243
- export { sign as n, genSeed as r, genKeys as t };
259
+ export { getMasterSeed as i, sign as n, genSeed as r, genKeys as t };
244
260
 
245
- //# sourceMappingURL=crypto-CPCBrCSZ.js.map
261
+ //# sourceMappingURL=crypto-DdEUFJar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto-DdEUFJar.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 await new jose.CompactSign(challengeDataBytes)\n .setProtectedHeader({ alg: \"ES256\", typ: \"JWT\" })\n .sign(privateKey);\n};\n"],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  const require_chunk = require("./chunk-CKQMccvm.cjs");
2
2
  let _noble_hashes_sha2_js = require("@noble/hashes/sha2.js");
3
+ let _scure_bip32 = require("@scure/bip32");
3
4
  let _scure_bip39 = require("@scure/bip39");
4
5
  let _scure_bip39_wordlists_english_js = require("@scure/bip39/wordlists/english.js");
5
6
  let elliptic = require("elliptic");
@@ -26,6 +27,21 @@ node_crypto = require_chunk.__toESM(node_crypto);
26
27
  function genSeed(salt, index) {
27
28
  return (0, _scure_bip39.entropyToMnemonic)((0, _noble_hashes_sha2_js.sha256)(new TextEncoder().encode(`${salt}_${index}`)), _scure_bip39_wordlists_english_js.wordlist);
28
29
  }
30
+ const getSeedFragment = async (salt, index) => {
31
+ const seed = await (0, _scure_bip39.mnemonicToSeed)(genSeed(salt, index));
32
+ const fragment = _scure_bip32.HDKey.fromMasterSeed(seed).derive("m/5655636'/4932953'");
33
+ return Buffer.concat([fragment.privateKey, fragment.chainCode]);
34
+ };
35
+ const getMasterSeed = async (salt) => {
36
+ const fragments = await Promise.all([
37
+ getSeedFragment(salt, 7),
38
+ getSeedFragment(salt, 8),
39
+ getSeedFragment(salt, 9)
40
+ ]);
41
+ const masterSeed = new Uint8Array(fragments[0].length);
42
+ for (let i = 0; i < fragments[0].length; i++) masterSeed[i] = fragments[0][i] ^ fragments[1][i] ^ fragments[2][i];
43
+ return masterSeed;
44
+ };
29
45
  //#endregion
30
46
  //#region src/crypto/key-encoder.ts
31
47
  const ECPrivateKeyASN = asn1_js.default.define("ECPrivateKey", function() {
@@ -258,6 +274,12 @@ Object.defineProperty(exports, "genSeed", {
258
274
  return genSeed;
259
275
  }
260
276
  });
277
+ Object.defineProperty(exports, "getMasterSeed", {
278
+ enumerable: true,
279
+ get: function() {
280
+ return getMasterSeed;
281
+ }
282
+ });
261
283
  Object.defineProperty(exports, "sign", {
262
284
  enumerable: true,
263
285
  get: function() {
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto-rlKUKWhL.cjs","names":["wordlist","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 await new jose.CompactSign(challengeDataBytes)\n .setProtectedHeader({ alg: \"ES256\", typ: \"JWT\" })\n .sign(privateKey);\n};\n"],"mappings":"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"}
package/lib/crypto.cjs CHANGED
@@ -1,5 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_crypto = require("./crypto-BDBF_rfw.cjs");
2
+ const require_crypto = require("./crypto-rlKUKWhL.cjs");
3
3
  exports.genKeys = require_crypto.genKeys;
4
4
  exports.genSeed = require_crypto.genSeed;
5
+ exports.getMasterSeed = require_crypto.getMasterSeed;
5
6
  exports.sign = require_crypto.sign;
package/lib/crypto.d.cts CHANGED
@@ -10,6 +10,7 @@
10
10
  * @returns A 24-word BIP39 mnemonic string
11
11
  */
12
12
  declare function genSeed(salt: string, index: number): string;
13
+ declare const getMasterSeed: (salt: string) => Promise<Uint8Array>;
13
14
  //#endregion
14
15
  //#region src/crypto/types.d.ts
15
16
  type GeneratedKeys = {
@@ -26,4 +27,4 @@ type GeneratedKeys = {
26
27
  declare function genKeys(entropy?: string): GeneratedKeys;
27
28
  declare const sign: (privateKeyPem: string, base64Challenge: string) => Promise<string>;
28
29
  //#endregion
29
- export { type GeneratedKeys, genKeys, genSeed, sign };
30
+ export { type GeneratedKeys, genKeys, genSeed, getMasterSeed, sign };
package/lib/crypto.d.ts CHANGED
@@ -10,6 +10,7 @@
10
10
  * @returns A 24-word BIP39 mnemonic string
11
11
  */
12
12
  declare function genSeed(salt: string, index: number): string;
13
+ declare const getMasterSeed: (salt: string) => Promise<Uint8Array>;
13
14
  //#endregion
14
15
  //#region src/crypto/types.d.ts
15
16
  type GeneratedKeys = {
@@ -26,4 +27,4 @@ type GeneratedKeys = {
26
27
  declare function genKeys(entropy?: string): GeneratedKeys;
27
28
  declare const sign: (privateKeyPem: string, base64Challenge: string) => Promise<string>;
28
29
  //#endregion
29
- export { type GeneratedKeys, genKeys, genSeed, sign };
30
+ export { type GeneratedKeys, genKeys, genSeed, getMasterSeed, sign };
package/lib/crypto.js CHANGED
@@ -1,2 +1,2 @@
1
- import { n as sign, r as genSeed, t as genKeys } from "./crypto-CPCBrCSZ.js";
2
- export { genKeys, genSeed, sign };
1
+ import { i as getMasterSeed, n as sign, r as genSeed, t as genKeys } from "./crypto-DdEUFJar.js";
2
+ export { genKeys, genSeed, getMasterSeed, sign };
@@ -1,5 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_chunk = require("./chunk-CKQMccvm.cjs");
3
+ const require_crypto = require("./crypto-rlKUKWhL.cjs");
3
4
  let invariant = require("invariant");
4
5
  invariant = require_chunk.__toESM(invariant);
5
6
  let ts_pattern = require("ts-pattern");
@@ -163,10 +164,18 @@ const STEPS = {
163
164
  }));
164
165
  return engine.client.onboarding.commitReviewByMasterAdmins.mutate({ onboardingId });
165
166
  },
166
- PENDING_EXTERNAL_SIGNERS_REGISTRATION: async ({ state, engine, externalSigners }, logger) => {
167
+ PENDING_EXTERNAL_SIGNERS_REGISTRATION: async ({ state, engine, externalSigners, debugAuthToken }, logger) => {
167
168
  checkHsmHostingMode(state, "ON_PREM");
168
169
  (0, invariant.default)(externalSigners && externalSigners.length > 0, "External signers must exist");
169
170
  const { id: onboardingId } = state;
171
+ if (debugAuthToken) {
172
+ const masterSeed = await require_crypto.getMasterSeed(engine.__options.salt);
173
+ await engine.createClient({ debugAuthToken }).debug.insertExternalSignerSeed.mutate({
174
+ workspaceName: state.workspaceName,
175
+ seed: Buffer.from(masterSeed).toString("base64")
176
+ });
177
+ logger.info("Inserted external signer seed");
178
+ }
170
179
  state = await engine.client.onboarding.startExternalSignersRegistration.mutate({
171
180
  onboardingId,
172
181
  externalSigners
@@ -196,7 +205,7 @@ const STEPS = {
196
205
  PENDING_WORKSPACE_INITIALIZATION: async ({ state, engine }) => engine.client.onboarding.initializeWorkspace.mutate({ onboardingId: state.id })
197
206
  };
198
207
  async function onboard(opts, logger) {
199
- const { engine, externalSigners, untilStep } = opts;
208
+ const { engine, externalSigners, debugAuthToken, untilStep } = opts;
200
209
  const { __onboardingId } = engine;
201
210
  logger.info(`Joining onboarding ${__onboardingId}`);
202
211
  let state = await engine.client.onboarding.getOnboarding.query({ onboardingId: __onboardingId });
@@ -211,7 +220,8 @@ async function onboard(opts, logger) {
211
220
  state = await step({
212
221
  engine,
213
222
  state,
214
- externalSigners
223
+ externalSigners,
224
+ debugAuthToken
215
225
  }, logger);
216
226
  }
217
227
  }
@@ -1 +1 @@
1
- {"version":3,"file":"onboarding.cjs","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 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 externalSigners?: 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 externalSigners: string[] | undefined,\n): void => {\n const hasExternalSigners = externalSigners && externalSigners.length > 0;\n const errorMessage = match(state.hsmHostingMode)\n .with(\"HOSTED\", () =>\n !hasExternalSigners ? null : \"Hosted HSM does not support external signers\",\n )\n .with(\"ON_PREM\", () =>\n hasExternalSigners ? null : \"On-premises HSM requires at least 1 external signer\",\n )\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 /* 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 ({ state, engine, externalSigners }, logger) => {\n checkHsmHostingMode(state, \"ON_PREM\");\n invariant(externalSigners && externalSigners.length > 0, \"External signers must exist\");\n const { id: onboardingId } = state;\n state = await engine.client.onboarding.startExternalSignersRegistration.mutate({\n onboardingId,\n externalSigners,\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 externalSigners?: string[];\n untilStep?: OnboardingStep;\n },\n logger: Logger,\n): Promise<void> {\n const { engine, externalSigners, 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, externalSigners);\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, externalSigners }, logger);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"onboarding.cjs","names":["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 externalSigners?: string[];\n debugAuthToken?: 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 externalSigners: string[] | undefined,\n): void => {\n const hasExternalSigners = externalSigners && externalSigners.length > 0;\n const errorMessage = match(state.hsmHostingMode)\n .with(\"HOSTED\", () =>\n !hasExternalSigners ? null : \"Hosted HSM does not support external signers\",\n )\n .with(\"ON_PREM\", () =>\n hasExternalSigners ? null : \"On-premises HSM requires at least 1 external signer\",\n )\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 /* 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, externalSigners, debugAuthToken },\n logger,\n ) => {\n checkHsmHostingMode(state, \"ON_PREM\");\n invariant(externalSigners && externalSigners.length > 0, \"External signers must exist\");\n const { id: onboardingId } = state;\n if (debugAuthToken) {\n const masterSeed = await getMasterSeed(engine.__options.salt);\n await engine.createClient({ debugAuthToken }).debug.insertExternalSignerSeed.mutate({\n workspaceName: state.workspaceName,\n seed: Buffer.from(masterSeed).toString(\"base64\"),\n });\n logger.info(\"Inserted external signer seed\");\n }\n state = await engine.client.onboarding.startExternalSignersRegistration.mutate({\n onboardingId,\n externalSigners,\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 externalSigners?: string[];\n debugAuthToken?: string;\n untilStep?: OnboardingStep;\n },\n logger: Logger,\n): Promise<void> {\n const { engine, externalSigners, debugAuthToken, 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, externalSigners);\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, externalSigners, debugAuthToken }, logger);\n }\n}\n"],"mappings":"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"}
@@ -14,6 +14,7 @@ declare const STEPS: {
14
14
  engine: Engine<WithOnboarding>;
15
15
  state: OnboardingFullStateResponse;
16
16
  externalSigners?: string[];
17
+ debugAuthToken?: string;
17
18
  }, logger: Logger) => Promise<{
18
19
  id: string;
19
20
  workspaceName: string;
@@ -47,7 +48,7 @@ declare const STEPS: {
47
48
  } | null;
48
49
  masterAdmins: {
49
50
  name: string;
50
- psdModel: "BLUE" | "STAX";
51
+ psdModel: "STAX";
51
52
  pubKey: string;
52
53
  registrationChallenge: {
53
54
  challenge: string;
@@ -116,7 +117,7 @@ declare const STEPS: {
116
117
  }[];
117
118
  sharedOwners: {
118
119
  name: string;
119
- psdModel: "BLUE" | "STAX";
120
+ psdModel: "STAX";
120
121
  pubKey: string;
121
122
  registrationChallenge: {
122
123
  challenge: string;
@@ -206,6 +207,7 @@ declare const STEPS: {
206
207
  engine: Engine<WithOnboarding>;
207
208
  state: OnboardingFullStateResponse;
208
209
  externalSigners?: string[];
210
+ debugAuthToken?: string;
209
211
  }, logger: Logger) => Promise<{
210
212
  id: string;
211
213
  workspaceName: string;
@@ -239,7 +241,7 @@ declare const STEPS: {
239
241
  } | null;
240
242
  masterAdmins: {
241
243
  name: string;
242
- psdModel: "BLUE" | "STAX";
244
+ psdModel: "STAX";
243
245
  pubKey: string;
244
246
  registrationChallenge: {
245
247
  challenge: string;
@@ -308,7 +310,7 @@ declare const STEPS: {
308
310
  }[];
309
311
  sharedOwners: {
310
312
  name: string;
311
- psdModel: "BLUE" | "STAX";
313
+ psdModel: "STAX";
312
314
  pubKey: string;
313
315
  registrationChallenge: {
314
316
  challenge: string;
@@ -398,6 +400,7 @@ declare const STEPS: {
398
400
  engine: Engine<WithOnboarding>;
399
401
  state: OnboardingFullStateResponse;
400
402
  externalSigners?: string[];
403
+ debugAuthToken?: string;
401
404
  }) => Promise<{
402
405
  id: string;
403
406
  workspaceName: string;
@@ -431,7 +434,7 @@ declare const STEPS: {
431
434
  } | null;
432
435
  masterAdmins: {
433
436
  name: string;
434
- psdModel: "BLUE" | "STAX";
437
+ psdModel: "STAX";
435
438
  pubKey: string;
436
439
  registrationChallenge: {
437
440
  challenge: string;
@@ -500,7 +503,7 @@ declare const STEPS: {
500
503
  }[];
501
504
  sharedOwners: {
502
505
  name: string;
503
- psdModel: "BLUE" | "STAX";
506
+ psdModel: "STAX";
504
507
  pubKey: string;
505
508
  registrationChallenge: {
506
509
  challenge: string;
@@ -590,6 +593,7 @@ declare const STEPS: {
590
593
  engine: Engine<WithOnboarding>;
591
594
  state: OnboardingFullStateResponse;
592
595
  externalSigners?: string[];
596
+ debugAuthToken?: string;
593
597
  }, logger: Logger) => Promise<{
594
598
  id: string;
595
599
  workspaceName: string;
@@ -623,7 +627,7 @@ declare const STEPS: {
623
627
  } | null;
624
628
  masterAdmins: {
625
629
  name: string;
626
- psdModel: "BLUE" | "STAX";
630
+ psdModel: "STAX";
627
631
  pubKey: string;
628
632
  registrationChallenge: {
629
633
  challenge: string;
@@ -692,7 +696,7 @@ declare const STEPS: {
692
696
  }[];
693
697
  sharedOwners: {
694
698
  name: string;
695
- psdModel: "BLUE" | "STAX";
699
+ psdModel: "STAX";
696
700
  pubKey: string;
697
701
  registrationChallenge: {
698
702
  challenge: string;
@@ -782,6 +786,7 @@ declare const STEPS: {
782
786
  engine: Engine<WithOnboarding>;
783
787
  state: OnboardingFullStateResponse;
784
788
  externalSigners?: string[];
789
+ debugAuthToken?: string;
785
790
  }) => Promise<{
786
791
  id: string;
787
792
  workspaceName: string;
@@ -815,7 +820,7 @@ declare const STEPS: {
815
820
  } | null;
816
821
  masterAdmins: {
817
822
  name: string;
818
- psdModel: "BLUE" | "STAX";
823
+ psdModel: "STAX";
819
824
  pubKey: string;
820
825
  registrationChallenge: {
821
826
  challenge: string;
@@ -884,7 +889,7 @@ declare const STEPS: {
884
889
  }[];
885
890
  sharedOwners: {
886
891
  name: string;
887
- psdModel: "BLUE" | "STAX";
892
+ psdModel: "STAX";
888
893
  pubKey: string;
889
894
  registrationChallenge: {
890
895
  challenge: string;
@@ -974,6 +979,7 @@ declare const STEPS: {
974
979
  engine: Engine<WithOnboarding>;
975
980
  state: OnboardingFullStateResponse;
976
981
  externalSigners?: string[];
982
+ debugAuthToken?: string;
977
983
  }, logger: Logger) => Promise<{
978
984
  id: string;
979
985
  workspaceName: string;
@@ -1007,7 +1013,7 @@ declare const STEPS: {
1007
1013
  } | null;
1008
1014
  masterAdmins: {
1009
1015
  name: string;
1010
- psdModel: "BLUE" | "STAX";
1016
+ psdModel: "STAX";
1011
1017
  pubKey: string;
1012
1018
  registrationChallenge: {
1013
1019
  challenge: string;
@@ -1076,7 +1082,7 @@ declare const STEPS: {
1076
1082
  }[];
1077
1083
  sharedOwners: {
1078
1084
  name: string;
1079
- psdModel: "BLUE" | "STAX";
1085
+ psdModel: "STAX";
1080
1086
  pubKey: string;
1081
1087
  registrationChallenge: {
1082
1088
  challenge: string;
@@ -1166,6 +1172,7 @@ declare const STEPS: {
1166
1172
  engine: Engine<WithOnboarding>;
1167
1173
  state: OnboardingFullStateResponse;
1168
1174
  externalSigners?: string[];
1175
+ debugAuthToken?: string;
1169
1176
  }, logger: Logger) => Promise<{
1170
1177
  id: string;
1171
1178
  workspaceName: string;
@@ -1199,7 +1206,7 @@ declare const STEPS: {
1199
1206
  } | null;
1200
1207
  masterAdmins: {
1201
1208
  name: string;
1202
- psdModel: "BLUE" | "STAX";
1209
+ psdModel: "STAX";
1203
1210
  pubKey: string;
1204
1211
  registrationChallenge: {
1205
1212
  challenge: string;
@@ -1268,7 +1275,7 @@ declare const STEPS: {
1268
1275
  }[];
1269
1276
  sharedOwners: {
1270
1277
  name: string;
1271
- psdModel: "BLUE" | "STAX";
1278
+ psdModel: "STAX";
1272
1279
  pubKey: string;
1273
1280
  registrationChallenge: {
1274
1281
  challenge: string;
@@ -1351,11 +1358,13 @@ declare const STEPS: {
1351
1358
  readonly PENDING_EXTERNAL_SIGNERS_REGISTRATION: ({
1352
1359
  state,
1353
1360
  engine,
1354
- externalSigners
1361
+ externalSigners,
1362
+ debugAuthToken
1355
1363
  }: {
1356
1364
  engine: Engine<WithOnboarding>;
1357
1365
  state: OnboardingFullStateResponse;
1358
1366
  externalSigners?: string[];
1367
+ debugAuthToken?: string;
1359
1368
  }, logger: Logger) => Promise<{
1360
1369
  id: string;
1361
1370
  workspaceName: string;
@@ -1389,7 +1398,7 @@ declare const STEPS: {
1389
1398
  } | null;
1390
1399
  masterAdmins: {
1391
1400
  name: string;
1392
- psdModel: "BLUE" | "STAX";
1401
+ psdModel: "STAX";
1393
1402
  pubKey: string;
1394
1403
  registrationChallenge: {
1395
1404
  challenge: string;
@@ -1458,7 +1467,7 @@ declare const STEPS: {
1458
1467
  }[];
1459
1468
  sharedOwners: {
1460
1469
  name: string;
1461
- psdModel: "BLUE" | "STAX";
1470
+ psdModel: "STAX";
1462
1471
  pubKey: string;
1463
1472
  registrationChallenge: {
1464
1473
  challenge: string;
@@ -1548,6 +1557,7 @@ declare const STEPS: {
1548
1557
  engine: Engine<WithOnboarding>;
1549
1558
  state: OnboardingFullStateResponse;
1550
1559
  externalSigners?: string[];
1560
+ debugAuthToken?: string;
1551
1561
  }, logger: Logger) => Promise<{
1552
1562
  id: string;
1553
1563
  workspaceName: string;
@@ -1581,7 +1591,7 @@ declare const STEPS: {
1581
1591
  } | null;
1582
1592
  masterAdmins: {
1583
1593
  name: string;
1584
- psdModel: "BLUE" | "STAX";
1594
+ psdModel: "STAX";
1585
1595
  pubKey: string;
1586
1596
  registrationChallenge: {
1587
1597
  challenge: string;
@@ -1650,7 +1660,7 @@ declare const STEPS: {
1650
1660
  }[];
1651
1661
  sharedOwners: {
1652
1662
  name: string;
1653
- psdModel: "BLUE" | "STAX";
1663
+ psdModel: "STAX";
1654
1664
  pubKey: string;
1655
1665
  registrationChallenge: {
1656
1666
  challenge: string;
@@ -1740,6 +1750,7 @@ declare const STEPS: {
1740
1750
  engine: Engine<WithOnboarding>;
1741
1751
  state: OnboardingFullStateResponse;
1742
1752
  externalSigners?: string[];
1753
+ debugAuthToken?: string;
1743
1754
  }) => Promise<{
1744
1755
  id: string;
1745
1756
  workspaceName: string;
@@ -1773,7 +1784,7 @@ declare const STEPS: {
1773
1784
  } | null;
1774
1785
  masterAdmins: {
1775
1786
  name: string;
1776
- psdModel: "BLUE" | "STAX";
1787
+ psdModel: "STAX";
1777
1788
  pubKey: string;
1778
1789
  registrationChallenge: {
1779
1790
  challenge: string;
@@ -1842,7 +1853,7 @@ declare const STEPS: {
1842
1853
  }[];
1843
1854
  sharedOwners: {
1844
1855
  name: string;
1845
- psdModel: "BLUE" | "STAX";
1856
+ psdModel: "STAX";
1846
1857
  pubKey: string;
1847
1858
  registrationChallenge: {
1848
1859
  challenge: string;
@@ -1926,6 +1937,7 @@ declare const STEPS: {
1926
1937
  declare function onboard(opts: {
1927
1938
  engine: Engine<WithOnboarding>;
1928
1939
  externalSigners?: string[];
1940
+ debugAuthToken?: string;
1929
1941
  untilStep?: OnboardingStep;
1930
1942
  }, logger: Logger): Promise<void>;
1931
1943
  //#endregion
@@ -14,6 +14,7 @@ declare const STEPS: {
14
14
  engine: Engine<WithOnboarding>;
15
15
  state: OnboardingFullStateResponse;
16
16
  externalSigners?: string[];
17
+ debugAuthToken?: string;
17
18
  }, logger: Logger) => Promise<{
18
19
  id: string;
19
20
  workspaceName: string;
@@ -47,7 +48,7 @@ declare const STEPS: {
47
48
  } | null;
48
49
  masterAdmins: {
49
50
  name: string;
50
- psdModel: "BLUE" | "STAX";
51
+ psdModel: "STAX";
51
52
  pubKey: string;
52
53
  registrationChallenge: {
53
54
  challenge: string;
@@ -116,7 +117,7 @@ declare const STEPS: {
116
117
  }[];
117
118
  sharedOwners: {
118
119
  name: string;
119
- psdModel: "BLUE" | "STAX";
120
+ psdModel: "STAX";
120
121
  pubKey: string;
121
122
  registrationChallenge: {
122
123
  challenge: string;
@@ -206,6 +207,7 @@ declare const STEPS: {
206
207
  engine: Engine<WithOnboarding>;
207
208
  state: OnboardingFullStateResponse;
208
209
  externalSigners?: string[];
210
+ debugAuthToken?: string;
209
211
  }, logger: Logger) => Promise<{
210
212
  id: string;
211
213
  workspaceName: string;
@@ -239,7 +241,7 @@ declare const STEPS: {
239
241
  } | null;
240
242
  masterAdmins: {
241
243
  name: string;
242
- psdModel: "BLUE" | "STAX";
244
+ psdModel: "STAX";
243
245
  pubKey: string;
244
246
  registrationChallenge: {
245
247
  challenge: string;
@@ -308,7 +310,7 @@ declare const STEPS: {
308
310
  }[];
309
311
  sharedOwners: {
310
312
  name: string;
311
- psdModel: "BLUE" | "STAX";
313
+ psdModel: "STAX";
312
314
  pubKey: string;
313
315
  registrationChallenge: {
314
316
  challenge: string;
@@ -398,6 +400,7 @@ declare const STEPS: {
398
400
  engine: Engine<WithOnboarding>;
399
401
  state: OnboardingFullStateResponse;
400
402
  externalSigners?: string[];
403
+ debugAuthToken?: string;
401
404
  }) => Promise<{
402
405
  id: string;
403
406
  workspaceName: string;
@@ -431,7 +434,7 @@ declare const STEPS: {
431
434
  } | null;
432
435
  masterAdmins: {
433
436
  name: string;
434
- psdModel: "BLUE" | "STAX";
437
+ psdModel: "STAX";
435
438
  pubKey: string;
436
439
  registrationChallenge: {
437
440
  challenge: string;
@@ -500,7 +503,7 @@ declare const STEPS: {
500
503
  }[];
501
504
  sharedOwners: {
502
505
  name: string;
503
- psdModel: "BLUE" | "STAX";
506
+ psdModel: "STAX";
504
507
  pubKey: string;
505
508
  registrationChallenge: {
506
509
  challenge: string;
@@ -590,6 +593,7 @@ declare const STEPS: {
590
593
  engine: Engine<WithOnboarding>;
591
594
  state: OnboardingFullStateResponse;
592
595
  externalSigners?: string[];
596
+ debugAuthToken?: string;
593
597
  }, logger: Logger) => Promise<{
594
598
  id: string;
595
599
  workspaceName: string;
@@ -623,7 +627,7 @@ declare const STEPS: {
623
627
  } | null;
624
628
  masterAdmins: {
625
629
  name: string;
626
- psdModel: "BLUE" | "STAX";
630
+ psdModel: "STAX";
627
631
  pubKey: string;
628
632
  registrationChallenge: {
629
633
  challenge: string;
@@ -692,7 +696,7 @@ declare const STEPS: {
692
696
  }[];
693
697
  sharedOwners: {
694
698
  name: string;
695
- psdModel: "BLUE" | "STAX";
699
+ psdModel: "STAX";
696
700
  pubKey: string;
697
701
  registrationChallenge: {
698
702
  challenge: string;
@@ -782,6 +786,7 @@ declare const STEPS: {
782
786
  engine: Engine<WithOnboarding>;
783
787
  state: OnboardingFullStateResponse;
784
788
  externalSigners?: string[];
789
+ debugAuthToken?: string;
785
790
  }) => Promise<{
786
791
  id: string;
787
792
  workspaceName: string;
@@ -815,7 +820,7 @@ declare const STEPS: {
815
820
  } | null;
816
821
  masterAdmins: {
817
822
  name: string;
818
- psdModel: "BLUE" | "STAX";
823
+ psdModel: "STAX";
819
824
  pubKey: string;
820
825
  registrationChallenge: {
821
826
  challenge: string;
@@ -884,7 +889,7 @@ declare const STEPS: {
884
889
  }[];
885
890
  sharedOwners: {
886
891
  name: string;
887
- psdModel: "BLUE" | "STAX";
892
+ psdModel: "STAX";
888
893
  pubKey: string;
889
894
  registrationChallenge: {
890
895
  challenge: string;
@@ -974,6 +979,7 @@ declare const STEPS: {
974
979
  engine: Engine<WithOnboarding>;
975
980
  state: OnboardingFullStateResponse;
976
981
  externalSigners?: string[];
982
+ debugAuthToken?: string;
977
983
  }, logger: Logger) => Promise<{
978
984
  id: string;
979
985
  workspaceName: string;
@@ -1007,7 +1013,7 @@ declare const STEPS: {
1007
1013
  } | null;
1008
1014
  masterAdmins: {
1009
1015
  name: string;
1010
- psdModel: "BLUE" | "STAX";
1016
+ psdModel: "STAX";
1011
1017
  pubKey: string;
1012
1018
  registrationChallenge: {
1013
1019
  challenge: string;
@@ -1076,7 +1082,7 @@ declare const STEPS: {
1076
1082
  }[];
1077
1083
  sharedOwners: {
1078
1084
  name: string;
1079
- psdModel: "BLUE" | "STAX";
1085
+ psdModel: "STAX";
1080
1086
  pubKey: string;
1081
1087
  registrationChallenge: {
1082
1088
  challenge: string;
@@ -1166,6 +1172,7 @@ declare const STEPS: {
1166
1172
  engine: Engine<WithOnboarding>;
1167
1173
  state: OnboardingFullStateResponse;
1168
1174
  externalSigners?: string[];
1175
+ debugAuthToken?: string;
1169
1176
  }, logger: Logger) => Promise<{
1170
1177
  id: string;
1171
1178
  workspaceName: string;
@@ -1199,7 +1206,7 @@ declare const STEPS: {
1199
1206
  } | null;
1200
1207
  masterAdmins: {
1201
1208
  name: string;
1202
- psdModel: "BLUE" | "STAX";
1209
+ psdModel: "STAX";
1203
1210
  pubKey: string;
1204
1211
  registrationChallenge: {
1205
1212
  challenge: string;
@@ -1268,7 +1275,7 @@ declare const STEPS: {
1268
1275
  }[];
1269
1276
  sharedOwners: {
1270
1277
  name: string;
1271
- psdModel: "BLUE" | "STAX";
1278
+ psdModel: "STAX";
1272
1279
  pubKey: string;
1273
1280
  registrationChallenge: {
1274
1281
  challenge: string;
@@ -1351,11 +1358,13 @@ declare const STEPS: {
1351
1358
  readonly PENDING_EXTERNAL_SIGNERS_REGISTRATION: ({
1352
1359
  state,
1353
1360
  engine,
1354
- externalSigners
1361
+ externalSigners,
1362
+ debugAuthToken
1355
1363
  }: {
1356
1364
  engine: Engine<WithOnboarding>;
1357
1365
  state: OnboardingFullStateResponse;
1358
1366
  externalSigners?: string[];
1367
+ debugAuthToken?: string;
1359
1368
  }, logger: Logger) => Promise<{
1360
1369
  id: string;
1361
1370
  workspaceName: string;
@@ -1389,7 +1398,7 @@ declare const STEPS: {
1389
1398
  } | null;
1390
1399
  masterAdmins: {
1391
1400
  name: string;
1392
- psdModel: "BLUE" | "STAX";
1401
+ psdModel: "STAX";
1393
1402
  pubKey: string;
1394
1403
  registrationChallenge: {
1395
1404
  challenge: string;
@@ -1458,7 +1467,7 @@ declare const STEPS: {
1458
1467
  }[];
1459
1468
  sharedOwners: {
1460
1469
  name: string;
1461
- psdModel: "BLUE" | "STAX";
1470
+ psdModel: "STAX";
1462
1471
  pubKey: string;
1463
1472
  registrationChallenge: {
1464
1473
  challenge: string;
@@ -1548,6 +1557,7 @@ declare const STEPS: {
1548
1557
  engine: Engine<WithOnboarding>;
1549
1558
  state: OnboardingFullStateResponse;
1550
1559
  externalSigners?: string[];
1560
+ debugAuthToken?: string;
1551
1561
  }, logger: Logger) => Promise<{
1552
1562
  id: string;
1553
1563
  workspaceName: string;
@@ -1581,7 +1591,7 @@ declare const STEPS: {
1581
1591
  } | null;
1582
1592
  masterAdmins: {
1583
1593
  name: string;
1584
- psdModel: "BLUE" | "STAX";
1594
+ psdModel: "STAX";
1585
1595
  pubKey: string;
1586
1596
  registrationChallenge: {
1587
1597
  challenge: string;
@@ -1650,7 +1660,7 @@ declare const STEPS: {
1650
1660
  }[];
1651
1661
  sharedOwners: {
1652
1662
  name: string;
1653
- psdModel: "BLUE" | "STAX";
1663
+ psdModel: "STAX";
1654
1664
  pubKey: string;
1655
1665
  registrationChallenge: {
1656
1666
  challenge: string;
@@ -1740,6 +1750,7 @@ declare const STEPS: {
1740
1750
  engine: Engine<WithOnboarding>;
1741
1751
  state: OnboardingFullStateResponse;
1742
1752
  externalSigners?: string[];
1753
+ debugAuthToken?: string;
1743
1754
  }) => Promise<{
1744
1755
  id: string;
1745
1756
  workspaceName: string;
@@ -1773,7 +1784,7 @@ declare const STEPS: {
1773
1784
  } | null;
1774
1785
  masterAdmins: {
1775
1786
  name: string;
1776
- psdModel: "BLUE" | "STAX";
1787
+ psdModel: "STAX";
1777
1788
  pubKey: string;
1778
1789
  registrationChallenge: {
1779
1790
  challenge: string;
@@ -1842,7 +1853,7 @@ declare const STEPS: {
1842
1853
  }[];
1843
1854
  sharedOwners: {
1844
1855
  name: string;
1845
- psdModel: "BLUE" | "STAX";
1856
+ psdModel: "STAX";
1846
1857
  pubKey: string;
1847
1858
  registrationChallenge: {
1848
1859
  challenge: string;
@@ -1926,6 +1937,7 @@ declare const STEPS: {
1926
1937
  declare function onboard(opts: {
1927
1938
  engine: Engine<WithOnboarding>;
1928
1939
  externalSigners?: string[];
1940
+ debugAuthToken?: string;
1929
1941
  untilStep?: OnboardingStep;
1930
1942
  }, logger: Logger): Promise<void>;
1931
1943
  //#endregion
package/lib/onboarding.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { i as getMasterSeed } from "./crypto-DdEUFJar.js";
1
2
  import invariant from "invariant";
2
3
  import { match } from "ts-pattern";
3
4
  //#region src/onboarding.ts
@@ -160,10 +161,18 @@ const STEPS = {
160
161
  }));
161
162
  return engine.client.onboarding.commitReviewByMasterAdmins.mutate({ onboardingId });
162
163
  },
163
- PENDING_EXTERNAL_SIGNERS_REGISTRATION: async ({ state, engine, externalSigners }, logger) => {
164
+ PENDING_EXTERNAL_SIGNERS_REGISTRATION: async ({ state, engine, externalSigners, debugAuthToken }, logger) => {
164
165
  checkHsmHostingMode(state, "ON_PREM");
165
166
  invariant(externalSigners && externalSigners.length > 0, "External signers must exist");
166
167
  const { id: onboardingId } = state;
168
+ if (debugAuthToken) {
169
+ const masterSeed = await getMasterSeed(engine.__options.salt);
170
+ await engine.createClient({ debugAuthToken }).debug.insertExternalSignerSeed.mutate({
171
+ workspaceName: state.workspaceName,
172
+ seed: Buffer.from(masterSeed).toString("base64")
173
+ });
174
+ logger.info("Inserted external signer seed");
175
+ }
167
176
  state = await engine.client.onboarding.startExternalSignersRegistration.mutate({
168
177
  onboardingId,
169
178
  externalSigners
@@ -193,7 +202,7 @@ const STEPS = {
193
202
  PENDING_WORKSPACE_INITIALIZATION: async ({ state, engine }) => engine.client.onboarding.initializeWorkspace.mutate({ onboardingId: state.id })
194
203
  };
195
204
  async function onboard(opts, logger) {
196
- const { engine, externalSigners, untilStep } = opts;
205
+ const { engine, externalSigners, debugAuthToken, untilStep } = opts;
197
206
  const { __onboardingId } = engine;
198
207
  logger.info(`Joining onboarding ${__onboardingId}`);
199
208
  let state = await engine.client.onboarding.getOnboarding.query({ onboardingId: __onboardingId });
@@ -208,7 +217,8 @@ async function onboard(opts, logger) {
208
217
  state = await step({
209
218
  engine,
210
219
  state,
211
- externalSigners
220
+ externalSigners,
221
+ debugAuthToken
212
222
  }, logger);
213
223
  }
214
224
  }
@@ -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 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 externalSigners?: 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 externalSigners: string[] | undefined,\n): void => {\n const hasExternalSigners = externalSigners && externalSigners.length > 0;\n const errorMessage = match(state.hsmHostingMode)\n .with(\"HOSTED\", () =>\n !hasExternalSigners ? null : \"Hosted HSM does not support external signers\",\n )\n .with(\"ON_PREM\", () =>\n hasExternalSigners ? null : \"On-premises HSM requires at least 1 external signer\",\n )\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 /* 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 ({ state, engine, externalSigners }, logger) => {\n checkHsmHostingMode(state, \"ON_PREM\");\n invariant(externalSigners && externalSigners.length > 0, \"External signers must exist\");\n const { id: onboardingId } = state;\n state = await engine.client.onboarding.startExternalSignersRegistration.mutate({\n onboardingId,\n externalSigners,\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 externalSigners?: string[];\n untilStep?: OnboardingStep;\n },\n logger: Logger,\n): Promise<void> {\n const { engine, externalSigners, 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, externalSigners);\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, externalSigners }, logger);\n }\n}\n"],"mappings":"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"}
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 externalSigners?: string[];\n debugAuthToken?: 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 externalSigners: string[] | undefined,\n): void => {\n const hasExternalSigners = externalSigners && externalSigners.length > 0;\n const errorMessage = match(state.hsmHostingMode)\n .with(\"HOSTED\", () =>\n !hasExternalSigners ? null : \"Hosted HSM does not support external signers\",\n )\n .with(\"ON_PREM\", () =>\n hasExternalSigners ? null : \"On-premises HSM requires at least 1 external signer\",\n )\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 /* 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, externalSigners, debugAuthToken },\n logger,\n ) => {\n checkHsmHostingMode(state, \"ON_PREM\");\n invariant(externalSigners && externalSigners.length > 0, \"External signers must exist\");\n const { id: onboardingId } = state;\n if (debugAuthToken) {\n const masterSeed = await getMasterSeed(engine.__options.salt);\n await engine.createClient({ debugAuthToken }).debug.insertExternalSignerSeed.mutate({\n workspaceName: state.workspaceName,\n seed: Buffer.from(masterSeed).toString(\"base64\"),\n });\n logger.info(\"Inserted external signer seed\");\n }\n state = await engine.client.onboarding.startExternalSignersRegistration.mutate({\n onboardingId,\n externalSigners,\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 externalSigners?: string[];\n debugAuthToken?: string;\n untilStep?: OnboardingStep;\n },\n logger: Logger,\n): Promise<void> {\n const { engine, externalSigners, debugAuthToken, 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, externalSigners);\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, externalSigners, debugAuthToken }, logger);\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ledgerhq/revault-sdk",
3
- "version": "0.26.5",
3
+ "version": "0.26.7",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "files": [
@@ -47,6 +47,7 @@
47
47
  "@ledgerhq/errors": "^6.32.0",
48
48
  "@ledgerhq/hw-transport": "^6.34.1",
49
49
  "@noble/hashes": "^2.0.1",
50
+ "@scure/bip32": "^2.0.1",
50
51
  "@scure/bip39": "^2.0.1",
51
52
  "@trpc/client": "11.16.0",
52
53
  "@trpc/server": "11.16.0",
@@ -63,7 +64,7 @@
63
64
  "ts-pattern": "^5.9.0",
64
65
  "uuid": "^14.0.0",
65
66
  "zod": "^4.3.6",
66
- "@ledgerhq/revault-api": "1.61.0"
67
+ "@ledgerhq/revault-api": "1.62.1"
67
68
  },
68
69
  "devDependencies": {
69
70
  "@eslint/js": "^9.39.4",
@@ -1 +0,0 @@
1
- {"version":3,"file":"crypto-BDBF_rfw.cjs","names":["wordlist","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 { entropyToMnemonic } 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","// ========================================================================== //\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 await 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-CPCBrCSZ.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 { entropyToMnemonic } 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","// ========================================================================== //\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 await new jose.CompactSign(challengeDataBytes)\n .setProtectedHeader({ alg: \"ES256\", typ: \"JWT\" })\n .sign(privateKey);\n};\n"],"mappings":"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"}