@umbra-privacy/qos-ceremony 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
Binary file
|
|
Binary file
|
package/dist-cli/cli.js
CHANGED
|
@@ -6437,10 +6437,10 @@ var init_hex_encoding = __esm({
|
|
|
6437
6437
|
});
|
|
6438
6438
|
|
|
6439
6439
|
// ../../../node_modules/.pnpm/@smithy+core@3.29.6/node_modules/@smithy/core/dist-es/submodules/serde/util-body-length/calculateBodyLength.js
|
|
6440
|
-
var
|
|
6440
|
+
var import_node_fs11, calculateBodyLength;
|
|
6441
6441
|
var init_calculateBodyLength = __esm({
|
|
6442
6442
|
"../../../node_modules/.pnpm/@smithy+core@3.29.6/node_modules/@smithy/core/dist-es/submodules/serde/util-body-length/calculateBodyLength.js"() {
|
|
6443
|
-
|
|
6443
|
+
import_node_fs11 = require("node:fs");
|
|
6444
6444
|
calculateBodyLength = (body) => {
|
|
6445
6445
|
if (!body) {
|
|
6446
6446
|
return 0;
|
|
@@ -6453,11 +6453,11 @@ var init_calculateBodyLength = __esm({
|
|
|
6453
6453
|
return body.size;
|
|
6454
6454
|
} else if (typeof body.start === "number" && typeof body.end === "number") {
|
|
6455
6455
|
return body.end + 1 - body.start;
|
|
6456
|
-
} else if (body instanceof
|
|
6456
|
+
} else if (body instanceof import_node_fs11.ReadStream) {
|
|
6457
6457
|
if (body.path != null) {
|
|
6458
|
-
return (0,
|
|
6458
|
+
return (0, import_node_fs11.lstatSync)(body.path).size;
|
|
6459
6459
|
} else if (typeof body.fd === "number") {
|
|
6460
|
-
return (0,
|
|
6460
|
+
return (0, import_node_fs11.fstatSync)(body.fd).size;
|
|
6461
6461
|
}
|
|
6462
6462
|
}
|
|
6463
6463
|
throw new Error(`Body Length computation failed for ${body}`);
|
|
@@ -6756,11 +6756,11 @@ var init_types = __esm({
|
|
|
6756
6756
|
});
|
|
6757
6757
|
|
|
6758
6758
|
// ../../../node_modules/.pnpm/@smithy+core@3.29.6/node_modules/@smithy/core/dist-es/submodules/config/shared-ini-file-loader/getHomeDir.js
|
|
6759
|
-
var import_node_os4,
|
|
6759
|
+
var import_node_os4, import_node_path8, homeDirCache, getHomeDirCacheKey, getHomeDir;
|
|
6760
6760
|
var init_getHomeDir = __esm({
|
|
6761
6761
|
"../../../node_modules/.pnpm/@smithy+core@3.29.6/node_modules/@smithy/core/dist-es/submodules/config/shared-ini-file-loader/getHomeDir.js"() {
|
|
6762
6762
|
import_node_os4 = require("node:os");
|
|
6763
|
-
|
|
6763
|
+
import_node_path8 = require("node:path");
|
|
6764
6764
|
homeDirCache = {};
|
|
6765
6765
|
getHomeDirCacheKey = () => {
|
|
6766
6766
|
if (process && process.geteuid) {
|
|
@@ -6769,7 +6769,7 @@ var init_getHomeDir = __esm({
|
|
|
6769
6769
|
return "DEFAULT";
|
|
6770
6770
|
};
|
|
6771
6771
|
getHomeDir = () => {
|
|
6772
|
-
const { HOME, USERPROFILE, HOMEPATH, HOMEDRIVE = `C:${
|
|
6772
|
+
const { HOME, USERPROFILE, HOMEPATH, HOMEDRIVE = `C:${import_node_path8.sep}` } = process.env;
|
|
6773
6773
|
if (HOME)
|
|
6774
6774
|
return HOME;
|
|
6775
6775
|
if (USERPROFILE)
|
|
@@ -6795,16 +6795,16 @@ var init_getProfileName = __esm({
|
|
|
6795
6795
|
});
|
|
6796
6796
|
|
|
6797
6797
|
// ../../../node_modules/.pnpm/@smithy+core@3.29.6/node_modules/@smithy/core/dist-es/submodules/config/shared-ini-file-loader/getSSOTokenFilepath.js
|
|
6798
|
-
var import_node_crypto,
|
|
6798
|
+
var import_node_crypto, import_node_path9, getSSOTokenFilepath;
|
|
6799
6799
|
var init_getSSOTokenFilepath = __esm({
|
|
6800
6800
|
"../../../node_modules/.pnpm/@smithy+core@3.29.6/node_modules/@smithy/core/dist-es/submodules/config/shared-ini-file-loader/getSSOTokenFilepath.js"() {
|
|
6801
6801
|
import_node_crypto = require("node:crypto");
|
|
6802
|
-
|
|
6802
|
+
import_node_path9 = require("node:path");
|
|
6803
6803
|
init_getHomeDir();
|
|
6804
6804
|
getSSOTokenFilepath = (id) => {
|
|
6805
6805
|
const hasher = (0, import_node_crypto.createHash)("sha1");
|
|
6806
6806
|
const cacheName = hasher.update(id).digest("hex");
|
|
6807
|
-
return (0,
|
|
6807
|
+
return (0, import_node_path9.join)(getHomeDir(), ".aws", "sso", "cache", `${cacheName}.json`);
|
|
6808
6808
|
};
|
|
6809
6809
|
}
|
|
6810
6810
|
});
|
|
@@ -6859,24 +6859,24 @@ var init_getConfigData = __esm({
|
|
|
6859
6859
|
});
|
|
6860
6860
|
|
|
6861
6861
|
// ../../../node_modules/.pnpm/@smithy+core@3.29.6/node_modules/@smithy/core/dist-es/submodules/config/shared-ini-file-loader/getConfigFilepath.js
|
|
6862
|
-
var
|
|
6862
|
+
var import_node_path10, ENV_CONFIG_PATH, getConfigFilepath;
|
|
6863
6863
|
var init_getConfigFilepath = __esm({
|
|
6864
6864
|
"../../../node_modules/.pnpm/@smithy+core@3.29.6/node_modules/@smithy/core/dist-es/submodules/config/shared-ini-file-loader/getConfigFilepath.js"() {
|
|
6865
|
-
|
|
6865
|
+
import_node_path10 = require("node:path");
|
|
6866
6866
|
init_getHomeDir();
|
|
6867
6867
|
ENV_CONFIG_PATH = "AWS_CONFIG_FILE";
|
|
6868
|
-
getConfigFilepath = () => process.env[ENV_CONFIG_PATH] || (0,
|
|
6868
|
+
getConfigFilepath = () => process.env[ENV_CONFIG_PATH] || (0, import_node_path10.join)(getHomeDir(), ".aws", "config");
|
|
6869
6869
|
}
|
|
6870
6870
|
});
|
|
6871
6871
|
|
|
6872
6872
|
// ../../../node_modules/.pnpm/@smithy+core@3.29.6/node_modules/@smithy/core/dist-es/submodules/config/shared-ini-file-loader/getCredentialsFilepath.js
|
|
6873
|
-
var
|
|
6873
|
+
var import_node_path11, ENV_CREDENTIALS_PATH, getCredentialsFilepath;
|
|
6874
6874
|
var init_getCredentialsFilepath = __esm({
|
|
6875
6875
|
"../../../node_modules/.pnpm/@smithy+core@3.29.6/node_modules/@smithy/core/dist-es/submodules/config/shared-ini-file-loader/getCredentialsFilepath.js"() {
|
|
6876
|
-
|
|
6876
|
+
import_node_path11 = require("node:path");
|
|
6877
6877
|
init_getHomeDir();
|
|
6878
6878
|
ENV_CREDENTIALS_PATH = "AWS_SHARED_CREDENTIALS_FILE";
|
|
6879
|
-
getCredentialsFilepath = () => process.env[ENV_CREDENTIALS_PATH] || (0,
|
|
6879
|
+
getCredentialsFilepath = () => process.env[ENV_CREDENTIALS_PATH] || (0, import_node_path11.join)(getHomeDir(), ".aws", "credentials");
|
|
6880
6880
|
}
|
|
6881
6881
|
});
|
|
6882
6882
|
|
|
@@ -6956,10 +6956,10 @@ var init_readFile = __esm({
|
|
|
6956
6956
|
});
|
|
6957
6957
|
|
|
6958
6958
|
// ../../../node_modules/.pnpm/@smithy+core@3.29.6/node_modules/@smithy/core/dist-es/submodules/config/shared-ini-file-loader/loadSharedConfigFiles.js
|
|
6959
|
-
var
|
|
6959
|
+
var import_node_path12, swallowError, loadSharedConfigFiles;
|
|
6960
6960
|
var init_loadSharedConfigFiles = __esm({
|
|
6961
6961
|
"../../../node_modules/.pnpm/@smithy+core@3.29.6/node_modules/@smithy/core/dist-es/submodules/config/shared-ini-file-loader/loadSharedConfigFiles.js"() {
|
|
6962
|
-
|
|
6962
|
+
import_node_path12 = require("node:path");
|
|
6963
6963
|
init_getConfigData();
|
|
6964
6964
|
init_getConfigFilepath();
|
|
6965
6965
|
init_getCredentialsFilepath();
|
|
@@ -6974,11 +6974,11 @@ var init_loadSharedConfigFiles = __esm({
|
|
|
6974
6974
|
const relativeHomeDirPrefix = "~/";
|
|
6975
6975
|
let resolvedFilepath = filepath;
|
|
6976
6976
|
if (filepath.startsWith(relativeHomeDirPrefix)) {
|
|
6977
|
-
resolvedFilepath = (0,
|
|
6977
|
+
resolvedFilepath = (0, import_node_path12.join)(homeDir, filepath.slice(2));
|
|
6978
6978
|
}
|
|
6979
6979
|
let resolvedConfigFilepath = configFilepath;
|
|
6980
6980
|
if (configFilepath.startsWith(relativeHomeDirPrefix)) {
|
|
6981
|
-
resolvedConfigFilepath = (0,
|
|
6981
|
+
resolvedConfigFilepath = (0, import_node_path12.join)(homeDir, configFilepath.slice(2));
|
|
6982
6982
|
}
|
|
6983
6983
|
const parsedFiles = await Promise.all([
|
|
6984
6984
|
readFile2(resolvedConfigFilepath, {
|
|
@@ -10082,17 +10082,17 @@ var init_HashCalculator = __esm({
|
|
|
10082
10082
|
});
|
|
10083
10083
|
|
|
10084
10084
|
// ../../../node_modules/.pnpm/@smithy+core@3.29.6/node_modules/@smithy/core/dist-es/submodules/checksum/hash-stream-node/fileStreamHasher.js
|
|
10085
|
-
var
|
|
10085
|
+
var import_node_fs12, fileStreamHasher, isReadStream;
|
|
10086
10086
|
var init_fileStreamHasher = __esm({
|
|
10087
10087
|
"../../../node_modules/.pnpm/@smithy+core@3.29.6/node_modules/@smithy/core/dist-es/submodules/checksum/hash-stream-node/fileStreamHasher.js"() {
|
|
10088
|
-
|
|
10088
|
+
import_node_fs12 = require("node:fs");
|
|
10089
10089
|
init_HashCalculator();
|
|
10090
10090
|
fileStreamHasher = (hashCtor, fileStream) => new Promise((resolve2, reject) => {
|
|
10091
10091
|
if (!isReadStream(fileStream)) {
|
|
10092
10092
|
reject(new Error("Unable to calculate hash for non-file streams."));
|
|
10093
10093
|
return;
|
|
10094
10094
|
}
|
|
10095
|
-
const fileStreamTee = (0,
|
|
10095
|
+
const fileStreamTee = (0, import_node_fs12.createReadStream)(fileStream.path, {
|
|
10096
10096
|
start: fileStream.start,
|
|
10097
10097
|
end: fileStream.end
|
|
10098
10098
|
});
|
|
@@ -26697,7 +26697,7 @@ var require_dist_cjs11 = __commonJS({
|
|
|
26697
26697
|
var { createHash: createHash5, createPrivateKey, createPublicKey, sign: sign2 } = require("node:crypto");
|
|
26698
26698
|
var { promises } = require("node:fs");
|
|
26699
26699
|
var { homedir: homedir3 } = require("node:os");
|
|
26700
|
-
var { dirname:
|
|
26700
|
+
var { dirname: dirname6, join: join11 } = require("node:path");
|
|
26701
26701
|
var LoginCredentialsFetcher = class _LoginCredentialsFetcher {
|
|
26702
26702
|
profileData;
|
|
26703
26703
|
init;
|
|
@@ -26845,7 +26845,7 @@ var require_dist_cjs11 = __commonJS({
|
|
|
26845
26845
|
}
|
|
26846
26846
|
async saveToken(token) {
|
|
26847
26847
|
const tokenFilePath = this.getTokenFilePath();
|
|
26848
|
-
const directory =
|
|
26848
|
+
const directory = dirname6(tokenFilePath);
|
|
26849
26849
|
try {
|
|
26850
26850
|
await promises.mkdir(directory, { recursive: true });
|
|
26851
26851
|
} catch (error2) {
|
|
@@ -32821,12 +32821,18 @@ var parseMembersDoc = (value) => {
|
|
|
32821
32821
|
Object.entries(operators).map(([alias, entry]) => {
|
|
32822
32822
|
if (!isRecord(entry))
|
|
32823
32823
|
throw new Error(`members: '${alias}' is not an object`);
|
|
32824
|
-
const { pubkeyHex, encryptionKey } = entry;
|
|
32824
|
+
const { pubkeyHex, encryptionKey, encryptionKeySalt } = entry;
|
|
32825
32825
|
if (typeof pubkeyHex !== "string" || !HEX.test(pubkeyHex))
|
|
32826
32826
|
throw new Error(`members: '${alias}' has no hex pubkeyHex`);
|
|
32827
32827
|
if (encryptionKey !== void 0 && (typeof encryptionKey !== "string" || !HEX.test(encryptionKey)))
|
|
32828
32828
|
throw new Error(`members: '${alias}' has a non-hex encryptionKey`);
|
|
32829
|
-
|
|
32829
|
+
if (encryptionKeySalt !== void 0 && (typeof encryptionKeySalt !== "string" || !HEX.test(encryptionKeySalt)))
|
|
32830
|
+
throw new Error(`members: '${alias}' has a non-hex encryptionKeySalt`);
|
|
32831
|
+
const record = {
|
|
32832
|
+
pubkeyHex,
|
|
32833
|
+
...encryptionKey === void 0 ? {} : { encryptionKey },
|
|
32834
|
+
...encryptionKeySalt === void 0 ? {} : { encryptionKeySalt }
|
|
32835
|
+
};
|
|
32830
32836
|
return [alias, record];
|
|
32831
32837
|
})
|
|
32832
32838
|
);
|
|
@@ -33238,6 +33244,28 @@ var buildAtRestClient = (options) => {
|
|
|
33238
33244
|
],
|
|
33239
33245
|
Math.max(timeout, MINT_AT_REST_TIMEOUT_MS)
|
|
33240
33246
|
).trim(),
|
|
33247
|
+
saltOf: (request) => run2(atRestBin, [
|
|
33248
|
+
"key",
|
|
33249
|
+
request.keyPath,
|
|
33250
|
+
"--print-salt",
|
|
33251
|
+
...modeArgs(request.mode)
|
|
33252
|
+
]).trim(),
|
|
33253
|
+
recoverKey: (request) => run2(
|
|
33254
|
+
atRestBin,
|
|
33255
|
+
[
|
|
33256
|
+
"key",
|
|
33257
|
+
request.outPath,
|
|
33258
|
+
"--mode",
|
|
33259
|
+
"hardware",
|
|
33260
|
+
"--salt",
|
|
33261
|
+
request.salt,
|
|
33262
|
+
"--expect-public",
|
|
33263
|
+
request.expectPublic,
|
|
33264
|
+
"--challenge-command",
|
|
33265
|
+
request.challengeCommand
|
|
33266
|
+
],
|
|
33267
|
+
Math.max(timeout, MINT_AT_REST_TIMEOUT_MS)
|
|
33268
|
+
).trim(),
|
|
33241
33269
|
verifyKey: (request) => run2(atRestBin, [
|
|
33242
33270
|
"key",
|
|
33243
33271
|
request.keyPath,
|
|
@@ -33576,12 +33604,10 @@ var keygen = async (o3) => {
|
|
|
33576
33604
|
createQosClient({ bin, timeoutMs: PROVISION_TIMEOUT_MS }),
|
|
33577
33605
|
o3.provision === true
|
|
33578
33606
|
);
|
|
33579
|
-
const
|
|
33580
|
-
|
|
33581
|
-
|
|
33582
|
-
|
|
33583
|
-
);
|
|
33584
|
-
printRegistration(alias, pubHex, encryptionKey);
|
|
33607
|
+
const atRest = createAtRestFor(o3);
|
|
33608
|
+
const encryptionKey = ensureAtRestKey(atRest, keys, o3.challengeCommand);
|
|
33609
|
+
const salt = keys.mode === "hardware" ? atRest.saltOf({ keyPath: keys.encryptionKeyPath, mode: keys.mode }) : void 0;
|
|
33610
|
+
printRegistration(alias, pubHex, encryptionKey, salt);
|
|
33585
33611
|
};
|
|
33586
33612
|
var fileIdentity = (qos, secretPath) => {
|
|
33587
33613
|
const pubPath = `${secretPath}.pub`;
|
|
@@ -33626,7 +33652,7 @@ var ensureAtRestKey = (atRest, keys, challengeCommand) => {
|
|
|
33626
33652
|
);
|
|
33627
33653
|
return minted;
|
|
33628
33654
|
};
|
|
33629
|
-
var printRegistration = (alias, pubHex, encryptionKey) => {
|
|
33655
|
+
var printRegistration = (alias, pubHex, encryptionKey, salt) => {
|
|
33630
33656
|
console.log(
|
|
33631
33657
|
"\nRegister this operator (admin, IAM-gated) so it can join ceremonies:"
|
|
33632
33658
|
);
|
|
@@ -33634,7 +33660,7 @@ var printRegistration = (alias, pubHex, encryptionKey) => {
|
|
|
33634
33660
|
" aws lambda invoke --function-name qos-coordinator-admin-<stack> --cli-binary-format raw-in-base64-out \\"
|
|
33635
33661
|
);
|
|
33636
33662
|
console.log(
|
|
33637
|
-
` --payload '{"action":"register-operator","service":"<namespace>","alias":"${alias}","pubkeyHex":"${pubHex}","encryptionKey":"${encryptionKey}"
|
|
33663
|
+
` --payload '{"action":"register-operator","service":"<namespace>","alias":"${alias}","pubkeyHex":"${pubHex}","encryptionKey":"${encryptionKey}",` + (salt ? `"encryptionKeySalt":"${salt}",` : "") + `"sets":["manifest","share","patch"]}' /dev/stdout`
|
|
33638
33664
|
);
|
|
33639
33665
|
};
|
|
33640
33666
|
var resolveYubikeyPublic = (qos, provisioner, mayProvision) => {
|
|
@@ -33893,15 +33919,82 @@ var provisionTvc = async (o3, deps = {
|
|
|
33893
33919
|
}
|
|
33894
33920
|
};
|
|
33895
33921
|
|
|
33896
|
-
// src/commands/
|
|
33922
|
+
// src/commands/recover-key.ts
|
|
33897
33923
|
var import_node_fs9 = require("node:fs");
|
|
33924
|
+
var import_node_path7 = require("node:path");
|
|
33925
|
+
var localFiles = {
|
|
33926
|
+
exists: import_node_fs9.existsSync,
|
|
33927
|
+
makeDirectory: (path) => {
|
|
33928
|
+
(0, import_node_fs9.mkdirSync)(path, { recursive: true, mode: 448 });
|
|
33929
|
+
}
|
|
33930
|
+
};
|
|
33931
|
+
var required2 = (value, name) => {
|
|
33932
|
+
if (!value) throw new Error(`recover-key requires ${name}`);
|
|
33933
|
+
return value;
|
|
33934
|
+
};
|
|
33935
|
+
var recoverKey = async (o3, deps) => {
|
|
33936
|
+
const alias = required2(o3.alias ?? process.env.CEREMONY_ALIAS, "--alias");
|
|
33937
|
+
const namespace = required2(
|
|
33938
|
+
o3.namespace ?? process.env.CEREMONY_NAMESPACE,
|
|
33939
|
+
"--namespace"
|
|
33940
|
+
);
|
|
33941
|
+
const keys = resolveOperatorKeys(o3, alias);
|
|
33942
|
+
if (keys.mode !== "hardware")
|
|
33943
|
+
throw new Error(
|
|
33944
|
+
"recover-key rebuilds a --yubikey key file from its registered salt; a --secret-path key file holds the seed itself, which no registry has, so it can only come from your backup"
|
|
33945
|
+
);
|
|
33946
|
+
const files = deps?.files ?? localFiles;
|
|
33947
|
+
if (files.exists(keys.encryptionKeyPath))
|
|
33948
|
+
throw new Error(
|
|
33949
|
+
`${keys.encryptionKeyPath} already exists \u2014 nothing to recover; \`keygen --yubikey\` re-derives it from the device to prove it still matches`
|
|
33950
|
+
);
|
|
33951
|
+
const { atRest, api } = deps ?? {
|
|
33952
|
+
files,
|
|
33953
|
+
atRest: createAtRestFor(o3),
|
|
33954
|
+
api: createCeremonyApi(
|
|
33955
|
+
required2(o3.api ?? process.env.CEREMONY_API, "--api")
|
|
33956
|
+
)
|
|
33957
|
+
};
|
|
33958
|
+
const record = (await api.getMemberRecords(namespace, 0))[alias];
|
|
33959
|
+
if (!record) throw new Error(`'${alias}' is not registered for ${namespace}`);
|
|
33960
|
+
if (!record.encryptionKey || !record.encryptionKeySalt)
|
|
33961
|
+
throw new Error(
|
|
33962
|
+
`the ${namespace} registry holds no encryptionKeySalt for '${alias}', so there is nothing to recover from \u2014 restore the key file from its backup, and re-register with the payload \`qos-ceremony keygen\` prints so the salt is on record next time`
|
|
33963
|
+
);
|
|
33964
|
+
files.makeDirectory((0, import_node_path7.dirname)(keys.encryptionKeyPath));
|
|
33965
|
+
atRest.recoverKey({
|
|
33966
|
+
outPath: keys.encryptionKeyPath,
|
|
33967
|
+
salt: record.encryptionKeySalt,
|
|
33968
|
+
expectPublic: record.encryptionKey,
|
|
33969
|
+
challengeCommand: o3.challengeCommand ?? DEFAULT_CHALLENGE_COMMAND
|
|
33970
|
+
});
|
|
33971
|
+
console.log(
|
|
33972
|
+
`recover-key: rebuilt ${keys.encryptionKeyPath} from the registered salt and this YubiKey; it derives the registered encryptionKey`
|
|
33973
|
+
);
|
|
33974
|
+
console.error(
|
|
33975
|
+
atRestCustodyNotice("recover-key", "hardware", keys.encryptionKeyPath)
|
|
33976
|
+
);
|
|
33977
|
+
};
|
|
33978
|
+
|
|
33979
|
+
// src/commands/share.ts
|
|
33980
|
+
var import_node_fs10 = require("node:fs");
|
|
33898
33981
|
var requireEncryptionKeyPath = (ctx) => {
|
|
33899
|
-
if (!(0,
|
|
33982
|
+
if (!(0, import_node_fs10.existsSync)(ctx.encryptionKeyPath))
|
|
33900
33983
|
throw new Error(
|
|
33901
33984
|
`no at-rest key at ${ctx.encryptionKeyPath} \u2014 the share is sealed under it before upload; run \`qos-ceremony keygen --alias ${ctx.alias} ${ctx.mode === "hardware" ? "--yubikey" : "--secret-path"}\` first`
|
|
33902
33985
|
);
|
|
33903
33986
|
return ctx.encryptionKeyPath;
|
|
33904
33987
|
};
|
|
33988
|
+
var checkRegisteredSalt = (alias, localSalt, registered) => {
|
|
33989
|
+
if (!registered)
|
|
33990
|
+
throw new Error(
|
|
33991
|
+
`no encryptionKeySalt is registered for '${alias}', so nothing was uploaded \u2014 the registry must hold it before a share is frozen under your key, or a lost key file cannot be rebuilt; re-register with the payload \`qos-ceremony keygen\` prints`
|
|
33992
|
+
);
|
|
33993
|
+
if (registered.toLowerCase() !== localSalt.toLowerCase())
|
|
33994
|
+
throw new Error(
|
|
33995
|
+
`the encryptionKeySalt registered for '${alias}' is not your key file's \u2014 a mistyped salt would rebuild a key that opens nothing; re-register with replaceEncryptionKeySalt: true and the salt keygen prints`
|
|
33996
|
+
);
|
|
33997
|
+
};
|
|
33905
33998
|
var checkRegisteredKey = (alias, localKey, registered) => {
|
|
33906
33999
|
if (!registered)
|
|
33907
34000
|
throw new Error(
|
|
@@ -34090,6 +34183,12 @@ var share = async (o3) => {
|
|
|
34090
34183
|
ctx.atRest.publicKey({ keyPath: encryptionKeyPath, mode: ctx.mode }),
|
|
34091
34184
|
record.encryptionKey
|
|
34092
34185
|
);
|
|
34186
|
+
if (ctx.mode === "hardware")
|
|
34187
|
+
checkRegisteredSalt(
|
|
34188
|
+
ctx.alias,
|
|
34189
|
+
ctx.atRest.saltOf({ keyPath: encryptionKeyPath, mode: ctx.mode }),
|
|
34190
|
+
record.encryptionKeySalt
|
|
34191
|
+
);
|
|
34093
34192
|
const wd = createWorkdir("ceremony-share-");
|
|
34094
34193
|
try {
|
|
34095
34194
|
if (o3.response)
|
|
@@ -34375,6 +34474,11 @@ withCommon(
|
|
|
34375
34474
|
"with --yubikey, mint PIV 9c/9d only when qos_client reports them empty"
|
|
34376
34475
|
)
|
|
34377
34476
|
).action(run(keygen));
|
|
34477
|
+
withCommon(
|
|
34478
|
+
program2.command("recover-key").description(
|
|
34479
|
+
"rebuild a lost --yubikey at-rest key file from the salt the registry holds and this YubiKey"
|
|
34480
|
+
)
|
|
34481
|
+
).action(run(recoverKey));
|
|
34378
34482
|
withCommon(
|
|
34379
34483
|
program2.command("share").description(
|
|
34380
34484
|
"upload your quorum-key share: lift it out of the quorum-gen response (--response), prove it opens under your at-rest key, and upload it double-sealed"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umbra-privacy/qos-ceremony",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "QOS TEE operator ceremony CLI — keygen/share/approve/provision + shift-traffic over the coordinator API, and the at-rest sealing tools. Shares are double-sealed everywhere they rest: ML-KEM-1024 over the QOS P-256 envelope. All crypto runs in embedded binaries (qos_client, umbra-at-rest); your private key never leaves the device. Ships NO coordinator code.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"qos",
|