@learncard/sss-key-manager 0.2.1 → 0.2.2
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/dist/escrow-attestation.d.ts +2 -9
- package/dist/escrow-attestation.d.ts.map +1 -1
- package/dist/escrow-authority.d.ts +112 -0
- package/dist/escrow-authority.d.ts.map +1 -0
- package/dist/escrow-authority.types.d.ts +51 -0
- package/dist/escrow-authority.types.d.ts.map +1 -0
- package/dist/escrow-crypto.d.ts +9 -1
- package/dist/escrow-crypto.d.ts.map +1 -1
- package/dist/escrow-enrollment-intent.d.ts +13 -0
- package/dist/escrow-enrollment-intent.d.ts.map +1 -0
- package/dist/escrow-enrollment-intent.types.d.ts +28 -0
- package/dist/escrow-enrollment-intent.types.d.ts.map +1 -0
- package/dist/escrow-nitro-attestation.d.ts +2 -0
- package/dist/escrow-nitro-attestation.d.ts.map +1 -1
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/sss-key-manager.cjs.development.js +1592 -213
- package/dist/sss-key-manager.cjs.development.js.map +4 -4
- package/dist/sss-key-manager.cjs.production.min.js +28 -23
- package/dist/sss-key-manager.cjs.production.min.js.map +4 -4
- package/dist/sss-key-manager.esm.js +1107 -163
- package/dist/sss-key-manager.esm.js.map +4 -4
- package/dist/sss-strategy.d.ts.map +1 -1
- package/dist/types.d.ts +16 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/__fixtures__/escrow-authority-v1.json +96 -0
- package/src/__fixtures__/escrow-carry-contact-contract-v1.json +33 -0
- package/src/__fixtures__/escrow-enrollment-intent-v1.json +26 -0
- package/src/__fixtures__/nitro-attestation-real/staging-nsm-document.json +16 -0
- package/src/escrow-attestation.ts +10 -9
- package/src/escrow-authority.test.ts +643 -0
- package/src/escrow-authority.ts +597 -0
- package/src/escrow-authority.types.ts +56 -0
- package/src/escrow-crypto.ts +39 -1
- package/src/escrow-enrollment-intent.test.ts +224 -0
- package/src/escrow-enrollment-intent.ts +236 -0
- package/src/escrow-enrollment-intent.types.ts +28 -0
- package/src/escrow-nitro-attestation.test.ts +72 -0
- package/src/escrow-nitro-attestation.ts +34 -3
- package/src/index.ts +27 -0
- package/src/sss-authority.test.ts +889 -0
- package/src/sss-strategy.ts +479 -38
- package/src/types.ts +22 -3
|
@@ -574,7 +574,7 @@ var require_types_cjs_development = __commonJS({
|
|
|
574
574
|
_function: /* @__PURE__ */ __name(() => _function, "_function"),
|
|
575
575
|
any: /* @__PURE__ */ __name(() => any, "any"),
|
|
576
576
|
array: /* @__PURE__ */ __name(() => array, "array"),
|
|
577
|
-
base64: /* @__PURE__ */ __name(() =>
|
|
577
|
+
base64: /* @__PURE__ */ __name(() => base6422, "base64"),
|
|
578
578
|
base64url: /* @__PURE__ */ __name(() => base64url2, "base64url"),
|
|
579
579
|
bigint: /* @__PURE__ */ __name(() => bigint2, "bigint"),
|
|
580
580
|
boolean: /* @__PURE__ */ __name(() => boolean2, "boolean"),
|
|
@@ -615,7 +615,7 @@ var require_types_cjs_development = __commonJS({
|
|
|
615
615
|
gt: /* @__PURE__ */ __name(() => _gt, "gt"),
|
|
616
616
|
gte: /* @__PURE__ */ __name(() => _gte, "gte"),
|
|
617
617
|
guid: /* @__PURE__ */ __name(() => guid2, "guid"),
|
|
618
|
-
hash: /* @__PURE__ */ __name(() =>
|
|
618
|
+
hash: /* @__PURE__ */ __name(() => hash2, "hash"),
|
|
619
619
|
hex: /* @__PURE__ */ __name(() => hex22, "hex"),
|
|
620
620
|
hostname: /* @__PURE__ */ __name(() => hostname2, "hostname"),
|
|
621
621
|
httpUrl: /* @__PURE__ */ __name(() => httpUrl, "httpUrl"),
|
|
@@ -664,7 +664,7 @@ var require_types_cjs_development = __commonJS({
|
|
|
664
664
|
nullable: /* @__PURE__ */ __name(() => nullable, "nullable"),
|
|
665
665
|
nullish: /* @__PURE__ */ __name(() => nullish2, "nullish"),
|
|
666
666
|
number: /* @__PURE__ */ __name(() => number2, "number"),
|
|
667
|
-
object: /* @__PURE__ */ __name(() =>
|
|
667
|
+
object: /* @__PURE__ */ __name(() => object2, "object"),
|
|
668
668
|
optional: /* @__PURE__ */ __name(() => optional, "optional"),
|
|
669
669
|
overwrite: /* @__PURE__ */ __name(() => _overwrite, "overwrite"),
|
|
670
670
|
parse: /* @__PURE__ */ __name(() => parse2, "parse"),
|
|
@@ -1003,7 +1003,7 @@ var require_types_cjs_development = __commonJS({
|
|
|
1003
1003
|
util: /* @__PURE__ */ __name(() => util_exports, "util"),
|
|
1004
1004
|
version: /* @__PURE__ */ __name(() => version, "version")
|
|
1005
1005
|
});
|
|
1006
|
-
var
|
|
1006
|
+
var _a2;
|
|
1007
1007
|
var NEVER = /* @__PURE__ */ Object.freeze({
|
|
1008
1008
|
status: "aborted"
|
|
1009
1009
|
});
|
|
@@ -1026,9 +1026,9 @@ var require_types_cjs_development = __commonJS({
|
|
|
1026
1026
|
inst._zod.traits.add(name);
|
|
1027
1027
|
initializer3(inst, def);
|
|
1028
1028
|
const proto = _.prototype;
|
|
1029
|
-
const
|
|
1030
|
-
for (let i = 0; i <
|
|
1031
|
-
const k =
|
|
1029
|
+
const keys2 = Object.keys(proto);
|
|
1030
|
+
for (let i = 0; i < keys2.length; i++) {
|
|
1031
|
+
const k = keys2[i];
|
|
1032
1032
|
if (!(k in inst)) {
|
|
1033
1033
|
inst[k] = proto[k].bind(inst);
|
|
1034
1034
|
}
|
|
@@ -1095,7 +1095,7 @@ var require_types_cjs_development = __commonJS({
|
|
|
1095
1095
|
this.name = "ZodEncodeError";
|
|
1096
1096
|
}
|
|
1097
1097
|
};
|
|
1098
|
-
(
|
|
1098
|
+
(_a2 = globalThis).__zod_globalConfig ?? (_a2.__zod_globalConfig = {});
|
|
1099
1099
|
var globalConfig = globalThis.__zod_globalConfig;
|
|
1100
1100
|
function config(newConfig) {
|
|
1101
1101
|
if (newConfig)
|
|
@@ -1250,9 +1250,9 @@ var require_types_cjs_development = __commonJS({
|
|
|
1250
1250
|
__name(floatSafeRemainder, "floatSafeRemainder");
|
|
1251
1251
|
__name2(floatSafeRemainder, "floatSafeRemainder");
|
|
1252
1252
|
var EVALUATING = /* @__PURE__ */ Symbol("evaluating");
|
|
1253
|
-
function defineLazy(
|
|
1253
|
+
function defineLazy(object22, key, getter) {
|
|
1254
1254
|
let value = void 0;
|
|
1255
|
-
Object.defineProperty(
|
|
1255
|
+
Object.defineProperty(object22, key, {
|
|
1256
1256
|
get() {
|
|
1257
1257
|
if (value === EVALUATING) {
|
|
1258
1258
|
return void 0;
|
|
@@ -1264,7 +1264,7 @@ var require_types_cjs_development = __commonJS({
|
|
|
1264
1264
|
return value;
|
|
1265
1265
|
},
|
|
1266
1266
|
set(v) {
|
|
1267
|
-
Object.defineProperty(
|
|
1267
|
+
Object.defineProperty(object22, key, {
|
|
1268
1268
|
value: v
|
|
1269
1269
|
// configurable: true,
|
|
1270
1270
|
});
|
|
@@ -1312,12 +1312,12 @@ var require_types_cjs_development = __commonJS({
|
|
|
1312
1312
|
__name(getElementAtPath, "getElementAtPath");
|
|
1313
1313
|
__name2(getElementAtPath, "getElementAtPath");
|
|
1314
1314
|
function promiseAllObject(promisesObj) {
|
|
1315
|
-
const
|
|
1316
|
-
const promises =
|
|
1315
|
+
const keys2 = Object.keys(promisesObj);
|
|
1316
|
+
const promises = keys2.map((key) => promisesObj[key]);
|
|
1317
1317
|
return Promise.all(promises).then((results) => {
|
|
1318
1318
|
const resolvedObj = {};
|
|
1319
|
-
for (let i = 0; i <
|
|
1320
|
-
resolvedObj[
|
|
1319
|
+
for (let i = 0; i < keys2.length; i++) {
|
|
1320
|
+
resolvedObj[keys2[i]] = results[i];
|
|
1321
1321
|
}
|
|
1322
1322
|
return resolvedObj;
|
|
1323
1323
|
});
|
|
@@ -1857,18 +1857,18 @@ var require_types_cjs_development = __commonJS({
|
|
|
1857
1857
|
__name2(cleanEnum, "cleanEnum");
|
|
1858
1858
|
function base64ToUint8Array(base643) {
|
|
1859
1859
|
const binaryString = atob(base643);
|
|
1860
|
-
const
|
|
1860
|
+
const bytes3 = new Uint8Array(binaryString.length);
|
|
1861
1861
|
for (let i = 0; i < binaryString.length; i++) {
|
|
1862
|
-
|
|
1862
|
+
bytes3[i] = binaryString.charCodeAt(i);
|
|
1863
1863
|
}
|
|
1864
|
-
return
|
|
1864
|
+
return bytes3;
|
|
1865
1865
|
}
|
|
1866
1866
|
__name(base64ToUint8Array, "base64ToUint8Array");
|
|
1867
1867
|
__name2(base64ToUint8Array, "base64ToUint8Array");
|
|
1868
|
-
function uint8ArrayToBase64(
|
|
1868
|
+
function uint8ArrayToBase64(bytes3) {
|
|
1869
1869
|
let binaryString = "";
|
|
1870
|
-
for (let i = 0; i <
|
|
1871
|
-
binaryString += String.fromCharCode(
|
|
1870
|
+
for (let i = 0; i < bytes3.length; i++) {
|
|
1871
|
+
binaryString += String.fromCharCode(bytes3[i]);
|
|
1872
1872
|
}
|
|
1873
1873
|
return btoa(binaryString);
|
|
1874
1874
|
}
|
|
@@ -1881,8 +1881,8 @@ var require_types_cjs_development = __commonJS({
|
|
|
1881
1881
|
}
|
|
1882
1882
|
__name(base64urlToUint8Array, "base64urlToUint8Array");
|
|
1883
1883
|
__name2(base64urlToUint8Array, "base64urlToUint8Array");
|
|
1884
|
-
function uint8ArrayToBase64url(
|
|
1885
|
-
return uint8ArrayToBase64(
|
|
1884
|
+
function uint8ArrayToBase64url(bytes3) {
|
|
1885
|
+
return uint8ArrayToBase64(bytes3).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
1886
1886
|
}
|
|
1887
1887
|
__name(uint8ArrayToBase64url, "uint8ArrayToBase64url");
|
|
1888
1888
|
__name2(uint8ArrayToBase64url, "uint8ArrayToBase64url");
|
|
@@ -1891,16 +1891,16 @@ var require_types_cjs_development = __commonJS({
|
|
|
1891
1891
|
if (cleanHex.length % 2 !== 0) {
|
|
1892
1892
|
throw new Error("Invalid hex string length");
|
|
1893
1893
|
}
|
|
1894
|
-
const
|
|
1894
|
+
const bytes3 = new Uint8Array(cleanHex.length / 2);
|
|
1895
1895
|
for (let i = 0; i < cleanHex.length; i += 2) {
|
|
1896
|
-
|
|
1896
|
+
bytes3[i / 2] = Number.parseInt(cleanHex.slice(i, i + 2), 16);
|
|
1897
1897
|
}
|
|
1898
|
-
return
|
|
1898
|
+
return bytes3;
|
|
1899
1899
|
}
|
|
1900
1900
|
__name(hexToUint8Array, "hexToUint8Array");
|
|
1901
1901
|
__name2(hexToUint8Array, "hexToUint8Array");
|
|
1902
|
-
function uint8ArrayToHex(
|
|
1903
|
-
return Array.from(
|
|
1902
|
+
function uint8ArrayToHex(bytes3) {
|
|
1903
|
+
return Array.from(bytes3).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1904
1904
|
}
|
|
1905
1905
|
__name(uint8ArrayToHex, "uint8ArrayToHex");
|
|
1906
1906
|
__name2(uint8ArrayToHex, "uint8ArrayToHex");
|
|
@@ -2149,7 +2149,7 @@ var require_types_cjs_development = __commonJS({
|
|
|
2149
2149
|
var safeDecodeAsync = /* @__PURE__ */ _safeDecodeAsync($ZodRealError);
|
|
2150
2150
|
var regexes_exports = {};
|
|
2151
2151
|
__export2(regexes_exports, {
|
|
2152
|
-
base64: /* @__PURE__ */ __name(() =>
|
|
2152
|
+
base64: /* @__PURE__ */ __name(() => base642, "base64"),
|
|
2153
2153
|
base64url: /* @__PURE__ */ __name(() => base64url, "base64url"),
|
|
2154
2154
|
bigint: /* @__PURE__ */ __name(() => bigint, "bigint"),
|
|
2155
2155
|
boolean: /* @__PURE__ */ __name(() => boolean, "boolean"),
|
|
@@ -2172,7 +2172,7 @@ var require_types_cjs_development = __commonJS({
|
|
|
2172
2172
|
html5Email: /* @__PURE__ */ __name(() => html5Email, "html5Email"),
|
|
2173
2173
|
httpProtocol: /* @__PURE__ */ __name(() => httpProtocol, "httpProtocol"),
|
|
2174
2174
|
idnEmail: /* @__PURE__ */ __name(() => idnEmail, "idnEmail"),
|
|
2175
|
-
integer: /* @__PURE__ */ __name(() =>
|
|
2175
|
+
integer: /* @__PURE__ */ __name(() => integer3, "integer"),
|
|
2176
2176
|
ipv4: /* @__PURE__ */ __name(() => ipv4, "ipv4"),
|
|
2177
2177
|
ipv6: /* @__PURE__ */ __name(() => ipv6, "ipv6"),
|
|
2178
2178
|
ksuid: /* @__PURE__ */ __name(() => ksuid, "ksuid"),
|
|
@@ -2246,7 +2246,7 @@ var require_types_cjs_development = __commonJS({
|
|
|
2246
2246
|
}, "mac");
|
|
2247
2247
|
var cidrv4 = /^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/([0-9]|[1-2][0-9]|3[0-2])$/;
|
|
2248
2248
|
var cidrv6 = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/;
|
|
2249
|
-
var
|
|
2249
|
+
var base642 = /^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$/;
|
|
2250
2250
|
var base64url = /^[A-Za-z0-9_-]*$/;
|
|
2251
2251
|
var hostname = /^(?=.{1,253}\.?$)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[-0-9a-zA-Z]{0,61}[0-9a-zA-Z])?)*\.?$/;
|
|
2252
2252
|
var domain = /^([a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/;
|
|
@@ -2283,7 +2283,7 @@ var require_types_cjs_development = __commonJS({
|
|
|
2283
2283
|
return new RegExp(`^${regex}$`);
|
|
2284
2284
|
}, "string");
|
|
2285
2285
|
var bigint = /^-?\d+n?$/;
|
|
2286
|
-
var
|
|
2286
|
+
var integer3 = /^-?\d+$/;
|
|
2287
2287
|
var number = /^-?\d+(?:\.\d+)?$/;
|
|
2288
2288
|
var boolean = /^(?:true|false)$/i;
|
|
2289
2289
|
var _null = /^null$/i;
|
|
@@ -2417,7 +2417,7 @@ var require_types_cjs_development = __commonJS({
|
|
|
2417
2417
|
bag.minimum = minimum;
|
|
2418
2418
|
bag.maximum = maximum;
|
|
2419
2419
|
if (isInt)
|
|
2420
|
-
bag.pattern =
|
|
2420
|
+
bag.pattern = integer3;
|
|
2421
2421
|
});
|
|
2422
2422
|
inst._zod.check = (payload) => {
|
|
2423
2423
|
const input = payload.value;
|
|
@@ -3257,7 +3257,7 @@ var require_types_cjs_development = __commonJS({
|
|
|
3257
3257
|
__name(isValidBase64, "isValidBase64");
|
|
3258
3258
|
__name2(isValidBase64, "isValidBase64");
|
|
3259
3259
|
var $ZodBase64 = /* @__PURE__ */ $constructor("$ZodBase64", (inst, def) => {
|
|
3260
|
-
def.pattern ?? (def.pattern =
|
|
3260
|
+
def.pattern ?? (def.pattern = base642);
|
|
3261
3261
|
$ZodStringFormat.init(inst, def);
|
|
3262
3262
|
inst._zod.bag.contentEncoding = "base64";
|
|
3263
3263
|
inst._zod.check = (payload) => {
|
|
@@ -3603,8 +3603,8 @@ var require_types_cjs_development = __commonJS({
|
|
|
3603
3603
|
__name(handlePropertyResult, "handlePropertyResult");
|
|
3604
3604
|
__name2(handlePropertyResult, "handlePropertyResult");
|
|
3605
3605
|
function normalizeDef(def) {
|
|
3606
|
-
const
|
|
3607
|
-
for (const k of
|
|
3606
|
+
const keys2 = Object.keys(def.shape);
|
|
3607
|
+
for (const k of keys2) {
|
|
3608
3608
|
if (!def.shape?.[k]?._zod?.traits?.has("$ZodType")) {
|
|
3609
3609
|
throw new Error(`Invalid element at key "${k}": expected a Zod schema`);
|
|
3610
3610
|
}
|
|
@@ -3612,9 +3612,9 @@ var require_types_cjs_development = __commonJS({
|
|
|
3612
3612
|
const okeys = optionalKeys(def.shape);
|
|
3613
3613
|
return {
|
|
3614
3614
|
...def,
|
|
3615
|
-
keys,
|
|
3616
|
-
keySet: new Set(
|
|
3617
|
-
numKeys:
|
|
3615
|
+
keys: keys2,
|
|
3616
|
+
keySet: new Set(keys2),
|
|
3617
|
+
numKeys: keys2.length,
|
|
3618
3618
|
optionalKeys: new Set(okeys)
|
|
3619
3619
|
};
|
|
3620
3620
|
}
|
|
@@ -8376,8 +8376,8 @@ var require_types_cjs_development = __commonJS({
|
|
|
8376
8376
|
}
|
|
8377
8377
|
__name(ko_default, "ko_default");
|
|
8378
8378
|
__name2(ko_default, "default");
|
|
8379
|
-
var capitalizeFirstCharacter = /* @__PURE__ */ __name2((
|
|
8380
|
-
return
|
|
8379
|
+
var capitalizeFirstCharacter = /* @__PURE__ */ __name2((text2) => {
|
|
8380
|
+
return text2.charAt(0).toUpperCase() + text2.slice(1);
|
|
8381
8381
|
}, "capitalizeFirstCharacter");
|
|
8382
8382
|
function getUnitTypeFromNumber(number4) {
|
|
8383
8383
|
const abs = Math.abs(number4);
|
|
@@ -11109,7 +11109,7 @@ var require_types_cjs_development = __commonJS({
|
|
|
11109
11109
|
}
|
|
11110
11110
|
__name(yo_default, "yo_default");
|
|
11111
11111
|
__name2(yo_default, "default");
|
|
11112
|
-
var
|
|
11112
|
+
var _a22;
|
|
11113
11113
|
var $output = /* @__PURE__ */ Symbol("ZodOutput");
|
|
11114
11114
|
var $input = /* @__PURE__ */ Symbol("ZodInput");
|
|
11115
11115
|
var $ZodRegistry = class {
|
|
@@ -11163,7 +11163,7 @@ var require_types_cjs_development = __commonJS({
|
|
|
11163
11163
|
}
|
|
11164
11164
|
__name(registry, "registry");
|
|
11165
11165
|
__name2(registry, "registry");
|
|
11166
|
-
(
|
|
11166
|
+
(_a22 = globalThis).__zod_globalRegistry ?? (_a22.__zod_globalRegistry = registry());
|
|
11167
11167
|
var globalRegistry = globalThis.__zod_globalRegistry;
|
|
11168
11168
|
// @__NO_SIDE_EFFECTS__
|
|
11169
11169
|
function _string(Class2, params) {
|
|
@@ -13497,7 +13497,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
13497
13497
|
_function: /* @__PURE__ */ __name(() => _function, "_function"),
|
|
13498
13498
|
any: /* @__PURE__ */ __name(() => any, "any"),
|
|
13499
13499
|
array: /* @__PURE__ */ __name(() => array, "array"),
|
|
13500
|
-
base64: /* @__PURE__ */ __name(() =>
|
|
13500
|
+
base64: /* @__PURE__ */ __name(() => base6422, "base64"),
|
|
13501
13501
|
base64url: /* @__PURE__ */ __name(() => base64url2, "base64url"),
|
|
13502
13502
|
bigint: /* @__PURE__ */ __name(() => bigint2, "bigint"),
|
|
13503
13503
|
boolean: /* @__PURE__ */ __name(() => boolean2, "boolean"),
|
|
@@ -13522,7 +13522,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
13522
13522
|
float64: /* @__PURE__ */ __name(() => float64, "float64"),
|
|
13523
13523
|
function: /* @__PURE__ */ __name(() => _function, "function"),
|
|
13524
13524
|
guid: /* @__PURE__ */ __name(() => guid2, "guid"),
|
|
13525
|
-
hash: /* @__PURE__ */ __name(() =>
|
|
13525
|
+
hash: /* @__PURE__ */ __name(() => hash2, "hash"),
|
|
13526
13526
|
hex: /* @__PURE__ */ __name(() => hex22, "hex"),
|
|
13527
13527
|
hostname: /* @__PURE__ */ __name(() => hostname2, "hostname"),
|
|
13528
13528
|
httpUrl: /* @__PURE__ */ __name(() => httpUrl, "httpUrl"),
|
|
@@ -13554,7 +13554,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
13554
13554
|
nullable: /* @__PURE__ */ __name(() => nullable, "nullable"),
|
|
13555
13555
|
nullish: /* @__PURE__ */ __name(() => nullish2, "nullish"),
|
|
13556
13556
|
number: /* @__PURE__ */ __name(() => number2, "number"),
|
|
13557
|
-
object: /* @__PURE__ */ __name(() =>
|
|
13557
|
+
object: /* @__PURE__ */ __name(() => object2, "object"),
|
|
13558
13558
|
optional: /* @__PURE__ */ __name(() => optional, "optional"),
|
|
13559
13559
|
partialRecord: /* @__PURE__ */ __name(() => partialRecord, "partialRecord"),
|
|
13560
13560
|
pipe: /* @__PURE__ */ __name(() => pipe, "pipe"),
|
|
@@ -14155,11 +14155,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
14155
14155
|
$ZodBase64.init(inst, def);
|
|
14156
14156
|
ZodStringFormat.init(inst, def);
|
|
14157
14157
|
});
|
|
14158
|
-
function
|
|
14158
|
+
function base6422(params) {
|
|
14159
14159
|
return /* @__PURE__ */ _base64(ZodBase64, params);
|
|
14160
14160
|
}
|
|
14161
|
-
__name(
|
|
14162
|
-
__name2(
|
|
14161
|
+
__name(base6422, "base642");
|
|
14162
|
+
__name2(base6422, "base64");
|
|
14163
14163
|
var ZodBase64URL = /* @__PURE__ */ $constructor("ZodBase64URL", (inst, def) => {
|
|
14164
14164
|
$ZodBase64URL.init(inst, def);
|
|
14165
14165
|
ZodStringFormat.init(inst, def);
|
|
@@ -14206,7 +14206,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
14206
14206
|
}
|
|
14207
14207
|
__name(hex22, "hex2");
|
|
14208
14208
|
__name2(hex22, "hex");
|
|
14209
|
-
function
|
|
14209
|
+
function hash2(alg, params) {
|
|
14210
14210
|
const enc = params?.enc ?? "hex";
|
|
14211
14211
|
const format = `${alg}_${enc}`;
|
|
14212
14212
|
const regex = regexes_exports[format];
|
|
@@ -14214,8 +14214,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
14214
14214
|
throw new Error(`Unrecognized hash format: ${format}`);
|
|
14215
14215
|
return /* @__PURE__ */ _stringFormat(ZodCustomStringFormat, format, regex, params);
|
|
14216
14216
|
}
|
|
14217
|
-
__name(
|
|
14218
|
-
__name2(
|
|
14217
|
+
__name(hash2, "hash");
|
|
14218
|
+
__name2(hash2, "hash");
|
|
14219
14219
|
var ZodNumber = /* @__PURE__ */ $constructor("ZodNumber", (inst, def) => {
|
|
14220
14220
|
$ZodNumber.init(inst, def);
|
|
14221
14221
|
ZodType.init(inst, def);
|
|
@@ -14527,7 +14527,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
14527
14527
|
}
|
|
14528
14528
|
});
|
|
14529
14529
|
});
|
|
14530
|
-
function
|
|
14530
|
+
function object2(shape, params) {
|
|
14531
14531
|
const def = {
|
|
14532
14532
|
type: "object",
|
|
14533
14533
|
shape: shape ?? {},
|
|
@@ -14535,8 +14535,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
14535
14535
|
};
|
|
14536
14536
|
return new ZodObject(def);
|
|
14537
14537
|
}
|
|
14538
|
-
__name(
|
|
14539
|
-
__name2(
|
|
14538
|
+
__name(object2, "object");
|
|
14539
|
+
__name2(object2, "object");
|
|
14540
14540
|
function strictObject(shape, params) {
|
|
14541
14541
|
return new ZodObject({
|
|
14542
14542
|
type: "object",
|
|
@@ -14731,11 +14731,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
14731
14731
|
inst._zod.processJSONSchema = (ctx, json2, params) => enumProcessor(inst, ctx, json2, params);
|
|
14732
14732
|
inst.enum = def.entries;
|
|
14733
14733
|
inst.options = Object.values(def.entries);
|
|
14734
|
-
const
|
|
14734
|
+
const keys2 = new Set(Object.keys(def.entries));
|
|
14735
14735
|
inst.extract = (values, params) => {
|
|
14736
14736
|
const newEntries = {};
|
|
14737
14737
|
for (const value of values) {
|
|
14738
|
-
if (
|
|
14738
|
+
if (keys2.has(value)) {
|
|
14739
14739
|
newEntries[value] = def.entries[value];
|
|
14740
14740
|
} else
|
|
14741
14741
|
throw new Error(`Key ${value} not found in enum`);
|
|
@@ -14750,7 +14750,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
14750
14750
|
inst.exclude = (values, params) => {
|
|
14751
14751
|
const newEntries = { ...def.entries };
|
|
14752
14752
|
for (const value of values) {
|
|
14753
|
-
if (
|
|
14753
|
+
if (keys2.has(value)) {
|
|
14754
14754
|
delete newEntries[value];
|
|
14755
14755
|
} else
|
|
14756
14756
|
throw new Error(`Key ${value} not found in enum`);
|
|
@@ -15886,7 +15886,18 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15886
15886
|
verificationMethod: external_exports.string(),
|
|
15887
15887
|
jws: external_exports.string().optional()
|
|
15888
15888
|
}).catchall(external_exports.any()).superRefine((proof, ctx) => {
|
|
15889
|
-
if (proof.created === void 0 &&
|
|
15889
|
+
if (proof.created === void 0 && // These standardized Data Integrity suites make created optional.
|
|
15890
|
+
// Keep the prior requirement for legacy and unknown proof suites.
|
|
15891
|
+
// https://www.w3.org/TR/vc-di-eddsa/#proof-configuration-eddsa-jcs-2022
|
|
15892
|
+
// https://www.w3.org/TR/vc-di-bbs/#proof-configuration
|
|
15893
|
+
(proof.type !== "DataIntegrityProof" || ![
|
|
15894
|
+
"ecdsa-rdfc-2019",
|
|
15895
|
+
"ecdsa-jcs-2019",
|
|
15896
|
+
"ecdsa-sd-2023",
|
|
15897
|
+
"eddsa-rdfc-2022",
|
|
15898
|
+
"eddsa-jcs-2022",
|
|
15899
|
+
"bbs-2023"
|
|
15900
|
+
].includes(proof.cryptosuite))) {
|
|
15890
15901
|
ctx.addIssue({
|
|
15891
15902
|
code: "custom",
|
|
15892
15903
|
path: ["created"],
|
|
@@ -18525,12 +18536,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18525
18536
|
}
|
|
18526
18537
|
return table;
|
|
18527
18538
|
})();
|
|
18528
|
-
var encodeBase64Url = /* @__PURE__ */ __name2((
|
|
18539
|
+
var encodeBase64Url = /* @__PURE__ */ __name2((bytes3) => {
|
|
18529
18540
|
let output = "";
|
|
18530
|
-
for (let index = 0; index <
|
|
18531
|
-
const first =
|
|
18532
|
-
const second =
|
|
18533
|
-
const third =
|
|
18541
|
+
for (let index = 0; index < bytes3.length; index += 3) {
|
|
18542
|
+
const first = bytes3[index];
|
|
18543
|
+
const second = bytes3[index + 1];
|
|
18544
|
+
const third = bytes3[index + 2];
|
|
18534
18545
|
output += BASE64URL_ALPHABET[first >> 2];
|
|
18535
18546
|
output += BASE64URL_ALPHABET[(first & 3) << 4 | (second ?? 0) >> 4];
|
|
18536
18547
|
if (second === void 0) break;
|
|
@@ -18571,8 +18582,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18571
18582
|
}, "isCanonicalBase64Url");
|
|
18572
18583
|
var decodedBase64UrlByteLength = /* @__PURE__ */ __name2((value) => decodeBase64Url(value)?.length ?? null, "decodedBase64UrlByteLength");
|
|
18573
18584
|
var utf8ByteLength = /* @__PURE__ */ __name2((value) => new TextEncoder().encode(value).length, "utf8ByteLength");
|
|
18574
|
-
var canonicalBase64Url = /* @__PURE__ */ __name2((
|
|
18575
|
-
message: `must be canonical base64url for exactly ${
|
|
18585
|
+
var canonicalBase64Url = /* @__PURE__ */ __name2((bytes3) => external_exports.string().refine((value) => isCanonicalBase64Url(value, bytes3), {
|
|
18586
|
+
message: `must be canonical base64url for exactly ${bytes3} bytes`
|
|
18576
18587
|
}), "canonicalBase64Url");
|
|
18577
18588
|
var ShareLinkIdValidator = canonicalBase64Url(SHARE_LINK_ID_BYTES);
|
|
18578
18589
|
var ShareContentKeyValidator = canonicalBase64Url(SHARE_CONTENT_KEY_BYTES);
|
|
@@ -19025,9 +19036,11 @@ __export(index_exports, {
|
|
|
19025
19036
|
ESCROW_ALGORITHM: () => ESCROW_ALGORITHM,
|
|
19026
19037
|
ESCROW_BLOB_INFO: () => ESCROW_BLOB_INFO,
|
|
19027
19038
|
ESCROW_CLIENT_KEY_ID: () => ESCROW_CLIENT_KEY_ID,
|
|
19039
|
+
ESCROW_ENROLLMENT_INTENT_DOMAIN: () => ESCROW_ENROLLMENT_INTENT_DOMAIN,
|
|
19028
19040
|
ESCROW_ENVELOPE_VERSION: () => ESCROW_ENVELOPE_VERSION,
|
|
19029
19041
|
ESCROW_PIN_MAX_ATTEMPTS: () => ESCROW_PIN_MAX_ATTEMPTS,
|
|
19030
19042
|
ESCROW_RELEASE_INFO: () => ESCROW_RELEASE_INFO,
|
|
19043
|
+
EscrowEvidenceError: () => EscrowEvidenceError,
|
|
19031
19044
|
EscrowHoldRestartThrottledError: () => EscrowHoldRestartThrottledError,
|
|
19032
19045
|
EscrowPinLockedError: () => EscrowPinLockedError,
|
|
19033
19046
|
EscrowPinMismatchError: () => EscrowPinMismatchError,
|
|
@@ -19055,6 +19068,7 @@ __export(index_exports, {
|
|
|
19055
19068
|
constantTimeEqualHex: () => constantTimeEqualHex,
|
|
19056
19069
|
countWords: () => countWords,
|
|
19057
19070
|
createAdaptiveStorage: () => createAdaptiveStorage,
|
|
19071
|
+
createEscrowEnrollmentIntent: () => createEscrowEnrollmentIntent,
|
|
19058
19072
|
createPasskeyCredential: () => createPasskeyCredential,
|
|
19059
19073
|
createQrLoginSession: () => createQrLoginSession,
|
|
19060
19074
|
createSSSKeyManager: () => createSSSKeyManager,
|
|
@@ -19068,6 +19082,7 @@ __export(index_exports, {
|
|
|
19068
19082
|
deriveKeyFromPasskey: () => deriveKeyFromPasskey,
|
|
19069
19083
|
deriveKeyFromPassword: () => deriveKeyFromPassword,
|
|
19070
19084
|
derivePinProof: () => derivePinProof,
|
|
19085
|
+
encodeEscrowEnrollmentIntent: () => encodeEscrowEnrollmentIntent,
|
|
19071
19086
|
encryptEmailRelayPayload: () => encryptEmailRelayPayload,
|
|
19072
19087
|
encryptEscrowBlob: () => encryptEscrowBlob,
|
|
19073
19088
|
encryptShareForTransfer: () => encryptShareForTransfer,
|
|
@@ -19080,6 +19095,7 @@ __export(index_exports, {
|
|
|
19080
19095
|
generatePinSalt: () => generatePinSalt,
|
|
19081
19096
|
generateRecoveryPhrase: () => generateRecoveryPhrase,
|
|
19082
19097
|
getDeviceShare: () => getDeviceShare,
|
|
19098
|
+
getEscrowBlobIdentity: () => getEscrowBlobIdentity,
|
|
19083
19099
|
getQrLoginSessionInfo: () => getQrLoginSessionInfo,
|
|
19084
19100
|
getShareVersion: () => getShareVersion,
|
|
19085
19101
|
hasDeviceShare: () => hasDeviceShare,
|
|
@@ -19101,9 +19117,11 @@ __export(index_exports, {
|
|
|
19101
19117
|
reconstructFromShares: () => reconstructFromShares,
|
|
19102
19118
|
reconstructPrivateKey: () => reconstructPrivateKey,
|
|
19103
19119
|
recoveryPhraseToShare: () => recoveryPhraseToShare,
|
|
19120
|
+
resolveEscrowEnrollmentAction: () => resolveEscrowEnrollmentAction,
|
|
19104
19121
|
sealEscrowRelease: () => sealEscrowRelease,
|
|
19105
19122
|
setPublicComputerMode: () => setPublicComputerMode,
|
|
19106
19123
|
shareToRecoveryPhrase: () => shareToRecoveryPhrase,
|
|
19124
|
+
signEscrowEnrollmentIntent: () => signEscrowEnrollmentIntent,
|
|
19107
19125
|
splitAndVerify: () => splitAndVerify,
|
|
19108
19126
|
splitPrivateKey: () => splitPrivateKey,
|
|
19109
19127
|
storeDeviceShare: () => storeDeviceShare,
|
|
@@ -19111,8 +19129,11 @@ __export(index_exports, {
|
|
|
19111
19129
|
validatePin: () => validatePin,
|
|
19112
19130
|
validateRecoveryPhrase: () => validateRecoveryPhrase,
|
|
19113
19131
|
verifyEnclaveAttestation: () => verifyEnclaveAttestation,
|
|
19132
|
+
verifyEscrowAuthorityState: () => verifyEscrowAuthorityState,
|
|
19133
|
+
verifyEscrowEnrollmentCommit: () => verifyEscrowEnrollmentCommit,
|
|
19114
19134
|
verifyNitroAttestationDocument: () => verifyNitroAttestationDocument,
|
|
19115
|
-
verifyStoredShares: () => verifyStoredShares
|
|
19135
|
+
verifyStoredShares: () => verifyStoredShares,
|
|
19136
|
+
violatesCarryContactRule: () => violatesCarryContactRule
|
|
19116
19137
|
});
|
|
19117
19138
|
module.exports = __toCommonJS(index_exports);
|
|
19118
19139
|
|
|
@@ -19273,37 +19294,37 @@ var DEFAULT_KDF_PARAMS = {
|
|
|
19273
19294
|
parallelism: ARGON2_PARALLELISM
|
|
19274
19295
|
};
|
|
19275
19296
|
function bufferToBase64(buf) {
|
|
19276
|
-
const
|
|
19297
|
+
const bytes3 = new Uint8Array(buf);
|
|
19277
19298
|
let binary = "";
|
|
19278
|
-
for (let i = 0; i <
|
|
19279
|
-
binary += String.fromCharCode(
|
|
19299
|
+
for (let i = 0; i < bytes3.byteLength; i++) {
|
|
19300
|
+
binary += String.fromCharCode(bytes3[i]);
|
|
19280
19301
|
}
|
|
19281
19302
|
return btoa(binary);
|
|
19282
19303
|
}
|
|
19283
19304
|
__name(bufferToBase64, "bufferToBase64");
|
|
19284
19305
|
function base64ToBuffer(b64) {
|
|
19285
19306
|
const binary = atob(b64);
|
|
19286
|
-
const
|
|
19307
|
+
const bytes3 = new Uint8Array(binary.length);
|
|
19287
19308
|
for (let i = 0; i < binary.length; i++) {
|
|
19288
|
-
|
|
19309
|
+
bytes3[i] = binary.charCodeAt(i);
|
|
19289
19310
|
}
|
|
19290
|
-
return
|
|
19311
|
+
return bytes3;
|
|
19291
19312
|
}
|
|
19292
19313
|
__name(base64ToBuffer, "base64ToBuffer");
|
|
19293
19314
|
function hexToBytes(hex2) {
|
|
19294
|
-
const
|
|
19315
|
+
const bytes3 = new Uint8Array(hex2.length / 2);
|
|
19295
19316
|
for (let i = 0; i < hex2.length; i += 2) {
|
|
19296
|
-
|
|
19317
|
+
bytes3[i / 2] = parseInt(hex2.slice(i, i + 2), 16);
|
|
19297
19318
|
}
|
|
19298
|
-
return
|
|
19319
|
+
return bytes3;
|
|
19299
19320
|
}
|
|
19300
19321
|
__name(hexToBytes, "hexToBytes");
|
|
19301
|
-
function bytesToHex(
|
|
19302
|
-
return Array.from(
|
|
19322
|
+
function bytesToHex(bytes3) {
|
|
19323
|
+
return Array.from(bytes3).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
19303
19324
|
}
|
|
19304
19325
|
__name(bytesToHex, "bytesToHex");
|
|
19305
19326
|
async function deriveKeyFromPassword(password, salt, params = DEFAULT_KDF_PARAMS) {
|
|
19306
|
-
const
|
|
19327
|
+
const hash2 = await (0, import_hash_wasm.argon2id)({
|
|
19307
19328
|
password,
|
|
19308
19329
|
salt,
|
|
19309
19330
|
iterations: params.timeCost,
|
|
@@ -19312,7 +19333,7 @@ async function deriveKeyFromPassword(password, salt, params = DEFAULT_KDF_PARAMS
|
|
|
19312
19333
|
hashLength: ARGON2_HASH_LENGTH,
|
|
19313
19334
|
outputType: "binary"
|
|
19314
19335
|
});
|
|
19315
|
-
return Uint8Array.from(
|
|
19336
|
+
return Uint8Array.from(hash2);
|
|
19316
19337
|
}
|
|
19317
19338
|
__name(deriveKeyFromPassword, "deriveKeyFromPassword");
|
|
19318
19339
|
async function encryptWithPassword(plaintext, password) {
|
|
@@ -19466,21 +19487,21 @@ async function getOrCreateMasterKey() {
|
|
|
19466
19487
|
}
|
|
19467
19488
|
__name(getOrCreateMasterKey, "getOrCreateMasterKey");
|
|
19468
19489
|
function bufferToBase642(buf) {
|
|
19469
|
-
const
|
|
19490
|
+
const bytes3 = new Uint8Array(buf);
|
|
19470
19491
|
let binary = "";
|
|
19471
|
-
for (let i = 0; i <
|
|
19472
|
-
binary += String.fromCharCode(
|
|
19492
|
+
for (let i = 0; i < bytes3.byteLength; i++) {
|
|
19493
|
+
binary += String.fromCharCode(bytes3[i]);
|
|
19473
19494
|
}
|
|
19474
19495
|
return btoa(binary);
|
|
19475
19496
|
}
|
|
19476
19497
|
__name(bufferToBase642, "bufferToBase64");
|
|
19477
19498
|
function base64ToBuffer2(b64) {
|
|
19478
19499
|
const binary = atob(b64);
|
|
19479
|
-
const
|
|
19500
|
+
const bytes3 = new Uint8Array(binary.length);
|
|
19480
19501
|
for (let i = 0; i < binary.length; i++) {
|
|
19481
|
-
|
|
19502
|
+
bytes3[i] = binary.charCodeAt(i);
|
|
19482
19503
|
}
|
|
19483
|
-
return
|
|
19504
|
+
return bytes3.buffer;
|
|
19484
19505
|
}
|
|
19485
19506
|
__name(base64ToBuffer2, "base64ToBuffer");
|
|
19486
19507
|
async function encryptShare(share, id) {
|
|
@@ -19888,21 +19909,21 @@ async function getWordlist() {
|
|
|
19888
19909
|
return wordlistPromise;
|
|
19889
19910
|
}
|
|
19890
19911
|
__name(getWordlist, "getWordlist");
|
|
19891
|
-
function bytesToBits(
|
|
19892
|
-
return Array.from(
|
|
19912
|
+
function bytesToBits(bytes3) {
|
|
19913
|
+
return Array.from(bytes3).map((b) => b.toString(2).padStart(8, "0")).join("");
|
|
19893
19914
|
}
|
|
19894
19915
|
__name(bytesToBits, "bytesToBits");
|
|
19895
19916
|
function bitsToBytes(bits) {
|
|
19896
|
-
const
|
|
19897
|
-
for (let i = 0; i <
|
|
19898
|
-
|
|
19917
|
+
const bytes3 = new Uint8Array(Math.ceil(bits.length / 8));
|
|
19918
|
+
for (let i = 0; i < bytes3.length; i++) {
|
|
19919
|
+
bytes3[i] = parseInt(bits.slice(i * 8, (i + 1) * 8).padEnd(8, "0"), 2);
|
|
19899
19920
|
}
|
|
19900
|
-
return
|
|
19921
|
+
return bytes3;
|
|
19901
19922
|
}
|
|
19902
19923
|
__name(bitsToBytes, "bitsToBytes");
|
|
19903
19924
|
async function computeChecksum(data) {
|
|
19904
|
-
const
|
|
19905
|
-
const hashBits = bytesToBits(new Uint8Array(
|
|
19925
|
+
const hash2 = await crypto.subtle.digest("SHA-256", data);
|
|
19926
|
+
const hashBits = bytesToBits(new Uint8Array(hash2));
|
|
19906
19927
|
const checksumLength = Math.floor(data.length / 4);
|
|
19907
19928
|
return hashBits.slice(0, checksumLength);
|
|
19908
19929
|
}
|
|
@@ -19935,12 +19956,12 @@ async function recoveryPhraseToShare(phrase) {
|
|
|
19935
19956
|
bits += index.toString(2).padStart(11, "0");
|
|
19936
19957
|
}
|
|
19937
19958
|
let dataByteCount = 0;
|
|
19938
|
-
for (let
|
|
19939
|
-
const checksumBits2 = Math.floor(
|
|
19940
|
-
const totalBits =
|
|
19959
|
+
for (let bytes3 = 1; bytes3 <= 64; bytes3++) {
|
|
19960
|
+
const checksumBits2 = Math.floor(bytes3 / 4);
|
|
19961
|
+
const totalBits = bytes3 * 8 + checksumBits2;
|
|
19941
19962
|
const wordsNeeded = Math.ceil(totalBits / 11);
|
|
19942
19963
|
if (wordsNeeded === words.length) {
|
|
19943
|
-
dataByteCount =
|
|
19964
|
+
dataByteCount = bytes3;
|
|
19944
19965
|
} else if (wordsNeeded > words.length) {
|
|
19945
19966
|
break;
|
|
19946
19967
|
}
|
|
@@ -20234,9 +20255,9 @@ __name(createSSSKeyManager, "createSSSKeyManager");
|
|
|
20234
20255
|
var EMAIL_RELAY_ENVELOPE_VERSION = 1;
|
|
20235
20256
|
var EMAIL_RELAY_ALGORITHM = "P-256-HKDF-SHA256-AES-256-GCM";
|
|
20236
20257
|
var encodeUtf8 = /* @__PURE__ */ __name((value) => {
|
|
20237
|
-
const
|
|
20238
|
-
const copy = new Uint8Array(new ArrayBuffer(
|
|
20239
|
-
copy.set(
|
|
20258
|
+
const bytes3 = new TextEncoder().encode(value);
|
|
20259
|
+
const copy = new Uint8Array(new ArrayBuffer(bytes3.byteLength));
|
|
20260
|
+
copy.set(bytes3);
|
|
20240
20261
|
return copy;
|
|
20241
20262
|
}, "encodeUtf8");
|
|
20242
20263
|
var EMAIL_RELAY_INFO = encodeUtf8("learncard-email-relay-v1");
|
|
@@ -20255,7 +20276,7 @@ var parseBranding = /* @__PURE__ */ __name((value) => {
|
|
|
20255
20276
|
if (value === void 0) return void 0;
|
|
20256
20277
|
if (!isRecord(value)) throw new Error("Invalid email relay branding");
|
|
20257
20278
|
const branding = {};
|
|
20258
|
-
const
|
|
20279
|
+
const keys2 = [
|
|
20259
20280
|
"brandName",
|
|
20260
20281
|
"logoUrl",
|
|
20261
20282
|
"logoAlt",
|
|
@@ -20267,7 +20288,7 @@ var parseBranding = /* @__PURE__ */ __name((value) => {
|
|
|
20267
20288
|
"fromDomain",
|
|
20268
20289
|
"copyrightHolder"
|
|
20269
20290
|
];
|
|
20270
|
-
for (const key of
|
|
20291
|
+
for (const key of keys2) {
|
|
20271
20292
|
const field = value[key];
|
|
20272
20293
|
if (field === void 0) continue;
|
|
20273
20294
|
if (typeof field !== "string" || field.length > 2048) {
|
|
@@ -20320,7 +20341,7 @@ var parseEmailRelayPlaintext = /* @__PURE__ */ __name((value) => {
|
|
|
20320
20341
|
branding: parseBranding(value.branding)
|
|
20321
20342
|
};
|
|
20322
20343
|
}, "parseEmailRelayPlaintext");
|
|
20323
|
-
var getAad = /* @__PURE__ */ __name((
|
|
20344
|
+
var getAad = /* @__PURE__ */ __name((envelope2) => encodeUtf8(`${envelope2.version}|${envelope2.algorithm}|${envelope2.keyId}`), "getAad");
|
|
20324
20345
|
var deriveAesKey = /* @__PURE__ */ __name(async (sharedSecret, salt, usage) => {
|
|
20325
20346
|
const keyMaterial = await crypto.subtle.importKey("raw", sharedSecret, "HKDF", false, [
|
|
20326
20347
|
"deriveKey"
|
|
@@ -20392,7 +20413,7 @@ var encryptEmailRelayPayload = /* @__PURE__ */ __name(async (input, publicKeyBas
|
|
|
20392
20413
|
};
|
|
20393
20414
|
}, "encryptEmailRelayPayload");
|
|
20394
20415
|
var decryptEmailRelayPayload = /* @__PURE__ */ __name(async (value, privateKeyBase64) => {
|
|
20395
|
-
const
|
|
20416
|
+
const envelope2 = parseEmailRelayEnvelope(value);
|
|
20396
20417
|
const privateKey = await crypto.subtle.importKey(
|
|
20397
20418
|
"pkcs8",
|
|
20398
20419
|
base64ToBuffer(privateKeyBase64.trim()).buffer,
|
|
@@ -20402,7 +20423,7 @@ var decryptEmailRelayPayload = /* @__PURE__ */ __name(async (value, privateKeyBa
|
|
|
20402
20423
|
);
|
|
20403
20424
|
const ephemeralPublicKey = await crypto.subtle.importKey(
|
|
20404
20425
|
"raw",
|
|
20405
|
-
base64ToBuffer(
|
|
20426
|
+
base64ToBuffer(envelope2.ephemeralPublicKey).buffer,
|
|
20406
20427
|
{ name: "ECDH", namedCurve: "P-256" },
|
|
20407
20428
|
false,
|
|
20408
20429
|
[]
|
|
@@ -20412,13 +20433,13 @@ var decryptEmailRelayPayload = /* @__PURE__ */ __name(async (value, privateKeyBa
|
|
|
20412
20433
|
privateKey,
|
|
20413
20434
|
256
|
|
20414
20435
|
);
|
|
20415
|
-
const salt = base64ToBuffer(
|
|
20416
|
-
const iv = base64ToBuffer(
|
|
20436
|
+
const salt = base64ToBuffer(envelope2.salt);
|
|
20437
|
+
const iv = base64ToBuffer(envelope2.iv);
|
|
20417
20438
|
const aesKey = await deriveAesKey(sharedSecret, salt, "decrypt");
|
|
20418
20439
|
const decrypted = await crypto.subtle.decrypt(
|
|
20419
|
-
{ name: "AES-GCM", iv, additionalData: getAad(
|
|
20440
|
+
{ name: "AES-GCM", iv, additionalData: getAad(envelope2) },
|
|
20420
20441
|
aesKey,
|
|
20421
|
-
base64ToBuffer(
|
|
20442
|
+
base64ToBuffer(envelope2.ciphertext)
|
|
20422
20443
|
);
|
|
20423
20444
|
const parsed = JSON.parse(new TextDecoder().decode(decrypted));
|
|
20424
20445
|
return parseEmailRelayPlaintext(parsed);
|
|
@@ -20430,10 +20451,11 @@ var ESCROW_ALGORITHM = "P-256-HKDF-SHA256-AES-256-GCM";
|
|
|
20430
20451
|
var ESCROW_BLOB_INFO = "learncard-escrow-blob-v1";
|
|
20431
20452
|
var ESCROW_RELEASE_INFO = "learncard-escrow-release-v1";
|
|
20432
20453
|
var ESCROW_CLIENT_KEY_ID = "client";
|
|
20454
|
+
var RECOVERY_LANGUAGES = ["en", "es", "fr", "ar"];
|
|
20433
20455
|
var encodeUtf82 = /* @__PURE__ */ __name((value) => {
|
|
20434
|
-
const
|
|
20435
|
-
const copy = new Uint8Array(new ArrayBuffer(
|
|
20436
|
-
copy.set(
|
|
20456
|
+
const bytes3 = new TextEncoder().encode(value);
|
|
20457
|
+
const copy = new Uint8Array(new ArrayBuffer(bytes3.byteLength));
|
|
20458
|
+
copy.set(bytes3);
|
|
20437
20459
|
return copy;
|
|
20438
20460
|
}, "encodeUtf8");
|
|
20439
20461
|
var isRecord2 = /* @__PURE__ */ __name((value) => typeof value === "object" && value !== null && !Array.isArray(value), "isRecord");
|
|
@@ -20469,6 +20491,22 @@ var parseEscrowBlobPlaintext = /* @__PURE__ */ __name((value) => {
|
|
|
20469
20491
|
if (typeof value.shareVersion !== "number" || !Number.isInteger(value.shareVersion) || value.shareVersion <= 0) {
|
|
20470
20492
|
throw new Error("Invalid escrow shareVersion");
|
|
20471
20493
|
}
|
|
20494
|
+
if (value.recoveryEmail !== void 0 !== (value.recoveryLanguage !== void 0)) {
|
|
20495
|
+
throw new Error("Invalid escrow recoveryEmail");
|
|
20496
|
+
}
|
|
20497
|
+
let recoveryContact = {};
|
|
20498
|
+
if (value.recoveryEmail !== void 0) {
|
|
20499
|
+
const email = requireString2(value, "recoveryEmail", { min: 3, max: 254 }).trim().toLowerCase();
|
|
20500
|
+
const at = email.split("@");
|
|
20501
|
+
if (!/^[\x21-\x7e]+$/.test(email) || at.length !== 2 || at[0].length === 0 || at[1].length === 0 || !at[1].includes(".") || at[1].startsWith(".") || at[1].endsWith(".")) {
|
|
20502
|
+
throw new Error("Invalid escrow recoveryEmail");
|
|
20503
|
+
}
|
|
20504
|
+
const language = requireString2(value, "recoveryLanguage", { min: 2, max: 2 });
|
|
20505
|
+
if (!RECOVERY_LANGUAGES.includes(language)) {
|
|
20506
|
+
throw new Error("Invalid escrow recoveryLanguage");
|
|
20507
|
+
}
|
|
20508
|
+
recoveryContact = { recoveryEmail: email, recoveryLanguage: language };
|
|
20509
|
+
}
|
|
20472
20510
|
return {
|
|
20473
20511
|
version: ESCROW_ENVELOPE_VERSION,
|
|
20474
20512
|
recoveryShare: requireString2(value, "recoveryShare", {
|
|
@@ -20484,7 +20522,8 @@ var parseEscrowBlobPlaintext = /* @__PURE__ */ __name((value) => {
|
|
|
20484
20522
|
max: 64,
|
|
20485
20523
|
pattern: /^[0-9a-f]{64}$/i
|
|
20486
20524
|
}).toLowerCase()
|
|
20487
|
-
} : {}
|
|
20525
|
+
} : {},
|
|
20526
|
+
...recoveryContact
|
|
20488
20527
|
};
|
|
20489
20528
|
}, "parseEscrowBlobPlaintext");
|
|
20490
20529
|
var parseEscrowReleasePlaintext = /* @__PURE__ */ __name((value) => {
|
|
@@ -20495,7 +20534,7 @@ var parseEscrowReleasePlaintext = /* @__PURE__ */ __name((value) => {
|
|
|
20495
20534
|
holdId: requireString2(value, "holdId", { max: 128, pattern: /^[A-Za-z0-9._-]+$/ })
|
|
20496
20535
|
};
|
|
20497
20536
|
}, "parseEscrowReleasePlaintext");
|
|
20498
|
-
var getAad2 = /* @__PURE__ */ __name((
|
|
20537
|
+
var getAad2 = /* @__PURE__ */ __name((envelope2) => encodeUtf82(`${envelope2.version}|${envelope2.algorithm}|${envelope2.keyId}`), "getAad");
|
|
20499
20538
|
var deriveAesKey2 = /* @__PURE__ */ __name(async (sharedSecret, salt, usage, info) => {
|
|
20500
20539
|
const keyMaterial = await crypto.subtle.importKey("raw", sharedSecret, "HKDF", false, [
|
|
20501
20540
|
"deriveKey"
|
|
@@ -20566,7 +20605,7 @@ var encryptToRecipient = /* @__PURE__ */ __name(async (plaintextJson, spki, keyI
|
|
|
20566
20605
|
};
|
|
20567
20606
|
}, "encryptToRecipient");
|
|
20568
20607
|
var decryptFromEnvelope = /* @__PURE__ */ __name(async (value, pkcs8, info) => {
|
|
20569
|
-
const
|
|
20608
|
+
const envelope2 = parseEscrowEnvelope(value);
|
|
20570
20609
|
const privateKey = await crypto.subtle.importKey(
|
|
20571
20610
|
"pkcs8",
|
|
20572
20611
|
base64ToBuffer(pkcs8.trim()),
|
|
@@ -20576,7 +20615,7 @@ var decryptFromEnvelope = /* @__PURE__ */ __name(async (value, pkcs8, info) => {
|
|
|
20576
20615
|
);
|
|
20577
20616
|
const ephemeralPublicKey = await crypto.subtle.importKey(
|
|
20578
20617
|
"raw",
|
|
20579
|
-
base64ToBuffer(
|
|
20618
|
+
base64ToBuffer(envelope2.ephemeralPublicKey),
|
|
20580
20619
|
{ name: "ECDH", namedCurve: "P-256" },
|
|
20581
20620
|
false,
|
|
20582
20621
|
[]
|
|
@@ -20586,13 +20625,13 @@ var decryptFromEnvelope = /* @__PURE__ */ __name(async (value, pkcs8, info) => {
|
|
|
20586
20625
|
privateKey,
|
|
20587
20626
|
256
|
|
20588
20627
|
);
|
|
20589
|
-
const salt = base64ToBuffer(
|
|
20590
|
-
const iv = base64ToBuffer(
|
|
20628
|
+
const salt = base64ToBuffer(envelope2.salt);
|
|
20629
|
+
const iv = base64ToBuffer(envelope2.iv);
|
|
20591
20630
|
const aesKey = await deriveAesKey2(sharedSecret, salt, "decrypt", info);
|
|
20592
20631
|
const decrypted = await crypto.subtle.decrypt(
|
|
20593
|
-
{ name: "AES-GCM", iv, additionalData: getAad2(
|
|
20632
|
+
{ name: "AES-GCM", iv, additionalData: getAad2(envelope2) },
|
|
20594
20633
|
aesKey,
|
|
20595
|
-
base64ToBuffer(
|
|
20634
|
+
base64ToBuffer(envelope2.ciphertext)
|
|
20596
20635
|
);
|
|
20597
20636
|
const parsed = JSON.parse(new TextDecoder().decode(decrypted));
|
|
20598
20637
|
return parsed;
|
|
@@ -20606,8 +20645,8 @@ var encryptEscrowBlob = /* @__PURE__ */ __name(async (input, enclavePublicKeySpk
|
|
|
20606
20645
|
ESCROW_BLOB_INFO
|
|
20607
20646
|
);
|
|
20608
20647
|
}, "encryptEscrowBlob");
|
|
20609
|
-
var decryptEscrowBlob = /* @__PURE__ */ __name(async (
|
|
20610
|
-
await decryptFromEnvelope(
|
|
20648
|
+
var decryptEscrowBlob = /* @__PURE__ */ __name(async (envelope2, enclavePrivateKeyPkcs8B64) => parseEscrowBlobPlaintext(
|
|
20649
|
+
await decryptFromEnvelope(envelope2, enclavePrivateKeyPkcs8B64, ESCROW_BLOB_INFO)
|
|
20611
20650
|
), "decryptEscrowBlob");
|
|
20612
20651
|
var sealEscrowRelease = /* @__PURE__ */ __name(async (input, clientEphemeralPublicKeySpkiB64) => {
|
|
20613
20652
|
const plaintext = parseEscrowReleasePlaintext({ ...input, version: ESCROW_ENVELOPE_VERSION });
|
|
@@ -20618,10 +20657,626 @@ var sealEscrowRelease = /* @__PURE__ */ __name(async (input, clientEphemeralPubl
|
|
|
20618
20657
|
ESCROW_RELEASE_INFO
|
|
20619
20658
|
);
|
|
20620
20659
|
}, "sealEscrowRelease");
|
|
20621
|
-
var openEscrowRelease = /* @__PURE__ */ __name(async (
|
|
20622
|
-
await decryptFromEnvelope(
|
|
20660
|
+
var openEscrowRelease = /* @__PURE__ */ __name(async (envelope2, clientEphemeralPrivateKeyPkcs8B64) => parseEscrowReleasePlaintext(
|
|
20661
|
+
await decryptFromEnvelope(envelope2, clientEphemeralPrivateKeyPkcs8B64, ESCROW_RELEASE_INFO)
|
|
20623
20662
|
), "openEscrowRelease");
|
|
20624
20663
|
|
|
20664
|
+
// ../../node_modules/@noble/ed25519/index.js
|
|
20665
|
+
var ed25519_CURVE = {
|
|
20666
|
+
p: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffedn,
|
|
20667
|
+
n: 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3edn,
|
|
20668
|
+
h: 8n,
|
|
20669
|
+
a: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffecn,
|
|
20670
|
+
d: 0x52036cee2b6ffe738cc740797779e89800700a4d4141d8ab75eb4dca135978a3n,
|
|
20671
|
+
Gx: 0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51an,
|
|
20672
|
+
Gy: 0x6666666666666666666666666666666666666666666666666666666666666658n
|
|
20673
|
+
};
|
|
20674
|
+
var { p: P, n: N, Gx, Gy, a: _a, d: _d } = ed25519_CURVE;
|
|
20675
|
+
var h = 8n;
|
|
20676
|
+
var L = 32;
|
|
20677
|
+
var L2 = 64;
|
|
20678
|
+
var err = /* @__PURE__ */ __name((m = "") => {
|
|
20679
|
+
throw new Error(m);
|
|
20680
|
+
}, "err");
|
|
20681
|
+
var isBig = /* @__PURE__ */ __name((n) => typeof n === "bigint", "isBig");
|
|
20682
|
+
var isStr = /* @__PURE__ */ __name((s) => typeof s === "string", "isStr");
|
|
20683
|
+
var isBytes = /* @__PURE__ */ __name((a) => a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array", "isBytes");
|
|
20684
|
+
var abytes = /* @__PURE__ */ __name((a, l) => !isBytes(a) || typeof l === "number" && l > 0 && a.length !== l ? err("Uint8Array expected") : a, "abytes");
|
|
20685
|
+
var u8n = /* @__PURE__ */ __name((len) => new Uint8Array(len), "u8n");
|
|
20686
|
+
var u8fr = /* @__PURE__ */ __name((buf) => Uint8Array.from(buf), "u8fr");
|
|
20687
|
+
var padh = /* @__PURE__ */ __name((n, pad) => n.toString(16).padStart(pad, "0"), "padh");
|
|
20688
|
+
var bytesToHex3 = /* @__PURE__ */ __name((b) => Array.from(abytes(b)).map((e) => padh(e, 2)).join(""), "bytesToHex");
|
|
20689
|
+
var C = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 };
|
|
20690
|
+
var _ch = /* @__PURE__ */ __name((ch) => {
|
|
20691
|
+
if (ch >= C._0 && ch <= C._9)
|
|
20692
|
+
return ch - C._0;
|
|
20693
|
+
if (ch >= C.A && ch <= C.F)
|
|
20694
|
+
return ch - (C.A - 10);
|
|
20695
|
+
if (ch >= C.a && ch <= C.f)
|
|
20696
|
+
return ch - (C.a - 10);
|
|
20697
|
+
return;
|
|
20698
|
+
}, "_ch");
|
|
20699
|
+
var hexToBytes3 = /* @__PURE__ */ __name((hex2) => {
|
|
20700
|
+
const e = "hex invalid";
|
|
20701
|
+
if (!isStr(hex2))
|
|
20702
|
+
return err(e);
|
|
20703
|
+
const hl = hex2.length;
|
|
20704
|
+
const al = hl / 2;
|
|
20705
|
+
if (hl % 2)
|
|
20706
|
+
return err(e);
|
|
20707
|
+
const array = u8n(al);
|
|
20708
|
+
for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {
|
|
20709
|
+
const n1 = _ch(hex2.charCodeAt(hi));
|
|
20710
|
+
const n2 = _ch(hex2.charCodeAt(hi + 1));
|
|
20711
|
+
if (n1 === void 0 || n2 === void 0)
|
|
20712
|
+
return err(e);
|
|
20713
|
+
array[ai] = n1 * 16 + n2;
|
|
20714
|
+
}
|
|
20715
|
+
return array;
|
|
20716
|
+
}, "hexToBytes");
|
|
20717
|
+
var toU8 = /* @__PURE__ */ __name((a, len) => abytes(isStr(a) ? hexToBytes3(a) : u8fr(abytes(a)), len), "toU8");
|
|
20718
|
+
var cr = /* @__PURE__ */ __name(() => globalThis?.crypto, "cr");
|
|
20719
|
+
var subtle = /* @__PURE__ */ __name(() => cr()?.subtle ?? err("crypto.subtle must be defined"), "subtle");
|
|
20720
|
+
var concatBytes = /* @__PURE__ */ __name((...arrs) => {
|
|
20721
|
+
const r = u8n(arrs.reduce((sum, a) => sum + abytes(a).length, 0));
|
|
20722
|
+
let pad = 0;
|
|
20723
|
+
arrs.forEach((a) => {
|
|
20724
|
+
r.set(a, pad);
|
|
20725
|
+
pad += a.length;
|
|
20726
|
+
});
|
|
20727
|
+
return r;
|
|
20728
|
+
}, "concatBytes");
|
|
20729
|
+
var randomBytes = /* @__PURE__ */ __name((len = L) => {
|
|
20730
|
+
const c = cr();
|
|
20731
|
+
return c.getRandomValues(u8n(len));
|
|
20732
|
+
}, "randomBytes");
|
|
20733
|
+
var big = BigInt;
|
|
20734
|
+
var arange = /* @__PURE__ */ __name((n, min, max, msg = "bad number: out of range") => isBig(n) && min <= n && n < max ? n : err(msg), "arange");
|
|
20735
|
+
var M = /* @__PURE__ */ __name((a, b = P) => {
|
|
20736
|
+
const r = a % b;
|
|
20737
|
+
return r >= 0n ? r : b + r;
|
|
20738
|
+
}, "M");
|
|
20739
|
+
var modN = /* @__PURE__ */ __name((a) => M(a, N), "modN");
|
|
20740
|
+
var invert = /* @__PURE__ */ __name((num, md) => {
|
|
20741
|
+
if (num === 0n || md <= 0n)
|
|
20742
|
+
err("no inverse n=" + num + " mod=" + md);
|
|
20743
|
+
let a = M(num, md), b = md, x = 0n, y = 1n, u = 1n, v = 0n;
|
|
20744
|
+
while (a !== 0n) {
|
|
20745
|
+
const q = b / a, r = b % a;
|
|
20746
|
+
const m = x - u * q, n = y - v * q;
|
|
20747
|
+
b = a, a = r, x = u, y = v, u = m, v = n;
|
|
20748
|
+
}
|
|
20749
|
+
return b === 1n ? M(x, md) : err("no inverse");
|
|
20750
|
+
}, "invert");
|
|
20751
|
+
var apoint = /* @__PURE__ */ __name((p) => p instanceof Point ? p : err("Point expected"), "apoint");
|
|
20752
|
+
var B256 = 2n ** 256n;
|
|
20753
|
+
var Point = class _Point {
|
|
20754
|
+
static {
|
|
20755
|
+
__name(this, "Point");
|
|
20756
|
+
}
|
|
20757
|
+
static BASE;
|
|
20758
|
+
static ZERO;
|
|
20759
|
+
ex;
|
|
20760
|
+
ey;
|
|
20761
|
+
ez;
|
|
20762
|
+
et;
|
|
20763
|
+
constructor(ex, ey, ez, et) {
|
|
20764
|
+
const max = B256;
|
|
20765
|
+
this.ex = arange(ex, 0n, max);
|
|
20766
|
+
this.ey = arange(ey, 0n, max);
|
|
20767
|
+
this.ez = arange(ez, 1n, max);
|
|
20768
|
+
this.et = arange(et, 0n, max);
|
|
20769
|
+
Object.freeze(this);
|
|
20770
|
+
}
|
|
20771
|
+
static fromAffine(p) {
|
|
20772
|
+
return new _Point(p.x, p.y, 1n, M(p.x * p.y));
|
|
20773
|
+
}
|
|
20774
|
+
/** RFC8032 5.1.3: Uint8Array to Point. */
|
|
20775
|
+
static fromBytes(hex2, zip215 = false) {
|
|
20776
|
+
const d = _d;
|
|
20777
|
+
const normed = u8fr(abytes(hex2, L));
|
|
20778
|
+
const lastByte = hex2[31];
|
|
20779
|
+
normed[31] = lastByte & ~128;
|
|
20780
|
+
const y = bytesToNumLE(normed);
|
|
20781
|
+
const max = zip215 ? B256 : P;
|
|
20782
|
+
arange(y, 0n, max);
|
|
20783
|
+
const y2 = M(y * y);
|
|
20784
|
+
const u = M(y2 - 1n);
|
|
20785
|
+
const v = M(d * y2 + 1n);
|
|
20786
|
+
let { isValid, value: x } = uvRatio(u, v);
|
|
20787
|
+
if (!isValid)
|
|
20788
|
+
err("bad point: y not sqrt");
|
|
20789
|
+
const isXOdd = (x & 1n) === 1n;
|
|
20790
|
+
const isLastByteOdd = (lastByte & 128) !== 0;
|
|
20791
|
+
if (!zip215 && x === 0n && isLastByteOdd)
|
|
20792
|
+
err("bad point: x==0, isLastByteOdd");
|
|
20793
|
+
if (isLastByteOdd !== isXOdd)
|
|
20794
|
+
x = M(-x);
|
|
20795
|
+
return new _Point(x, y, 1n, M(x * y));
|
|
20796
|
+
}
|
|
20797
|
+
/** Checks if the point is valid and on-curve. */
|
|
20798
|
+
assertValidity() {
|
|
20799
|
+
const a = _a;
|
|
20800
|
+
const d = _d;
|
|
20801
|
+
const p = this;
|
|
20802
|
+
if (p.is0())
|
|
20803
|
+
throw new Error("bad point: ZERO");
|
|
20804
|
+
const { ex: X, ey: Y, ez: Z, et: T } = p;
|
|
20805
|
+
const X2 = M(X * X);
|
|
20806
|
+
const Y2 = M(Y * Y);
|
|
20807
|
+
const Z2 = M(Z * Z);
|
|
20808
|
+
const Z4 = M(Z2 * Z2);
|
|
20809
|
+
const aX2 = M(X2 * a);
|
|
20810
|
+
const left = M(Z2 * M(aX2 + Y2));
|
|
20811
|
+
const right = M(Z4 + M(d * M(X2 * Y2)));
|
|
20812
|
+
if (left !== right)
|
|
20813
|
+
throw new Error("bad point: equation left != right (1)");
|
|
20814
|
+
const XY = M(X * Y);
|
|
20815
|
+
const ZT = M(Z * T);
|
|
20816
|
+
if (XY !== ZT)
|
|
20817
|
+
throw new Error("bad point: equation left != right (2)");
|
|
20818
|
+
return this;
|
|
20819
|
+
}
|
|
20820
|
+
/** Equality check: compare points P&Q. */
|
|
20821
|
+
equals(other) {
|
|
20822
|
+
const { ex: X1, ey: Y1, ez: Z1 } = this;
|
|
20823
|
+
const { ex: X2, ey: Y2, ez: Z2 } = apoint(other);
|
|
20824
|
+
const X1Z2 = M(X1 * Z2);
|
|
20825
|
+
const X2Z1 = M(X2 * Z1);
|
|
20826
|
+
const Y1Z2 = M(Y1 * Z2);
|
|
20827
|
+
const Y2Z1 = M(Y2 * Z1);
|
|
20828
|
+
return X1Z2 === X2Z1 && Y1Z2 === Y2Z1;
|
|
20829
|
+
}
|
|
20830
|
+
is0() {
|
|
20831
|
+
return this.equals(I);
|
|
20832
|
+
}
|
|
20833
|
+
/** Flip point over y coordinate. */
|
|
20834
|
+
negate() {
|
|
20835
|
+
return new _Point(M(-this.ex), this.ey, this.ez, M(-this.et));
|
|
20836
|
+
}
|
|
20837
|
+
/** Point doubling. Complete formula. Cost: `4M + 4S + 1*a + 6add + 1*2`. */
|
|
20838
|
+
double() {
|
|
20839
|
+
const { ex: X1, ey: Y1, ez: Z1 } = this;
|
|
20840
|
+
const a = _a;
|
|
20841
|
+
const A = M(X1 * X1);
|
|
20842
|
+
const B = M(Y1 * Y1);
|
|
20843
|
+
const C2 = M(2n * M(Z1 * Z1));
|
|
20844
|
+
const D = M(a * A);
|
|
20845
|
+
const x1y1 = X1 + Y1;
|
|
20846
|
+
const E = M(M(x1y1 * x1y1) - A - B);
|
|
20847
|
+
const G2 = D + B;
|
|
20848
|
+
const F = G2 - C2;
|
|
20849
|
+
const H = D - B;
|
|
20850
|
+
const X3 = M(E * F);
|
|
20851
|
+
const Y3 = M(G2 * H);
|
|
20852
|
+
const T3 = M(E * H);
|
|
20853
|
+
const Z3 = M(F * G2);
|
|
20854
|
+
return new _Point(X3, Y3, Z3, T3);
|
|
20855
|
+
}
|
|
20856
|
+
/** Point addition. Complete formula. Cost: `8M + 1*k + 8add + 1*2`. */
|
|
20857
|
+
add(other) {
|
|
20858
|
+
const { ex: X1, ey: Y1, ez: Z1, et: T1 } = this;
|
|
20859
|
+
const { ex: X2, ey: Y2, ez: Z2, et: T2 } = apoint(other);
|
|
20860
|
+
const a = _a;
|
|
20861
|
+
const d = _d;
|
|
20862
|
+
const A = M(X1 * X2);
|
|
20863
|
+
const B = M(Y1 * Y2);
|
|
20864
|
+
const C2 = M(T1 * d * T2);
|
|
20865
|
+
const D = M(Z1 * Z2);
|
|
20866
|
+
const E = M((X1 + Y1) * (X2 + Y2) - A - B);
|
|
20867
|
+
const F = M(D - C2);
|
|
20868
|
+
const G2 = M(D + C2);
|
|
20869
|
+
const H = M(B - a * A);
|
|
20870
|
+
const X3 = M(E * F);
|
|
20871
|
+
const Y3 = M(G2 * H);
|
|
20872
|
+
const T3 = M(E * H);
|
|
20873
|
+
const Z3 = M(F * G2);
|
|
20874
|
+
return new _Point(X3, Y3, Z3, T3);
|
|
20875
|
+
}
|
|
20876
|
+
/**
|
|
20877
|
+
* Point-by-scalar multiplication. Scalar must be in range 1 <= n < CURVE.n.
|
|
20878
|
+
* Uses {@link wNAF} for base point.
|
|
20879
|
+
* Uses fake point to mitigate side-channel leakage.
|
|
20880
|
+
* @param n scalar by which point is multiplied
|
|
20881
|
+
* @param safe safe mode guards against timing attacks; unsafe mode is faster
|
|
20882
|
+
*/
|
|
20883
|
+
multiply(n, safe = true) {
|
|
20884
|
+
if (!safe && (n === 0n || this.is0()))
|
|
20885
|
+
return I;
|
|
20886
|
+
arange(n, 1n, N);
|
|
20887
|
+
if (n === 1n)
|
|
20888
|
+
return this;
|
|
20889
|
+
if (this.equals(G))
|
|
20890
|
+
return wNAF(n).p;
|
|
20891
|
+
let p = I;
|
|
20892
|
+
let f = G;
|
|
20893
|
+
for (let d = this; n > 0n; d = d.double(), n >>= 1n) {
|
|
20894
|
+
if (n & 1n)
|
|
20895
|
+
p = p.add(d);
|
|
20896
|
+
else if (safe)
|
|
20897
|
+
f = f.add(d);
|
|
20898
|
+
}
|
|
20899
|
+
return p;
|
|
20900
|
+
}
|
|
20901
|
+
/** Convert point to 2d xy affine point. (X, Y, Z) ∋ (x=X/Z, y=Y/Z) */
|
|
20902
|
+
toAffine() {
|
|
20903
|
+
const { ex: x, ey: y, ez: z } = this;
|
|
20904
|
+
if (this.equals(I))
|
|
20905
|
+
return { x: 0n, y: 1n };
|
|
20906
|
+
const iz = invert(z, P);
|
|
20907
|
+
if (M(z * iz) !== 1n)
|
|
20908
|
+
err("invalid inverse");
|
|
20909
|
+
return { x: M(x * iz), y: M(y * iz) };
|
|
20910
|
+
}
|
|
20911
|
+
toBytes() {
|
|
20912
|
+
const { x, y } = this.assertValidity().toAffine();
|
|
20913
|
+
const b = numTo32bLE(y);
|
|
20914
|
+
b[31] |= x & 1n ? 128 : 0;
|
|
20915
|
+
return b;
|
|
20916
|
+
}
|
|
20917
|
+
toHex() {
|
|
20918
|
+
return bytesToHex3(this.toBytes());
|
|
20919
|
+
}
|
|
20920
|
+
// encode to hex string
|
|
20921
|
+
clearCofactor() {
|
|
20922
|
+
return this.multiply(big(h), false);
|
|
20923
|
+
}
|
|
20924
|
+
isSmallOrder() {
|
|
20925
|
+
return this.clearCofactor().is0();
|
|
20926
|
+
}
|
|
20927
|
+
isTorsionFree() {
|
|
20928
|
+
let p = this.multiply(N / 2n, false).double();
|
|
20929
|
+
if (N % 2n)
|
|
20930
|
+
p = p.add(this);
|
|
20931
|
+
return p.is0();
|
|
20932
|
+
}
|
|
20933
|
+
static fromHex(hex2, zip215) {
|
|
20934
|
+
return _Point.fromBytes(toU8(hex2), zip215);
|
|
20935
|
+
}
|
|
20936
|
+
get x() {
|
|
20937
|
+
return this.toAffine().x;
|
|
20938
|
+
}
|
|
20939
|
+
get y() {
|
|
20940
|
+
return this.toAffine().y;
|
|
20941
|
+
}
|
|
20942
|
+
toRawBytes() {
|
|
20943
|
+
return this.toBytes();
|
|
20944
|
+
}
|
|
20945
|
+
};
|
|
20946
|
+
var G = new Point(Gx, Gy, 1n, M(Gx * Gy));
|
|
20947
|
+
var I = new Point(0n, 1n, 1n, 0n);
|
|
20948
|
+
Point.BASE = G;
|
|
20949
|
+
Point.ZERO = I;
|
|
20950
|
+
var numTo32bLE = /* @__PURE__ */ __name((num) => hexToBytes3(padh(arange(num, 0n, B256), L2)).reverse(), "numTo32bLE");
|
|
20951
|
+
var bytesToNumLE = /* @__PURE__ */ __name((b) => big("0x" + bytesToHex3(u8fr(abytes(b)).reverse())), "bytesToNumLE");
|
|
20952
|
+
var pow2 = /* @__PURE__ */ __name((x, power) => {
|
|
20953
|
+
let r = x;
|
|
20954
|
+
while (power-- > 0n) {
|
|
20955
|
+
r *= r;
|
|
20956
|
+
r %= P;
|
|
20957
|
+
}
|
|
20958
|
+
return r;
|
|
20959
|
+
}, "pow2");
|
|
20960
|
+
var pow_2_252_3 = /* @__PURE__ */ __name((x) => {
|
|
20961
|
+
const x2 = x * x % P;
|
|
20962
|
+
const b2 = x2 * x % P;
|
|
20963
|
+
const b4 = pow2(b2, 2n) * b2 % P;
|
|
20964
|
+
const b5 = pow2(b4, 1n) * x % P;
|
|
20965
|
+
const b10 = pow2(b5, 5n) * b5 % P;
|
|
20966
|
+
const b20 = pow2(b10, 10n) * b10 % P;
|
|
20967
|
+
const b40 = pow2(b20, 20n) * b20 % P;
|
|
20968
|
+
const b80 = pow2(b40, 40n) * b40 % P;
|
|
20969
|
+
const b160 = pow2(b80, 80n) * b80 % P;
|
|
20970
|
+
const b240 = pow2(b160, 80n) * b80 % P;
|
|
20971
|
+
const b250 = pow2(b240, 10n) * b10 % P;
|
|
20972
|
+
const pow_p_5_8 = pow2(b250, 2n) * x % P;
|
|
20973
|
+
return { pow_p_5_8, b2 };
|
|
20974
|
+
}, "pow_2_252_3");
|
|
20975
|
+
var RM1 = 0x2b8324804fc1df0b2b4d00993dfbd7a72f431806ad2fe478c4ee1b274a0ea0b0n;
|
|
20976
|
+
var uvRatio = /* @__PURE__ */ __name((u, v) => {
|
|
20977
|
+
const v3 = M(v * v * v);
|
|
20978
|
+
const v7 = M(v3 * v3 * v);
|
|
20979
|
+
const pow = pow_2_252_3(u * v7).pow_p_5_8;
|
|
20980
|
+
let x = M(u * v3 * pow);
|
|
20981
|
+
const vx2 = M(v * x * x);
|
|
20982
|
+
const root1 = x;
|
|
20983
|
+
const root2 = M(x * RM1);
|
|
20984
|
+
const useRoot1 = vx2 === u;
|
|
20985
|
+
const useRoot2 = vx2 === M(-u);
|
|
20986
|
+
const noRoot = vx2 === M(-u * RM1);
|
|
20987
|
+
if (useRoot1)
|
|
20988
|
+
x = root1;
|
|
20989
|
+
if (useRoot2 || noRoot)
|
|
20990
|
+
x = root2;
|
|
20991
|
+
if ((M(x) & 1n) === 1n)
|
|
20992
|
+
x = M(-x);
|
|
20993
|
+
return { isValid: useRoot1 || useRoot2, value: x };
|
|
20994
|
+
}, "uvRatio");
|
|
20995
|
+
var modL_LE = /* @__PURE__ */ __name((hash2) => modN(bytesToNumLE(hash2)), "modL_LE");
|
|
20996
|
+
var sha512a = /* @__PURE__ */ __name((...m) => etc.sha512Async(...m), "sha512a");
|
|
20997
|
+
var hash2extK = /* @__PURE__ */ __name((hashed) => {
|
|
20998
|
+
const head = hashed.slice(0, L);
|
|
20999
|
+
head[0] &= 248;
|
|
21000
|
+
head[31] &= 127;
|
|
21001
|
+
head[31] |= 64;
|
|
21002
|
+
const prefix = hashed.slice(L, L2);
|
|
21003
|
+
const scalar = modL_LE(head);
|
|
21004
|
+
const point = G.multiply(scalar);
|
|
21005
|
+
const pointBytes = point.toBytes();
|
|
21006
|
+
return { head, prefix, scalar, point, pointBytes };
|
|
21007
|
+
}, "hash2extK");
|
|
21008
|
+
var getExtendedPublicKeyAsync = /* @__PURE__ */ __name((priv) => sha512a(toU8(priv, L)).then(hash2extK), "getExtendedPublicKeyAsync");
|
|
21009
|
+
var getPublicKeyAsync = /* @__PURE__ */ __name((priv) => getExtendedPublicKeyAsync(priv).then((p) => p.pointBytes), "getPublicKeyAsync");
|
|
21010
|
+
var hashFinishA = /* @__PURE__ */ __name((res) => sha512a(res.hashable).then(res.finish), "hashFinishA");
|
|
21011
|
+
var _sign = /* @__PURE__ */ __name((e, rBytes, msg) => {
|
|
21012
|
+
const { pointBytes: P2, scalar: s } = e;
|
|
21013
|
+
const r = modL_LE(rBytes);
|
|
21014
|
+
const R = G.multiply(r).toBytes();
|
|
21015
|
+
const hashable = concatBytes(R, P2, msg);
|
|
21016
|
+
const finish = /* @__PURE__ */ __name((hashed) => {
|
|
21017
|
+
const S = modN(r + modL_LE(hashed) * s);
|
|
21018
|
+
return abytes(concatBytes(R, numTo32bLE(S)), L2);
|
|
21019
|
+
}, "finish");
|
|
21020
|
+
return { hashable, finish };
|
|
21021
|
+
}, "_sign");
|
|
21022
|
+
var signAsync = /* @__PURE__ */ __name(async (msg, privKey) => {
|
|
21023
|
+
const m = toU8(msg);
|
|
21024
|
+
const e = await getExtendedPublicKeyAsync(privKey);
|
|
21025
|
+
const rBytes = await sha512a(e.prefix, m);
|
|
21026
|
+
return hashFinishA(_sign(e, rBytes, m));
|
|
21027
|
+
}, "signAsync");
|
|
21028
|
+
var etc = {
|
|
21029
|
+
sha512Async: /* @__PURE__ */ __name(async (...messages) => {
|
|
21030
|
+
const s = subtle();
|
|
21031
|
+
const m = concatBytes(...messages);
|
|
21032
|
+
return u8n(await s.digest("SHA-512", m.buffer));
|
|
21033
|
+
}, "sha512Async"),
|
|
21034
|
+
sha512Sync: void 0,
|
|
21035
|
+
bytesToHex: bytesToHex3,
|
|
21036
|
+
hexToBytes: hexToBytes3,
|
|
21037
|
+
concatBytes,
|
|
21038
|
+
mod: M,
|
|
21039
|
+
invert,
|
|
21040
|
+
randomBytes
|
|
21041
|
+
};
|
|
21042
|
+
var W = 8;
|
|
21043
|
+
var scalarBits = 256;
|
|
21044
|
+
var pwindows = Math.ceil(scalarBits / W) + 1;
|
|
21045
|
+
var pwindowSize = 2 ** (W - 1);
|
|
21046
|
+
var precompute = /* @__PURE__ */ __name(() => {
|
|
21047
|
+
const points = [];
|
|
21048
|
+
let p = G;
|
|
21049
|
+
let b = p;
|
|
21050
|
+
for (let w = 0; w < pwindows; w++) {
|
|
21051
|
+
b = p;
|
|
21052
|
+
points.push(b);
|
|
21053
|
+
for (let i = 1; i < pwindowSize; i++) {
|
|
21054
|
+
b = b.add(p);
|
|
21055
|
+
points.push(b);
|
|
21056
|
+
}
|
|
21057
|
+
p = b.double();
|
|
21058
|
+
}
|
|
21059
|
+
return points;
|
|
21060
|
+
}, "precompute");
|
|
21061
|
+
var Gpows = void 0;
|
|
21062
|
+
var ctneg = /* @__PURE__ */ __name((cnd, p) => {
|
|
21063
|
+
const n = p.negate();
|
|
21064
|
+
return cnd ? n : p;
|
|
21065
|
+
}, "ctneg");
|
|
21066
|
+
var wNAF = /* @__PURE__ */ __name((n) => {
|
|
21067
|
+
const comp = Gpows || (Gpows = precompute());
|
|
21068
|
+
let p = I;
|
|
21069
|
+
let f = G;
|
|
21070
|
+
const pow_2_w = 2 ** W;
|
|
21071
|
+
const maxNum = pow_2_w;
|
|
21072
|
+
const mask = big(pow_2_w - 1);
|
|
21073
|
+
const shiftBy = big(W);
|
|
21074
|
+
for (let w = 0; w < pwindows; w++) {
|
|
21075
|
+
let wbits = Number(n & mask);
|
|
21076
|
+
n >>= shiftBy;
|
|
21077
|
+
if (wbits > pwindowSize) {
|
|
21078
|
+
wbits -= maxNum;
|
|
21079
|
+
n += 1n;
|
|
21080
|
+
}
|
|
21081
|
+
const off = w * pwindowSize;
|
|
21082
|
+
const offF = off;
|
|
21083
|
+
const offP = off + Math.abs(wbits) - 1;
|
|
21084
|
+
const isEven = w % 2 !== 0;
|
|
21085
|
+
const isNeg = wbits < 0;
|
|
21086
|
+
if (wbits === 0) {
|
|
21087
|
+
f = f.add(ctneg(isEven, comp[offF]));
|
|
21088
|
+
} else {
|
|
21089
|
+
p = p.add(ctneg(isNeg, comp[offP]));
|
|
21090
|
+
}
|
|
21091
|
+
}
|
|
21092
|
+
return { p, f };
|
|
21093
|
+
}, "wNAF");
|
|
21094
|
+
|
|
21095
|
+
// src/escrow-enrollment-intent.ts
|
|
21096
|
+
var ESCROW_ENROLLMENT_INTENT_DOMAIN = "learncard-escrow-enrollment-intent-v2\0";
|
|
21097
|
+
var BASE58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
21098
|
+
var FIELDS = [
|
|
21099
|
+
"version",
|
|
21100
|
+
"tenant",
|
|
21101
|
+
"did",
|
|
21102
|
+
"authorityGeneration",
|
|
21103
|
+
"expectedEnrollmentVersion",
|
|
21104
|
+
"action",
|
|
21105
|
+
"sourceBlobIdentity",
|
|
21106
|
+
"targetBlobIdentity",
|
|
21107
|
+
"pinAction",
|
|
21108
|
+
"shareVersion",
|
|
21109
|
+
"enrollmentEpoch",
|
|
21110
|
+
"requestId",
|
|
21111
|
+
"allowRewrap",
|
|
21112
|
+
"recoveryEmail",
|
|
21113
|
+
"recoveryLanguage"
|
|
21114
|
+
];
|
|
21115
|
+
var ACTIONS = ["enroll", "replace", "disable", "carry"];
|
|
21116
|
+
var PIN_ACTIONS = ["set", "change", "clear", "keep"];
|
|
21117
|
+
var RECOVERY_LANGUAGES2 = ["en", "es", "fr", "ar"];
|
|
21118
|
+
var requireIntent = /* @__PURE__ */ __name((condition) => {
|
|
21119
|
+
if (!condition) throw new Error("Invalid escrow enrollment intent");
|
|
21120
|
+
}, "requireIntent");
|
|
21121
|
+
var matches = /* @__PURE__ */ __name((value, pattern) => typeof value === "string" && pattern.exec(value)?.[0] === value, "matches");
|
|
21122
|
+
var utf8 = /* @__PURE__ */ __name((value) => new TextEncoder().encode(value), "utf8");
|
|
21123
|
+
var integer = /* @__PURE__ */ __name((value, width) => {
|
|
21124
|
+
requireIntent(
|
|
21125
|
+
Number.isSafeInteger(value) && value >= 0 && (width === 8 || value <= 4294967295)
|
|
21126
|
+
);
|
|
21127
|
+
const bytes3 = new Uint8Array(width);
|
|
21128
|
+
const view = new DataView(bytes3.buffer);
|
|
21129
|
+
if (width === 4) view.setUint32(0, value, false);
|
|
21130
|
+
else view.setBigUint64(0, BigInt(value), false);
|
|
21131
|
+
return bytes3;
|
|
21132
|
+
}, "integer");
|
|
21133
|
+
var join = /* @__PURE__ */ __name((fields) => {
|
|
21134
|
+
const result = new Uint8Array(fields.reduce((length, field) => length + field.length, 0));
|
|
21135
|
+
let offset = 0;
|
|
21136
|
+
for (const field of fields) {
|
|
21137
|
+
result.set(field, offset);
|
|
21138
|
+
offset += field.length;
|
|
21139
|
+
}
|
|
21140
|
+
return result;
|
|
21141
|
+
}, "join");
|
|
21142
|
+
var hashBytes = /* @__PURE__ */ __name((value) => {
|
|
21143
|
+
if (value === null) return new Uint8Array();
|
|
21144
|
+
requireIntent(matches(value, /^[0-9a-f]{64}$/));
|
|
21145
|
+
return new Uint8Array(hexToBytes(value));
|
|
21146
|
+
}, "hashBytes");
|
|
21147
|
+
var didPublicKey = /* @__PURE__ */ __name((did) => {
|
|
21148
|
+
requireIntent(typeof did === "string" && did.startsWith("did:key:z") && did.length === 56);
|
|
21149
|
+
let value = 0n;
|
|
21150
|
+
for (const char of did.slice(9)) {
|
|
21151
|
+
const digit = BASE58.indexOf(char);
|
|
21152
|
+
requireIntent(digit >= 0);
|
|
21153
|
+
value = value * 58n + BigInt(digit);
|
|
21154
|
+
}
|
|
21155
|
+
const bytes3 = new Uint8Array(34);
|
|
21156
|
+
for (let i = 33; i >= 0; i--) {
|
|
21157
|
+
bytes3[i] = Number(value & 255n);
|
|
21158
|
+
value >>= 8n;
|
|
21159
|
+
}
|
|
21160
|
+
requireIntent(value === 0n && bytes3[0] === 237 && bytes3[1] === 1);
|
|
21161
|
+
const key = bytes3.slice(2);
|
|
21162
|
+
try {
|
|
21163
|
+
requireIntent(!Point.fromHex(key, false).isSmallOrder());
|
|
21164
|
+
} catch {
|
|
21165
|
+
throw new Error("Invalid escrow enrollment intent");
|
|
21166
|
+
}
|
|
21167
|
+
return key;
|
|
21168
|
+
}, "didPublicKey");
|
|
21169
|
+
var encodeEscrowEnrollmentIntent = /* @__PURE__ */ __name((intent) => {
|
|
21170
|
+
requireIntent(typeof intent === "object" && intent !== null && !Array.isArray(intent));
|
|
21171
|
+
requireIntent(
|
|
21172
|
+
Object.keys(intent).length === FIELDS.length && FIELDS.every((field) => Object.prototype.hasOwnProperty.call(intent, field))
|
|
21173
|
+
);
|
|
21174
|
+
requireIntent(intent.version === 2 && typeof intent.allowRewrap === "boolean");
|
|
21175
|
+
requireIntent(matches(intent.tenant, /^[A-Za-z0-9_-]{1,128}$/));
|
|
21176
|
+
requireIntent(matches(intent.authorityGeneration, /^[A-Za-z0-9_-]{1,128}$/));
|
|
21177
|
+
requireIntent(matches(intent.requestId, /^[A-Za-z0-9._-]{1,112}$/));
|
|
21178
|
+
didPublicKey(intent.did);
|
|
21179
|
+
const action = ACTIONS.indexOf(intent.action);
|
|
21180
|
+
const pin = PIN_ACTIONS.indexOf(intent.pinAction);
|
|
21181
|
+
requireIntent(action >= 0 && pin >= 0 && intent.shareVersion > 0 && intent.enrollmentEpoch > 0);
|
|
21182
|
+
const source = hashBytes(intent.sourceBlobIdentity);
|
|
21183
|
+
const target = hashBytes(intent.targetBlobIdentity);
|
|
21184
|
+
if (intent.action === "enroll") requireIntent(source.length === 0 && target.length === 32);
|
|
21185
|
+
else if (intent.action === "disable")
|
|
21186
|
+
requireIntent(
|
|
21187
|
+
source.length === 32 && target.length === 0 && intent.pinAction === "keep" && !intent.allowRewrap
|
|
21188
|
+
);
|
|
21189
|
+
else
|
|
21190
|
+
requireIntent(
|
|
21191
|
+
source.length === 32 && target.length === 32 && intent.sourceBlobIdentity !== intent.targetBlobIdentity
|
|
21192
|
+
);
|
|
21193
|
+
if (intent.action === "carry") requireIntent(intent.pinAction === "keep");
|
|
21194
|
+
if (intent.recoveryEmail === null) {
|
|
21195
|
+
requireIntent(
|
|
21196
|
+
intent.recoveryLanguage === null && (intent.action === "disable" || intent.action === "carry")
|
|
21197
|
+
);
|
|
21198
|
+
} else {
|
|
21199
|
+
requireIntent(intent.action === "enroll" || intent.action === "replace");
|
|
21200
|
+
requireIntent(
|
|
21201
|
+
matches(intent.recoveryEmail, /^[\x21-\x7e]{3,254}$/) && intent.recoveryEmail === intent.recoveryEmail.trim().toLowerCase()
|
|
21202
|
+
);
|
|
21203
|
+
const at = intent.recoveryEmail.split("@");
|
|
21204
|
+
requireIntent(
|
|
21205
|
+
at.length === 2 && at[0].length > 0 && at[1].length > 0 && at[1].includes(".") && !at[1].startsWith(".") && !at[1].endsWith(".")
|
|
21206
|
+
);
|
|
21207
|
+
requireIntent(
|
|
21208
|
+
intent.recoveryLanguage !== null && RECOVERY_LANGUAGES2.includes(intent.recoveryLanguage)
|
|
21209
|
+
);
|
|
21210
|
+
}
|
|
21211
|
+
const fields = [
|
|
21212
|
+
integer(intent.version, 4),
|
|
21213
|
+
utf8(intent.tenant),
|
|
21214
|
+
utf8(intent.did),
|
|
21215
|
+
utf8(intent.authorityGeneration),
|
|
21216
|
+
integer(intent.expectedEnrollmentVersion, 8),
|
|
21217
|
+
Uint8Array.of(action),
|
|
21218
|
+
source,
|
|
21219
|
+
target,
|
|
21220
|
+
Uint8Array.of(pin),
|
|
21221
|
+
integer(intent.shareVersion, 4),
|
|
21222
|
+
integer(intent.enrollmentEpoch, 8),
|
|
21223
|
+
utf8(intent.requestId),
|
|
21224
|
+
Uint8Array.of(Number(intent.allowRewrap)),
|
|
21225
|
+
intent.recoveryEmail === null ? new Uint8Array() : utf8(intent.recoveryEmail),
|
|
21226
|
+
intent.recoveryLanguage === null ? new Uint8Array() : utf8(intent.recoveryLanguage)
|
|
21227
|
+
];
|
|
21228
|
+
return join([
|
|
21229
|
+
utf8(ESCROW_ENROLLMENT_INTENT_DOMAIN),
|
|
21230
|
+
...fields.flatMap((field) => [integer(field.length, 4), field])
|
|
21231
|
+
]);
|
|
21232
|
+
}, "encodeEscrowEnrollmentIntent");
|
|
21233
|
+
var signEscrowEnrollmentIntent = /* @__PURE__ */ __name(async (intent, privateKey) => {
|
|
21234
|
+
encodeEscrowEnrollmentIntent(intent);
|
|
21235
|
+
const snapshot = { ...intent };
|
|
21236
|
+
const message = encodeEscrowEnrollmentIntent(snapshot);
|
|
21237
|
+
requireIntent(matches(privateKey, /^[0-9a-f]{64}$/i));
|
|
21238
|
+
const seed = hexToBytes(privateKey);
|
|
21239
|
+
try {
|
|
21240
|
+
const publicKey = await getPublicKeyAsync(seed);
|
|
21241
|
+
const expected = didPublicKey(snapshot.did);
|
|
21242
|
+
requireIntent(publicKey.every((byte, index) => byte === expected[index]));
|
|
21243
|
+
const signature = await signAsync(message, seed);
|
|
21244
|
+
return { intent: snapshot, signature: bufferToBase64(new Uint8Array(signature).buffer) };
|
|
21245
|
+
} finally {
|
|
21246
|
+
seed.fill(0);
|
|
21247
|
+
}
|
|
21248
|
+
}, "signEscrowEnrollmentIntent");
|
|
21249
|
+
var getEscrowBlobIdentity = /* @__PURE__ */ __name(async (input) => {
|
|
21250
|
+
const envelope2 = parseEscrowEnvelope(input);
|
|
21251
|
+
const decode2 = /* @__PURE__ */ __name((value) => {
|
|
21252
|
+
const bytes3 = new Uint8Array(base64ToBuffer(value));
|
|
21253
|
+
requireIntent(bufferToBase64(bytes3.buffer) === value);
|
|
21254
|
+
return bytes3;
|
|
21255
|
+
}, "decode");
|
|
21256
|
+
const point = decode2(envelope2.ephemeralPublicKey);
|
|
21257
|
+
const salt = decode2(envelope2.salt);
|
|
21258
|
+
const iv = decode2(envelope2.iv);
|
|
21259
|
+
const ciphertext = decode2(envelope2.ciphertext);
|
|
21260
|
+
requireIntent(
|
|
21261
|
+
point.length === 65 && point[0] === 4 && salt.length === 32 && iv.length === 12 && ciphertext.length >= 16
|
|
21262
|
+
);
|
|
21263
|
+
await crypto.subtle.importKey("raw", point, { name: "ECDH", namedCurve: "P-256" }, false, []);
|
|
21264
|
+
const fields = [
|
|
21265
|
+
Uint8Array.of(1),
|
|
21266
|
+
utf8(envelope2.algorithm),
|
|
21267
|
+
utf8(envelope2.keyId),
|
|
21268
|
+
point.slice(1, 33),
|
|
21269
|
+
salt,
|
|
21270
|
+
iv,
|
|
21271
|
+
ciphertext
|
|
21272
|
+
];
|
|
21273
|
+
const message = join([
|
|
21274
|
+
utf8("learncard-escrow-blob-id-v1\0"),
|
|
21275
|
+
...fields.flatMap((field) => [integer(field.length, 8), field])
|
|
21276
|
+
]);
|
|
21277
|
+
return bytesToHex(new Uint8Array(await crypto.subtle.digest("SHA-256", message)));
|
|
21278
|
+
}, "getEscrowBlobIdentity");
|
|
21279
|
+
|
|
20625
21280
|
// src/escrow-nitro-attestation.ts
|
|
20626
21281
|
var import_reflect_metadata = require("reflect-metadata");
|
|
20627
21282
|
|
|
@@ -20819,11 +21474,11 @@ var slice = useBuffer ? (
|
|
|
20819
21474
|
* @param {number} end
|
|
20820
21475
|
*/
|
|
20821
21476
|
// Buffer.slice() returns a view, not a copy, so we need special handling
|
|
20822
|
-
(
|
|
20823
|
-
if (isBuffer(
|
|
20824
|
-
return new Uint8Array(
|
|
21477
|
+
(bytes3, start, end) => {
|
|
21478
|
+
if (isBuffer(bytes3)) {
|
|
21479
|
+
return new Uint8Array(bytes3.subarray(start, end));
|
|
20825
21480
|
}
|
|
20826
|
-
return
|
|
21481
|
+
return bytes3.slice(start, end);
|
|
20827
21482
|
}
|
|
20828
21483
|
) : (
|
|
20829
21484
|
// eslint-disable-line operator-linebreak
|
|
@@ -20832,8 +21487,8 @@ var slice = useBuffer ? (
|
|
|
20832
21487
|
* @param {number} start
|
|
20833
21488
|
* @param {number} end
|
|
20834
21489
|
*/
|
|
20835
|
-
(
|
|
20836
|
-
return
|
|
21490
|
+
(bytes3, start, end) => {
|
|
21491
|
+
return bytes3.slice(start, end);
|
|
20837
21492
|
}
|
|
20838
21493
|
);
|
|
20839
21494
|
var concat = useBuffer ? (
|
|
@@ -20982,12 +21637,12 @@ var Bl = class {
|
|
|
20982
21637
|
/**
|
|
20983
21638
|
* @param {ByteView|number[]} bytes
|
|
20984
21639
|
*/
|
|
20985
|
-
push(
|
|
21640
|
+
push(bytes3) {
|
|
20986
21641
|
let topChunk = this.chunks[this.chunks.length - 1];
|
|
20987
|
-
const newMax = this.cursor +
|
|
21642
|
+
const newMax = this.cursor + bytes3.length;
|
|
20988
21643
|
if (newMax <= this.maxCursor + 1) {
|
|
20989
21644
|
const chunkPos = topChunk.length - (this.maxCursor - this.cursor) - 1;
|
|
20990
|
-
topChunk.set(
|
|
21645
|
+
topChunk.set(bytes3, chunkPos);
|
|
20991
21646
|
} else {
|
|
20992
21647
|
if (topChunk) {
|
|
20993
21648
|
const chunkPos = topChunk.length - (this.maxCursor - this.cursor) - 1;
|
|
@@ -20996,20 +21651,20 @@ var Bl = class {
|
|
|
20996
21651
|
this.maxCursor = this.cursor - 1;
|
|
20997
21652
|
}
|
|
20998
21653
|
}
|
|
20999
|
-
if (
|
|
21654
|
+
if (bytes3.length < 64 && bytes3.length < this.chunkSize) {
|
|
21000
21655
|
topChunk = alloc(this.chunkSize);
|
|
21001
21656
|
this.chunks.push(topChunk);
|
|
21002
21657
|
this.maxCursor += topChunk.length;
|
|
21003
21658
|
if (this._initReuseChunk === null) {
|
|
21004
21659
|
this._initReuseChunk = topChunk;
|
|
21005
21660
|
}
|
|
21006
|
-
topChunk.set(
|
|
21661
|
+
topChunk.set(bytes3, 0);
|
|
21007
21662
|
} else {
|
|
21008
|
-
this.chunks.push(
|
|
21009
|
-
this.maxCursor +=
|
|
21663
|
+
this.chunks.push(bytes3);
|
|
21664
|
+
this.maxCursor += bytes3.length;
|
|
21010
21665
|
}
|
|
21011
21666
|
}
|
|
21012
|
-
this.cursor +=
|
|
21667
|
+
this.cursor += bytes3.length;
|
|
21013
21668
|
}
|
|
21014
21669
|
/**
|
|
21015
21670
|
* @param {boolean} [reset]
|
|
@@ -21062,12 +21717,12 @@ var U8Bl = class {
|
|
|
21062
21717
|
/**
|
|
21063
21718
|
* @param {ByteView|number[]} bytes
|
|
21064
21719
|
*/
|
|
21065
|
-
push(
|
|
21066
|
-
if (this.cursor +
|
|
21720
|
+
push(bytes3) {
|
|
21721
|
+
if (this.cursor + bytes3.length > this.dest.length) {
|
|
21067
21722
|
throw new Error("write out of bounds, destination buffer is too small");
|
|
21068
21723
|
}
|
|
21069
|
-
this.dest.set(
|
|
21070
|
-
this.cursor +=
|
|
21724
|
+
this.dest.set(bytes3, this.cursor);
|
|
21725
|
+
this.cursor += bytes3.length;
|
|
21071
21726
|
}
|
|
21072
21727
|
/**
|
|
21073
21728
|
* @param {boolean} [reset]
|
|
@@ -21321,14 +21976,14 @@ function tokenBytes(token) {
|
|
|
21321
21976
|
}
|
|
21322
21977
|
__name(tokenBytes, "tokenBytes");
|
|
21323
21978
|
function encodeBytes(writer, token) {
|
|
21324
|
-
const
|
|
21325
|
-
encodeUintValue(writer, token.type.majorEncoded,
|
|
21326
|
-
writer.push(
|
|
21979
|
+
const bytes3 = tokenBytes(token);
|
|
21980
|
+
encodeUintValue(writer, token.type.majorEncoded, bytes3.length);
|
|
21981
|
+
writer.push(bytes3);
|
|
21327
21982
|
}
|
|
21328
21983
|
__name(encodeBytes, "encodeBytes");
|
|
21329
21984
|
encodeBytes.encodedSize = /* @__PURE__ */ __name(function encodedSize4(token) {
|
|
21330
|
-
const
|
|
21331
|
-
return encodeUintValue.encodedSize(
|
|
21985
|
+
const bytes3 = tokenBytes(token);
|
|
21986
|
+
return encodeUintValue.encodedSize(bytes3.length) + bytes3.length;
|
|
21332
21987
|
}, "encodedSize");
|
|
21333
21988
|
encodeBytes.compareTokens = /* @__PURE__ */ __name(function compareTokens3(tok1, tok2) {
|
|
21334
21989
|
return compareBytes(tokenBytes(tok1), tokenBytes(tok2));
|
|
@@ -21341,20 +21996,20 @@ __name(compareBytes, "compareBytes");
|
|
|
21341
21996
|
// ../../node_modules/cborg/lib/3string.js
|
|
21342
21997
|
var textDecoder = new TextDecoder();
|
|
21343
21998
|
var ASCII_THRESHOLD = 32;
|
|
21344
|
-
function toStr(
|
|
21999
|
+
function toStr(bytes3, start, end) {
|
|
21345
22000
|
const len = end - start;
|
|
21346
22001
|
if (len < ASCII_THRESHOLD) {
|
|
21347
22002
|
let str = "";
|
|
21348
22003
|
for (let i = start; i < end; i++) {
|
|
21349
|
-
const c =
|
|
22004
|
+
const c = bytes3[i];
|
|
21350
22005
|
if (c & 128) {
|
|
21351
|
-
return textDecoder.decode(
|
|
22006
|
+
return textDecoder.decode(bytes3.subarray(start, end));
|
|
21352
22007
|
}
|
|
21353
22008
|
str += String.fromCharCode(c);
|
|
21354
22009
|
}
|
|
21355
22010
|
return str;
|
|
21356
22011
|
}
|
|
21357
|
-
return textDecoder.decode(
|
|
22012
|
+
return textDecoder.decode(bytes3.subarray(start, end));
|
|
21358
22013
|
}
|
|
21359
22014
|
__name(toStr, "toStr");
|
|
21360
22015
|
function toToken2(data, pos, prefix, length, options) {
|
|
@@ -21534,7 +22189,7 @@ function decodeBreak(_data, _pos, _minor, options) {
|
|
|
21534
22189
|
return new Token(Type.break, void 0, 1);
|
|
21535
22190
|
}
|
|
21536
22191
|
__name(decodeBreak, "decodeBreak");
|
|
21537
|
-
function createToken(value,
|
|
22192
|
+
function createToken(value, bytes3, options) {
|
|
21538
22193
|
if (options) {
|
|
21539
22194
|
if (options.allowNaN === false && Number.isNaN(value)) {
|
|
21540
22195
|
throw new Error(`${decodeErrPrefix} NaN values are not supported`);
|
|
@@ -21543,7 +22198,7 @@ function createToken(value, bytes2, options) {
|
|
|
21543
22198
|
throw new Error(`${decodeErrPrefix} Infinity values are not supported`);
|
|
21544
22199
|
}
|
|
21545
22200
|
}
|
|
21546
|
-
return new Token(Type.float, value,
|
|
22201
|
+
return new Token(Type.float, value, bytes3);
|
|
21547
22202
|
}
|
|
21548
22203
|
__name(createToken, "createToken");
|
|
21549
22204
|
function decodeFloat16(data, pos, _minor, options) {
|
|
@@ -21741,13 +22396,13 @@ function majorSevenBytes(token, options) {
|
|
|
21741
22396
|
if (cached !== void 0) {
|
|
21742
22397
|
return cached;
|
|
21743
22398
|
}
|
|
21744
|
-
const
|
|
22399
|
+
const bytes3 = encodeMajorSevenBytes(token, float64);
|
|
21745
22400
|
if (float64) {
|
|
21746
|
-
tokenEx._keyBytesFloat64 =
|
|
22401
|
+
tokenEx._keyBytesFloat64 = bytes3;
|
|
21747
22402
|
} else {
|
|
21748
|
-
tokenEx._keyBytes =
|
|
22403
|
+
tokenEx._keyBytes = bytes3;
|
|
21749
22404
|
}
|
|
21750
|
-
return
|
|
22405
|
+
return bytes3;
|
|
21751
22406
|
}
|
|
21752
22407
|
__name(majorSevenBytes, "majorSevenBytes");
|
|
21753
22408
|
encodeFloat.compareTokens = /* @__PURE__ */ __name(function compareTokens4(tok1, tok2, options) {
|
|
@@ -22123,15 +22778,15 @@ var typeEncoders = {
|
|
|
22123
22778
|
*/
|
|
22124
22779
|
Object(obj, typ, options, refStack) {
|
|
22125
22780
|
const isMap = typ !== "Object";
|
|
22126
|
-
const
|
|
22127
|
-
const maxLength = isMap ? obj.size :
|
|
22781
|
+
const keys2 = isMap ? obj.keys() : Object.keys(obj);
|
|
22782
|
+
const maxLength = isMap ? obj.size : keys2.length;
|
|
22128
22783
|
let entries;
|
|
22129
22784
|
if (maxLength) {
|
|
22130
22785
|
entries = new Array(maxLength);
|
|
22131
22786
|
refStack = Ref.createCheck(refStack, obj);
|
|
22132
22787
|
const skipUndefined = !isMap && options.ignoreUndefinedProperties;
|
|
22133
22788
|
let i = 0;
|
|
22134
|
-
for (const key of
|
|
22789
|
+
for (const key of keys2) {
|
|
22135
22790
|
const value = isMap ? obj.get(key) : obj[key];
|
|
22136
22791
|
if (skipUndefined && value === void 0) {
|
|
22137
22792
|
continue;
|
|
@@ -22282,8 +22937,8 @@ function canDirectEncode(options) {
|
|
|
22282
22937
|
__name(canDirectEncode, "canDirectEncode");
|
|
22283
22938
|
function directEncodeMap(writer, data, typ, options, refStack) {
|
|
22284
22939
|
const isMap = typ === "Map";
|
|
22285
|
-
const
|
|
22286
|
-
const maxLength = isMap ? data.size :
|
|
22940
|
+
const keys2 = isMap ? data.keys() : Object.keys(data);
|
|
22941
|
+
const maxLength = isMap ? data.size : keys2.length;
|
|
22287
22942
|
if (!maxLength) {
|
|
22288
22943
|
writer.pushByte(MAJOR_MAP);
|
|
22289
22944
|
return;
|
|
@@ -22292,7 +22947,7 @@ function directEncodeMap(writer, data, typ, options, refStack) {
|
|
|
22292
22947
|
const skipUndefined = !isMap && options.ignoreUndefinedProperties;
|
|
22293
22948
|
const entries = new Array(maxLength);
|
|
22294
22949
|
let length = 0;
|
|
22295
|
-
for (const key of
|
|
22950
|
+
for (const key of keys2) {
|
|
22296
22951
|
const value = isMap ? data.get(key) : data[key];
|
|
22297
22952
|
if (skipUndefined && value === void 0) {
|
|
22298
22953
|
continue;
|
|
@@ -22351,9 +23006,9 @@ function directEncode(writer, data, options, refStack) {
|
|
|
22351
23006
|
}
|
|
22352
23007
|
return;
|
|
22353
23008
|
case "string": {
|
|
22354
|
-
const
|
|
22355
|
-
directEncodeUintValue(writer, MAJOR_STRING,
|
|
22356
|
-
writer.push(
|
|
23009
|
+
const bytes3 = fromString(data);
|
|
23010
|
+
directEncodeUintValue(writer, MAJOR_STRING, bytes3.length);
|
|
23011
|
+
writer.push(bytes3);
|
|
22357
23012
|
return;
|
|
22358
23013
|
}
|
|
22359
23014
|
case "Uint8Array":
|
|
@@ -22716,15 +23371,15 @@ var AWS_ROOT_SHA256 = "641a0321a3e244efe456463195d606317ed7cdcc3c1756e09893f3c68
|
|
|
22716
23371
|
var fail = /* @__PURE__ */ __name((reason) => {
|
|
22717
23372
|
throw new NitroAttestationError(reason);
|
|
22718
23373
|
}, "fail");
|
|
22719
|
-
var hex = /* @__PURE__ */ __name((
|
|
23374
|
+
var hex = /* @__PURE__ */ __name((bytes3) => Array.from(bytes3, (byte) => byte.toString(16).padStart(2, "0")).join(""), "hex");
|
|
22720
23375
|
var bytes = /* @__PURE__ */ __name((value, reason) => value instanceof Uint8Array && value.length > 0 ? value : fail(reason), "bytes");
|
|
22721
23376
|
var map = /* @__PURE__ */ __name((value, reason) => value instanceof Map ? value : fail(reason), "map");
|
|
22722
|
-
var decodeCbor = /* @__PURE__ */ __name((value) => {
|
|
23377
|
+
var decodeCbor = /* @__PURE__ */ __name((value, { allowIndefinite = false } = {}) => {
|
|
22723
23378
|
try {
|
|
22724
23379
|
return decode(value, {
|
|
22725
23380
|
useMaps: true,
|
|
22726
23381
|
rejectDuplicateMapKeys: true,
|
|
22727
|
-
allowIndefinite
|
|
23382
|
+
allowIndefinite,
|
|
22728
23383
|
allowUndefined: false,
|
|
22729
23384
|
allowNaN: false,
|
|
22730
23385
|
allowInfinity: false,
|
|
@@ -22782,7 +23437,7 @@ var verifyNitroAttestationDocument = /* @__PURE__ */ __name(async (documentB64,
|
|
|
22782
23437
|
const payloadBytes = bytes(payloadValue, "cose");
|
|
22783
23438
|
const signature = bytes(signatureValue, "signature");
|
|
22784
23439
|
if (signature.length !== 96) fail("signature");
|
|
22785
|
-
const payload = map(decodeCbor(payloadBytes), "cbor");
|
|
23440
|
+
const payload = map(decodeCbor(payloadBytes, { allowIndefinite: true }), "cbor");
|
|
22786
23441
|
const moduleId = payload.get("module_id");
|
|
22787
23442
|
const timestamp = payload.get("timestamp");
|
|
22788
23443
|
if (typeof moduleId !== "string" || !moduleId || payload.get("digest") !== "SHA384")
|
|
@@ -22872,13 +23527,36 @@ var verifyNitroAttestationDocument = /* @__PURE__ */ __name(async (documentB64,
|
|
|
22872
23527
|
} catch {
|
|
22873
23528
|
return fail("user-data");
|
|
22874
23529
|
}
|
|
23530
|
+
const rawLedgerKey = payload.get("public_key");
|
|
23531
|
+
let ledgerPublicKey;
|
|
23532
|
+
let measurementHash;
|
|
23533
|
+
if (rawLedgerKey !== void 0 && rawLedgerKey !== null) {
|
|
23534
|
+
const ledger = new Uint8Array(bytes(rawLedgerKey, "user-data"));
|
|
23535
|
+
if (ledger.length !== 65 || ledger[0] !== 4) fail("user-data");
|
|
23536
|
+
try {
|
|
23537
|
+
await crypto.subtle.importKey(
|
|
23538
|
+
"raw",
|
|
23539
|
+
ledger,
|
|
23540
|
+
{ name: "ECDSA", namedCurve: "P-256" },
|
|
23541
|
+
false,
|
|
23542
|
+
["verify"]
|
|
23543
|
+
);
|
|
23544
|
+
} catch {
|
|
23545
|
+
return fail("user-data");
|
|
23546
|
+
}
|
|
23547
|
+
const tuple = new Uint8Array(144);
|
|
23548
|
+
for (let i = 0; i < 3; i++) tuple.set(bytes(rawPcrs.get(i), "pcr"), i * 48);
|
|
23549
|
+
measurementHash = hex(new Uint8Array(await crypto.subtle.digest("SHA-256", tuple)));
|
|
23550
|
+
ledgerPublicKey = bufferToBase64(ledger.buffer);
|
|
23551
|
+
}
|
|
22875
23552
|
return {
|
|
22876
23553
|
escrowPublicKeySpkiB64: bufferToBase64(new Uint8Array(spki).buffer),
|
|
22877
23554
|
keyId: newFormat?.keyId,
|
|
22878
23555
|
previousKeyIds: newFormat?.previousKeyIds ?? [],
|
|
22879
23556
|
pcrs,
|
|
22880
23557
|
timestamp,
|
|
22881
|
-
moduleId
|
|
23558
|
+
moduleId,
|
|
23559
|
+
...ledgerPublicKey ? { ledgerPublicKey, measurementHash } : {}
|
|
22882
23560
|
};
|
|
22883
23561
|
}, "verifyNitroAttestationDocument");
|
|
22884
23562
|
|
|
@@ -22932,7 +23610,13 @@ var verifyEnclaveAttestation = /* @__PURE__ */ __name(async (attestation, policy
|
|
|
22932
23610
|
publicKey: verified.escrowPublicKeySpkiB64,
|
|
22933
23611
|
keyId: attestation.keyId,
|
|
22934
23612
|
previousKeyIds: verified.previousKeyIds,
|
|
22935
|
-
mode: "nitro"
|
|
23613
|
+
mode: "nitro",
|
|
23614
|
+
...verified.keyId && verified.ledgerPublicKey && verified.measurementHash ? {
|
|
23615
|
+
authority: {
|
|
23616
|
+
ledgerPublicKey: verified.ledgerPublicKey,
|
|
23617
|
+
measurement: verified.measurementHash
|
|
23618
|
+
}
|
|
23619
|
+
} : {}
|
|
22936
23620
|
};
|
|
22937
23621
|
}
|
|
22938
23622
|
const publicKey = normalizePublicKey(attestation.publicKey);
|
|
@@ -22954,6 +23638,393 @@ var verifyEnclaveAttestation = /* @__PURE__ */ __name(async (attestation, policy
|
|
|
22954
23638
|
};
|
|
22955
23639
|
}, "verifyEnclaveAttestation");
|
|
22956
23640
|
|
|
23641
|
+
// src/escrow-authority.types.ts
|
|
23642
|
+
var EscrowEvidenceError = class extends Error {
|
|
23643
|
+
static {
|
|
23644
|
+
__name(this, "EscrowEvidenceError");
|
|
23645
|
+
}
|
|
23646
|
+
constructor() {
|
|
23647
|
+
super("Automatic recovery evidence could not be verified.");
|
|
23648
|
+
this.name = "EscrowEvidenceError";
|
|
23649
|
+
}
|
|
23650
|
+
};
|
|
23651
|
+
|
|
23652
|
+
// src/escrow-authority.ts
|
|
23653
|
+
var fail2 = /* @__PURE__ */ __name(() => {
|
|
23654
|
+
throw new EscrowEvidenceError();
|
|
23655
|
+
}, "fail");
|
|
23656
|
+
var requireEvidence = /* @__PURE__ */ __name((condition) => {
|
|
23657
|
+
if (!condition) fail2();
|
|
23658
|
+
}, "requireEvidence");
|
|
23659
|
+
var object = /* @__PURE__ */ __name((value) => {
|
|
23660
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return fail2();
|
|
23661
|
+
return value;
|
|
23662
|
+
}, "object");
|
|
23663
|
+
var keys = /* @__PURE__ */ __name((value, names) => {
|
|
23664
|
+
requireEvidence(
|
|
23665
|
+
Object.keys(value).length === names.length && names.every((name) => Object.prototype.hasOwnProperty.call(value, name))
|
|
23666
|
+
);
|
|
23667
|
+
}, "keys");
|
|
23668
|
+
var integer2 = /* @__PURE__ */ __name((value, minimum = 0, maximum = Number.MAX_SAFE_INTEGER) => {
|
|
23669
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < minimum || value > maximum)
|
|
23670
|
+
return fail2();
|
|
23671
|
+
return value;
|
|
23672
|
+
}, "integer");
|
|
23673
|
+
var text = /* @__PURE__ */ __name((value, maximum) => {
|
|
23674
|
+
if (typeof value !== "string" || !value.length || value.length > maximum) return fail2();
|
|
23675
|
+
return value;
|
|
23676
|
+
}, "text");
|
|
23677
|
+
var bytes2 = /* @__PURE__ */ __name((value, length) => {
|
|
23678
|
+
if (!Array.isArray(value) || value.length !== length || !value.every(
|
|
23679
|
+
(byte) => typeof byte === "number" && Number.isInteger(byte) && byte >= 0 && byte <= 255
|
|
23680
|
+
))
|
|
23681
|
+
return fail2();
|
|
23682
|
+
return Uint8Array.from(value);
|
|
23683
|
+
}, "bytes");
|
|
23684
|
+
var base64 = /* @__PURE__ */ __name((value, maximum) => {
|
|
23685
|
+
const encoded = text(value, maximum);
|
|
23686
|
+
try {
|
|
23687
|
+
const decoded = new Uint8Array(base64ToBuffer(encoded));
|
|
23688
|
+
requireEvidence(bufferToBase64(decoded.buffer) === encoded);
|
|
23689
|
+
return decoded;
|
|
23690
|
+
} catch {
|
|
23691
|
+
return fail2();
|
|
23692
|
+
}
|
|
23693
|
+
}, "base64");
|
|
23694
|
+
var frame = /* @__PURE__ */ __name((value) => {
|
|
23695
|
+
const result = new Uint8Array(4 + value.length);
|
|
23696
|
+
new DataView(result.buffer).setUint32(0, value.length, false);
|
|
23697
|
+
result.set(value, 4);
|
|
23698
|
+
return result;
|
|
23699
|
+
}, "frame");
|
|
23700
|
+
var join2 = /* @__PURE__ */ __name((...values) => {
|
|
23701
|
+
const result = new Uint8Array(values.reduce((n, v) => n + v.length, 0));
|
|
23702
|
+
let offset = 0;
|
|
23703
|
+
for (const value of values) {
|
|
23704
|
+
result.set(value, offset);
|
|
23705
|
+
offset += value.length;
|
|
23706
|
+
}
|
|
23707
|
+
return result;
|
|
23708
|
+
}, "join");
|
|
23709
|
+
var hash = /* @__PURE__ */ __name(async (value) => bytesToHex(new Uint8Array(await crypto.subtle.digest("SHA-256", new Uint8Array(value)))), "hash");
|
|
23710
|
+
var utf82 = /* @__PURE__ */ __name((value) => new TextEncoder().encode(value), "utf8");
|
|
23711
|
+
var escrowAuthorityMeasurements = /* @__PURE__ */ __name(async (policy) => {
|
|
23712
|
+
if (policy.mode !== "nitro") return [];
|
|
23713
|
+
const hashes = [];
|
|
23714
|
+
for (const pin of policy.pinnedMeasurements) {
|
|
23715
|
+
const tuple = [pin.pcr0, pin.pcr1, pin.pcr2];
|
|
23716
|
+
if (!tuple.every((pcr) => typeof pcr === "string" && /^[0-9a-f]{96}$/i.test(pcr))) continue;
|
|
23717
|
+
if (pin.pcr0 === "00".repeat(48)) continue;
|
|
23718
|
+
const encoded = tuple.join("");
|
|
23719
|
+
const decoded = Uint8Array.from(
|
|
23720
|
+
{ length: 144 },
|
|
23721
|
+
(_, i) => parseInt(encoded.slice(i * 2, i * 2 + 2), 16)
|
|
23722
|
+
);
|
|
23723
|
+
hashes.push(await hash(decoded));
|
|
23724
|
+
}
|
|
23725
|
+
return hashes;
|
|
23726
|
+
}, "escrowAuthorityMeasurements");
|
|
23727
|
+
var P256_ORDER = BigInt("0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551");
|
|
23728
|
+
var verifyRecord = /* @__PURE__ */ __name(async (input, kind, identity, historical) => {
|
|
23729
|
+
requireEvidence(identity.mode === "nitro" && !!identity.authority);
|
|
23730
|
+
const raw = object(input);
|
|
23731
|
+
keys(raw, ["version", "kind", "keyId", "measurement", "payload", "signature"]);
|
|
23732
|
+
requireEvidence(raw.version === 1 && raw.kind === kind);
|
|
23733
|
+
const keyId = text(raw.keyId, 128);
|
|
23734
|
+
requireEvidence(
|
|
23735
|
+
historical ? [identity.keyId, ...identity.previousKeyIds].includes(keyId) : keyId === identity.keyId
|
|
23736
|
+
);
|
|
23737
|
+
const measurement = bytes2(raw.measurement, 32);
|
|
23738
|
+
requireEvidence(
|
|
23739
|
+
historical ? historical.allowedMeasurements.includes(bytesToHex(measurement)) : bytesToHex(measurement) === identity.authority?.measurement
|
|
23740
|
+
);
|
|
23741
|
+
const payloadB64 = text(raw.payload, kind === "snapshot" ? 49152 : 8192);
|
|
23742
|
+
const signatureB64 = text(raw.signature, 88);
|
|
23743
|
+
const payload = base64(payloadB64, kind === "snapshot" ? 49152 : 8192);
|
|
23744
|
+
const signature = base64(signatureB64, 88);
|
|
23745
|
+
const ledgerKey = base64(identity.authority?.ledgerPublicKey, 88);
|
|
23746
|
+
requireEvidence(ledgerKey.length === 65 && ledgerKey[0] === 4);
|
|
23747
|
+
requireEvidence(signature.length === 64);
|
|
23748
|
+
const s = BigInt(`0x${bytesToHex(signature.slice(32))}`);
|
|
23749
|
+
requireEvidence(s > 0n && s <= P256_ORDER / 2n);
|
|
23750
|
+
const message = join2(
|
|
23751
|
+
utf82("learncard-authority-signed-record-v1\0"),
|
|
23752
|
+
Uint8Array.of(kind === "snapshot" ? 2 : 1),
|
|
23753
|
+
frame(utf82(keyId)),
|
|
23754
|
+
measurement,
|
|
23755
|
+
frame(payload)
|
|
23756
|
+
);
|
|
23757
|
+
try {
|
|
23758
|
+
const key = await crypto.subtle.importKey(
|
|
23759
|
+
"raw",
|
|
23760
|
+
ledgerKey,
|
|
23761
|
+
{ name: "ECDSA", namedCurve: "P-256" },
|
|
23762
|
+
false,
|
|
23763
|
+
["verify"]
|
|
23764
|
+
);
|
|
23765
|
+
requireEvidence(
|
|
23766
|
+
await crypto.subtle.verify({ name: "ECDSA", hash: "SHA-256" }, key, signature, message)
|
|
23767
|
+
);
|
|
23768
|
+
const decoded = JSON.parse(
|
|
23769
|
+
new TextDecoder("utf-8", { fatal: true }).decode(payload)
|
|
23770
|
+
);
|
|
23771
|
+
const record = {
|
|
23772
|
+
version: 1,
|
|
23773
|
+
kind,
|
|
23774
|
+
keyId,
|
|
23775
|
+
measurement: Array.from(measurement),
|
|
23776
|
+
payload: payloadB64,
|
|
23777
|
+
signature: signatureB64
|
|
23778
|
+
};
|
|
23779
|
+
return { record, payload: decoded };
|
|
23780
|
+
} catch {
|
|
23781
|
+
return fail2();
|
|
23782
|
+
}
|
|
23783
|
+
}, "verifyRecord");
|
|
23784
|
+
var envelope = /* @__PURE__ */ __name((value) => {
|
|
23785
|
+
try {
|
|
23786
|
+
const e = parseEscrowEnvelope(value);
|
|
23787
|
+
return {
|
|
23788
|
+
version: e.version,
|
|
23789
|
+
algorithm: e.algorithm,
|
|
23790
|
+
keyId: e.keyId,
|
|
23791
|
+
ephemeralPublicKey: e.ephemeralPublicKey,
|
|
23792
|
+
salt: e.salt,
|
|
23793
|
+
iv: e.iv,
|
|
23794
|
+
ciphertext: e.ciphertext
|
|
23795
|
+
};
|
|
23796
|
+
} catch {
|
|
23797
|
+
return fail2();
|
|
23798
|
+
}
|
|
23799
|
+
}, "envelope");
|
|
23800
|
+
var state = /* @__PURE__ */ __name((value) => {
|
|
23801
|
+
const raw = object(value);
|
|
23802
|
+
keys(raw, [
|
|
23803
|
+
"tenant",
|
|
23804
|
+
"authorityGeneration",
|
|
23805
|
+
"did",
|
|
23806
|
+
"enrollmentVersion",
|
|
23807
|
+
"enrollmentEpoch",
|
|
23808
|
+
"status",
|
|
23809
|
+
"envelope",
|
|
23810
|
+
"shareVersion",
|
|
23811
|
+
"hasPin",
|
|
23812
|
+
"pinGeneration",
|
|
23813
|
+
"attemptsUsed"
|
|
23814
|
+
]);
|
|
23815
|
+
if (raw.status !== "empty" && raw.status !== "active" && raw.status !== "disabled")
|
|
23816
|
+
return fail2();
|
|
23817
|
+
if (typeof raw.hasPin !== "boolean") return fail2();
|
|
23818
|
+
const result = {
|
|
23819
|
+
tenant: text(raw.tenant, 128),
|
|
23820
|
+
authorityGeneration: text(raw.authorityGeneration, 128),
|
|
23821
|
+
did: text(raw.did, 8192),
|
|
23822
|
+
enrollmentVersion: integer2(raw.enrollmentVersion),
|
|
23823
|
+
enrollmentEpoch: integer2(raw.enrollmentEpoch),
|
|
23824
|
+
status: raw.status,
|
|
23825
|
+
envelope: raw.envelope === null ? null : envelope(raw.envelope),
|
|
23826
|
+
shareVersion: raw.shareVersion === null ? null : integer2(raw.shareVersion, 1, 4294967295),
|
|
23827
|
+
hasPin: raw.hasPin,
|
|
23828
|
+
pinGeneration: integer2(raw.pinGeneration),
|
|
23829
|
+
attemptsUsed: integer2(raw.attemptsUsed, 0, 10)
|
|
23830
|
+
};
|
|
23831
|
+
requireEvidence(
|
|
23832
|
+
result.pinGeneration <= result.enrollmentVersion && result.enrollmentEpoch <= result.enrollmentVersion && (!result.hasPin || result.pinGeneration > 0) && (result.hasPin || result.attemptsUsed === 0)
|
|
23833
|
+
);
|
|
23834
|
+
if (result.status === "empty")
|
|
23835
|
+
requireEvidence(
|
|
23836
|
+
result.enrollmentVersion === 0 && result.enrollmentEpoch === 0 && !result.envelope && result.shareVersion === null && !result.hasPin
|
|
23837
|
+
);
|
|
23838
|
+
else requireEvidence(result.enrollmentVersion > 0 && result.enrollmentEpoch > 0);
|
|
23839
|
+
if (result.status === "active")
|
|
23840
|
+
requireEvidence(!!result.envelope && result.shareVersion !== null);
|
|
23841
|
+
else requireEvidence(result.envelope === null && result.shareVersion === null);
|
|
23842
|
+
return result;
|
|
23843
|
+
}, "state");
|
|
23844
|
+
var verifyEscrowAuthorityState = /* @__PURE__ */ __name(async (response, nonce, tenant, did, identity) => {
|
|
23845
|
+
requireEvidence(/^[0-9a-f]{64}$/.test(nonce) && nonce.length === 64);
|
|
23846
|
+
const raw = object(response);
|
|
23847
|
+
keys(raw, ["state", "proof"]);
|
|
23848
|
+
const { payload } = await verifyRecord(raw.proof, "snapshot", identity);
|
|
23849
|
+
if (!Array.isArray(payload) || payload.length !== 2 || payload[0] !== nonce) return fail2();
|
|
23850
|
+
const signed = state(payload[1]);
|
|
23851
|
+
requireEvidence(signed.tenant === tenant && signed.did === did);
|
|
23852
|
+
requireEvidence(JSON.stringify(signed) === JSON.stringify(state(raw.state)));
|
|
23853
|
+
if (signed.envelope) {
|
|
23854
|
+
requireEvidence(
|
|
23855
|
+
[identity.keyId, ...identity.previousKeyIds].includes(signed.envelope.keyId)
|
|
23856
|
+
);
|
|
23857
|
+
await getEscrowBlobIdentity(signed.envelope);
|
|
23858
|
+
}
|
|
23859
|
+
return signed;
|
|
23860
|
+
}, "verifyEscrowAuthorityState");
|
|
23861
|
+
var verifyEscrowEnrollmentCommit = /* @__PURE__ */ __name(async (response, intent, identity) => {
|
|
23862
|
+
const raw = object(response);
|
|
23863
|
+
const { record, payload } = await verifyRecord(raw.receipt, "commit", identity);
|
|
23864
|
+
const data = object(payload);
|
|
23865
|
+
keys(data, ["commit", "eventHash", "requestDigest", "resultBlobIdentity", "enrollmentEpoch"]);
|
|
23866
|
+
const commit = object(data.commit);
|
|
23867
|
+
keys(commit, ["schemaVersion", "binding", "executionId", "revisions", "transactionDigest"]);
|
|
23868
|
+
const binding = object(commit.binding);
|
|
23869
|
+
keys(binding, ["tenant", "generation", "didHash"]);
|
|
23870
|
+
const revisions = object(commit.revisions);
|
|
23871
|
+
keys(revisions, ["operation", "enrollment"]);
|
|
23872
|
+
requireEvidence(
|
|
23873
|
+
commit.schemaVersion === 1 && binding.tenant === intent.tenant && binding.generation === intent.authorityGeneration
|
|
23874
|
+
);
|
|
23875
|
+
requireEvidence(bytesToHex(bytes2(binding.didHash, 32)) === await hash(utf82(intent.did)));
|
|
23876
|
+
requireEvidence(
|
|
23877
|
+
integer2(revisions.enrollment, 1) === intent.expectedEnrollmentVersion + 1 && integer2(revisions.operation, 1) >= integer2(revisions.enrollment, 1)
|
|
23878
|
+
);
|
|
23879
|
+
bytes2(commit.executionId, 16);
|
|
23880
|
+
bytes2(commit.transactionDigest, 32);
|
|
23881
|
+
bytes2(data.eventHash, 32);
|
|
23882
|
+
requireEvidence(integer2(data.enrollmentEpoch, 1) === intent.enrollmentEpoch);
|
|
23883
|
+
requireEvidence(
|
|
23884
|
+
bytesToHex(bytes2(data.requestDigest, 32)) === await hash(encodeEscrowEnrollmentIntent(intent))
|
|
23885
|
+
);
|
|
23886
|
+
if (intent.action === "disable") {
|
|
23887
|
+
requireEvidence(
|
|
23888
|
+
(raw.envelope === null || raw.envelope === void 0) && data.resultBlobIdentity === null
|
|
23889
|
+
);
|
|
23890
|
+
return { envelope: null, receipt: record };
|
|
23891
|
+
}
|
|
23892
|
+
const output = envelope(raw.envelope);
|
|
23893
|
+
requireEvidence(
|
|
23894
|
+
output.keyId === identity.keyId && bytesToHex(bytes2(data.resultBlobIdentity, 32)) === await getEscrowBlobIdentity(output)
|
|
23895
|
+
);
|
|
23896
|
+
return { envelope: output, receipt: record };
|
|
23897
|
+
}, "verifyEscrowEnrollmentCommit");
|
|
23898
|
+
var holdDigest = /* @__PURE__ */ __name(async (tenant, record) => {
|
|
23899
|
+
const h2 = record.hold;
|
|
23900
|
+
const didHash = await hash(utf82(h2.did));
|
|
23901
|
+
return hash(
|
|
23902
|
+
utf82(
|
|
23903
|
+
JSON.stringify([
|
|
23904
|
+
"learncard-hold-v1",
|
|
23905
|
+
tenant,
|
|
23906
|
+
h2.holdId,
|
|
23907
|
+
didHash,
|
|
23908
|
+
h2.shareVersion,
|
|
23909
|
+
h2.blobHash,
|
|
23910
|
+
h2.enrollmentEpoch,
|
|
23911
|
+
h2.releasePolicy,
|
|
23912
|
+
h2.clientEphemeralPublicKey,
|
|
23913
|
+
h2.createdLo,
|
|
23914
|
+
h2.createdHi,
|
|
23915
|
+
record.holdDurationMs,
|
|
23916
|
+
h2.policyVersion,
|
|
23917
|
+
record.ledgerSeq
|
|
23918
|
+
])
|
|
23919
|
+
)
|
|
23920
|
+
);
|
|
23921
|
+
}, "holdDigest");
|
|
23922
|
+
var verifyEscrowHoldRecord = /* @__PURE__ */ __name(async (record, expected, identity, historical) => {
|
|
23923
|
+
requireEvidence(
|
|
23924
|
+
record.hold.holdId === expected.holdId && record.hold.did === expected.did && record.hold.clientEphemeralPublicKey === expected.clientEphemeralPublicKey && record.hold.blobHash === expected.blobHash
|
|
23925
|
+
);
|
|
23926
|
+
let signed;
|
|
23927
|
+
try {
|
|
23928
|
+
signed = JSON.parse(
|
|
23929
|
+
new TextDecoder("utf-8", { fatal: true }).decode(base64(record.hold.signature, 8192))
|
|
23930
|
+
);
|
|
23931
|
+
} catch {
|
|
23932
|
+
return fail2();
|
|
23933
|
+
}
|
|
23934
|
+
const { record: receipt, payload } = await verifyRecord(signed, "commit", identity, historical);
|
|
23935
|
+
const data = object(payload);
|
|
23936
|
+
keys(data, ["commit", "eventHash", "requestDigest", "resultBlobIdentity", "enrollmentEpoch"]);
|
|
23937
|
+
const commit = object(data.commit);
|
|
23938
|
+
keys(commit, ["schemaVersion", "binding", "executionId", "revisions", "transactionDigest"]);
|
|
23939
|
+
const binding = object(commit.binding);
|
|
23940
|
+
keys(binding, ["tenant", "generation", "didHash"]);
|
|
23941
|
+
requireEvidence(commit.schemaVersion === 1 && binding.tenant === expected.tenant);
|
|
23942
|
+
const authorityGeneration = text(binding.generation, 128);
|
|
23943
|
+
if (historical) requireEvidence(authorityGeneration === historical.authorityGeneration);
|
|
23944
|
+
requireEvidence(bytesToHex(bytes2(binding.didHash, 32)) === await hash(utf82(expected.did)));
|
|
23945
|
+
requireEvidence(integer2(data.enrollmentEpoch, 1) === record.hold.enrollmentEpoch);
|
|
23946
|
+
requireEvidence(bytesToHex(bytes2(data.resultBlobIdentity, 32)) === record.hold.blobHash);
|
|
23947
|
+
const digest = await holdDigest(expected.tenant, record);
|
|
23948
|
+
requireEvidence(bytesToHex(bytes2(data.requestDigest, 32)) === digest);
|
|
23949
|
+
return { receipt, authorityGeneration, holdDigest: digest };
|
|
23950
|
+
}, "verifyEscrowHoldRecord");
|
|
23951
|
+
var verifyEscrowHoldConfirmation = /* @__PURE__ */ __name(async (receipt, record, expected, identity) => {
|
|
23952
|
+
const raw = object(receipt);
|
|
23953
|
+
const kind = raw.kind;
|
|
23954
|
+
if (kind !== "commit" && kind !== "snapshot") return fail2();
|
|
23955
|
+
const { record: verified, payload } = await verifyRecord(raw, kind, identity);
|
|
23956
|
+
if (kind === "snapshot") {
|
|
23957
|
+
if (!Array.isArray(payload) || payload.length !== 7) return fail2();
|
|
23958
|
+
const [tag, holdId, digestBytes] = payload;
|
|
23959
|
+
requireEvidence(
|
|
23960
|
+
tag === "learncard-authority-hold-snapshot-v2" && holdId === record.hold.holdId && payload[6] === expected.authorityGeneration
|
|
23961
|
+
);
|
|
23962
|
+
requireEvidence(
|
|
23963
|
+
bytesToHex(bytes2(digestBytes, 32)) === await holdDigest(expected.tenant, record)
|
|
23964
|
+
);
|
|
23965
|
+
requireEvidence(payload[3] === "pending");
|
|
23966
|
+
integer2(payload[4], 1);
|
|
23967
|
+
return verified;
|
|
23968
|
+
}
|
|
23969
|
+
const data = object(payload);
|
|
23970
|
+
keys(data, ["commit", "eventHash", "requestDigest", "resultBlobIdentity", "enrollmentEpoch"]);
|
|
23971
|
+
const commit = object(data.commit);
|
|
23972
|
+
keys(commit, ["schemaVersion", "binding", "executionId", "revisions", "transactionDigest"]);
|
|
23973
|
+
const binding = object(commit.binding);
|
|
23974
|
+
keys(binding, ["tenant", "generation", "didHash"]);
|
|
23975
|
+
requireEvidence(
|
|
23976
|
+
commit.schemaVersion === 1 && binding.tenant === expected.tenant && binding.generation === expected.authorityGeneration
|
|
23977
|
+
);
|
|
23978
|
+
requireEvidence(bytesToHex(bytes2(binding.didHash, 32)) === await hash(utf82(expected.did)));
|
|
23979
|
+
requireEvidence(integer2(data.enrollmentEpoch, 1) === record.hold.enrollmentEpoch);
|
|
23980
|
+
requireEvidence(bytesToHex(bytes2(data.resultBlobIdentity, 32)) === record.hold.blobHash);
|
|
23981
|
+
bytes2(data.requestDigest, 32);
|
|
23982
|
+
return verified;
|
|
23983
|
+
}, "verifyEscrowHoldConfirmation");
|
|
23984
|
+
var resolveEscrowEnrollmentAction = /* @__PURE__ */ __name((current, input) => {
|
|
23985
|
+
const disabling = input === "disable";
|
|
23986
|
+
const pinAction = disabling ? "keep" : input === "set" ? current.hasPin ? "change" : "set" : input === "clear" ? current.hasPin ? "clear" : "keep" : "keep";
|
|
23987
|
+
const action = disabling ? "disable" : current.status !== "active" ? "enroll" : current.hasPin && pinAction === "keep" ? "carry" : "replace";
|
|
23988
|
+
return { action, pinAction, bindsRecoveryContact: action === "enroll" || action === "replace" };
|
|
23989
|
+
}, "resolveEscrowEnrollmentAction");
|
|
23990
|
+
var violatesCarryContactRule = /* @__PURE__ */ __name((action, target) => action === "carry" && !!target && (!!target.recoveryEmail || !!target.recoveryLanguage), "violatesCarryContactRule");
|
|
23991
|
+
var createEscrowEnrollmentIntent = /* @__PURE__ */ __name(async (input) => {
|
|
23992
|
+
const current = state(input.state);
|
|
23993
|
+
const target = input.target === null ? null : envelope(input.target);
|
|
23994
|
+
const disabling = input.pinAction === "disable";
|
|
23995
|
+
requireEvidence(
|
|
23996
|
+
current.enrollmentVersion < Number.MAX_SAFE_INTEGER && (disabling || current.enrollmentEpoch < Number.MAX_SAFE_INTEGER)
|
|
23997
|
+
);
|
|
23998
|
+
if (disabling && current.status !== "active") return fail2();
|
|
23999
|
+
if (current.status === "disabled" && current.hasPin && input.pinAction === "automatic")
|
|
24000
|
+
return fail2();
|
|
24001
|
+
const { action, pinAction, bindsRecoveryContact } = resolveEscrowEnrollmentAction(
|
|
24002
|
+
current,
|
|
24003
|
+
input.pinAction
|
|
24004
|
+
);
|
|
24005
|
+
requireEvidence(!disabling || input.target === null);
|
|
24006
|
+
requireEvidence(disabling || input.target !== null);
|
|
24007
|
+
if (action === "carry") requireEvidence(input.shareVersion > (current.shareVersion ?? 0));
|
|
24008
|
+
const intent = {
|
|
24009
|
+
version: 2,
|
|
24010
|
+
tenant: current.tenant,
|
|
24011
|
+
did: current.did,
|
|
24012
|
+
authorityGeneration: current.authorityGeneration,
|
|
24013
|
+
expectedEnrollmentVersion: current.enrollmentVersion,
|
|
24014
|
+
action,
|
|
24015
|
+
sourceBlobIdentity: current.envelope ? await getEscrowBlobIdentity(current.envelope) : null,
|
|
24016
|
+
targetBlobIdentity: target ? await getEscrowBlobIdentity(target) : null,
|
|
24017
|
+
pinAction,
|
|
24018
|
+
shareVersion: disabling ? current.shareVersion : input.shareVersion,
|
|
24019
|
+
enrollmentEpoch: current.enrollmentEpoch + (disabling ? 0 : 1),
|
|
24020
|
+
requestId: crypto.randomUUID(),
|
|
24021
|
+
allowRewrap: !disabling,
|
|
24022
|
+
recoveryEmail: bindsRecoveryContact ? input.recoveryEmail : null,
|
|
24023
|
+
recoveryLanguage: bindsRecoveryContact ? input.recoveryLanguage : null
|
|
24024
|
+
};
|
|
24025
|
+
return signEscrowEnrollmentIntent(intent, input.privateKey);
|
|
24026
|
+
}, "createEscrowEnrollmentIntent");
|
|
24027
|
+
|
|
22957
24028
|
// src/types.ts
|
|
22958
24029
|
var import_types = __toESM(require_dist());
|
|
22959
24030
|
var EscrowPinUnavailableError = class extends Error {
|
|
@@ -23698,6 +24769,10 @@ function createSSSStrategy(config) {
|
|
|
23698
24769
|
const localWrites = /* @__PURE__ */ new Set();
|
|
23699
24770
|
const guardedStorage = /* @__PURE__ */ __name(() => {
|
|
23700
24771
|
const generation = storageGeneration;
|
|
24772
|
+
const assertCurrent = /* @__PURE__ */ __name(() => {
|
|
24773
|
+
if (generation !== storageGeneration)
|
|
24774
|
+
throw new Error("This recovery request was cancelled.");
|
|
24775
|
+
}, "assertCurrent");
|
|
23701
24776
|
const write = /* @__PURE__ */ __name((operation) => {
|
|
23702
24777
|
if (generation !== storageGeneration) {
|
|
23703
24778
|
return Promise.reject(new Error("This recovery request was cancelled."));
|
|
@@ -23708,6 +24783,7 @@ function createSSSStrategy(config) {
|
|
|
23708
24783
|
}, "write");
|
|
23709
24784
|
const guarded = {
|
|
23710
24785
|
...storage,
|
|
24786
|
+
assertCurrent,
|
|
23711
24787
|
storeDeviceShare: /* @__PURE__ */ __name((share, id) => write(() => storage.storeDeviceShare(share, id)), "storeDeviceShare"),
|
|
23712
24788
|
storeShareVersion: /* @__PURE__ */ __name((version, id) => write(() => storage.storeShareVersion(version, id)), "storeShareVersion"),
|
|
23713
24789
|
clearAllShares: /* @__PURE__ */ __name((id) => write(() => storage.clearAllShares(id)), "clearAllShares"),
|
|
@@ -23725,6 +24801,7 @@ function createSSSStrategy(config) {
|
|
|
23725
24801
|
let lastServerSnapshot = null;
|
|
23726
24802
|
let escrowEnrollmentInFlight;
|
|
23727
24803
|
let staleEscrowReenrollAttempted = false;
|
|
24804
|
+
let verifiedEscrowEnvelope;
|
|
23728
24805
|
let unenrolledRotation;
|
|
23729
24806
|
const escrowRequest = /* @__PURE__ */ __name(async (path, init, pinAttempt = false) => {
|
|
23730
24807
|
const response = await fetch(`${serverUrl}/keys/escrow${path}`, {
|
|
@@ -23783,16 +24860,89 @@ function createSSSStrategy(config) {
|
|
|
23783
24860
|
);
|
|
23784
24861
|
return verifyEnclaveAttestation(attestation, config.escrow.attestation, nonce);
|
|
23785
24862
|
}, "fetchVerifiedEnclaveKey");
|
|
23786
|
-
const
|
|
24863
|
+
const fetchEscrowHoldStatus = /* @__PURE__ */ __name(async (params) => {
|
|
24864
|
+
const query = new URLSearchParams(
|
|
24865
|
+
"holdId" in params ? { holdId: params.holdId } : { providerType: params.providerType }
|
|
24866
|
+
);
|
|
24867
|
+
const secret = "holdId" in params ? params.resumeToken : params.token;
|
|
24868
|
+
const result = await escrowRequest(`/status?${query}`, {
|
|
24869
|
+
method: "GET",
|
|
24870
|
+
headers: {
|
|
24871
|
+
...buildHeaders("", void 0, tenantId),
|
|
24872
|
+
"X-Auth-Token": secret
|
|
24873
|
+
}
|
|
24874
|
+
});
|
|
24875
|
+
return result.hold;
|
|
24876
|
+
}, "fetchEscrowHoldStatus");
|
|
24877
|
+
const recoveryExpectations = /* @__PURE__ */ __name((holdId, expected) => {
|
|
24878
|
+
if (!expected || expected.holdId !== holdId || expected.tenant !== (tenantId ?? "learncard") || !expected.did || !expected.clientEphemeralPublicKey || !expected.blobHash || !expected.authorityGeneration || !expected.holdDigest || !expected.ledgerPublicKey || !expected.keyId)
|
|
24879
|
+
throw new EscrowEvidenceError();
|
|
24880
|
+
return { ...expected };
|
|
24881
|
+
}, "recoveryExpectations");
|
|
24882
|
+
const verifyPendingHold = /* @__PURE__ */ __name(async (status, expected, identity) => {
|
|
24883
|
+
if (!config.escrow || identity.mode !== "nitro" || !identity.authority || identity.authority.ledgerPublicKey !== expected.ledgerPublicKey || ![identity.keyId, ...identity.previousKeyIds].includes(expected.keyId) || status.holdId !== expected.holdId || !status.holdRecord)
|
|
24884
|
+
throw new EscrowEvidenceError();
|
|
24885
|
+
const record = status.holdRecord;
|
|
24886
|
+
const verified = await verifyEscrowHoldRecord(record, expected, identity, {
|
|
24887
|
+
historical: true,
|
|
24888
|
+
allowedMeasurements: await escrowAuthorityMeasurements(config.escrow.attestation),
|
|
24889
|
+
authorityGeneration: expected.authorityGeneration
|
|
24890
|
+
});
|
|
24891
|
+
if (verified.holdDigest !== expected.holdDigest || verified.receipt.keyId !== expected.keyId)
|
|
24892
|
+
throw new EscrowEvidenceError();
|
|
24893
|
+
return record;
|
|
24894
|
+
}, "verifyPendingHold");
|
|
24895
|
+
const fetchAuthorityState = /* @__PURE__ */ __name(async (token, providerType, privateKey, did, signer, identity, assertCurrent) => {
|
|
24896
|
+
assertCurrent();
|
|
24897
|
+
if (identity.mode !== "nitro" || !identity.authority)
|
|
24898
|
+
throw new Error("The enclave does not support verified enrollment.");
|
|
24899
|
+
const nonce = Array.from(
|
|
24900
|
+
crypto.getRandomValues(new Uint8Array(32)),
|
|
24901
|
+
(byte) => byte.toString(16).padStart(2, "0")
|
|
24902
|
+
).join("");
|
|
24903
|
+
const vp = await requestFreshDidAuthVp(serverUrl, privateKey, did, signer, tenantId);
|
|
24904
|
+
assertCurrent();
|
|
24905
|
+
const response = await escrowRequest("/authority-state", {
|
|
24906
|
+
method: "POST",
|
|
24907
|
+
headers: buildHeaders(token, vp, tenantId),
|
|
24908
|
+
body: JSON.stringify({ authToken: token, providerType, nonce })
|
|
24909
|
+
});
|
|
24910
|
+
const result = await verifyEscrowAuthorityState(
|
|
24911
|
+
response,
|
|
24912
|
+
nonce,
|
|
24913
|
+
tenantId ?? "learncard",
|
|
24914
|
+
did,
|
|
24915
|
+
identity
|
|
24916
|
+
);
|
|
24917
|
+
assertCurrent();
|
|
24918
|
+
return result;
|
|
24919
|
+
}, "fetchAuthorityState");
|
|
24920
|
+
const enrollEscrow = /* @__PURE__ */ __name(async (token, providerType, privateKey, primaryDid, shares, shareVersion, signDidAuthVp, verifiedKey, pinMaterial, clearPin = false, assertCurrent = guardedStorage().assertCurrent, recoveryEmail = "", recoveryLanguage = "") => {
|
|
23787
24921
|
if (!config.escrow?.enabled) throw new Error("Escrow enrollment is disabled");
|
|
23788
24922
|
if (!signDidAuthVp) throw new Error("DID proof signing is required for escrow enrollment");
|
|
23789
|
-
const
|
|
23790
|
-
|
|
24923
|
+
const identity = verifiedKey ?? await fetchVerifiedEnclaveKey();
|
|
24924
|
+
assertCurrent();
|
|
24925
|
+
const { publicKey, keyId } = identity;
|
|
24926
|
+
const authority = config.escrow.attestation.mode === "nitro" ? await fetchAuthorityState(
|
|
24927
|
+
token,
|
|
24928
|
+
providerType,
|
|
24929
|
+
privateKey,
|
|
24930
|
+
primaryDid,
|
|
24931
|
+
signDidAuthVp,
|
|
24932
|
+
identity,
|
|
24933
|
+
assertCurrent
|
|
24934
|
+
) : void 0;
|
|
24935
|
+
const bindsRecoveryContact = !authority || resolveEscrowEnrollmentAction(
|
|
24936
|
+
authority,
|
|
24937
|
+
pinMaterial ? "set" : clearPin ? "clear" : "automatic"
|
|
24938
|
+
).bindsRecoveryContact;
|
|
24939
|
+
const envelope2 = await encryptEscrowBlob(
|
|
23791
24940
|
{
|
|
23792
24941
|
recoveryShare: shares.recoveryShare,
|
|
23793
24942
|
did: primaryDid,
|
|
23794
24943
|
shareVersion,
|
|
23795
|
-
...pinMaterial ? { pinVerifier: pinMaterial.pinVerifier } : {}
|
|
24944
|
+
...pinMaterial ? { pinVerifier: pinMaterial.pinVerifier } : {},
|
|
24945
|
+
...authority && recoveryEmail && bindsRecoveryContact ? { recoveryEmail, recoveryLanguage } : {}
|
|
23796
24946
|
},
|
|
23797
24947
|
publicKey,
|
|
23798
24948
|
keyId
|
|
@@ -23804,36 +24954,60 @@ function createSSSStrategy(config) {
|
|
|
23804
24954
|
signDidAuthVp,
|
|
23805
24955
|
tenantId
|
|
23806
24956
|
);
|
|
23807
|
-
await
|
|
24957
|
+
const signedIntent = authority ? await createEscrowEnrollmentIntent({
|
|
24958
|
+
state: authority,
|
|
24959
|
+
target: envelope2,
|
|
24960
|
+
shareVersion,
|
|
24961
|
+
privateKey,
|
|
24962
|
+
pinAction: pinMaterial ? "set" : clearPin ? "clear" : "automatic",
|
|
24963
|
+
recoveryEmail,
|
|
24964
|
+
recoveryLanguage
|
|
24965
|
+
}) : void 0;
|
|
24966
|
+
assertCurrent();
|
|
24967
|
+
verifiedEscrowEnvelope = void 0;
|
|
24968
|
+
const response = await escrowRequest("", {
|
|
23808
24969
|
method: "POST",
|
|
23809
24970
|
headers: buildHeaders(token, vp, tenantId),
|
|
23810
24971
|
body: JSON.stringify({
|
|
23811
24972
|
authToken: token,
|
|
23812
24973
|
providerType,
|
|
23813
|
-
envelope,
|
|
24974
|
+
envelope: envelope2,
|
|
23814
24975
|
shareVersion,
|
|
23815
24976
|
enclaveKeyId: keyId,
|
|
23816
24977
|
...pinMaterial ? { pinSalt: pinMaterial.pinSalt } : {},
|
|
23817
|
-
...clearPin ? { clearPin: true } : {}
|
|
24978
|
+
...(signedIntent ? signedIntent.intent.pinAction === "clear" : clearPin) ? { clearPin: true } : {},
|
|
24979
|
+
...signedIntent ? { signedIntent, sourceEnvelope: authority?.envelope ?? null } : {}
|
|
23818
24980
|
})
|
|
23819
24981
|
});
|
|
24982
|
+
if (signedIntent) {
|
|
24983
|
+
const committed = await verifyEscrowEnrollmentCommit(
|
|
24984
|
+
response,
|
|
24985
|
+
signedIntent.intent,
|
|
24986
|
+
identity
|
|
24987
|
+
);
|
|
24988
|
+
assertCurrent();
|
|
24989
|
+
verifiedEscrowEnvelope = committed.envelope ?? void 0;
|
|
24990
|
+
}
|
|
23820
24991
|
}, "enrollEscrow");
|
|
23821
24992
|
const tryEnrollEscrow = /* @__PURE__ */ __name(async (...args) => {
|
|
23822
24993
|
if (!config.escrow?.enabled) return;
|
|
23823
24994
|
try {
|
|
23824
24995
|
await enrollEscrow(...args);
|
|
23825
|
-
} catch (
|
|
24996
|
+
} catch (err2) {
|
|
23826
24997
|
try {
|
|
23827
|
-
if (config.onEscrowError) config.onEscrowError(
|
|
24998
|
+
if (config.onEscrowError) config.onEscrowError(err2);
|
|
23828
24999
|
else console.warn("SSS: escrow enrollment failed");
|
|
23829
25000
|
} catch {
|
|
23830
25001
|
console.warn("SSS: escrow error reporting failed");
|
|
23831
25002
|
}
|
|
23832
25003
|
}
|
|
23833
25004
|
}, "tryEnrollEscrow");
|
|
23834
|
-
const ensureEscrowEnrollmentUnguarded = /* @__PURE__ */ __name(async (self, params, storage2, forceRotate = false) => {
|
|
25005
|
+
const ensureEscrowEnrollmentUnguarded = /* @__PURE__ */ __name(async (self, params, storage2, forceRotate = false, allowDisabledEnrollment = false) => {
|
|
25006
|
+
let clearPinForEnrollment = forceRotate;
|
|
23835
25007
|
if (!config.escrow?.enabled) return { enrolled: false, reason: "disabled" };
|
|
23836
25008
|
const pin = params.options?.pin;
|
|
25009
|
+
const recoveryEmail = params.options?.recoveryEmail ?? "";
|
|
25010
|
+
const recoveryLanguage = params.options?.recoveryLanguage ?? "";
|
|
23837
25011
|
if (pin !== void 0) {
|
|
23838
25012
|
const validation = validatePin(pin);
|
|
23839
25013
|
if (!validation.ok)
|
|
@@ -23842,12 +25016,35 @@ function createSSSStrategy(config) {
|
|
|
23842
25016
|
);
|
|
23843
25017
|
}
|
|
23844
25018
|
const status = await self.fetchServerKeyStatus(params.token, params.providerType);
|
|
25019
|
+
storage2.assertCurrent();
|
|
23845
25020
|
if (status.escrowOptedOut) return { enrolled: false, reason: "opted-out" };
|
|
23846
|
-
|
|
25021
|
+
let currentlyEnrolled = status.shareVersion !== null && status.recoveryMethods.some(
|
|
23847
25022
|
(method) => method.type === "escrow" && method.shareVersion === status.shareVersion && (Boolean(method.confirmedAt) || "confirmationStatus" in method && method.confirmationStatus === "confirmed")
|
|
23848
25023
|
);
|
|
23849
|
-
|
|
23850
|
-
if (
|
|
25024
|
+
let verifiedKey;
|
|
25025
|
+
if (config.escrow.attestation.mode === "nitro") {
|
|
25026
|
+
if (!status.primaryDid || !params.signDidAuthVp)
|
|
25027
|
+
throw new Error("Owner proof signing is required for escrow enrollment.");
|
|
25028
|
+
verifiedKey = await fetchVerifiedEnclaveKey();
|
|
25029
|
+
const current = await fetchAuthorityState(
|
|
25030
|
+
params.token,
|
|
25031
|
+
params.providerType,
|
|
25032
|
+
params.privateKey,
|
|
25033
|
+
status.primaryDid,
|
|
25034
|
+
params.signDidAuthVp,
|
|
25035
|
+
verifiedKey,
|
|
25036
|
+
storage2.assertCurrent
|
|
25037
|
+
);
|
|
25038
|
+
if (current.status === "disabled") {
|
|
25039
|
+
verifiedEscrowEnvelope = void 0;
|
|
25040
|
+
if (!allowDisabledEnrollment) return { enrolled: false, reason: "opted-out" };
|
|
25041
|
+
clearPinForEnrollment ||= current.hasPin && pin === void 0;
|
|
25042
|
+
}
|
|
25043
|
+
currentlyEnrolled = currentlyEnrolled && current.status === "active" && current.shareVersion === status.shareVersion && current.envelope?.keyId === verifiedKey.keyId;
|
|
25044
|
+
if (currentlyEnrolled) verifiedEscrowEnvelope = current.envelope ?? void 0;
|
|
25045
|
+
}
|
|
25046
|
+
const repairingStaleBlob = pin === void 0 && !clearPinForEnrollment && currentlyEnrolled && !!status.escrowStale && !staleEscrowReenrollAttempted;
|
|
25047
|
+
if (!clearPinForEnrollment && pin === void 0 && currentlyEnrolled && !repairingStaleBlob)
|
|
23851
25048
|
return { enrolled: true, changed: false };
|
|
23852
25049
|
if (repairingStaleBlob) staleEscrowReenrollAttempted = true;
|
|
23853
25050
|
if (!status.primaryDid) throw new Error("Cannot enroll escrow without a primary DID");
|
|
@@ -23855,7 +25052,7 @@ function createSSSStrategy(config) {
|
|
|
23855
25052
|
throw new Error("DID proof signing is required for escrow enrollment");
|
|
23856
25053
|
}
|
|
23857
25054
|
try {
|
|
23858
|
-
if (!
|
|
25055
|
+
if (!clearPinForEnrollment && pin === void 0 && unenrolledRotation && unenrolledRotation.shareVersion === status.shareVersion && unenrolledRotation.primaryDid === status.primaryDid) {
|
|
23859
25056
|
const retry = unenrolledRotation;
|
|
23860
25057
|
await enrollEscrow(
|
|
23861
25058
|
params.token,
|
|
@@ -23867,12 +25064,16 @@ function createSSSStrategy(config) {
|
|
|
23867
25064
|
params.signDidAuthVp,
|
|
23868
25065
|
void 0,
|
|
23869
25066
|
void 0,
|
|
23870
|
-
retry.clearPin
|
|
25067
|
+
retry.clearPin,
|
|
25068
|
+
storage2.assertCurrent,
|
|
25069
|
+
recoveryEmail,
|
|
25070
|
+
recoveryLanguage
|
|
23871
25071
|
);
|
|
23872
25072
|
unenrolledRotation = void 0;
|
|
23873
25073
|
return { enrolled: true, changed: true, shareVersion: retry.shareVersion };
|
|
23874
25074
|
}
|
|
23875
|
-
|
|
25075
|
+
verifiedKey ??= await fetchVerifiedEnclaveKey();
|
|
25076
|
+
storage2.assertCurrent();
|
|
23876
25077
|
const pinSalt = pin !== void 0 ? generatePinSalt() : void 0;
|
|
23877
25078
|
const pinMaterial = pin !== void 0 && pinSalt !== void 0 ? { pinSalt, pinVerifier: await derivePinProof(pin, pinSalt) } : void 0;
|
|
23878
25079
|
const storageId = activeStorageId;
|
|
@@ -23901,7 +25102,12 @@ function createSSSStrategy(config) {
|
|
|
23901
25102
|
authShare: shares.authShare,
|
|
23902
25103
|
primaryDid: status.primaryDid
|
|
23903
25104
|
};
|
|
23904
|
-
unenrolledRotation = pinMaterial ? void 0 : {
|
|
25105
|
+
unenrolledRotation = pinMaterial ? void 0 : {
|
|
25106
|
+
shares,
|
|
25107
|
+
shareVersion,
|
|
25108
|
+
primaryDid: status.primaryDid,
|
|
25109
|
+
clearPin: clearPinForEnrollment
|
|
25110
|
+
};
|
|
23905
25111
|
await enrollEscrow(
|
|
23906
25112
|
params.token,
|
|
23907
25113
|
params.providerType,
|
|
@@ -23912,14 +25118,17 @@ function createSSSStrategy(config) {
|
|
|
23912
25118
|
params.signDidAuthVp,
|
|
23913
25119
|
verifiedKey,
|
|
23914
25120
|
pinMaterial,
|
|
23915
|
-
|
|
25121
|
+
clearPinForEnrollment,
|
|
25122
|
+
storage2.assertCurrent,
|
|
25123
|
+
recoveryEmail,
|
|
25124
|
+
recoveryLanguage
|
|
23916
25125
|
);
|
|
23917
25126
|
unenrolledRotation = void 0;
|
|
23918
25127
|
return { enrolled: true, changed: true, shareVersion };
|
|
23919
|
-
} catch (
|
|
23920
|
-
if (!repairingStaleBlob) throw
|
|
25128
|
+
} catch (err2) {
|
|
25129
|
+
if (!repairingStaleBlob || config.escrow.attestation.mode === "nitro") throw err2;
|
|
23921
25130
|
try {
|
|
23922
|
-
if (config.onEscrowError) config.onEscrowError(
|
|
25131
|
+
if (config.onEscrowError) config.onEscrowError(err2);
|
|
23923
25132
|
else console.warn("SSS: escrow enrollment failed");
|
|
23924
25133
|
} catch {
|
|
23925
25134
|
console.warn("SSS: escrow error reporting failed");
|
|
@@ -23958,6 +25167,7 @@ function createSSSStrategy(config) {
|
|
|
23958
25167
|
},
|
|
23959
25168
|
// --- User scoping ---
|
|
23960
25169
|
setActiveUser(userId) {
|
|
25170
|
+
verifiedEscrowEnvelope = void 0;
|
|
23961
25171
|
if (activeStorageId !== `sss-device-share:${userId}`) storageGeneration++;
|
|
23962
25172
|
activeStorageId = `sss-device-share:${userId}`;
|
|
23963
25173
|
lastServerSnapshot = null;
|
|
@@ -24002,6 +25212,7 @@ function createSSSStrategy(config) {
|
|
|
24002
25212
|
);
|
|
24003
25213
|
}
|
|
24004
25214
|
storageGeneration++;
|
|
25215
|
+
verifiedEscrowEnvelope = void 0;
|
|
24005
25216
|
await Promise.allSettled(localWrites);
|
|
24006
25217
|
await clearPendingShareCandidates(storage, storageId);
|
|
24007
25218
|
return storage.clearAllShares(storageId);
|
|
@@ -24300,8 +25511,58 @@ function createSSSStrategy(config) {
|
|
|
24300
25511
|
return { state: enrolled ? "enrolled" : "not-enrolled", escrowPin: status.escrowPin };
|
|
24301
25512
|
},
|
|
24302
25513
|
async disableEscrowRecovery(params) {
|
|
25514
|
+
const assertCurrent = guardedStorage().assertCurrent;
|
|
24303
25515
|
const status = await this.fetchServerKeyStatus(params.token, params.providerType);
|
|
24304
25516
|
if (!status.primaryDid) throw new Error("Cannot disable escrow without a primary DID");
|
|
25517
|
+
if (config.escrow?.attestation.mode === "nitro") {
|
|
25518
|
+
const identity = await fetchVerifiedEnclaveKey();
|
|
25519
|
+
const current = await fetchAuthorityState(
|
|
25520
|
+
params.token,
|
|
25521
|
+
params.providerType,
|
|
25522
|
+
params.privateKey,
|
|
25523
|
+
status.primaryDid,
|
|
25524
|
+
params.signDidAuthVp,
|
|
25525
|
+
identity,
|
|
25526
|
+
assertCurrent
|
|
25527
|
+
);
|
|
25528
|
+
if (current.status === "disabled") {
|
|
25529
|
+
verifiedEscrowEnvelope = void 0;
|
|
25530
|
+
return;
|
|
25531
|
+
}
|
|
25532
|
+
const signedIntent = await createEscrowEnrollmentIntent({
|
|
25533
|
+
state: current,
|
|
25534
|
+
target: null,
|
|
25535
|
+
shareVersion: current.shareVersion ?? 0,
|
|
25536
|
+
privateKey: params.privateKey,
|
|
25537
|
+
pinAction: "disable",
|
|
25538
|
+
// Disable always nulls these server-side regardless of input.
|
|
25539
|
+
recoveryEmail: "",
|
|
25540
|
+
recoveryLanguage: ""
|
|
25541
|
+
});
|
|
25542
|
+
const vp2 = await requestFreshDidAuthVp(
|
|
25543
|
+
serverUrl,
|
|
25544
|
+
params.privateKey,
|
|
25545
|
+
status.primaryDid,
|
|
25546
|
+
params.signDidAuthVp,
|
|
25547
|
+
tenantId
|
|
25548
|
+
);
|
|
25549
|
+
assertCurrent();
|
|
25550
|
+
const response = await escrowRequest("/disable", {
|
|
25551
|
+
method: "POST",
|
|
25552
|
+
headers: buildHeaders(params.token, vp2, tenantId),
|
|
25553
|
+
body: JSON.stringify({
|
|
25554
|
+
authToken: params.token,
|
|
25555
|
+
providerType: params.providerType,
|
|
25556
|
+
optOut: true,
|
|
25557
|
+
signedIntent,
|
|
25558
|
+
sourceEnvelope: current.envelope
|
|
25559
|
+
})
|
|
25560
|
+
});
|
|
25561
|
+
await verifyEscrowEnrollmentCommit(response, signedIntent.intent, identity);
|
|
25562
|
+
assertCurrent();
|
|
25563
|
+
verifiedEscrowEnvelope = void 0;
|
|
25564
|
+
return;
|
|
25565
|
+
}
|
|
24305
25566
|
const vp = await requestFreshDidAuthVp(
|
|
24306
25567
|
serverUrl,
|
|
24307
25568
|
params.privateKey,
|
|
@@ -24342,13 +25603,29 @@ function createSSSStrategy(config) {
|
|
|
24342
25603
|
providerType: params.providerType
|
|
24343
25604
|
})
|
|
24344
25605
|
});
|
|
24345
|
-
return ensureEscrowEnrollmentUnguarded(this, params, storage2);
|
|
25606
|
+
return ensureEscrowEnrollmentUnguarded(this, params, storage2, false, true);
|
|
24346
25607
|
});
|
|
24347
25608
|
},
|
|
24348
25609
|
async setEscrowPin({ pin, ...params }) {
|
|
24349
25610
|
const storage2 = guardedStorage();
|
|
24350
25611
|
const result = await withRotationLock(
|
|
24351
|
-
() =>
|
|
25612
|
+
() => (
|
|
25613
|
+
// P9.1: preserve the caller's recoveryEmail/recoveryLanguage — do
|
|
25614
|
+
// not replace `params.options` wholesale, or nitro enroll/replace
|
|
25615
|
+
// loses its required recovery contact.
|
|
25616
|
+
ensureEscrowEnrollmentUnguarded(
|
|
25617
|
+
this,
|
|
25618
|
+
{
|
|
25619
|
+
...params,
|
|
25620
|
+
options: {
|
|
25621
|
+
pin,
|
|
25622
|
+
recoveryEmail: params.options?.recoveryEmail,
|
|
25623
|
+
recoveryLanguage: params.options?.recoveryLanguage
|
|
25624
|
+
}
|
|
25625
|
+
},
|
|
25626
|
+
storage2
|
|
25627
|
+
)
|
|
25628
|
+
)
|
|
24352
25629
|
);
|
|
24353
25630
|
if (!result.enrolled || !result.changed) {
|
|
24354
25631
|
throw new Error("Automatic recovery is not available for this account.");
|
|
@@ -24380,8 +25657,15 @@ function createSSSStrategy(config) {
|
|
|
24380
25657
|
escrowEnrollmentInFlight = void 0;
|
|
24381
25658
|
}
|
|
24382
25659
|
},
|
|
25660
|
+
getVerifiedEscrowEnvelope() {
|
|
25661
|
+
return verifiedEscrowEnvelope ? { ...verifiedEscrowEnvelope } : null;
|
|
25662
|
+
},
|
|
24383
25663
|
/** Start or explicitly restart a hold with fresh client-bound resume secrets. */
|
|
24384
25664
|
async startEscrowRecovery(params) {
|
|
25665
|
+
const expectedDid = params.expectedDid;
|
|
25666
|
+
const nitro = config.escrow?.attestation.mode === "nitro";
|
|
25667
|
+
if (nitro && (!expectedDid || (params.tenantId ?? tenantId) !== tenantId))
|
|
25668
|
+
throw new EscrowEvidenceError();
|
|
24385
25669
|
const sessionProof = params.recoverySessionToken !== void 0;
|
|
24386
25670
|
if (sessionProof ? params.token !== void 0 || params.providerType !== void 0 : !params.token || !params.providerType) {
|
|
24387
25671
|
throw new Error("Provide exactly one identity proof");
|
|
@@ -24401,25 +25685,101 @@ function createSSSStrategy(config) {
|
|
|
24401
25685
|
},
|
|
24402
25686
|
params.options?.releasePolicy === "pin"
|
|
24403
25687
|
);
|
|
24404
|
-
|
|
25688
|
+
let expectations;
|
|
25689
|
+
if (nitro && result.resumeToken !== null) {
|
|
25690
|
+
const identity = await fetchVerifiedEnclaveKey();
|
|
25691
|
+
if (identity.mode !== "nitro" || !identity.authority || !result.holdRecord || !expectedDid)
|
|
25692
|
+
throw new EscrowEvidenceError();
|
|
25693
|
+
const verified = await verifyEscrowHoldRecord(
|
|
25694
|
+
result.holdRecord,
|
|
25695
|
+
{
|
|
25696
|
+
tenant: tenantId ?? "learncard",
|
|
25697
|
+
did: expectedDid,
|
|
25698
|
+
holdId: result.holdId,
|
|
25699
|
+
clientEphemeralPublicKey: pair.publicKey,
|
|
25700
|
+
blobHash: result.holdRecord.hold.blobHash
|
|
25701
|
+
},
|
|
25702
|
+
identity
|
|
25703
|
+
);
|
|
25704
|
+
expectations = {
|
|
25705
|
+
tenant: tenantId ?? "learncard",
|
|
25706
|
+
did: expectedDid,
|
|
25707
|
+
holdId: result.holdId,
|
|
25708
|
+
clientEphemeralPublicKey: pair.publicKey,
|
|
25709
|
+
blobHash: result.holdRecord.hold.blobHash,
|
|
25710
|
+
authorityGeneration: verified.authorityGeneration,
|
|
25711
|
+
holdDigest: verified.holdDigest,
|
|
25712
|
+
ledgerPublicKey: identity.authority.ledgerPublicKey,
|
|
25713
|
+
keyId: verified.receipt.keyId
|
|
25714
|
+
};
|
|
25715
|
+
}
|
|
25716
|
+
return { ...result, clientEphemeralPrivateKey: pair.privateKey, expectations };
|
|
24405
25717
|
},
|
|
24406
25718
|
/** Read hold status; secrets (auth or resume token) never travel in a URL. */
|
|
24407
25719
|
async getEscrowRecoveryStatus(params) {
|
|
24408
|
-
const
|
|
24409
|
-
|
|
24410
|
-
)
|
|
24411
|
-
|
|
24412
|
-
|
|
24413
|
-
|
|
24414
|
-
|
|
24415
|
-
|
|
24416
|
-
|
|
24417
|
-
|
|
24418
|
-
|
|
24419
|
-
|
|
25720
|
+
const expected = config.escrow?.attestation.mode === "nitro" && "holdId" in params ? recoveryExpectations(params.holdId, params.expectations) : void 0;
|
|
25721
|
+
const status = await fetchEscrowHoldStatus(params);
|
|
25722
|
+
if (expected && status)
|
|
25723
|
+
await verifyPendingHold(status, expected, await fetchVerifiedEnclaveKey());
|
|
25724
|
+
return status;
|
|
25725
|
+
},
|
|
25726
|
+
/** Submit the confirmation code emailed by the enclave for an authority-mode hold. */
|
|
25727
|
+
async confirmEscrowRecovery(params) {
|
|
25728
|
+
let pending;
|
|
25729
|
+
if (config.escrow?.attestation.mode === "nitro") {
|
|
25730
|
+
const expected = recoveryExpectations(params.holdId, params.expectations);
|
|
25731
|
+
if ((params.tenantId ?? tenantId) !== tenantId) throw new EscrowEvidenceError();
|
|
25732
|
+
const identity = await fetchVerifiedEnclaveKey();
|
|
25733
|
+
const status = await fetchEscrowHoldStatus({
|
|
25734
|
+
holdId: params.holdId,
|
|
25735
|
+
resumeToken: params.resumeToken
|
|
25736
|
+
});
|
|
25737
|
+
if (!status?.holdRecord) {
|
|
25738
|
+
throw new EscrowEvidenceError();
|
|
24420
25739
|
}
|
|
24421
|
-
|
|
24422
|
-
|
|
25740
|
+
const holdRecord = await verifyPendingHold(status, expected, identity);
|
|
25741
|
+
pending = { identity, holdRecord, expected };
|
|
25742
|
+
}
|
|
25743
|
+
const confirm = /* @__PURE__ */ __name(() => escrowRequest("/confirm", {
|
|
25744
|
+
method: "POST",
|
|
25745
|
+
headers: buildHeaders("", void 0, params.tenantId ?? tenantId),
|
|
25746
|
+
body: JSON.stringify({
|
|
25747
|
+
holdId: params.holdId,
|
|
25748
|
+
resumeToken: params.resumeToken,
|
|
25749
|
+
code: params.code
|
|
25750
|
+
})
|
|
25751
|
+
}), "confirm");
|
|
25752
|
+
const result = await confirm();
|
|
25753
|
+
if (pending) {
|
|
25754
|
+
if (!result.receipt) {
|
|
25755
|
+
throw new EscrowEvidenceError();
|
|
25756
|
+
}
|
|
25757
|
+
const receipt = await verifyEscrowHoldConfirmation(
|
|
25758
|
+
result.receipt,
|
|
25759
|
+
pending.holdRecord,
|
|
25760
|
+
pending.expected,
|
|
25761
|
+
pending.identity
|
|
25762
|
+
);
|
|
25763
|
+
if (receipt.kind === "commit") {
|
|
25764
|
+
const readback = await confirm();
|
|
25765
|
+
const snapshot = await verifyEscrowHoldConfirmation(
|
|
25766
|
+
readback.receipt,
|
|
25767
|
+
pending.holdRecord,
|
|
25768
|
+
pending.expected,
|
|
25769
|
+
pending.identity
|
|
25770
|
+
);
|
|
25771
|
+
if (snapshot.kind !== "snapshot") throw new EscrowEvidenceError();
|
|
25772
|
+
}
|
|
25773
|
+
}
|
|
25774
|
+
return { success: true };
|
|
25775
|
+
},
|
|
25776
|
+
/** Request a fresh confirmation code for a hold awaiting confirmation. */
|
|
25777
|
+
async resendEscrowRecoveryCode(params) {
|
|
25778
|
+
return escrowRequest("/resend", {
|
|
25779
|
+
method: "POST",
|
|
25780
|
+
headers: buildHeaders("", void 0, params.tenantId ?? tenantId),
|
|
25781
|
+
body: JSON.stringify({ holdId: params.holdId, resumeToken: params.resumeToken })
|
|
25782
|
+
});
|
|
24423
25783
|
},
|
|
24424
25784
|
/** Cancel a pending hold with a fresh DID-owner proof. */
|
|
24425
25785
|
async cancelEscrowRecovery(params) {
|
|
@@ -24451,8 +25811,19 @@ function createSSSStrategy(config) {
|
|
|
24451
25811
|
const start = input.method === "escrow-pin" ? await this.startEscrowRecovery({
|
|
24452
25812
|
token,
|
|
24453
25813
|
providerType,
|
|
25814
|
+
expectedDid: input.expectedDid,
|
|
24454
25815
|
options: { releasePolicy: "pin" }
|
|
24455
25816
|
}) : input;
|
|
25817
|
+
const expected = config.escrow?.attestation.mode === "nitro" ? recoveryExpectations(start.holdId, start.expectations) : void 0;
|
|
25818
|
+
if (expected) {
|
|
25819
|
+
if (!start.resumeToken) throw new EscrowEvidenceError();
|
|
25820
|
+
const status = await fetchEscrowHoldStatus({
|
|
25821
|
+
holdId: start.holdId,
|
|
25822
|
+
resumeToken: start.resumeToken
|
|
25823
|
+
});
|
|
25824
|
+
if (!status) throw new EscrowEvidenceError();
|
|
25825
|
+
await verifyPendingHold(status, expected, await fetchVerifiedEnclaveKey());
|
|
25826
|
+
}
|
|
24456
25827
|
let pinProof;
|
|
24457
25828
|
if (input.method === "escrow-pin") {
|
|
24458
25829
|
if (!("pinSalt" in start) || !start.pinSalt || !start.resumeToken)
|
|
@@ -24476,6 +25847,8 @@ function createSSSStrategy(config) {
|
|
|
24476
25847
|
material.sealedShare,
|
|
24477
25848
|
start.clientEphemeralPrivateKey
|
|
24478
25849
|
);
|
|
25850
|
+
if (expected && (plaintext.did !== expected.did || plaintext.holdId !== expected.holdId))
|
|
25851
|
+
throw new EscrowEvidenceError();
|
|
24479
25852
|
if (plaintext.holdId !== start.holdId || plaintext.did !== material.primaryDid || plaintext.shareVersion !== material.shareVersion) {
|
|
24480
25853
|
throw new Error("Escrow recovery material does not match the request");
|
|
24481
25854
|
}
|
|
@@ -24889,10 +26262,10 @@ function createSSSStrategy(config) {
|
|
|
24889
26262
|
const pending = pendingPhraseConfirmation;
|
|
24890
26263
|
if (!pending) throw new Error("Generate a new recovery phrase to continue");
|
|
24891
26264
|
const phraseWords = pending.phrase.trim().toLowerCase().split(/\s+/);
|
|
24892
|
-
const
|
|
26265
|
+
const matches2 = input.challengeWords.length === pending.challengeWordIndices.length && pending.challengeWordIndices.every(
|
|
24893
26266
|
(wordIndex, answerIndex) => input.challengeWords[answerIndex]?.trim().toLowerCase() === phraseWords[wordIndex]
|
|
24894
26267
|
);
|
|
24895
|
-
if (!
|
|
26268
|
+
if (!matches2) {
|
|
24896
26269
|
throw new Error("Those words do not match. Check your phrase and try again.");
|
|
24897
26270
|
}
|
|
24898
26271
|
} else if (input.method === "backup") {
|
|
@@ -25278,6 +26651,7 @@ function createSSSStrategy(config) {
|
|
|
25278
26651
|
},
|
|
25279
26652
|
async cleanup() {
|
|
25280
26653
|
storageGeneration++;
|
|
26654
|
+
verifiedEscrowEnvelope = void 0;
|
|
25281
26655
|
await Promise.allSettled(localWrites);
|
|
25282
26656
|
}
|
|
25283
26657
|
};
|
|
@@ -25498,3 +26872,8 @@ var notifyDevicesForQrSession = /* @__PURE__ */ __name(async (config, sessionId,
|
|
|
25498
26872
|
return { sent: false, deviceCount: 0 };
|
|
25499
26873
|
}
|
|
25500
26874
|
}, "notifyDevicesForQrSession");
|
|
26875
|
+
/*! Bundled license information:
|
|
26876
|
+
|
|
26877
|
+
@noble/ed25519/index.js:
|
|
26878
|
+
(*! noble-ed25519 - MIT License (c) 2019 Paul Miller (paulmillr.com) *)
|
|
26879
|
+
*/
|