@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 +1 -1
- package/lib/bake.js +1 -1
- package/lib/{crypto-CPCBrCSZ.js → crypto-DdEUFJar.js} +19 -3
- package/lib/crypto-DdEUFJar.js.map +1 -0
- package/lib/{crypto-BDBF_rfw.cjs → crypto-rlKUKWhL.cjs} +22 -0
- package/lib/crypto-rlKUKWhL.cjs.map +1 -0
- package/lib/crypto.cjs +2 -1
- package/lib/crypto.d.cts +2 -1
- package/lib/crypto.d.ts +2 -1
- package/lib/crypto.js +2 -2
- package/lib/onboarding.cjs +13 -3
- package/lib/onboarding.cjs.map +1 -1
- package/lib/onboarding.d.cts +33 -21
- package/lib/onboarding.d.ts +33 -21
- package/lib/onboarding.js +13 -3
- package/lib/onboarding.js.map +1 -1
- package/package.json +3 -2
- package/lib/crypto-BDBF_rfw.cjs.map +0 -1
- package/lib/crypto-CPCBrCSZ.js.map +0 -1
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-
|
|
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-
|
|
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 {
|
|
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-
|
|
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-
|
|
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-
|
|
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 };
|
package/lib/onboarding.cjs
CHANGED
|
@@ -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
|
}
|
package/lib/onboarding.cjs.map
CHANGED
|
@@ -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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"}
|
package/lib/onboarding.d.cts
CHANGED
|
@@ -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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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.d.ts
CHANGED
|
@@ -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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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
|
}
|
package/lib/onboarding.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"onboarding.js","names":[],"sources":["../src/onboarding.ts"],"sourcesContent":["import type {\n ClaimedRole,\n HsmHostingMode,\n OnboardingFullStateResponse,\n OnboardingStep,\n} from \"@ledgerhq/revault-api\";\nimport invariant from \"invariant\";\nimport { match } from \"ts-pattern\";\n\nimport 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.
|
|
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.
|
|
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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"}
|