@reclaimprotocol/js-sdk 5.0.0-dev.1 → 5.0.0-dev.3
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/README.md +228 -46
- package/dist/index.d.ts +360 -60
- package/dist/index.js +1427 -270
- package/dist/index.js.map +1 -1
- package/package.json +6 -2
package/dist/index.js
CHANGED
|
@@ -22,6 +22,18 @@ var __spreadValues = (a, b) => {
|
|
|
22
22
|
return a;
|
|
23
23
|
};
|
|
24
24
|
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
25
|
+
var __objRest = (source, exclude) => {
|
|
26
|
+
var target = {};
|
|
27
|
+
for (var prop in source)
|
|
28
|
+
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
29
|
+
target[prop] = source[prop];
|
|
30
|
+
if (source != null && __getOwnPropSymbols)
|
|
31
|
+
for (var prop of __getOwnPropSymbols(source)) {
|
|
32
|
+
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
33
|
+
target[prop] = source[prop];
|
|
34
|
+
}
|
|
35
|
+
return target;
|
|
36
|
+
};
|
|
25
37
|
var __commonJS = (cb, mod) => function __require() {
|
|
26
38
|
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
27
39
|
};
|
|
@@ -72,7 +84,7 @@ var require_package = __commonJS({
|
|
|
72
84
|
"package.json"(exports2, module2) {
|
|
73
85
|
module2.exports = {
|
|
74
86
|
name: "@reclaimprotocol/js-sdk",
|
|
75
|
-
version: "5.0.0-dev.
|
|
87
|
+
version: "5.0.0-dev.3",
|
|
76
88
|
description: "Designed to request proofs from the Reclaim protocol and manage the flow of claims and witness interactions.",
|
|
77
89
|
main: "dist/index.js",
|
|
78
90
|
types: "dist/index.d.ts",
|
|
@@ -148,6 +160,8 @@ var require_package = __commonJS({
|
|
|
148
160
|
"@commitlint/config-conventional": "^17.7.0",
|
|
149
161
|
"@release-it/conventional-changelog": "10.0.6",
|
|
150
162
|
"@types/jest": "^30.0.0",
|
|
163
|
+
"@types/node-forge": "^1.3.14",
|
|
164
|
+
"@types/qrcode": "^1.5.5",
|
|
151
165
|
"@types/qs": "^6.9.11",
|
|
152
166
|
"@types/url-parse": "^1.4.11",
|
|
153
167
|
"@types/uuid": "^9.0.7",
|
|
@@ -163,6 +177,8 @@ var require_package = __commonJS({
|
|
|
163
177
|
canonicalize: "^2.0.0",
|
|
164
178
|
ethers: "^6.9.1",
|
|
165
179
|
"fetch-retry": "^6.0.0",
|
|
180
|
+
"node-forge": "^1.3.3",
|
|
181
|
+
qrcode: "^1.5.4",
|
|
166
182
|
"url-parse": "^1.5.10",
|
|
167
183
|
uuid: "^9.0.1"
|
|
168
184
|
},
|
|
@@ -177,14 +193,16 @@ var require_package = __commonJS({
|
|
|
177
193
|
var index_exports = {};
|
|
178
194
|
__export(index_exports, {
|
|
179
195
|
ReclaimProofRequest: () => ReclaimProofRequest,
|
|
196
|
+
TeeVerificationError: () => TeeVerificationError,
|
|
180
197
|
assertValidProofsByHash: () => assertValidProofsByHash,
|
|
181
198
|
assertValidateProof: () => assertValidateProof,
|
|
182
199
|
assertVerifiedProof: () => assertVerifiedProof,
|
|
183
200
|
clearDeviceCache: () => clearDeviceCache,
|
|
184
201
|
createLinkWithTemplateData: () => createLinkWithTemplateData,
|
|
185
|
-
|
|
202
|
+
fetchProviderConfigs: () => fetchProviderConfigs,
|
|
186
203
|
fetchProviderHashRequirementsBy: () => fetchProviderHashRequirementsBy,
|
|
187
204
|
fetchStatusUrl: () => fetchStatusUrl,
|
|
205
|
+
generateSpecsFromRequestSpecTemplate: () => generateSpecsFromRequestSpecTemplate,
|
|
188
206
|
getAttestors: () => getAttestors,
|
|
189
207
|
getDeviceType: () => getDeviceType,
|
|
190
208
|
getHttpProviderClaimParamsFromProof: () => getHttpProviderClaimParamsFromProof,
|
|
@@ -197,9 +215,12 @@ __export(index_exports, {
|
|
|
197
215
|
isHttpProviderClaimParams: () => isHttpProviderClaimParams,
|
|
198
216
|
isMobileDevice: () => isMobileDevice,
|
|
199
217
|
recoverSignersOfSignedClaim: () => recoverSignersOfSignedClaim,
|
|
218
|
+
takePairsWhereValueIsArray: () => takePairsWhereValueIsArray,
|
|
219
|
+
takeTemplateParametersFromProofs: () => takeTemplateParametersFromProofs,
|
|
200
220
|
transformForOnchain: () => transformForOnchain,
|
|
201
221
|
updateSession: () => updateSession,
|
|
202
|
-
verifyProof: () => verifyProof
|
|
222
|
+
verifyProof: () => verifyProof,
|
|
223
|
+
verifyTeeAttestation: () => verifyTeeAttestation
|
|
203
224
|
});
|
|
204
225
|
module.exports = __toCommonJS(index_exports);
|
|
205
226
|
|
|
@@ -212,20 +233,20 @@ var RECLAIM_EXTENSION_ACTIONS = {
|
|
|
212
233
|
};
|
|
213
234
|
|
|
214
235
|
// src/Reclaim.ts
|
|
215
|
-
var
|
|
236
|
+
var import_ethers5 = require("ethers");
|
|
216
237
|
var import_canonicalize3 = __toESM(require("canonicalize"));
|
|
217
238
|
|
|
218
239
|
// src/utils/errors.ts
|
|
219
240
|
function createErrorClass(name) {
|
|
220
241
|
return class extends Error {
|
|
221
242
|
constructor(message, innerError) {
|
|
222
|
-
const fullMessage = innerError ? `${message || ""} caused by ${innerError.name}: ${innerError.message}` : message;
|
|
243
|
+
const fullMessage = innerError ? `${message || ""} caused by ${innerError && typeof innerError === "object" && "name" in innerError ? innerError.name : "Error"}: ${innerError && typeof innerError === "object" && "message" in innerError ? innerError.message : String(innerError)}` : message;
|
|
223
244
|
super(fullMessage);
|
|
224
245
|
this.innerError = innerError;
|
|
225
246
|
this.name = name;
|
|
226
247
|
if (innerError) {
|
|
227
248
|
this.stack += `
|
|
228
|
-
Caused by: ${innerError.stack}`;
|
|
249
|
+
Caused by: ${innerError && typeof innerError === "object" && "stack" in innerError ? innerError.stack : String(innerError)}`;
|
|
229
250
|
}
|
|
230
251
|
}
|
|
231
252
|
};
|
|
@@ -233,6 +254,7 @@ Caused by: ${innerError.stack}`;
|
|
|
233
254
|
var TimeoutError = createErrorClass("TimeoutError");
|
|
234
255
|
var ProofNotVerifiedError = createErrorClass("ProofNotVerifiedError");
|
|
235
256
|
var ProofNotValidatedError = createErrorClass("ProofNotValidatedError");
|
|
257
|
+
var InvalidRequestSpecError = createErrorClass("InvalidRequestSpecError");
|
|
236
258
|
var UnknownProofsNotValidatedError = createErrorClass("UnknownProofsNotValidatedError");
|
|
237
259
|
var SessionNotStartedError = createErrorClass("SessionNotStartedError");
|
|
238
260
|
var ProviderNotFoundError = createErrorClass("ProviderNotFoundError");
|
|
@@ -258,6 +280,7 @@ var InavlidParametersError = createErrorClass("InavlidParametersError");
|
|
|
258
280
|
var ProofSubmissionFailedError = createErrorClass("ProofSubmissionFailedError");
|
|
259
281
|
var ErrorDuringVerificationError = createErrorClass("ErrorDuringVerificationError");
|
|
260
282
|
var CallbackUrlRequiredError = createErrorClass("CallbackUrlRequiredError");
|
|
283
|
+
var TeeVerificationError = createErrorClass("TeeVerificationError");
|
|
261
284
|
|
|
262
285
|
// src/utils/logger.ts
|
|
263
286
|
var SimpleLogger = class {
|
|
@@ -353,15 +376,13 @@ var constants = {
|
|
|
353
376
|
get DEFAULT_ATTESTORS_URL() {
|
|
354
377
|
return `${BACKEND_BASE_URL}/api/attestors`;
|
|
355
378
|
},
|
|
356
|
-
|
|
357
|
-
return `${BACKEND_BASE_URL}/api/providers/${providerId}?versionNumber=${exactProviderVersionString}`;
|
|
379
|
+
DEFAULT_PROVIDER_CONFIGS_URL(providerId, exactProviderVersionString, allowedTags) {
|
|
380
|
+
return `${BACKEND_BASE_URL}/api/providers/${providerId}/configs?versionNumber=${exactProviderVersionString || ""}&allowedTags=${(allowedTags == null ? void 0 : allowedTags.join(",")) || ""}`;
|
|
358
381
|
},
|
|
359
382
|
// URL for sharing Reclaim templates
|
|
360
383
|
RECLAIM_SHARE_URL: "https://share.reclaimprotocol.org/verifier/?template=",
|
|
361
384
|
// Chrome extension URL for Reclaim Protocol
|
|
362
|
-
CHROME_EXTENSION_URL: "https://chromewebstore.google.com/detail/reclaim-extension/oafieibbbcepkmenknelhmgaoahamdeh"
|
|
363
|
-
// QR Code API base URL
|
|
364
|
-
QR_CODE_API_URL: "https://api.qrserver.com/v1/create-qr-code/"
|
|
385
|
+
CHROME_EXTENSION_URL: "https://chromewebstore.google.com/detail/reclaim-extension/oafieibbbcepkmenknelhmgaoahamdeh"
|
|
365
386
|
};
|
|
366
387
|
|
|
367
388
|
// src/utils/validationUtils.ts
|
|
@@ -602,92 +623,6 @@ var http = {
|
|
|
602
623
|
}
|
|
603
624
|
};
|
|
604
625
|
|
|
605
|
-
// src/witness.ts
|
|
606
|
-
var import_ethers2 = require("ethers");
|
|
607
|
-
function createSignDataForClaim(data) {
|
|
608
|
-
const identifier = getIdentifierFromClaimInfo(data);
|
|
609
|
-
const lines = [
|
|
610
|
-
identifier,
|
|
611
|
-
data.owner.toLowerCase(),
|
|
612
|
-
data.timestampS.toString(),
|
|
613
|
-
data.epoch.toString()
|
|
614
|
-
];
|
|
615
|
-
return lines.join("\n");
|
|
616
|
-
}
|
|
617
|
-
function getIdentifierFromClaimInfo(info) {
|
|
618
|
-
let canonicalContext = info.context || "";
|
|
619
|
-
if (canonicalContext.length > 0) {
|
|
620
|
-
try {
|
|
621
|
-
const ctx = JSON.parse(canonicalContext);
|
|
622
|
-
canonicalContext = canonicalStringify(ctx);
|
|
623
|
-
} catch (e) {
|
|
624
|
-
throw new Error("unable to parse non-empty context. Must be JSON");
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
const str = `${info.provider}
|
|
628
|
-
${info.parameters}
|
|
629
|
-
${canonicalContext}`;
|
|
630
|
-
return import_ethers2.ethers.keccak256(strToUint8Array(str)).toLowerCase();
|
|
631
|
-
}
|
|
632
|
-
function hashProofClaimParams(params) {
|
|
633
|
-
const serializedParams = getProviderParamsAsCanonicalizedString(params);
|
|
634
|
-
return import_ethers2.ethers.keccak256(
|
|
635
|
-
strToUint8Array(serializedParams)
|
|
636
|
-
).toLowerCase();
|
|
637
|
-
}
|
|
638
|
-
function strToUint8Array(str) {
|
|
639
|
-
return new TextEncoder().encode(str);
|
|
640
|
-
}
|
|
641
|
-
function getProviderParamsAsCanonicalizedString(params) {
|
|
642
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
643
|
-
const filteredParams = {
|
|
644
|
-
url: (_a = params == null ? void 0 : params.url) != null ? _a : "",
|
|
645
|
-
// METHOD needs to be explicitly specified and absence or unknown method should cause error, but we're choosing to ignore it in this case
|
|
646
|
-
method: (_b = params == null ? void 0 : params.method) != null ? _b : "GET",
|
|
647
|
-
body: (_c = params == null ? void 0 : params.body) != null ? _c : "",
|
|
648
|
-
responseMatches: (_e = (_d = params == null ? void 0 : params.responseMatches) == null ? void 0 : _d.map((it) => {
|
|
649
|
-
var _a2, _b2;
|
|
650
|
-
return {
|
|
651
|
-
value: (_a2 = it.value) != null ? _a2 : "",
|
|
652
|
-
// This needs to be explicitly specified and absence should cause error, but we're choosing to ignore it in this case
|
|
653
|
-
type: (_b2 = it.type) != null ? _b2 : "contains",
|
|
654
|
-
invert: it.invert || void 0,
|
|
655
|
-
isOptional: it.isOptional || void 0
|
|
656
|
-
};
|
|
657
|
-
})) != null ? _e : [],
|
|
658
|
-
responseRedactions: (_g = (_f = params == null ? void 0 : params.responseRedactions) == null ? void 0 : _f.map((it) => {
|
|
659
|
-
var _a2, _b2, _c2;
|
|
660
|
-
return {
|
|
661
|
-
xPath: (_a2 = it.xPath) != null ? _a2 : "",
|
|
662
|
-
jsonPath: (_b2 = it.jsonPath) != null ? _b2 : "",
|
|
663
|
-
regex: (_c2 = it.regex) != null ? _c2 : "",
|
|
664
|
-
hash: it.hash || void 0
|
|
665
|
-
};
|
|
666
|
-
})) != null ? _g : []
|
|
667
|
-
};
|
|
668
|
-
const serializedParams = canonicalStringify(filteredParams);
|
|
669
|
-
return serializedParams;
|
|
670
|
-
}
|
|
671
|
-
|
|
672
|
-
// src/utils/providerUtils.ts
|
|
673
|
-
function getProviderHashRequirementsFromSpec(spec) {
|
|
674
|
-
var _a;
|
|
675
|
-
return {
|
|
676
|
-
hashes: ((_a = spec == null ? void 0 : spec.requests) == null ? void 0 : _a.map(hashRequestSpec)) || []
|
|
677
|
-
};
|
|
678
|
-
}
|
|
679
|
-
function hashRequestSpec(request) {
|
|
680
|
-
const hash = hashProofClaimParams(__spreadProps(__spreadValues({}, request), {
|
|
681
|
-
// Body is strictly empty unless body sniff is explicitly enabled
|
|
682
|
-
body: request.bodySniff.enabled ? request.bodySniff.template : ""
|
|
683
|
-
}));
|
|
684
|
-
return {
|
|
685
|
-
value: hash,
|
|
686
|
-
required: request.required,
|
|
687
|
-
multiple: request.multiple
|
|
688
|
-
};
|
|
689
|
-
}
|
|
690
|
-
|
|
691
626
|
// src/utils/sessionUtils.ts
|
|
692
627
|
var logger4 = logger_default.logger;
|
|
693
628
|
function initSession(providerId, appId, timestamp, signature, versionNumber) {
|
|
@@ -764,17 +699,24 @@ function fetchStatusUrl(sessionId) {
|
|
|
764
699
|
}
|
|
765
700
|
});
|
|
766
701
|
}
|
|
767
|
-
function
|
|
702
|
+
function fetchProviderConfigs(providerId, exactProviderVersionString, allowedTags) {
|
|
768
703
|
return __async(this, null, function* () {
|
|
769
704
|
validateFunctionParams(
|
|
770
705
|
[
|
|
771
|
-
{ input: providerId, paramName: "providerId", isString: true }
|
|
772
|
-
{ input: exactProviderVersionString, paramName: "exactProviderVersionString", isString: true }
|
|
706
|
+
{ input: providerId, paramName: "providerId", isString: true }
|
|
773
707
|
],
|
|
774
|
-
"
|
|
708
|
+
"fetchProviderConfigs"
|
|
775
709
|
);
|
|
710
|
+
if (exactProviderVersionString != null && exactProviderVersionString != void 0) {
|
|
711
|
+
validateFunctionParams(
|
|
712
|
+
[
|
|
713
|
+
{ input: exactProviderVersionString, paramName: "exactProviderVersionString", isString: true }
|
|
714
|
+
],
|
|
715
|
+
"fetchProviderConfigs"
|
|
716
|
+
);
|
|
717
|
+
}
|
|
776
718
|
try {
|
|
777
|
-
const response = yield http.client(constants.
|
|
719
|
+
const response = yield http.client(constants.DEFAULT_PROVIDER_CONFIGS_URL(providerId, exactProviderVersionString, allowedTags), {
|
|
778
720
|
method: "GET",
|
|
779
721
|
headers: { "Content-Type": "application/json" }
|
|
780
722
|
});
|
|
@@ -792,19 +734,116 @@ function fetchProviderConfig(providerId, exactProviderVersionString) {
|
|
|
792
734
|
}
|
|
793
735
|
});
|
|
794
736
|
}
|
|
795
|
-
function fetchProviderHashRequirementsBy(providerId, exactProviderVersion) {
|
|
796
|
-
return __async(this, null, function* () {
|
|
797
|
-
var _a, _b;
|
|
798
|
-
const providerResponse = yield fetchProviderConfig(providerId, exactProviderVersion);
|
|
799
|
-
const providerConfig = providerResponse.providers;
|
|
800
|
-
return getProviderHashRequirementsFromSpec({
|
|
801
|
-
requests: [...(_a = providerConfig == null ? void 0 : providerConfig.requestData) != null ? _a : [], ...(_b = providerConfig == null ? void 0 : providerConfig.allowedInjectedRequestData) != null ? _b : []]
|
|
802
|
-
});
|
|
803
|
-
});
|
|
804
|
-
}
|
|
805
737
|
|
|
806
738
|
// src/utils/proofUtils.ts
|
|
807
739
|
var import_ethers3 = require("ethers");
|
|
740
|
+
|
|
741
|
+
// src/witness.ts
|
|
742
|
+
var import_ethers2 = require("ethers");
|
|
743
|
+
function createSignDataForClaim(data) {
|
|
744
|
+
const identifier = getIdentifierFromClaimInfo(data);
|
|
745
|
+
const lines = [
|
|
746
|
+
identifier,
|
|
747
|
+
data.owner.toLowerCase(),
|
|
748
|
+
data.timestampS.toString(),
|
|
749
|
+
data.epoch.toString()
|
|
750
|
+
];
|
|
751
|
+
return lines.join("\n");
|
|
752
|
+
}
|
|
753
|
+
function getIdentifierFromClaimInfo(info) {
|
|
754
|
+
let canonicalContext = info.context || "";
|
|
755
|
+
if (canonicalContext.length > 0) {
|
|
756
|
+
try {
|
|
757
|
+
const ctx = JSON.parse(canonicalContext);
|
|
758
|
+
canonicalContext = canonicalStringify(ctx);
|
|
759
|
+
} catch (e) {
|
|
760
|
+
throw new Error("unable to parse non-empty context. Must be JSON");
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
const str = `${info.provider}
|
|
764
|
+
${info.parameters}
|
|
765
|
+
${canonicalContext}`;
|
|
766
|
+
return import_ethers2.ethers.keccak256(strToUint8Array(str)).toLowerCase();
|
|
767
|
+
}
|
|
768
|
+
function hashProofClaimParams(params) {
|
|
769
|
+
const serializedParams = getProviderParamsAsCanonicalizedString(params);
|
|
770
|
+
if (Array.isArray(serializedParams)) {
|
|
771
|
+
return serializedParams.map(
|
|
772
|
+
(serialized) => import_ethers2.ethers.keccak256(strToUint8Array(serialized)).toLowerCase()
|
|
773
|
+
);
|
|
774
|
+
}
|
|
775
|
+
return import_ethers2.ethers.keccak256(
|
|
776
|
+
strToUint8Array(serializedParams)
|
|
777
|
+
).toLowerCase();
|
|
778
|
+
}
|
|
779
|
+
function strToUint8Array(str) {
|
|
780
|
+
return new TextEncoder().encode(str);
|
|
781
|
+
}
|
|
782
|
+
function getProviderParamsAsCanonicalizedString(params) {
|
|
783
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
|
|
784
|
+
const pairsCount = (_b = (_a = params == null ? void 0 : params.responseMatches) == null ? void 0 : _a.length) != null ? _b : 0;
|
|
785
|
+
const validCanonicalizedStrings = [];
|
|
786
|
+
const totalCombinations = 1 << pairsCount;
|
|
787
|
+
for (let i = 0; i < totalCombinations; i++) {
|
|
788
|
+
let isValidCombination = true;
|
|
789
|
+
let includedCount = 0;
|
|
790
|
+
const currentMatches = [];
|
|
791
|
+
const currentRedactions = [];
|
|
792
|
+
for (let j = 0; j < pairsCount; j++) {
|
|
793
|
+
const isIncluded = (i & 1 << j) !== 0;
|
|
794
|
+
const match = (_c = params == null ? void 0 : params.responseMatches) == null ? void 0 : _c[j];
|
|
795
|
+
const redaction = (_d = params == null ? void 0 : params.responseRedactions) == null ? void 0 : _d[j];
|
|
796
|
+
if (isIncluded) {
|
|
797
|
+
if (match) {
|
|
798
|
+
currentMatches.push({
|
|
799
|
+
value: (_e = match.value) != null ? _e : "",
|
|
800
|
+
// This needs to be explicitly specified and absence should cause error, but we're choosing to ignore it in this case
|
|
801
|
+
type: (_f = match.type) != null ? _f : "contains",
|
|
802
|
+
invert: match.invert || void 0
|
|
803
|
+
});
|
|
804
|
+
}
|
|
805
|
+
if (redaction) {
|
|
806
|
+
currentRedactions.push({
|
|
807
|
+
xPath: (_g = redaction.xPath) != null ? _g : "",
|
|
808
|
+
jsonPath: (_h = redaction.jsonPath) != null ? _h : "",
|
|
809
|
+
regex: (_i = redaction.regex) != null ? _i : "",
|
|
810
|
+
hash: redaction.hash || void 0
|
|
811
|
+
});
|
|
812
|
+
}
|
|
813
|
+
includedCount++;
|
|
814
|
+
} else {
|
|
815
|
+
if (match && !match.isOptional) {
|
|
816
|
+
isValidCombination = false;
|
|
817
|
+
break;
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
if (isValidCombination && includedCount > 0) {
|
|
822
|
+
const filteredParams = {
|
|
823
|
+
url: (_j = params == null ? void 0 : params.url) != null ? _j : "",
|
|
824
|
+
// METHOD needs to be explicitly specified and absence or unknown method should cause error, but we're choosing to ignore it in this case
|
|
825
|
+
method: (_k = params == null ? void 0 : params.method) != null ? _k : "GET",
|
|
826
|
+
body: (_l = params == null ? void 0 : params.body) != null ? _l : "",
|
|
827
|
+
responseMatches: currentMatches,
|
|
828
|
+
responseRedactions: currentRedactions
|
|
829
|
+
};
|
|
830
|
+
validCanonicalizedStrings.push(canonicalStringify(filteredParams));
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
if (validCanonicalizedStrings.length === 0) {
|
|
834
|
+
const filteredParams = {
|
|
835
|
+
url: (_m = params == null ? void 0 : params.url) != null ? _m : "",
|
|
836
|
+
method: (_n = params == null ? void 0 : params.method) != null ? _n : "GET",
|
|
837
|
+
body: (_o = params == null ? void 0 : params.body) != null ? _o : "",
|
|
838
|
+
responseMatches: [],
|
|
839
|
+
responseRedactions: []
|
|
840
|
+
};
|
|
841
|
+
return canonicalStringify(filteredParams);
|
|
842
|
+
}
|
|
843
|
+
return validCanonicalizedStrings.length === 1 ? validCanonicalizedStrings[0] : validCanonicalizedStrings;
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
// src/utils/proofUtils.ts
|
|
808
847
|
var logger5 = logger_default.logger;
|
|
809
848
|
function getShortenedUrl(url) {
|
|
810
849
|
return __async(this, null, function* () {
|
|
@@ -818,7 +857,7 @@ function getShortenedUrl(url) {
|
|
|
818
857
|
});
|
|
819
858
|
const res = yield response.json();
|
|
820
859
|
if (!response.ok) {
|
|
821
|
-
logger5.info(`Failed to shorten URL:
|
|
860
|
+
logger5.info(`Failed to shorten URL: status=${response.status}`);
|
|
822
861
|
return url;
|
|
823
862
|
}
|
|
824
863
|
const shortenedVerificationUrl = res.result.shortUrl;
|
|
@@ -881,6 +920,7 @@ function assertVerifiedProof(proof, attestors) {
|
|
|
881
920
|
}
|
|
882
921
|
|
|
883
922
|
// src/utils/modalUtils.ts
|
|
923
|
+
var import_qrcode = __toESM(require("qrcode"));
|
|
884
924
|
var logger6 = logger_default.logger;
|
|
885
925
|
var QRCodeModal = class {
|
|
886
926
|
constructor(options = {}) {
|
|
@@ -1091,17 +1131,22 @@ var QRCodeModal = class {
|
|
|
1091
1131
|
generateQRCode(text, containerId) {
|
|
1092
1132
|
return __async(this, null, function* () {
|
|
1093
1133
|
try {
|
|
1094
|
-
const
|
|
1134
|
+
const dataUrl = yield import_qrcode.default.toDataURL(text, {
|
|
1135
|
+
width: 200,
|
|
1136
|
+
margin: 1,
|
|
1137
|
+
color: {
|
|
1138
|
+
dark: "#000000",
|
|
1139
|
+
light: "#ffffff"
|
|
1140
|
+
}
|
|
1141
|
+
});
|
|
1095
1142
|
const container = document.getElementById(containerId);
|
|
1096
1143
|
const styles = this.getThemeStyles();
|
|
1097
1144
|
if (container) {
|
|
1098
1145
|
container.innerHTML = `
|
|
1099
|
-
<img src="${
|
|
1100
|
-
alt="QR Code for Reclaim verification"
|
|
1101
|
-
style="width: 200px; height: 200px; border-radius: 4px;"
|
|
1102
|
-
onerror="this.style.display='none'; this.nextElementSibling.style.display='block';">
|
|
1146
|
+
<img src="${dataUrl}"
|
|
1147
|
+
alt="QR Code for Reclaim verification"
|
|
1148
|
+
style="width: 200px; height: 200px; border-radius: 4px;">
|
|
1103
1149
|
<div style="display: none; padding: 20px; color: ${styles.textColor}; font-size: 14px;">
|
|
1104
|
-
QR code could not be loaded.<br>
|
|
1105
1150
|
<a href="${text}" target="_blank" style="color: ${styles.linkColor}; text-decoration: underline;">
|
|
1106
1151
|
Click here to open verification link
|
|
1107
1152
|
</a>
|
|
@@ -1329,10 +1374,123 @@ function clearDeviceCache() {
|
|
|
1329
1374
|
cachedMobileType = null;
|
|
1330
1375
|
}
|
|
1331
1376
|
|
|
1332
|
-
// src/utils/
|
|
1377
|
+
// src/utils/providerUtils.ts
|
|
1333
1378
|
var logger7 = logger_default.logger;
|
|
1379
|
+
function fetchProviderHashRequirementsBy(providerId, exactProviderVersionString, allowedTags, proofs) {
|
|
1380
|
+
return __async(this, null, function* () {
|
|
1381
|
+
var _a, _b;
|
|
1382
|
+
const providerResponse = yield fetchProviderConfigs(providerId, exactProviderVersionString, allowedTags);
|
|
1383
|
+
try {
|
|
1384
|
+
const providerConfigs = providerResponse.providers;
|
|
1385
|
+
if (!providerConfigs || !providerConfigs.length) {
|
|
1386
|
+
throw new ProviderConfigFetchError(`No provider configs found for providerId: ${providerId}, exactProviderVersionString: ${exactProviderVersionString}`);
|
|
1387
|
+
}
|
|
1388
|
+
const hashRequirements = [];
|
|
1389
|
+
for (const providerConfig of providerConfigs) {
|
|
1390
|
+
hashRequirements.push(getProviderHashRequirementsFromSpec({
|
|
1391
|
+
requests: [...(_a = providerConfig == null ? void 0 : providerConfig.requestData) != null ? _a : [], ...generateSpecsFromRequestSpecTemplate((_b = providerConfig == null ? void 0 : providerConfig.allowedInjectedRequestData) != null ? _b : [], takeTemplateParametersFromProofs(proofs))]
|
|
1392
|
+
}));
|
|
1393
|
+
}
|
|
1394
|
+
return hashRequirements;
|
|
1395
|
+
} catch (e) {
|
|
1396
|
+
const errorMessage = `Failed to fetch provider hash requirements for providerId: ${providerId}, exactProviderVersionString: ${exactProviderVersionString}`;
|
|
1397
|
+
logger7.info(errorMessage, e);
|
|
1398
|
+
throw new ProviderConfigFetchError(`Error fetching provider hash requirements for providerId: ${providerId}, exactProviderVersionString: ${exactProviderVersionString}`);
|
|
1399
|
+
}
|
|
1400
|
+
});
|
|
1401
|
+
}
|
|
1402
|
+
function generateSpecsFromRequestSpecTemplate(requestSpecTemplates, templateParameters) {
|
|
1403
|
+
var _a;
|
|
1404
|
+
if (!requestSpecTemplates) return [];
|
|
1405
|
+
const generatedRequestTemplate = [];
|
|
1406
|
+
for (const template of requestSpecTemplates) {
|
|
1407
|
+
const templateVariables = (_a = template.templateParams) != null ? _a : [];
|
|
1408
|
+
if (!templateVariables.length) {
|
|
1409
|
+
generatedRequestTemplate.push(template);
|
|
1410
|
+
continue;
|
|
1411
|
+
}
|
|
1412
|
+
const templateParamsPairMatch = Object.entries(templateParameters).filter(([key, value]) => templateVariables.includes(key) && value.length);
|
|
1413
|
+
const hasAllTemplateVariableMatch = templateParamsPairMatch.length === templateVariables.length;
|
|
1414
|
+
if (!hasAllTemplateVariableMatch) {
|
|
1415
|
+
throw new InvalidRequestSpecError(`Not all template variables are present for template`);
|
|
1416
|
+
}
|
|
1417
|
+
const templateParamsPairMatchLength = templateParamsPairMatch[0][1].length;
|
|
1418
|
+
const allTemplateVariablesHaveSameLength = templateParamsPairMatch.every(([key, value]) => value.length === templateParamsPairMatchLength);
|
|
1419
|
+
if (!allTemplateVariablesHaveSameLength) {
|
|
1420
|
+
throw new InvalidRequestSpecError(`Not all template variables have same length for template`);
|
|
1421
|
+
}
|
|
1422
|
+
const getRequestSpecVariableTemplate = (key) => {
|
|
1423
|
+
return `\${${key}}`;
|
|
1424
|
+
};
|
|
1425
|
+
for (let i = 0; i < templateParamsPairMatchLength; i++) {
|
|
1426
|
+
const currentTemplateParams = {};
|
|
1427
|
+
for (const [key, values] of templateParamsPairMatch) {
|
|
1428
|
+
currentTemplateParams[key] = values[i];
|
|
1429
|
+
}
|
|
1430
|
+
const spec = __spreadProps(__spreadValues({}, template), {
|
|
1431
|
+
responseMatches: template.responseMatches ? template.responseMatches.map((m) => __spreadValues({}, m)) : [],
|
|
1432
|
+
responseRedactions: template.responseRedactions ? template.responseRedactions.map((r) => __spreadValues({}, r)) : []
|
|
1433
|
+
});
|
|
1434
|
+
for (const match of spec.responseMatches) {
|
|
1435
|
+
for (const [key, value] of Object.entries(currentTemplateParams)) {
|
|
1436
|
+
match.value = match.value.split(getRequestSpecVariableTemplate(key)).join(value);
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
for (const redaction of spec.responseRedactions) {
|
|
1440
|
+
for (const [key, value] of Object.entries(currentTemplateParams)) {
|
|
1441
|
+
redaction.jsonPath = redaction.jsonPath.split(getRequestSpecVariableTemplate(key)).join(value);
|
|
1442
|
+
redaction.xPath = redaction.xPath.split(getRequestSpecVariableTemplate(key)).join(value);
|
|
1443
|
+
redaction.regex = redaction.regex.split(getRequestSpecVariableTemplate(key)).join(value);
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1446
|
+
generatedRequestTemplate.push(spec);
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
return generatedRequestTemplate;
|
|
1450
|
+
}
|
|
1451
|
+
function takeTemplateParametersFromProofs(proofs) {
|
|
1452
|
+
return takePairsWhereValueIsArray(proofs == null ? void 0 : proofs.map((it) => JSON.parse(it.claimData.context).extractedParameters).reduce((acc, it) => __spreadValues(__spreadValues({}, acc), it), {}));
|
|
1453
|
+
}
|
|
1454
|
+
function takePairsWhereValueIsArray(o) {
|
|
1455
|
+
if (!o) return {};
|
|
1456
|
+
const pairs = {};
|
|
1457
|
+
for (const [key, value] of Object.entries(o)) {
|
|
1458
|
+
if (Array.isArray(value) && value.length) {
|
|
1459
|
+
pairs[key] = value;
|
|
1460
|
+
} else {
|
|
1461
|
+
try {
|
|
1462
|
+
const parsedValue = JSON.parse(value);
|
|
1463
|
+
if (Array.isArray(parsedValue) && parsedValue.length) {
|
|
1464
|
+
pairs[key] = parsedValue;
|
|
1465
|
+
}
|
|
1466
|
+
} catch (_) {
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
1470
|
+
return pairs;
|
|
1471
|
+
}
|
|
1472
|
+
function getProviderHashRequirementsFromSpec(spec) {
|
|
1473
|
+
var _a;
|
|
1474
|
+
return {
|
|
1475
|
+
hashes: ((_a = spec == null ? void 0 : spec.requests) == null ? void 0 : _a.map(hashRequestSpec)) || []
|
|
1476
|
+
};
|
|
1477
|
+
}
|
|
1478
|
+
function hashRequestSpec(request) {
|
|
1479
|
+
const hash = hashProofClaimParams(__spreadProps(__spreadValues({}, request), {
|
|
1480
|
+
// Body is strictly empty unless body sniff is explicitly enabled
|
|
1481
|
+
body: request.bodySniff.enabled ? request.bodySniff.template : ""
|
|
1482
|
+
}));
|
|
1483
|
+
return {
|
|
1484
|
+
value: hash,
|
|
1485
|
+
required: request.required,
|
|
1486
|
+
multiple: request.multiple
|
|
1487
|
+
};
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1490
|
+
// src/utils/proofValidationUtils.ts
|
|
1491
|
+
var logger8 = logger_default.logger;
|
|
1334
1492
|
var HASH_REQUIRED_DEFAULT = true;
|
|
1335
|
-
var HASH_MATCH_MULTIPLE_DEFAULT =
|
|
1493
|
+
var HASH_MATCH_MULTIPLE_DEFAULT = true;
|
|
1336
1494
|
function assertValidProofsByHash(proofs, config) {
|
|
1337
1495
|
var _a, _b;
|
|
1338
1496
|
if (!config.hashes) {
|
|
@@ -1342,31 +1500,36 @@ function assertValidProofsByHash(proofs, config) {
|
|
|
1342
1500
|
for (let i = 0; i < proofs.length; i++) {
|
|
1343
1501
|
const proof = proofs[i];
|
|
1344
1502
|
const claimParams = getHttpProviderClaimParamsFromProof(proof);
|
|
1345
|
-
const
|
|
1346
|
-
|
|
1503
|
+
const computedHashesOfProof = hashProofClaimParams(claimParams);
|
|
1504
|
+
const proofHashes = Array.isArray(computedHashesOfProof) ? computedHashesOfProof.map((h) => h.toLowerCase().trim()) : [computedHashesOfProof.toLowerCase().trim()];
|
|
1505
|
+
unvalidatedProofHashByIndex.set(i, proofHashes);
|
|
1347
1506
|
}
|
|
1348
1507
|
for (const hashRequirement of config.hashes) {
|
|
1349
1508
|
let found = false;
|
|
1350
|
-
const
|
|
1509
|
+
const expectedHashes = Array.isArray(hashRequirement.value) ? hashRequirement.value.map((h) => h.toLowerCase().trim()) : [hashRequirement.value.toLowerCase().trim()];
|
|
1351
1510
|
const isRequired = (_a = hashRequirement.required) != null ? _a : HASH_REQUIRED_DEFAULT;
|
|
1352
1511
|
const canMatchMultiple = (_b = hashRequirement.multiple) != null ? _b : HASH_MATCH_MULTIPLE_DEFAULT;
|
|
1353
|
-
for (const [i,
|
|
1354
|
-
|
|
1512
|
+
for (const [i, proofHashes] of unvalidatedProofHashByIndex.entries()) {
|
|
1513
|
+
const intersection = expectedHashes.filter((eh) => proofHashes.includes(eh));
|
|
1514
|
+
if (intersection.length > 0) {
|
|
1355
1515
|
unvalidatedProofHashByIndex.delete(i);
|
|
1356
1516
|
if (!found) {
|
|
1357
1517
|
found = true;
|
|
1358
1518
|
} else if (!canMatchMultiple) {
|
|
1359
|
-
|
|
1519
|
+
const expectedHashStr = expectedHashes.length === 1 ? expectedHashes[0] : `[${expectedHashes.join(", ")}]`;
|
|
1520
|
+
throw new ProofNotValidatedError(`Proof by hash '${expectedHashStr}' is not allowed to appear more than once`);
|
|
1360
1521
|
}
|
|
1361
1522
|
}
|
|
1362
1523
|
}
|
|
1363
1524
|
if (!found && isRequired) {
|
|
1364
|
-
|
|
1525
|
+
const expectedHashStr = expectedHashes.length === 1 ? expectedHashes[0] : `[${expectedHashes.join(", ")}]`;
|
|
1526
|
+
throw new ProofNotValidatedError(`Proof by required hash '${expectedHashStr}' was not found`);
|
|
1365
1527
|
}
|
|
1366
1528
|
}
|
|
1367
1529
|
if (unvalidatedProofHashByIndex.size > 0) {
|
|
1368
1530
|
const contactSupport = "Please contact Reclaim Protocol Support team or mail us at support@reclaimprotocol.org.";
|
|
1369
|
-
|
|
1531
|
+
const unvalidatedHashesStrArr = [...unvalidatedProofHashByIndex.values()].map((h) => h.length === 1 ? h[0] : `[${h.join(", ")}]`);
|
|
1532
|
+
throw new UnknownProofsNotValidatedError(`Extra ${unvalidatedProofHashByIndex.size} proof(s) by hashes ${unvalidatedHashesStrArr.join(", ")} was found but could not be validated and indicates a security risk. ${contactSupport}`);
|
|
1370
1533
|
}
|
|
1371
1534
|
}
|
|
1372
1535
|
var allowedHttpMethods = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE"]);
|
|
@@ -1375,7 +1538,7 @@ function isHttpProviderClaimParams(claimParams) {
|
|
|
1375
1538
|
return false;
|
|
1376
1539
|
}
|
|
1377
1540
|
const params = claimParams;
|
|
1378
|
-
return typeof params.url === "string" && typeof params.method === "string" && allowedHttpMethods.has(params.method) && typeof params.body === "string" && Array.isArray(params.responseMatches) && params.responseMatches.length > 0 && Array.isArray(params.responseRedactions);
|
|
1541
|
+
return typeof params.url === "string" && typeof params.method === "string" && allowedHttpMethods.has(params.method) && (params.body == null || typeof params.body === "string") && Array.isArray(params.responseMatches) && params.responseMatches.length > 0 && Array.isArray(params.responseRedactions);
|
|
1379
1542
|
}
|
|
1380
1543
|
function getHttpProviderClaimParamsFromProof(proof) {
|
|
1381
1544
|
try {
|
|
@@ -1388,31 +1551,781 @@ function getHttpProviderClaimParamsFromProof(proof) {
|
|
|
1388
1551
|
throw new ProofNotValidatedError("Proof has no HTTP provider params to hash");
|
|
1389
1552
|
}
|
|
1390
1553
|
function assertValidateProof(proofs, config) {
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1554
|
+
return __async(this, null, function* () {
|
|
1555
|
+
if ("dangerouslyDisableContentValidation" in config && config.dangerouslyDisableContentValidation) {
|
|
1556
|
+
logger8.warn("Validation skipped because it was disabled during proof verification");
|
|
1557
|
+
return;
|
|
1558
|
+
}
|
|
1559
|
+
if ("providerId" in config) {
|
|
1560
|
+
if (!config.providerId || typeof config.providerId !== "string") {
|
|
1561
|
+
throw new ProofNotValidatedError("Provider id is required for proof validation");
|
|
1562
|
+
}
|
|
1563
|
+
if (config.providerVersion && typeof config.providerVersion !== "string") {
|
|
1564
|
+
throw new ProofNotValidatedError("Provider version must be a string");
|
|
1565
|
+
}
|
|
1566
|
+
const hashRequirementsFromProvider = yield fetchProviderHashRequirementsBy(config.providerId, config.providerVersion, config.allowedTags, proofs);
|
|
1567
|
+
if (!hashRequirementsFromProvider.length) {
|
|
1568
|
+
throw new ProofNotValidatedError("Could not find any provider information for the given provider id and version");
|
|
1569
|
+
}
|
|
1570
|
+
if (hashRequirementsFromProvider.length != 1) {
|
|
1571
|
+
let lastError = null;
|
|
1572
|
+
for (const hashRequirement of hashRequirementsFromProvider) {
|
|
1573
|
+
try {
|
|
1574
|
+
return yield assertValidateProof(proofs, hashRequirement);
|
|
1575
|
+
} catch (e) {
|
|
1576
|
+
lastError = e;
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1579
|
+
throw new ProofNotValidatedError("Could not validate proof", lastError);
|
|
1580
|
+
} else {
|
|
1581
|
+
return assertValidateProof(proofs, hashRequirementsFromProvider[0]);
|
|
1582
|
+
}
|
|
1583
|
+
}
|
|
1584
|
+
const effectiveHashRequirement = ("hashes" in config && Array.isArray(config == null ? void 0 : config.hashes) ? config.hashes : []).map((it) => {
|
|
1585
|
+
if (typeof it == "string") {
|
|
1586
|
+
return {
|
|
1587
|
+
value: it
|
|
1588
|
+
};
|
|
1589
|
+
} else {
|
|
1590
|
+
return it;
|
|
1591
|
+
}
|
|
1592
|
+
});
|
|
1593
|
+
return assertValidProofsByHash(proofs, {
|
|
1594
|
+
hashes: effectiveHashRequirement
|
|
1595
|
+
});
|
|
1596
|
+
});
|
|
1597
|
+
}
|
|
1598
|
+
|
|
1599
|
+
// src/utils/verifyTee.ts
|
|
1600
|
+
var import_node_forge = __toESM(require("node-forge"));
|
|
1601
|
+
var import_ethers4 = require("ethers");
|
|
1602
|
+
|
|
1603
|
+
// src/utils/amdCerts.ts
|
|
1604
|
+
var AMD_CERTS = {
|
|
1605
|
+
"Milan": `-----BEGIN CERTIFICATE-----
|
|
1606
|
+
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
|
|
1641
|
+
0YPk
|
|
1642
|
+
-----END CERTIFICATE-----
|
|
1643
|
+
-----BEGIN CERTIFICATE-----
|
|
1644
|
+
MIIGYzCCBBKgAwIBAgIDAQAAMEYGCSqGSIb3DQEBCjA5oA8wDQYJYIZIAWUDBAIC
|
|
1645
|
+
BQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAICBQCiAwIBMKMDAgEBMHsxFDAS
|
|
1646
|
+
BgNVBAsMC0VuZ2luZWVyaW5nMQswCQYDVQQGEwJVUzEUMBIGA1UEBwwLU2FudGEg
|
|
1647
|
+
Q2xhcmExCzAJBgNVBAgMAkNBMR8wHQYDVQQKDBZBZHZhbmNlZCBNaWNybyBEZXZp
|
|
1648
|
+
Y2VzMRIwEAYDVQQDDAlBUkstTWlsYW4wHhcNMjAxMDIyMTcyMzA1WhcNNDUxMDIy
|
|
1649
|
+
MTcyMzA1WjB7MRQwEgYDVQQLDAtFbmdpbmVlcmluZzELMAkGA1UEBhMCVVMxFDAS
|
|
1650
|
+
BgNVBAcMC1NhbnRhIENsYXJhMQswCQYDVQQIDAJDQTEfMB0GA1UECgwWQWR2YW5j
|
|
1651
|
+
ZWQgTWljcm8gRGV2aWNlczESMBAGA1UEAwwJQVJLLU1pbGFuMIICIjANBgkqhkiG
|
|
1652
|
+
9w0BAQEFAAOCAg8AMIICCgKCAgEA0Ld52RJOdeiJlqK2JdsVmD7FktuotWwX1fNg
|
|
1653
|
+
W41XY9Xz1HEhSUmhLz9Cu9DHRlvgJSNxbeYYsnJfvyjx1MfU0V5tkKiU1EesNFta
|
|
1654
|
+
1kTA0szNisdYc9isqk7mXT5+KfGRbfc4V/9zRIcE8jlHN61S1ju8X93+6dxDUrG2
|
|
1655
|
+
SzxqJ4BhqyYmUDruPXJSX4vUc01P7j98MpqOS95rORdGHeI52Naz5m2B+O+vjsC0
|
|
1656
|
+
60d37jY9LFeuOP4Meri8qgfi2S5kKqg/aF6aPtuAZQVR7u3KFYXP59XmJgtcog05
|
|
1657
|
+
gmI0T/OitLhuzVvpZcLph0odh/1IPXqx3+MnjD97A7fXpqGd/y8KxX7jksTEzAOg
|
|
1658
|
+
bKAeam3lm+3yKIcTYMlsRMXPcjNbIvmsBykD//xSniusuHBkgnlENEWx1UcbQQrs
|
|
1659
|
+
+gVDkuVPhsnzIRNgYvM48Y+7LGiJYnrmE8xcrexekBxrva2V9TJQqnN3Q53kt5vi
|
|
1660
|
+
Qi3+gCfmkwC0F0tirIZbLkXPrPwzZ0M9eNxhIySb2npJfgnqz55I0u33wh4r0ZNQ
|
|
1661
|
+
eTGfw03MBUtyuzGesGkcw+loqMaq1qR4tjGbPYxCvpCq7+OgpCCoMNit2uLo9M18
|
|
1662
|
+
fHz10lOMT8nWAUvRZFzteXCm+7PHdYPlmQwUw3LvenJ/ILXoQPHfbkH0CyPfhl1j
|
|
1663
|
+
WhJFZasCAwEAAaN+MHwwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSFrBrRQ/fI
|
|
1664
|
+
rFXUxR1BSKvVeErUUzAPBgNVHRMBAf8EBTADAQH/MDoGA1UdHwQzMDEwL6AtoCuG
|
|
1665
|
+
KWh0dHBzOi8va2RzaW50Zi5hbWQuY29tL3ZjZWsvdjEvTWlsYW4vY3JsMEYGCSqG
|
|
1666
|
+
SIb3DQEBCjA5oA8wDQYJYIZIAWUDBAICBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZI
|
|
1667
|
+
AWUDBAICBQCiAwIBMKMDAgEBA4ICAQC6m0kDp6zv4Ojfgy+zleehsx6ol0ocgVel
|
|
1668
|
+
ETobpx+EuCsqVFRPK1jZ1sp/lyd9+0fQ0r66n7kagRk4Ca39g66WGTJMeJdqYriw
|
|
1669
|
+
STjjDCKVPSesWXYPVAyDhmP5n2v+BYipZWhpvqpaiO+EGK5IBP+578QeW/sSokrK
|
|
1670
|
+
dHaLAxG2LhZxj9aF73fqC7OAJZ5aPonw4RE299FVarh1Tx2eT3wSgkDgutCTB1Yq
|
|
1671
|
+
zT5DuwvAe+co2CIVIzMDamYuSFjPN0BCgojl7V+bTou7dMsqIu/TW/rPCX9/EUcp
|
|
1672
|
+
KGKqPQ3P+N9r1hjEFY1plBg93t53OOo49GNI+V1zvXPLI6xIFVsh+mto2RtgEX/e
|
|
1673
|
+
pmMKTNN6psW88qg7c1hTWtN6MbRuQ0vm+O+/2tKBF2h8THb94OvvHHoFDpbCELlq
|
|
1674
|
+
HnIYhxy0YKXGyaW1NjfULxrrmxVW4wcn5E8GddmvNa6yYm8scJagEi13mhGu4Jqh
|
|
1675
|
+
3QU3sf8iUSUr09xQDwHtOQUVIqx4maBZPBtSMf+qUDtjXSSq8lfWcd8bLr9mdsUn
|
|
1676
|
+
JZJ0+tuPMKmBnSH860llKk+VpVQsgqbzDIvOLvD6W1Umq25boxCYJ+TuBoa4s+HH
|
|
1677
|
+
CViAvgT9kf/rBq1d+ivj6skkHxuzcxbk1xv6ZGxrteJxVH7KlX7YRdZ6eARKwLe4
|
|
1678
|
+
AFZEAwoKCQ==
|
|
1679
|
+
-----END CERTIFICATE-----`,
|
|
1680
|
+
"Genoa": `-----BEGIN CERTIFICATE-----
|
|
1681
|
+
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
|
|
1716
|
+
2cko
|
|
1717
|
+
-----END CERTIFICATE-----
|
|
1718
|
+
-----BEGIN CERTIFICATE-----
|
|
1719
|
+
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
|
|
1753
|
+
/wMz1R1BHg==
|
|
1754
|
+
-----END CERTIFICATE-----`
|
|
1755
|
+
};
|
|
1756
|
+
|
|
1757
|
+
// src/utils/verifyTee.ts
|
|
1758
|
+
var crlCache = {};
|
|
1759
|
+
var logger9 = logger_default.logger;
|
|
1760
|
+
function toUint8Array(input) {
|
|
1761
|
+
if (typeof Buffer !== "undefined" && typeof Buffer.isBuffer === "function" && Buffer.isBuffer(input)) {
|
|
1762
|
+
return new Uint8Array(input);
|
|
1394
1763
|
}
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1764
|
+
if (input instanceof Uint8Array) {
|
|
1765
|
+
return new Uint8Array(input);
|
|
1766
|
+
}
|
|
1767
|
+
if (typeof ArrayBuffer !== "undefined" && input instanceof ArrayBuffer) {
|
|
1768
|
+
return new Uint8Array(input);
|
|
1769
|
+
}
|
|
1770
|
+
throw new Error("Unsupported binary data type");
|
|
1771
|
+
}
|
|
1772
|
+
function uint8ArrayToBinaryString(bytes) {
|
|
1773
|
+
let result = "";
|
|
1774
|
+
const chunkSize = 32768;
|
|
1775
|
+
for (let i = 0; i < bytes.length; i += chunkSize) {
|
|
1776
|
+
const chunk = bytes.subarray(i, i + chunkSize);
|
|
1777
|
+
result += String.fromCharCode(...chunk);
|
|
1778
|
+
}
|
|
1779
|
+
return result;
|
|
1780
|
+
}
|
|
1781
|
+
function binaryStringToUint8Array(binary) {
|
|
1782
|
+
const result = new Uint8Array(binary.length);
|
|
1783
|
+
for (let i = 0; i < binary.length; i++) {
|
|
1784
|
+
result[i] = binary.charCodeAt(i);
|
|
1785
|
+
}
|
|
1786
|
+
return result;
|
|
1787
|
+
}
|
|
1788
|
+
function base64ToUint8Array(base64) {
|
|
1789
|
+
if (typeof atob === "function") {
|
|
1790
|
+
const binary = atob(base64);
|
|
1791
|
+
return binaryStringToUint8Array(binary);
|
|
1792
|
+
}
|
|
1793
|
+
if (typeof Buffer !== "undefined") {
|
|
1794
|
+
return new Uint8Array(Buffer.from(base64, "base64"));
|
|
1795
|
+
}
|
|
1796
|
+
throw new Error("Base64 decoding is not supported in this environment");
|
|
1797
|
+
}
|
|
1798
|
+
function arrayBufferToHex(buffer) {
|
|
1799
|
+
const view = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
|
|
1800
|
+
let hex = "";
|
|
1801
|
+
for (let i = 0; i < view.length; i++) {
|
|
1802
|
+
hex += view[i].toString(16).padStart(2, "0");
|
|
1803
|
+
}
|
|
1804
|
+
return hex;
|
|
1805
|
+
}
|
|
1806
|
+
function concatUint8Arrays(parts) {
|
|
1807
|
+
const totalLength = parts.reduce((sum, arr) => sum + arr.length, 0);
|
|
1808
|
+
const result = new Uint8Array(totalLength);
|
|
1809
|
+
let offset = 0;
|
|
1810
|
+
for (const arr of parts) {
|
|
1811
|
+
result.set(arr, offset);
|
|
1812
|
+
offset += arr.length;
|
|
1813
|
+
}
|
|
1814
|
+
return result;
|
|
1815
|
+
}
|
|
1816
|
+
function reverseBytes(bytes) {
|
|
1817
|
+
const copy = Uint8Array.from(bytes);
|
|
1818
|
+
copy.reverse();
|
|
1819
|
+
return copy;
|
|
1820
|
+
}
|
|
1821
|
+
function normalizeSerial(s) {
|
|
1822
|
+
let cleaned = s.toLowerCase().replace(/[^a-f0-9]/g, "");
|
|
1823
|
+
while (cleaned.startsWith("0") && cleaned.length > 1) cleaned = cleaned.substring(1);
|
|
1824
|
+
return cleaned;
|
|
1825
|
+
}
|
|
1826
|
+
var isNode = typeof process !== "undefined" && process.versions && process.versions.node;
|
|
1827
|
+
var getSubtleCrypto = () => {
|
|
1828
|
+
var _a;
|
|
1829
|
+
if (typeof window !== "undefined" && ((_a = window.crypto) == null ? void 0 : _a.subtle)) return window.crypto.subtle;
|
|
1830
|
+
if (isNode) return require("crypto").webcrypto.subtle;
|
|
1831
|
+
throw new Error("No WebCrypto subtle implementation found in this environment");
|
|
1832
|
+
};
|
|
1833
|
+
function parseCert(buffer) {
|
|
1834
|
+
const bytes = toUint8Array(buffer);
|
|
1835
|
+
const asn1 = import_node_forge.default.asn1.fromDer(uint8ArrayToBinaryString(bytes));
|
|
1836
|
+
const certSeq = asn1.value;
|
|
1837
|
+
const tbsAsn1 = certSeq[0];
|
|
1838
|
+
const sigAlgAsn1 = certSeq[1];
|
|
1839
|
+
const sigValueAsn1 = certSeq[2];
|
|
1840
|
+
const tbsFields = tbsAsn1.value;
|
|
1841
|
+
let idx = 0;
|
|
1842
|
+
if (tbsFields[idx].tagClass === 128) idx++;
|
|
1843
|
+
const serialAsn1 = tbsFields[idx++];
|
|
1844
|
+
const serialNumber = import_node_forge.default.util.bytesToHex(serialAsn1.value);
|
|
1845
|
+
idx++;
|
|
1846
|
+
idx++;
|
|
1847
|
+
const validityAsn1 = tbsFields[idx++];
|
|
1848
|
+
idx++;
|
|
1849
|
+
const spkiAsn1 = tbsFields[idx];
|
|
1850
|
+
if (!validityAsn1 || !Array.isArray(validityAsn1.value) || validityAsn1.value.length < 2) {
|
|
1851
|
+
throw new Error("Certificate validity window is malformed");
|
|
1852
|
+
}
|
|
1853
|
+
const notBeforeNode = validityAsn1.value[0];
|
|
1854
|
+
const notAfterNode = validityAsn1.value[1];
|
|
1855
|
+
const notBefore = notBeforeNode ? parseAsn1Time(notBeforeNode) : void 0;
|
|
1856
|
+
const notAfter = notAfterNode ? parseAsn1Time(notAfterNode) : void 0;
|
|
1857
|
+
const sigRaw = typeof sigValueAsn1.value === "string" ? sigValueAsn1.value : "";
|
|
1858
|
+
const signature = binaryStringToUint8Array(sigRaw.substring(1));
|
|
1859
|
+
const sigAlgOid = import_node_forge.default.asn1.derToOid(sigAlgAsn1.value[0].value);
|
|
1860
|
+
return {
|
|
1861
|
+
serialNumber: normalizeSerial(serialNumber),
|
|
1862
|
+
tbsDer: binaryStringToUint8Array(import_node_forge.default.asn1.toDer(tbsAsn1).getBytes()),
|
|
1863
|
+
signature,
|
|
1864
|
+
sigAlgOid,
|
|
1865
|
+
spkiDer: binaryStringToUint8Array(import_node_forge.default.asn1.toDer(spkiAsn1).getBytes()),
|
|
1866
|
+
notBefore,
|
|
1867
|
+
notAfter
|
|
1868
|
+
};
|
|
1869
|
+
}
|
|
1870
|
+
function verifySignature(publicKeyPem, data, signature, sigAlgOid) {
|
|
1871
|
+
return __async(this, null, function* () {
|
|
1872
|
+
const cryptoSubtle = getSubtleCrypto();
|
|
1873
|
+
const forgeCert = import_node_forge.default.pki.certificateFromPem(publicKeyPem);
|
|
1874
|
+
const spkiBuf = binaryStringToUint8Array(import_node_forge.default.asn1.toDer(import_node_forge.default.pki.publicKeyToAsn1(forgeCert.publicKey)).getBytes());
|
|
1875
|
+
let importParams;
|
|
1876
|
+
let verifyParams;
|
|
1877
|
+
if (sigAlgOid === "1.2.840.113549.1.1.10") {
|
|
1878
|
+
importParams = { name: "RSA-PSS", hash: "SHA-384" };
|
|
1879
|
+
verifyParams = { name: "RSA-PSS", saltLength: 48 };
|
|
1880
|
+
} else if (sigAlgOid === "1.2.840.113549.1.1.11" || sigAlgOid === "1.2.840.113549.1.1.12" || sigAlgOid === "1.2.840.113549.1.1.5") {
|
|
1881
|
+
importParams = { name: "RSASSA-PKCS1-v1_5", hash: sigAlgOid === "1.2.840.113549.1.1.12" ? "SHA-384" : "SHA-256" };
|
|
1882
|
+
verifyParams = { name: "RSASSA-PKCS1-v1_5" };
|
|
1883
|
+
} else if (sigAlgOid === "1.2.840.10045.4.3.3") {
|
|
1884
|
+
importParams = { name: "ECDSA", namedCurve: "P-384" };
|
|
1885
|
+
verifyParams = { name: "ECDSA", hash: "SHA-384" };
|
|
1400
1886
|
} else {
|
|
1401
|
-
|
|
1887
|
+
importParams = { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" };
|
|
1888
|
+
verifyParams = { name: "RSASSA-PKCS1-v1_5" };
|
|
1889
|
+
}
|
|
1890
|
+
const key = yield cryptoSubtle.importKey("spki", spkiBuf, importParams, false, ["verify"]);
|
|
1891
|
+
const isValid = yield cryptoSubtle.verify(verifyParams, key, signature, data);
|
|
1892
|
+
if (!isValid) throw new Error(`Signature verification failed (OID: ${sigAlgOid}, ImportParams: ${JSON.stringify(importParams)})`);
|
|
1893
|
+
});
|
|
1894
|
+
}
|
|
1895
|
+
var COSIGN_PUBLIC_KEY = `-----BEGIN PUBLIC KEY-----
|
|
1896
|
+
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEjiL30OjPuxa+GC1I7SAcBv2u2pMt
|
|
1897
|
+
h9WbP33IvB3eFww+C1hoW0fwdZPiq4FxBtKNiZuFpmYuFngW/nJteBu9kQ==
|
|
1898
|
+
-----END PUBLIC KEY-----
|
|
1899
|
+
`;
|
|
1900
|
+
function verifyTeeAttestation(proof, expectedApplicationId) {
|
|
1901
|
+
return __async(this, null, function* () {
|
|
1902
|
+
try {
|
|
1903
|
+
let teeAttestation = proof.teeAttestation;
|
|
1904
|
+
if (!teeAttestation) {
|
|
1905
|
+
throw new Error("Missing teeAttestation in proof");
|
|
1906
|
+
}
|
|
1907
|
+
if (typeof teeAttestation === "string") {
|
|
1908
|
+
teeAttestation = JSON.parse(teeAttestation);
|
|
1909
|
+
}
|
|
1910
|
+
let expectedNonceSignature;
|
|
1911
|
+
let nonceDataObj;
|
|
1912
|
+
try {
|
|
1913
|
+
const context = JSON.parse(proof.claimData.context);
|
|
1914
|
+
expectedNonceSignature = context.attestationNonce;
|
|
1915
|
+
nonceDataObj = context.attestationNonceData;
|
|
1916
|
+
} catch (e) {
|
|
1917
|
+
throw new Error("Failed to parse proof context to extract attestationNonce");
|
|
1918
|
+
}
|
|
1919
|
+
if (!expectedNonceSignature || !nonceDataObj) {
|
|
1920
|
+
throw new Error("Proof context is missing attestationNonce or attestationNonceData");
|
|
1921
|
+
}
|
|
1922
|
+
if (teeAttestation.nonce !== expectedNonceSignature) {
|
|
1923
|
+
throw new Error(`Nonce Mismatch! Expected signature ${expectedNonceSignature}, got ${teeAttestation.nonce}`);
|
|
1924
|
+
}
|
|
1925
|
+
const { applicationId, sessionId, timestamp } = nonceDataObj;
|
|
1926
|
+
if (expectedApplicationId && applicationId.toLowerCase() !== expectedApplicationId.toLowerCase()) {
|
|
1927
|
+
throw new Error(`Application ID Mismatch! Expected ${expectedApplicationId}, but proof context contains ${applicationId}`);
|
|
1928
|
+
}
|
|
1929
|
+
const expectedNonceData = `${applicationId}:${sessionId}:${timestamp}`;
|
|
1930
|
+
const nonceMsg = import_ethers4.ethers.getBytes(import_ethers4.ethers.keccak256(new TextEncoder().encode(expectedNonceData)));
|
|
1931
|
+
const recoveredAddress = import_ethers4.ethers.verifyMessage(nonceMsg, expectedNonceSignature);
|
|
1932
|
+
if (recoveredAddress.toLowerCase() !== applicationId.toLowerCase()) {
|
|
1933
|
+
throw new Error(`Nonce signature verification failed: recovered ${recoveredAddress}, expected ${applicationId}`);
|
|
1934
|
+
}
|
|
1935
|
+
try {
|
|
1936
|
+
const context = JSON.parse(proof.claimData.context);
|
|
1937
|
+
const paramSessionId = context.attestationNonceData.sessionId;
|
|
1938
|
+
if (!paramSessionId) {
|
|
1939
|
+
throw new Error(`Proof parameters are missing proxySessionId or sessionId`);
|
|
1940
|
+
}
|
|
1941
|
+
if (paramSessionId.toString() !== sessionId.toString()) {
|
|
1942
|
+
throw new Error(`Session ID Mismatch! Expected ${sessionId}, but proof parameters contain ${paramSessionId}`);
|
|
1943
|
+
}
|
|
1944
|
+
const claimTimestampMs = proof.claimData.timestampS * 1e3;
|
|
1945
|
+
const nonceTimestampMs = parseInt(timestamp, 10);
|
|
1946
|
+
const diffMs = Math.abs(claimTimestampMs - nonceTimestampMs);
|
|
1947
|
+
const TEN_MINUTES_MS = 10 * 60 * 1e3;
|
|
1948
|
+
if (diffMs > TEN_MINUTES_MS) {
|
|
1949
|
+
throw new Error(`Timestamp Skew Too Large! claimData.timestampS and attestationNonce timestamp differ by ${Math.round(diffMs / 1e3)}s (limit: 600s)`);
|
|
1950
|
+
}
|
|
1951
|
+
} catch (e) {
|
|
1952
|
+
if (e instanceof Error && (e.message.includes("Session ID Mismatch!") || e.message.includes("Timestamp Skew"))) {
|
|
1953
|
+
throw e;
|
|
1954
|
+
}
|
|
1955
|
+
throw new Error(`Failed to cross-verify session ID: ${e.message}`);
|
|
1956
|
+
}
|
|
1957
|
+
const reportBuffer = base64ToUint8Array(teeAttestation.snp_report);
|
|
1958
|
+
const report = parseAttestationReport(reportBuffer);
|
|
1959
|
+
if (report.isDebugEnabled) {
|
|
1960
|
+
throw new Error("POLICY CHECK FAILED: Debug mode is ALLOWED. Environment is compromised.");
|
|
1961
|
+
}
|
|
1962
|
+
const certBuffer = base64ToUint8Array(teeAttestation.vlek_cert);
|
|
1963
|
+
yield verifyAMDChain(certBuffer);
|
|
1964
|
+
verifyTCB(certBuffer, report);
|
|
1965
|
+
yield verifyHardwareSignature(reportBuffer, certBuffer);
|
|
1966
|
+
yield verifyReportData(teeAttestation, proof.claimData.context, report);
|
|
1967
|
+
return true;
|
|
1968
|
+
} catch (error) {
|
|
1969
|
+
logger9.error("TEE attestation verification failed:", error);
|
|
1970
|
+
return false;
|
|
1971
|
+
}
|
|
1972
|
+
});
|
|
1973
|
+
}
|
|
1974
|
+
function parseAttestationReport(buffer) {
|
|
1975
|
+
if (buffer.length < 1e3) {
|
|
1976
|
+
throw new Error(`Report buffer is too small: ${buffer.length} bytes`);
|
|
1977
|
+
}
|
|
1978
|
+
const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
1979
|
+
const policy = view.getBigUint64(8, true);
|
|
1980
|
+
const isDebugEnabled = (policy & BigInt(1) << BigInt(19)) !== BigInt(0);
|
|
1981
|
+
const reported_tcb = {
|
|
1982
|
+
bootloader: buffer[56],
|
|
1983
|
+
tee: buffer[57],
|
|
1984
|
+
snp: buffer[62],
|
|
1985
|
+
microcode: buffer[63]
|
|
1986
|
+
};
|
|
1987
|
+
const reportData = arrayBufferToHex(buffer.subarray(80, 144));
|
|
1988
|
+
return { policy, isDebugEnabled, reported_tcb, reportData };
|
|
1989
|
+
}
|
|
1990
|
+
function getExtValue(certAsn1, oidString) {
|
|
1991
|
+
const tbsCert = certAsn1.value[0];
|
|
1992
|
+
if (!tbsCert || !tbsCert.value) return null;
|
|
1993
|
+
const extBlockWrapper = tbsCert.value.find((node) => node.tagClass === import_node_forge.default.asn1.Class.CONTEXT_SPECIFIC && node.type === 3);
|
|
1994
|
+
if (!extBlockWrapper || !extBlockWrapper.value || !extBlockWrapper.value.length) return null;
|
|
1995
|
+
const extSequence = extBlockWrapper.value[0];
|
|
1996
|
+
for (const ext of extSequence.value) {
|
|
1997
|
+
const extIdAsn1 = ext.value[0];
|
|
1998
|
+
const extIdStr = import_node_forge.default.asn1.derToOid(extIdAsn1.value);
|
|
1999
|
+
if (extIdStr === oidString) {
|
|
2000
|
+
const extValueAsn1 = ext.value[ext.value.length - 1];
|
|
2001
|
+
const rawOctetStringBytes = extValueAsn1.value;
|
|
2002
|
+
try {
|
|
2003
|
+
const innerAsn1 = import_node_forge.default.asn1.fromDer(import_node_forge.default.util.createBuffer(rawOctetStringBytes));
|
|
2004
|
+
if (innerAsn1.type === 2) {
|
|
2005
|
+
const bytes = innerAsn1.value;
|
|
2006
|
+
if (typeof bytes === "string" && bytes.length > 0) {
|
|
2007
|
+
return bytes.charCodeAt(bytes.length - 1);
|
|
2008
|
+
} else {
|
|
2009
|
+
throw new Error(`Extension ${oidString} INTEGER value is empty or invalid`);
|
|
2010
|
+
}
|
|
2011
|
+
} else {
|
|
2012
|
+
throw new Error(`Extension ${oidString} does not contain an INTEGER, found type ${innerAsn1.type}`);
|
|
2013
|
+
}
|
|
2014
|
+
} catch (e) {
|
|
2015
|
+
throw new Error(`Failed to strictly parse AMD TCB extension ${oidString}: ${e.message}`);
|
|
2016
|
+
}
|
|
2017
|
+
}
|
|
2018
|
+
}
|
|
2019
|
+
return null;
|
|
2020
|
+
}
|
|
2021
|
+
function verifyTCB(vlekCertBuffer, report) {
|
|
2022
|
+
const certAsn1 = import_node_forge.default.asn1.fromDer(import_node_forge.default.util.createBuffer(uint8ArrayToBinaryString(vlekCertBuffer)));
|
|
2023
|
+
const OID_BOOTLOADER = "1.3.6.1.4.1.3704.1.3.1";
|
|
2024
|
+
const OID_TEE = "1.3.6.1.4.1.3704.1.3.2";
|
|
2025
|
+
const OID_SNP = "1.3.6.1.4.1.3704.1.3.3";
|
|
2026
|
+
const OID_MICROCODE = "1.3.6.1.4.1.3704.1.3.8";
|
|
2027
|
+
const certTcb = {
|
|
2028
|
+
bootloader: getExtValue(certAsn1, OID_BOOTLOADER),
|
|
2029
|
+
tee: getExtValue(certAsn1, OID_TEE),
|
|
2030
|
+
snp: getExtValue(certAsn1, OID_SNP),
|
|
2031
|
+
microcode: getExtValue(certAsn1, OID_MICROCODE)
|
|
2032
|
+
};
|
|
2033
|
+
if (certTcb.bootloader !== null && report.reported_tcb.bootloader < certTcb.bootloader) {
|
|
2034
|
+
throw new Error(`TCB Downgrade! Bootloader reported ${report.reported_tcb.bootloader}, but certificate requires ${certTcb.bootloader}`);
|
|
2035
|
+
}
|
|
2036
|
+
if (certTcb.tee !== null && report.reported_tcb.tee < certTcb.tee) {
|
|
2037
|
+
throw new Error(`TCB Downgrade! TEE reported ${report.reported_tcb.tee}, but certificate requires ${certTcb.tee}`);
|
|
2038
|
+
}
|
|
2039
|
+
if (certTcb.snp !== null && report.reported_tcb.snp < certTcb.snp) {
|
|
2040
|
+
throw new Error(`TCB Downgrade! SNP reported ${report.reported_tcb.snp}, but certificate requires ${certTcb.snp}`);
|
|
2041
|
+
}
|
|
2042
|
+
if (certTcb.microcode !== null && report.reported_tcb.microcode < certTcb.microcode) {
|
|
2043
|
+
throw new Error(`TCB Downgrade! Microcode reported ${report.reported_tcb.microcode}, but certificate requires ${certTcb.microcode}`);
|
|
2044
|
+
}
|
|
2045
|
+
}
|
|
2046
|
+
function parseAsn1Time(node) {
|
|
2047
|
+
const s = node.value;
|
|
2048
|
+
if (node.type === import_node_forge.default.asn1.Type.UTCTIME) {
|
|
2049
|
+
const yr = parseInt(s.substring(0, 2), 10);
|
|
2050
|
+
return new Date(Date.UTC(
|
|
2051
|
+
yr >= 50 ? 1900 + yr : 2e3 + yr,
|
|
2052
|
+
parseInt(s.substring(2, 4), 10) - 1,
|
|
2053
|
+
parseInt(s.substring(4, 6), 10),
|
|
2054
|
+
parseInt(s.substring(6, 8), 10),
|
|
2055
|
+
parseInt(s.substring(8, 10), 10),
|
|
2056
|
+
parseInt(s.substring(10, 12), 10)
|
|
2057
|
+
));
|
|
2058
|
+
} else {
|
|
2059
|
+
return new Date(Date.UTC(
|
|
2060
|
+
parseInt(s.substring(0, 4), 10),
|
|
2061
|
+
parseInt(s.substring(4, 6), 10) - 1,
|
|
2062
|
+
parseInt(s.substring(6, 8), 10),
|
|
2063
|
+
parseInt(s.substring(8, 10), 10),
|
|
2064
|
+
parseInt(s.substring(10, 12), 10),
|
|
2065
|
+
parseInt(s.substring(12, 14), 10)
|
|
2066
|
+
));
|
|
2067
|
+
}
|
|
2068
|
+
}
|
|
2069
|
+
function verifyCRL(crlBuf, arkPem, vlekSerial) {
|
|
2070
|
+
return __async(this, null, function* () {
|
|
2071
|
+
const crlAsn1 = import_node_forge.default.asn1.fromDer(import_node_forge.default.util.createBuffer(uint8ArrayToBinaryString(crlBuf)));
|
|
2072
|
+
if (!Array.isArray(crlAsn1.value) || crlAsn1.value.length < 3) {
|
|
2073
|
+
throw new Error("CRL ASN.1 structure is invalid: expected SEQUENCE with TBSCertList, AlgorithmIdentifier, BIT STRING");
|
|
2074
|
+
}
|
|
2075
|
+
const tbsAsn1 = crlAsn1.value[0];
|
|
2076
|
+
const sigBitsAsn1 = crlAsn1.value[2];
|
|
2077
|
+
if (!Array.isArray(tbsAsn1.value)) {
|
|
2078
|
+
throw new Error("CRL TBSCertList is not a valid SEQUENCE");
|
|
2079
|
+
}
|
|
2080
|
+
const tbsFields = tbsAsn1.value;
|
|
2081
|
+
let fi = 0;
|
|
2082
|
+
if (fi < tbsFields.length && tbsFields[fi].tagClass === import_node_forge.default.asn1.Class.UNIVERSAL && tbsFields[fi].type === import_node_forge.default.asn1.Type.INTEGER) {
|
|
2083
|
+
fi++;
|
|
2084
|
+
}
|
|
2085
|
+
if (fi < tbsFields.length) fi++;
|
|
2086
|
+
if (fi >= tbsFields.length) throw new Error("CRL TBSCertList missing issuer");
|
|
2087
|
+
const issuerAsn1 = tbsFields[fi++];
|
|
2088
|
+
if (fi >= tbsFields.length) throw new Error("CRL TBSCertList missing thisUpdate");
|
|
2089
|
+
const thisUpdateAsn1 = tbsFields[fi++];
|
|
2090
|
+
let nextUpdateAsn1 = null;
|
|
2091
|
+
if (fi < tbsFields.length && tbsFields[fi].tagClass === import_node_forge.default.asn1.Class.UNIVERSAL && (tbsFields[fi].type === import_node_forge.default.asn1.Type.UTCTIME || tbsFields[fi].type === import_node_forge.default.asn1.Type.GENERALIZEDTIME)) {
|
|
2092
|
+
nextUpdateAsn1 = tbsFields[fi++];
|
|
2093
|
+
}
|
|
2094
|
+
let revokedSeq = null;
|
|
2095
|
+
if (fi < tbsFields.length && tbsFields[fi].tagClass === import_node_forge.default.asn1.Class.UNIVERSAL && tbsFields[fi].type === import_node_forge.default.asn1.Type.SEQUENCE) {
|
|
2096
|
+
revokedSeq = tbsFields[fi];
|
|
2097
|
+
}
|
|
2098
|
+
const now = /* @__PURE__ */ new Date();
|
|
2099
|
+
const thisUpdate = parseAsn1Time(thisUpdateAsn1);
|
|
2100
|
+
if (thisUpdate > now) {
|
|
2101
|
+
throw new Error(`CRL is not yet valid: thisUpdate is ${thisUpdate.toISOString()}`);
|
|
2102
|
+
}
|
|
2103
|
+
if (nextUpdateAsn1) {
|
|
2104
|
+
const nextUpdate = parseAsn1Time(nextUpdateAsn1);
|
|
2105
|
+
if (nextUpdate < now) {
|
|
2106
|
+
throw new Error(`CRL has expired: nextUpdate was ${nextUpdate.toISOString()}`);
|
|
2107
|
+
}
|
|
2108
|
+
}
|
|
2109
|
+
const crlIssuerDer = import_node_forge.default.asn1.toDer(issuerAsn1).getBytes();
|
|
2110
|
+
const arkForgeCert = import_node_forge.default.pki.certificateFromPem(arkPem);
|
|
2111
|
+
const arkCertAsn1 = import_node_forge.default.pki.certificateToAsn1(arkForgeCert);
|
|
2112
|
+
const arkSubjectAsn1 = arkCertAsn1.value[0].value[5];
|
|
2113
|
+
const arkSubjectDer = import_node_forge.default.asn1.toDer(arkSubjectAsn1).getBytes();
|
|
2114
|
+
if (crlIssuerDer !== arkSubjectDer) {
|
|
2115
|
+
throw new Error("CRL issuer does not match AMD ARK certificate subject \u2014 chain mismatch");
|
|
2116
|
+
}
|
|
2117
|
+
const tbsDerBuf = binaryStringToUint8Array(import_node_forge.default.asn1.toDer(tbsAsn1).getBytes());
|
|
2118
|
+
const sigRaw = typeof sigBitsAsn1.value === "string" ? sigBitsAsn1.value : "";
|
|
2119
|
+
const sigBuf = binaryStringToUint8Array(sigRaw.substring(1));
|
|
2120
|
+
const cryptoSubtle = getSubtleCrypto();
|
|
2121
|
+
const spkiBuf = binaryStringToUint8Array(
|
|
2122
|
+
import_node_forge.default.asn1.toDer(import_node_forge.default.pki.publicKeyToAsn1(arkForgeCert.publicKey)).getBytes()
|
|
2123
|
+
);
|
|
2124
|
+
const arkCryptoKey = yield cryptoSubtle.importKey(
|
|
2125
|
+
"spki",
|
|
2126
|
+
spkiBuf,
|
|
2127
|
+
{ name: "RSA-PSS", hash: "SHA-384" },
|
|
2128
|
+
false,
|
|
2129
|
+
["verify"]
|
|
2130
|
+
);
|
|
2131
|
+
const isValid = yield cryptoSubtle.verify(
|
|
2132
|
+
{ name: "RSA-PSS", saltLength: 48 },
|
|
2133
|
+
// SHA-384 salt length is 48
|
|
2134
|
+
arkCryptoKey,
|
|
2135
|
+
sigBuf,
|
|
2136
|
+
tbsDerBuf
|
|
2137
|
+
);
|
|
2138
|
+
if (!isValid) {
|
|
2139
|
+
throw new Error("CRL signature is INVALID \u2014 the CRL may be tampered or forged");
|
|
2140
|
+
}
|
|
2141
|
+
const targetSerial = normalizeSerial(vlekSerial);
|
|
2142
|
+
if (revokedSeq && Array.isArray(revokedSeq.value)) {
|
|
2143
|
+
for (const entry of revokedSeq.value) {
|
|
2144
|
+
if (!Array.isArray(entry.value) || entry.value.length < 2) continue;
|
|
2145
|
+
const serialAsn1 = entry.value[0];
|
|
2146
|
+
if (serialAsn1.type !== import_node_forge.default.asn1.Type.INTEGER || typeof serialAsn1.value !== "string") continue;
|
|
2147
|
+
const serialHex = import_node_forge.default.util.bytesToHex(serialAsn1.value);
|
|
2148
|
+
if (normalizeSerial(serialHex) === targetSerial) {
|
|
2149
|
+
throw new Error("\u{1F6A8} VLEK Certificate is REVOKED per AMD CRL! This hardware may be compromised.");
|
|
2150
|
+
}
|
|
2151
|
+
}
|
|
2152
|
+
}
|
|
2153
|
+
});
|
|
2154
|
+
}
|
|
2155
|
+
function assertCertValidity(label, cert) {
|
|
2156
|
+
const now = Date.now();
|
|
2157
|
+
if (cert.notBefore && now < cert.notBefore.getTime()) {
|
|
2158
|
+
throw new Error(`${label} certificate is not yet valid (notBefore: ${cert.notBefore.toISOString()})`);
|
|
2159
|
+
}
|
|
2160
|
+
if (cert.notAfter && now > cert.notAfter.getTime()) {
|
|
2161
|
+
throw new Error(`${label} certificate expired on ${cert.notAfter.toISOString()}`);
|
|
2162
|
+
}
|
|
2163
|
+
}
|
|
2164
|
+
function verifyAMDChain(vlekCertBuffer) {
|
|
2165
|
+
return __async(this, null, function* () {
|
|
2166
|
+
const processors = ["Milan", "Genoa"];
|
|
2167
|
+
let chainVerified = false;
|
|
2168
|
+
const vlek = parseCert(vlekCertBuffer);
|
|
2169
|
+
assertCertValidity("VLEK", vlek);
|
|
2170
|
+
for (const processor of processors) {
|
|
2171
|
+
let matchedChain = false;
|
|
2172
|
+
try {
|
|
2173
|
+
const chainPem = AMD_CERTS[processor];
|
|
2174
|
+
if (!chainPem) continue;
|
|
2175
|
+
const certs = chainPem.split("-----END CERTIFICATE-----").map((c) => c.trim()).filter((c) => c.length > 0).map((c) => c + "\n-----END CERTIFICATE-----\n");
|
|
2176
|
+
const askCert = import_node_forge.default.pki.certificateFromPem(certs[0]);
|
|
2177
|
+
const arkCert = import_node_forge.default.pki.certificateFromPem(certs[1]);
|
|
2178
|
+
const askDer = import_node_forge.default.asn1.toDer(import_node_forge.default.pki.certificateToAsn1(askCert)).getBytes();
|
|
2179
|
+
const arkDer = import_node_forge.default.asn1.toDer(import_node_forge.default.pki.certificateToAsn1(arkCert)).getBytes();
|
|
2180
|
+
const ask = parseCert(binaryStringToUint8Array(askDer));
|
|
2181
|
+
const ark = parseCert(binaryStringToUint8Array(arkDer));
|
|
2182
|
+
assertCertValidity("ASK", ask);
|
|
2183
|
+
assertCertValidity("ARK", ark);
|
|
2184
|
+
try {
|
|
2185
|
+
yield verifySignature(certs[1], ark.tbsDer, ark.signature, ark.sigAlgOid);
|
|
2186
|
+
} catch (e) {
|
|
2187
|
+
throw new Error(`AMD ARK self-signature verification failed: ${e.message}`);
|
|
2188
|
+
}
|
|
2189
|
+
try {
|
|
2190
|
+
yield verifySignature(certs[1], ask.tbsDer, ask.signature, ask.sigAlgOid);
|
|
2191
|
+
} catch (e) {
|
|
2192
|
+
throw new Error(`AMD ASK-by-ARK signature verification failed: ${e.message}`);
|
|
2193
|
+
}
|
|
2194
|
+
try {
|
|
2195
|
+
yield verifySignature(certs[0], vlek.tbsDer, vlek.signature, vlek.sigAlgOid);
|
|
2196
|
+
} catch (e) {
|
|
2197
|
+
throw new Error(`VLEK-by-ASK signature verification failed: ${e.message}`);
|
|
2198
|
+
}
|
|
2199
|
+
matchedChain = true;
|
|
2200
|
+
let crlBuf;
|
|
2201
|
+
const now = Date.now();
|
|
2202
|
+
if (crlCache[processor] && now - crlCache[processor].fetchedAt < 36e5) {
|
|
2203
|
+
crlBuf = crlCache[processor].buffer;
|
|
2204
|
+
} else {
|
|
2205
|
+
const crlUrl = `https://kdsintf.amd.com/vlek/v1/${processor}/crl`;
|
|
2206
|
+
const controller = new AbortController();
|
|
2207
|
+
const timeoutId = setTimeout(() => controller.abort(), 5e3);
|
|
2208
|
+
const crlResp = yield fetch(crlUrl, { signal: controller.signal });
|
|
2209
|
+
clearTimeout(timeoutId);
|
|
2210
|
+
if (!crlResp.ok) continue;
|
|
2211
|
+
crlBuf = new Uint8Array(yield crlResp.arrayBuffer());
|
|
2212
|
+
crlCache[processor] = { buffer: crlBuf, fetchedAt: now };
|
|
2213
|
+
}
|
|
2214
|
+
if (vlek.serialNumber && crlBuf) {
|
|
2215
|
+
yield verifyCRL(crlBuf, certs[1], vlek.serialNumber);
|
|
2216
|
+
}
|
|
2217
|
+
chainVerified = true;
|
|
2218
|
+
break;
|
|
2219
|
+
} catch (e) {
|
|
2220
|
+
if (matchedChain) {
|
|
2221
|
+
throw e;
|
|
2222
|
+
}
|
|
2223
|
+
continue;
|
|
2224
|
+
}
|
|
2225
|
+
}
|
|
2226
|
+
if (!chainVerified) {
|
|
2227
|
+
throw new Error("VLEK Certificate failed verification against all known AMD Root of Trust chains!");
|
|
2228
|
+
}
|
|
2229
|
+
});
|
|
2230
|
+
}
|
|
2231
|
+
function verifyHardwareSignature(reportBytes, certBytes) {
|
|
2232
|
+
return __async(this, null, function* () {
|
|
2233
|
+
const vlek = parseCert(certBytes);
|
|
2234
|
+
const sigOffset = 672;
|
|
2235
|
+
const rLE = reportBytes.subarray(sigOffset, sigOffset + 72);
|
|
2236
|
+
const sLE = reportBytes.subarray(sigOffset + 72, sigOffset + 144);
|
|
2237
|
+
const rBE = reverseBytes(rLE);
|
|
2238
|
+
const sBE = reverseBytes(sLE);
|
|
2239
|
+
const signedData = reportBytes.subarray(0, 672);
|
|
2240
|
+
const cryptoSubtle = getSubtleCrypto();
|
|
2241
|
+
const importedKey = yield cryptoSubtle.importKey(
|
|
2242
|
+
"spki",
|
|
2243
|
+
vlek.spkiDer,
|
|
2244
|
+
{ name: "ECDSA", namedCurve: "P-384" },
|
|
2245
|
+
false,
|
|
2246
|
+
["verify"]
|
|
2247
|
+
);
|
|
2248
|
+
const rPadding = rBE.subarray(0, rBE.length - 48);
|
|
2249
|
+
const sPadding = sBE.subarray(0, sBE.length - 48);
|
|
2250
|
+
if (!rPadding.every((b) => b === 0) || !sPadding.every((b) => b === 0)) {
|
|
2251
|
+
throw new Error("Hardware ECDSA signature is malformed: non-zero padding bytes detected in the structural signature coordinates.");
|
|
2252
|
+
}
|
|
2253
|
+
const r48 = rBE.subarray(rBE.length - 48);
|
|
2254
|
+
const s48 = sBE.subarray(sBE.length - 48);
|
|
2255
|
+
const rawSignature = concatUint8Arrays([r48, s48]);
|
|
2256
|
+
const isValid = yield cryptoSubtle.verify(
|
|
2257
|
+
{ name: "ECDSA", hash: { name: "SHA-384" } },
|
|
2258
|
+
importedKey,
|
|
2259
|
+
rawSignature,
|
|
2260
|
+
signedData
|
|
2261
|
+
);
|
|
2262
|
+
if (!isValid) {
|
|
2263
|
+
throw new Error("Hardware ECDSA signature is completely invalid!");
|
|
1402
2264
|
}
|
|
1403
2265
|
});
|
|
1404
|
-
|
|
1405
|
-
|
|
2266
|
+
}
|
|
2267
|
+
function verifyReportData(teeAttestation, proofContext, report) {
|
|
2268
|
+
return __async(this, null, function* () {
|
|
2269
|
+
if (!teeAttestation.workload_digest || !teeAttestation.verifier_digest) {
|
|
2270
|
+
throw new Error("POLICY CHECK FAILED: Missing workload_digest or verifier_digest in TEE attestation.");
|
|
2271
|
+
}
|
|
2272
|
+
const { attestationNonce: nonce } = JSON.parse(proofContext);
|
|
2273
|
+
const cryptoSubtle = getSubtleCrypto();
|
|
2274
|
+
const extractDigestBytes = (imageRef) => {
|
|
2275
|
+
const marker = "@sha256:";
|
|
2276
|
+
const idx = imageRef.lastIndexOf(marker);
|
|
2277
|
+
if (idx < 0) throw new Error(`Image ref missing @sha256: digest: ${imageRef}`);
|
|
2278
|
+
const hexDigest = imageRef.substring(idx + marker.length);
|
|
2279
|
+
if (hexDigest.length !== 64) throw new Error(`SHA256 digest must be 64 hex chars, got ${hexDigest.length} in: ${imageRef}`);
|
|
2280
|
+
const bytes = new Uint8Array(32);
|
|
2281
|
+
for (let i = 0; i < 32; i++) bytes[i] = parseInt(hexDigest.substring(i * 2, i * 2 + 2), 16);
|
|
2282
|
+
return bytes;
|
|
2283
|
+
};
|
|
2284
|
+
const importedCosignKey = yield cryptoSubtle.importKey(
|
|
2285
|
+
"spki",
|
|
2286
|
+
base64ToUint8Array(
|
|
2287
|
+
COSIGN_PUBLIC_KEY.replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", "").replace(/\s+/g, "")
|
|
2288
|
+
),
|
|
2289
|
+
{ name: "ECDSA", namedCurve: "P-256" },
|
|
2290
|
+
true,
|
|
2291
|
+
["verify"]
|
|
2292
|
+
);
|
|
2293
|
+
const pubKeySpkiDer = yield cryptoSubtle.exportKey("spki", importedCosignKey);
|
|
2294
|
+
const pubKeyHashBuffer = yield cryptoSubtle.digest("SHA-256", pubKeySpkiDer);
|
|
2295
|
+
const pubKeyHashBytes = new Uint8Array(pubKeyHashBuffer);
|
|
2296
|
+
const nonceHex = (teeAttestation.nonce || nonce).replace(/^0x/i, "");
|
|
2297
|
+
const nonceBytes = new Uint8Array(nonceHex.length / 2);
|
|
2298
|
+
for (let i = 0; i < nonceBytes.length; i++) nonceBytes[i] = parseInt(nonceHex.substring(i * 2, i * 2 + 2), 16);
|
|
2299
|
+
const workloadBytes = extractDigestBytes(teeAttestation.workload_digest);
|
|
2300
|
+
const verifierBytes = extractDigestBytes(teeAttestation.verifier_digest);
|
|
2301
|
+
const domainSep = new TextEncoder().encode("POPCORN_TEE_REPORT_DATA_V1");
|
|
2302
|
+
const version = new Uint8Array([1]);
|
|
2303
|
+
const payload = new Uint8Array(
|
|
2304
|
+
domainSep.length + version.length + workloadBytes.length + verifierBytes.length + pubKeyHashBytes.length + nonceBytes.length
|
|
2305
|
+
);
|
|
2306
|
+
let offset = 0;
|
|
2307
|
+
for (const chunk of [domainSep, version, workloadBytes, verifierBytes, pubKeyHashBytes, nonceBytes]) {
|
|
2308
|
+
payload.set(chunk, offset);
|
|
2309
|
+
offset += chunk.length;
|
|
2310
|
+
}
|
|
2311
|
+
const hashBuffer = yield cryptoSubtle.digest("SHA-256", payload);
|
|
2312
|
+
const hashHex = arrayBufferToHex(hashBuffer);
|
|
2313
|
+
const expected64ByteHex = hashHex + hashHex;
|
|
2314
|
+
if (report.reportData !== expected64ByteHex) {
|
|
2315
|
+
throw new Error(`REPORT_DATA Mismatch! Hardware report is not bound to these image digests or nonce.
|
|
2316
|
+
Expected: ${expected64ByteHex}
|
|
2317
|
+
Got: ${report.reportData}`);
|
|
2318
|
+
}
|
|
1406
2319
|
});
|
|
1407
2320
|
}
|
|
1408
2321
|
|
|
1409
2322
|
// src/Reclaim.ts
|
|
1410
|
-
var
|
|
2323
|
+
var logger10 = logger_default.logger;
|
|
1411
2324
|
var sdkVersion = require_package().version;
|
|
1412
2325
|
function verifyProof(proofOrProofs, config) {
|
|
1413
2326
|
return __async(this, null, function* () {
|
|
2327
|
+
const proofs = Array.isArray(proofOrProofs) ? proofOrProofs : [proofOrProofs];
|
|
1414
2328
|
try {
|
|
1415
|
-
const proofs = Array.isArray(proofOrProofs) ? proofOrProofs : [proofOrProofs];
|
|
1416
2329
|
if (proofs.length === 0) {
|
|
1417
2330
|
throw new ProofNotValidatedError("No proofs provided");
|
|
1418
2331
|
}
|
|
@@ -1423,14 +2336,64 @@ function verifyProof(proofOrProofs, config) {
|
|
|
1423
2336
|
for (const proof of proofs) {
|
|
1424
2337
|
yield assertVerifiedProof(proof, attestors);
|
|
1425
2338
|
}
|
|
1426
|
-
assertValidateProof(proofs, config);
|
|
1427
|
-
|
|
2339
|
+
yield assertValidateProof(proofs, config);
|
|
2340
|
+
const result = {
|
|
2341
|
+
isVerified: true,
|
|
2342
|
+
data: proofs.map(extractProofData)
|
|
2343
|
+
};
|
|
2344
|
+
if (config.verifyTEE) {
|
|
2345
|
+
const hasTeeData = proofs.every((proof) => proof.teeAttestation || JSON.parse(proof.claimData.context).attestationNonce);
|
|
2346
|
+
if (!hasTeeData) {
|
|
2347
|
+
const teeError = new TeeVerificationError("TEE verification requested but one or more proofs are missing TEE attestation data");
|
|
2348
|
+
logger10.error(teeError.message);
|
|
2349
|
+
result.isTeeVerified = false;
|
|
2350
|
+
result.isVerified = false;
|
|
2351
|
+
result.error = teeError;
|
|
2352
|
+
return result;
|
|
2353
|
+
}
|
|
2354
|
+
try {
|
|
2355
|
+
const teeResults = yield Promise.all(proofs.map((proof) => verifyTeeAttestation(proof)));
|
|
2356
|
+
result.isTeeVerified = teeResults.every((r) => r === true);
|
|
2357
|
+
if (!result.isTeeVerified) {
|
|
2358
|
+
const teeError = new TeeVerificationError("TEE attestation verification failed for one or more proofs");
|
|
2359
|
+
logger10.error(teeError.message);
|
|
2360
|
+
result.isVerified = false;
|
|
2361
|
+
result.error = teeError;
|
|
2362
|
+
}
|
|
2363
|
+
} catch (error) {
|
|
2364
|
+
const teeError = new TeeVerificationError("Error verifying TEE attestation", error);
|
|
2365
|
+
logger10.error(teeError.message);
|
|
2366
|
+
result.isTeeVerified = false;
|
|
2367
|
+
result.isVerified = false;
|
|
2368
|
+
result.error = teeError;
|
|
2369
|
+
}
|
|
2370
|
+
}
|
|
2371
|
+
return result;
|
|
1428
2372
|
} catch (error) {
|
|
1429
|
-
|
|
1430
|
-
return
|
|
2373
|
+
logger10.error("Error in validating proof:", error);
|
|
2374
|
+
return {
|
|
2375
|
+
isVerified: false,
|
|
2376
|
+
data: [],
|
|
2377
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
2378
|
+
};
|
|
1431
2379
|
}
|
|
1432
2380
|
});
|
|
1433
2381
|
}
|
|
2382
|
+
function extractProofData(proof) {
|
|
2383
|
+
try {
|
|
2384
|
+
const context = JSON.parse(proof.claimData.context);
|
|
2385
|
+
const _a = context, { extractedParameters } = _a, rest = __objRest(_a, ["extractedParameters"]);
|
|
2386
|
+
return {
|
|
2387
|
+
context: rest,
|
|
2388
|
+
extractedParameters: extractedParameters != null ? extractedParameters : {}
|
|
2389
|
+
};
|
|
2390
|
+
} catch (e) {
|
|
2391
|
+
return {
|
|
2392
|
+
context: {},
|
|
2393
|
+
extractedParameters: {}
|
|
2394
|
+
};
|
|
2395
|
+
}
|
|
2396
|
+
}
|
|
1434
2397
|
function transformForOnchain(proof) {
|
|
1435
2398
|
const claimInfoBuilder = /* @__PURE__ */ new Map([
|
|
1436
2399
|
["context", proof.claimData.context],
|
|
@@ -1479,6 +2442,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
1479
2442
|
this.intervals = /* @__PURE__ */ new Map();
|
|
1480
2443
|
this.jsonProofResponse = false;
|
|
1481
2444
|
this.extensionID = "reclaim-extension";
|
|
2445
|
+
this.appSharePageUrl = "https://share.reclaimprotocol.org/verify";
|
|
1482
2446
|
this.FAILURE_TIMEOUT = 30 * 1e3;
|
|
1483
2447
|
/**
|
|
1484
2448
|
* Validates signature and returns template data
|
|
@@ -1546,34 +2510,42 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
1546
2510
|
logger_default.setLogLevel("silent");
|
|
1547
2511
|
}
|
|
1548
2512
|
if (options.useAppClip === void 0) {
|
|
1549
|
-
options.useAppClip =
|
|
2513
|
+
options.useAppClip = false;
|
|
2514
|
+
}
|
|
2515
|
+
const customUrl = (_b = options.portalUrl) != null ? _b : options.customSharePageUrl;
|
|
2516
|
+
this.customSharePageUrl = customUrl != null ? customUrl : "https://portal.reclaimprotocol.org";
|
|
2517
|
+
if (customUrl) {
|
|
2518
|
+
this.appSharePageUrl = customUrl;
|
|
1550
2519
|
}
|
|
2520
|
+
options.customSharePageUrl = this.customSharePageUrl;
|
|
1551
2521
|
if (options == null ? void 0 : options.envUrl) {
|
|
1552
2522
|
setBackendBaseUrl(options.envUrl);
|
|
1553
|
-
} else if (
|
|
1554
|
-
|
|
2523
|
+
} else if (this.customSharePageUrl) {
|
|
2524
|
+
try {
|
|
2525
|
+
if (new URL(this.customSharePageUrl).hostname === "eu.portal.reclaimprotocol.org") {
|
|
2526
|
+
setBackendBaseUrl("https://eu.api.reclaimprotocol.org");
|
|
2527
|
+
}
|
|
2528
|
+
} catch (e) {
|
|
2529
|
+
}
|
|
1555
2530
|
}
|
|
1556
2531
|
if (options.extensionID) {
|
|
1557
2532
|
this.extensionID = options.extensionID;
|
|
1558
2533
|
}
|
|
1559
|
-
if (options == null ? void 0 : options.customSharePageUrl) {
|
|
1560
|
-
this.customSharePageUrl = options.customSharePageUrl;
|
|
1561
|
-
}
|
|
1562
2534
|
if (options == null ? void 0 : options.customAppClipUrl) {
|
|
1563
2535
|
this.customAppClipUrl = options.customAppClipUrl;
|
|
1564
2536
|
}
|
|
1565
2537
|
this.options = options;
|
|
1566
2538
|
this.sdkVersion = "js-" + sdkVersion;
|
|
1567
|
-
|
|
2539
|
+
logger10.info(`Initializing client with applicationId: ${this.applicationId}`);
|
|
1568
2540
|
}
|
|
1569
2541
|
/**
|
|
1570
|
-
* Initializes a new Reclaim proof request instance with automatic signature generation and session creation
|
|
2542
|
+
* Initializes a new Reclaim proof request instance with automatic signature generation and session creation.
|
|
1571
2543
|
*
|
|
1572
2544
|
* @param applicationId - Your Reclaim application ID
|
|
1573
2545
|
* @param appSecret - Your application secret key for signing requests
|
|
1574
2546
|
* @param providerId - The ID of the provider to use for proof generation
|
|
1575
2547
|
* @param options - Optional configuration options for the proof request
|
|
1576
|
-
* @returns
|
|
2548
|
+
* @returns A fully initialized proof request instance
|
|
1577
2549
|
* @throws {InitError} When initialization fails due to invalid parameters or session creation errors
|
|
1578
2550
|
*
|
|
1579
2551
|
* @example
|
|
@@ -1582,7 +2554,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
1582
2554
|
* 'your-app-id',
|
|
1583
2555
|
* 'your-app-secret',
|
|
1584
2556
|
* 'provider-id',
|
|
1585
|
-
* {
|
|
2557
|
+
* { portalUrl: 'https://portal.reclaimprotocol.org', log: true }
|
|
1586
2558
|
* );
|
|
1587
2559
|
* ```
|
|
1588
2560
|
*/
|
|
@@ -1635,6 +2607,11 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
1635
2607
|
{ paramName: "envUrl", input: options.envUrl, isString: true }
|
|
1636
2608
|
], "the constructor");
|
|
1637
2609
|
}
|
|
2610
|
+
if (options.portalUrl) {
|
|
2611
|
+
validateFunctionParams([
|
|
2612
|
+
{ paramName: "portalUrl", input: options.portalUrl, isString: true }
|
|
2613
|
+
], "the constructor");
|
|
2614
|
+
}
|
|
1638
2615
|
if (options.customSharePageUrl) {
|
|
1639
2616
|
validateFunctionParams([
|
|
1640
2617
|
{ paramName: "customSharePageUrl", input: options.customSharePageUrl, isString: true }
|
|
@@ -1657,7 +2634,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
1657
2634
|
Intl.getCanonicalLocales(options.preferredLocale);
|
|
1658
2635
|
return true;
|
|
1659
2636
|
} catch (error) {
|
|
1660
|
-
|
|
2637
|
+
logger10.info("Failed to canonicalize locale", error);
|
|
1661
2638
|
return false;
|
|
1662
2639
|
}
|
|
1663
2640
|
}
|
|
@@ -1671,10 +2648,21 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
1671
2648
|
proofRequestInstance.sessionId = data.sessionId;
|
|
1672
2649
|
proofRequestInstance.resolvedProviderVersion = data.resolvedProviderVersion;
|
|
1673
2650
|
proofRequestInstance.context.reclaimSessionId = data.sessionId;
|
|
2651
|
+
if (options == null ? void 0 : options.acceptTeeAttestation) {
|
|
2652
|
+
const wallet = new import_ethers5.ethers.Wallet(appSecret);
|
|
2653
|
+
const nonceData = `${applicationId}:${data.sessionId}:${proofRequestInstance.timeStamp}`;
|
|
2654
|
+
const nonceMsg = import_ethers5.ethers.getBytes(import_ethers5.ethers.keccak256(new TextEncoder().encode(nonceData)));
|
|
2655
|
+
const nonceSignature = yield wallet.signMessage(nonceMsg);
|
|
2656
|
+
proofRequestInstance.setAttestationContext(nonceSignature, {
|
|
2657
|
+
applicationId,
|
|
2658
|
+
sessionId: data.sessionId,
|
|
2659
|
+
timestamp: proofRequestInstance.timeStamp
|
|
2660
|
+
});
|
|
2661
|
+
}
|
|
1674
2662
|
return proofRequestInstance;
|
|
1675
2663
|
} catch (error) {
|
|
1676
2664
|
console.error(error);
|
|
1677
|
-
|
|
2665
|
+
logger10.info("Failed to initialize ReclaimProofRequest", error);
|
|
1678
2666
|
throw new InitError("Failed to initialize ReclaimProofRequest", error);
|
|
1679
2667
|
}
|
|
1680
2668
|
});
|
|
@@ -1791,7 +2779,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
1791
2779
|
Intl.getCanonicalLocales(options.preferredLocale);
|
|
1792
2780
|
return true;
|
|
1793
2781
|
} catch (error) {
|
|
1794
|
-
|
|
2782
|
+
logger10.info("Failed to canonicalize locale", error);
|
|
1795
2783
|
return false;
|
|
1796
2784
|
}
|
|
1797
2785
|
}
|
|
@@ -1800,6 +2788,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
1800
2788
|
const proofRequestInstance = new _ReclaimProofRequest(applicationId, providerId, options);
|
|
1801
2789
|
proofRequestInstance.sessionId = sessionId;
|
|
1802
2790
|
proofRequestInstance.context = context;
|
|
2791
|
+
proofRequestInstance.setAttestationContext(context == null ? void 0 : context.attestationNonce, context == null ? void 0 : context.attestationNonceData);
|
|
1803
2792
|
proofRequestInstance.parameters = parameters;
|
|
1804
2793
|
proofRequestInstance.appCallbackUrl = appCallbackUrl;
|
|
1805
2794
|
proofRequestInstance.redirectUrl = redirectUrl;
|
|
@@ -1815,7 +2804,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
1815
2804
|
proofRequestInstance.cancelRedirectUrlOptions = cancelRedirectUrlOptions;
|
|
1816
2805
|
return proofRequestInstance;
|
|
1817
2806
|
} catch (error) {
|
|
1818
|
-
|
|
2807
|
+
logger10.info("Failed to parse JSON string in fromJsonString:", error);
|
|
1819
2808
|
throw new InvalidParamError("Invalid JSON string provided to fromJsonString");
|
|
1820
2809
|
}
|
|
1821
2810
|
});
|
|
@@ -1856,11 +2845,11 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
1856
2845
|
*
|
|
1857
2846
|
* @param url - The URL where users should be redirected after successful proof generation
|
|
1858
2847
|
* @param method - The redirection method that should be used for redirection. Allowed options: `GET`, and `POST`.
|
|
1859
|
-
* `POST` form redirection is only supported in
|
|
2848
|
+
* `POST` form redirection is only supported in Portal flow.
|
|
1860
2849
|
* @param body - List of name-value pairs to be sent as the body of the form request.
|
|
1861
2850
|
* `When `method` is set to `POST`, `body` will be sent with 'application/x-www-form-urlencoded' content type.
|
|
1862
2851
|
* When `method` is set to `GET`, if `body` is set then `body` will be sent as query parameters.
|
|
1863
|
-
* Sending `body` on redirection is only supported in
|
|
2852
|
+
* Sending `body` on redirection is only supported in Portal flow.
|
|
1864
2853
|
*
|
|
1865
2854
|
* @throws {InvalidParamError} When URL is invalid
|
|
1866
2855
|
*
|
|
@@ -1922,11 +2911,11 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
1922
2911
|
*
|
|
1923
2912
|
* @param url - The URL where users should be redirected after an error which aborts the verification process
|
|
1924
2913
|
* @param method - The redirection method that should be used for redirection. Allowed options: `GET`, and `POST`.
|
|
1925
|
-
* `POST` form redirection is only supported in
|
|
2914
|
+
* `POST` form redirection is only supported in Portal flow.
|
|
1926
2915
|
* @param body - List of name-value pairs to be sent as the body of the form request.
|
|
1927
2916
|
* When `method` is set to `POST`, `body` will be sent with 'application/x-www-form-urlencoded' content type.
|
|
1928
2917
|
* When `method` is set to `GET`, if `body` is set then `body` will be sent as query parameters.
|
|
1929
|
-
* Sending `body` on redirection is only supported in
|
|
2918
|
+
* Sending `body` on redirection is only supported in Portal flow.
|
|
1930
2919
|
* @throws {InvalidParamError} When URL is invalid
|
|
1931
2920
|
*
|
|
1932
2921
|
* @example
|
|
@@ -1976,9 +2965,9 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
1976
2965
|
try {
|
|
1977
2966
|
validateModalOptions(options, "setModalOptions");
|
|
1978
2967
|
this.modalOptions = __spreadValues(__spreadValues({}, this.modalOptions), options);
|
|
1979
|
-
|
|
2968
|
+
logger10.info("Modal options set successfully");
|
|
1980
2969
|
} catch (error) {
|
|
1981
|
-
|
|
2970
|
+
logger10.info("Error setting modal options:", error);
|
|
1982
2971
|
throw new SetParamsError("Error setting modal options", error);
|
|
1983
2972
|
}
|
|
1984
2973
|
}
|
|
@@ -2006,8 +2995,9 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2006
2995
|
{ input: context, paramName: "context", isString: false }
|
|
2007
2996
|
], "setJsonContext");
|
|
2008
2997
|
this.context = JSON.parse(canonicalStringify(__spreadProps(__spreadValues({}, context), { reclaimSessionId: this.sessionId })));
|
|
2998
|
+
this.applyAttestationContext();
|
|
2009
2999
|
} catch (error) {
|
|
2010
|
-
|
|
3000
|
+
logger10.info("Error setting context", error);
|
|
2011
3001
|
throw new SetContextError("Error setting context", error);
|
|
2012
3002
|
}
|
|
2013
3003
|
}
|
|
@@ -2037,8 +3027,9 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2037
3027
|
{ input: message, paramName: "message", isString: true }
|
|
2038
3028
|
], "setContext");
|
|
2039
3029
|
this.context = { contextAddress: address, contextMessage: message, reclaimSessionId: this.sessionId };
|
|
3030
|
+
this.applyAttestationContext();
|
|
2040
3031
|
} catch (error) {
|
|
2041
|
-
|
|
3032
|
+
logger10.info("Error setting context", error);
|
|
2042
3033
|
throw new SetContextError("Error setting context", error);
|
|
2043
3034
|
}
|
|
2044
3035
|
}
|
|
@@ -2073,7 +3064,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2073
3064
|
validateParameters(params);
|
|
2074
3065
|
this.parameters = __spreadValues(__spreadValues({}, this.parameters), params);
|
|
2075
3066
|
} catch (error) {
|
|
2076
|
-
|
|
3067
|
+
logger10.info("Error Setting Params:", error);
|
|
2077
3068
|
throw new SetParamsError("Error setting params", error);
|
|
2078
3069
|
}
|
|
2079
3070
|
}
|
|
@@ -2097,7 +3088,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2097
3088
|
validateFunctionParams([{ input: this.sessionId, paramName: "sessionId", isString: true }], "getAppCallbackUrl");
|
|
2098
3089
|
return this.appCallbackUrl || `${constants.DEFAULT_RECLAIM_CALLBACK_URL}${this.sessionId}`;
|
|
2099
3090
|
} catch (error) {
|
|
2100
|
-
|
|
3091
|
+
logger10.info("Error getting app callback url", error);
|
|
2101
3092
|
throw new GetAppCallbackUrlError("Error getting app callback url", error);
|
|
2102
3093
|
}
|
|
2103
3094
|
}
|
|
@@ -2121,7 +3112,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2121
3112
|
validateFunctionParams([{ input: this.sessionId, paramName: "sessionId", isString: true }], "getCancelCallbackUrl");
|
|
2122
3113
|
return this.cancelCallbackUrl || `${constants.DEFAULT_RECLAIM_CANCEL_CALLBACK_URL}${this.sessionId}`;
|
|
2123
3114
|
} catch (error) {
|
|
2124
|
-
|
|
3115
|
+
logger10.info("Error getting cancel callback url", error);
|
|
2125
3116
|
throw new GetAppCallbackUrlError("Error getting cancel callback url", error);
|
|
2126
3117
|
}
|
|
2127
3118
|
}
|
|
@@ -2144,7 +3135,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2144
3135
|
validateFunctionParams([{ input: this.sessionId, paramName: "sessionId", isString: true }], "getStatusUrl");
|
|
2145
3136
|
return `${constants.DEFAULT_RECLAIM_STATUS_URL}${this.sessionId}`;
|
|
2146
3137
|
} catch (error) {
|
|
2147
|
-
|
|
3138
|
+
logger10.info("Error fetching Status Url", error);
|
|
2148
3139
|
throw new GetStatusUrlError("Error fetching status url", error);
|
|
2149
3140
|
}
|
|
2150
3141
|
}
|
|
@@ -2174,25 +3165,25 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2174
3165
|
try {
|
|
2175
3166
|
validateFunctionParams([{ input: signature, paramName: "signature", isString: true }], "setSignature");
|
|
2176
3167
|
this.signature = signature;
|
|
2177
|
-
|
|
3168
|
+
logger10.info(`Signature set successfully for applicationId: ${this.applicationId}`);
|
|
2178
3169
|
} catch (error) {
|
|
2179
|
-
|
|
3170
|
+
logger10.info("Error setting signature", error);
|
|
2180
3171
|
throw new SetSignatureError("Error setting signature", error);
|
|
2181
3172
|
}
|
|
2182
3173
|
}
|
|
2183
3174
|
generateSignature(applicationSecret) {
|
|
2184
3175
|
return __async(this, null, function* () {
|
|
2185
3176
|
try {
|
|
2186
|
-
const wallet = new
|
|
3177
|
+
const wallet = new import_ethers5.ethers.Wallet(applicationSecret);
|
|
2187
3178
|
const canonicalData = (0, import_canonicalize3.default)({ providerId: this.providerId, timestamp: this.timeStamp });
|
|
2188
3179
|
if (!canonicalData) {
|
|
2189
3180
|
throw new SignatureGeneratingError("Failed to canonicalize data for signing.");
|
|
2190
3181
|
}
|
|
2191
|
-
const messageHash =
|
|
2192
|
-
return yield wallet.signMessage(
|
|
3182
|
+
const messageHash = import_ethers5.ethers.keccak256(new TextEncoder().encode(canonicalData));
|
|
3183
|
+
return yield wallet.signMessage(import_ethers5.ethers.getBytes(messageHash));
|
|
2193
3184
|
} catch (err) {
|
|
2194
|
-
|
|
2195
|
-
throw new SignatureGeneratingError(`Error generating signature for
|
|
3185
|
+
logger10.info(`Error generating proof request for applicationId: ${this.applicationId}, providerId: ${this.providerId}, timeStamp: ${this.timeStamp}`);
|
|
3186
|
+
throw new SignatureGeneratingError(`Error generating signature for applicationId: ${this.applicationId}`);
|
|
2196
3187
|
}
|
|
2197
3188
|
});
|
|
2198
3189
|
}
|
|
@@ -2202,12 +3193,97 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2202
3193
|
this.intervals.delete(this.sessionId);
|
|
2203
3194
|
}
|
|
2204
3195
|
}
|
|
3196
|
+
setAttestationContext(nonce, data) {
|
|
3197
|
+
if (!nonce || !data) {
|
|
3198
|
+
return;
|
|
3199
|
+
}
|
|
3200
|
+
this.attestationNonce = nonce;
|
|
3201
|
+
this.attestationNonceData = data;
|
|
3202
|
+
this.applyAttestationContext();
|
|
3203
|
+
}
|
|
3204
|
+
applyAttestationContext() {
|
|
3205
|
+
if (!this.attestationNonce || !this.attestationNonceData) {
|
|
3206
|
+
return;
|
|
3207
|
+
}
|
|
3208
|
+
this.context = __spreadProps(__spreadValues({}, this.context), {
|
|
3209
|
+
attestationNonce: this.attestationNonce,
|
|
3210
|
+
attestationNonceData: this.attestationNonceData
|
|
3211
|
+
});
|
|
3212
|
+
}
|
|
3213
|
+
encodeTemplateData(templateData) {
|
|
3214
|
+
let template = encodeURIComponent(JSON.stringify(templateData));
|
|
3215
|
+
template = replaceAll(template, "(", "%28");
|
|
3216
|
+
template = replaceAll(template, ")", "%29");
|
|
3217
|
+
return template;
|
|
3218
|
+
}
|
|
2205
3219
|
buildSharePageUrl(template) {
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
3220
|
+
return `${this.appSharePageUrl}/?template=${template}`;
|
|
3221
|
+
}
|
|
3222
|
+
openPortalTab(templateData, preOpenedTab) {
|
|
3223
|
+
return __async(this, null, function* () {
|
|
3224
|
+
const newTab = preOpenedTab != null ? preOpenedTab : window.open("about:blank", "_blank");
|
|
3225
|
+
const link = yield createLinkWithTemplateData(templateData, this.customSharePageUrl);
|
|
3226
|
+
logger10.info("Opening portal in new tab: " + link);
|
|
3227
|
+
if (newTab) {
|
|
3228
|
+
this.portalTab = newTab;
|
|
3229
|
+
newTab.location = link;
|
|
3230
|
+
setTimeout(() => {
|
|
3231
|
+
try {
|
|
3232
|
+
if (newTab.location.href === "about:blank") {
|
|
3233
|
+
newTab.close();
|
|
3234
|
+
this.portalTab = void 0;
|
|
3235
|
+
window.open(link, "_blank");
|
|
3236
|
+
}
|
|
3237
|
+
} catch (_) {
|
|
3238
|
+
}
|
|
3239
|
+
}, 500);
|
|
3240
|
+
}
|
|
3241
|
+
});
|
|
3242
|
+
}
|
|
3243
|
+
closePortalTab() {
|
|
3244
|
+
var _a;
|
|
3245
|
+
try {
|
|
3246
|
+
(_a = this.portalTab) == null ? void 0 : _a.close();
|
|
3247
|
+
} catch (_) {
|
|
2209
3248
|
}
|
|
2210
|
-
|
|
3249
|
+
this.portalTab = void 0;
|
|
3250
|
+
}
|
|
3251
|
+
embedPortalIframe(templateData, target) {
|
|
3252
|
+
return __async(this, null, function* () {
|
|
3253
|
+
let link = yield createLinkWithTemplateData(templateData, this.customSharePageUrl);
|
|
3254
|
+
const separator = link.includes("?") ? "&" : "?";
|
|
3255
|
+
link = `${link}${separator}embedded=true`;
|
|
3256
|
+
logger10.info("Embedding portal in iframe: " + link);
|
|
3257
|
+
this.closeEmbeddedFlow();
|
|
3258
|
+
const iframe = document.createElement("iframe");
|
|
3259
|
+
iframe.src = link;
|
|
3260
|
+
iframe.style.width = "100%";
|
|
3261
|
+
iframe.style.height = "100%";
|
|
3262
|
+
iframe.style.border = "none";
|
|
3263
|
+
iframe.setAttribute("allow", "clipboard-write");
|
|
3264
|
+
iframe.setAttribute("sandbox", "allow-scripts allow-same-origin allow-forms");
|
|
3265
|
+
target.appendChild(iframe);
|
|
3266
|
+
this.portalIframe = iframe;
|
|
3267
|
+
});
|
|
3268
|
+
}
|
|
3269
|
+
/**
|
|
3270
|
+
* Closes the embedded portal iframe and stops the session polling.
|
|
3271
|
+
*
|
|
3272
|
+
* Call this to programmatically cancel the embedded verification flow
|
|
3273
|
+
* that was started with `triggerReclaimFlow({ target: element })`.
|
|
3274
|
+
* Also called automatically when verification succeeds or fails.
|
|
3275
|
+
*
|
|
3276
|
+
* @example
|
|
3277
|
+
* ```typescript
|
|
3278
|
+
* proofRequest.closeEmbeddedFlow();
|
|
3279
|
+
* ```
|
|
3280
|
+
*/
|
|
3281
|
+
closeEmbeddedFlow() {
|
|
3282
|
+
if (this.portalIframe) {
|
|
3283
|
+
this.portalIframe.remove();
|
|
3284
|
+
this.portalIframe = void 0;
|
|
3285
|
+
}
|
|
3286
|
+
this.clearInterval();
|
|
2211
3287
|
}
|
|
2212
3288
|
/**
|
|
2213
3289
|
* Exports the Reclaim proof verification request as a JSON string
|
|
@@ -2261,13 +3337,15 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2261
3337
|
});
|
|
2262
3338
|
}
|
|
2263
3339
|
/**
|
|
2264
|
-
* Generates and returns the request URL for proof verification
|
|
3340
|
+
* Generates and returns the request URL for proof verification.
|
|
3341
|
+
*
|
|
3342
|
+
* Defaults to portal mode. Pass `{ verificationMode: 'app' }` for native app flow URLs.
|
|
2265
3343
|
*
|
|
2266
|
-
*
|
|
2267
|
-
*
|
|
2268
|
-
* -
|
|
2269
|
-
*
|
|
2270
|
-
*
|
|
3344
|
+
* - Portal mode (default): returns portal URL on all platforms
|
|
3345
|
+
* - App mode: returns share page URL on all platforms
|
|
3346
|
+
* - App mode + `useAppClip: true` on iOS: returns App Clip URL instead
|
|
3347
|
+
*
|
|
3348
|
+
* Falls back to `launchOptions` set at init time if not passed at call time.
|
|
2271
3349
|
*
|
|
2272
3350
|
* @param launchOptions - Optional launch configuration to override default behavior
|
|
2273
3351
|
* @returns Promise<string> - The generated request URL
|
|
@@ -2275,105 +3353,155 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2275
3353
|
*
|
|
2276
3354
|
* @example
|
|
2277
3355
|
* ```typescript
|
|
2278
|
-
*
|
|
2279
|
-
*
|
|
3356
|
+
* // Portal URL (default)
|
|
3357
|
+
* const url = await proofRequest.getRequestUrl();
|
|
3358
|
+
*
|
|
3359
|
+
* // Verifier app flow URL
|
|
3360
|
+
* const url = await proofRequest.getRequestUrl({ verificationMode: 'app' });
|
|
2280
3361
|
* ```
|
|
2281
3362
|
*/
|
|
2282
3363
|
getRequestUrl(launchOptions) {
|
|
2283
3364
|
return __async(this, null, function* () {
|
|
2284
3365
|
var _a, _b, _c;
|
|
2285
3366
|
const options = launchOptions || ((_a = this.options) == null ? void 0 : _a.launchOptions) || {};
|
|
2286
|
-
|
|
3367
|
+
const mode = (_b = options.verificationMode) != null ? _b : "portal";
|
|
3368
|
+
logger10.info("Creating Request Url");
|
|
2287
3369
|
if (!this.signature) {
|
|
2288
3370
|
throw new SignatureNotFoundError("Signature is not set.");
|
|
2289
3371
|
}
|
|
2290
3372
|
try {
|
|
2291
3373
|
const templateData = this.getTemplateData();
|
|
2292
3374
|
yield updateSession(this.sessionId, "SESSION_STARTED" /* SESSION_STARTED */);
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
template = replaceAll(template, "(", "%28");
|
|
2297
|
-
template = replaceAll(template, ")", "%29");
|
|
2298
|
-
const isIos = getMobileDeviceType() === "ios" /* IOS */;
|
|
2299
|
-
if (!isIos) {
|
|
2300
|
-
let instantAppUrl = this.buildSharePageUrl(template);
|
|
2301
|
-
const isDeferredDeeplinksFlowEnabled = (_c = options.canUseDeferredDeepLinksFlow) != null ? _c : false;
|
|
2302
|
-
if (isDeferredDeeplinksFlowEnabled) {
|
|
2303
|
-
instantAppUrl = instantAppUrl.replace("/verifier", "/link");
|
|
2304
|
-
}
|
|
2305
|
-
logger8.info("Instant App Url created successfully: " + instantAppUrl);
|
|
2306
|
-
return instantAppUrl;
|
|
2307
|
-
} else {
|
|
3375
|
+
if (mode === "app") {
|
|
3376
|
+
const template = this.encodeTemplateData(templateData);
|
|
3377
|
+
if (((_c = this.options) == null ? void 0 : _c.useAppClip) && getDeviceType() === "mobile" /* MOBILE */ && getMobileDeviceType() === "ios" /* IOS */) {
|
|
2308
3378
|
const appClipUrl = this.customAppClipUrl ? `${this.customAppClipUrl}&template=${template}` : `https://appclip.apple.com/id?p=org.reclaimprotocol.app.clip&template=${template}`;
|
|
2309
|
-
|
|
3379
|
+
logger10.info("App Clip Url created successfully: " + appClipUrl);
|
|
2310
3380
|
return appClipUrl;
|
|
2311
3381
|
}
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
return link;
|
|
3382
|
+
const sharePageUrl = yield createLinkWithTemplateData(templateData, this.appSharePageUrl);
|
|
3383
|
+
logger10.info("Share page Url created successfully: " + sharePageUrl);
|
|
3384
|
+
return sharePageUrl;
|
|
2316
3385
|
}
|
|
3386
|
+
const link = yield createLinkWithTemplateData(templateData, this.customSharePageUrl);
|
|
3387
|
+
logger10.info("Request Url created successfully: " + link);
|
|
3388
|
+
return link;
|
|
2317
3389
|
} catch (error) {
|
|
2318
|
-
|
|
3390
|
+
logger10.info("Error creating Request Url:", error);
|
|
2319
3391
|
throw error;
|
|
2320
3392
|
}
|
|
2321
3393
|
});
|
|
2322
3394
|
}
|
|
2323
3395
|
/**
|
|
2324
|
-
* Triggers the appropriate Reclaim verification flow based on device type and configuration
|
|
3396
|
+
* Triggers the appropriate Reclaim verification flow based on device type and configuration.
|
|
2325
3397
|
*
|
|
2326
|
-
*
|
|
2327
|
-
*
|
|
2328
|
-
*
|
|
2329
|
-
* -
|
|
2330
|
-
* -
|
|
3398
|
+
* Defaults to portal mode (remote browser verification). Pass `{ verificationMode: 'app' }`
|
|
3399
|
+
* for verifier app flow via the share page.
|
|
3400
|
+
*
|
|
3401
|
+
* - **Embedded iframe**: Pass `{ target: element }` to embed the portal inside a DOM element instead of a new tab
|
|
3402
|
+
* - Desktop: browser extension takes priority in both modes
|
|
3403
|
+
* - Desktop portal mode (no extension): opens portal in new tab
|
|
3404
|
+
* - Desktop app mode (no extension): shows QR code modal with share page URL
|
|
3405
|
+
* - Mobile portal mode: opens portal in new tab
|
|
3406
|
+
* - Mobile app mode: opens share page (or App Clip on iOS if `useAppClip` is `true`)
|
|
2331
3407
|
*
|
|
2332
3408
|
* @param launchOptions - Optional launch configuration to override default behavior
|
|
2333
|
-
* @returns Promise<
|
|
3409
|
+
* @returns Promise<FlowHandle> - Handle to control the flow (close, access iframe)
|
|
2334
3410
|
* @throws {SignatureNotFoundError} When signature is not set
|
|
2335
3411
|
*
|
|
2336
3412
|
* @example
|
|
2337
3413
|
* ```typescript
|
|
2338
|
-
*
|
|
2339
|
-
*
|
|
3414
|
+
* // Portal flow (default) — opens in new tab
|
|
3415
|
+
* const handle = await proofRequest.triggerReclaimFlow();
|
|
3416
|
+
* handle.tab; // Window reference to the opened tab
|
|
3417
|
+
* handle.close(); // close tab and stop polling
|
|
3418
|
+
*
|
|
3419
|
+
* // Embed portal in an iframe inside a DOM element
|
|
3420
|
+
* const handle = await proofRequest.triggerReclaimFlow({ target: document.getElementById('reclaim-container') });
|
|
3421
|
+
* handle.iframe; // HTMLIFrameElement reference
|
|
3422
|
+
* handle.close(); // remove iframe and stop polling
|
|
3423
|
+
*
|
|
3424
|
+
* // Verifier app flow
|
|
3425
|
+
* await proofRequest.triggerReclaimFlow({ verificationMode: 'app' });
|
|
3426
|
+
*
|
|
3427
|
+
* // App Clip on iOS (requires useAppClip: true at init)
|
|
3428
|
+
* const request = await ReclaimProofRequest.init(APP_ID, SECRET, PROVIDER, { useAppClip: true });
|
|
3429
|
+
* await request.triggerReclaimFlow({ verificationMode: 'app' });
|
|
3430
|
+
*
|
|
3431
|
+
* // Can also set verificationMode at init time via launchOptions
|
|
3432
|
+
* const request = await ReclaimProofRequest.init(APP_ID, SECRET, PROVIDER, {
|
|
3433
|
+
* launchOptions: { verificationMode: 'app' }
|
|
3434
|
+
* });
|
|
3435
|
+
* await request.triggerReclaimFlow(); // uses 'app' mode from init
|
|
2340
3436
|
* ```
|
|
2341
3437
|
*/
|
|
2342
3438
|
triggerReclaimFlow(launchOptions) {
|
|
2343
3439
|
return __async(this, null, function* () {
|
|
2344
|
-
var _a, _b;
|
|
3440
|
+
var _a, _b, _c, _d, _e;
|
|
2345
3441
|
const options = launchOptions || ((_a = this.options) == null ? void 0 : _a.launchOptions) || {};
|
|
3442
|
+
const mode = (_b = options.verificationMode) != null ? _b : "portal";
|
|
2346
3443
|
if (!this.signature) {
|
|
2347
3444
|
throw new SignatureNotFoundError("Signature is not set.");
|
|
2348
3445
|
}
|
|
2349
3446
|
try {
|
|
2350
3447
|
const templateData = this.getTemplateData();
|
|
2351
3448
|
this.templateData = templateData;
|
|
2352
|
-
|
|
3449
|
+
logger10.info(`Triggering Reclaim flow (mode: ${mode})`);
|
|
2353
3450
|
const deviceType = getDeviceType();
|
|
2354
3451
|
updateSession(this.sessionId, "SESSION_STARTED" /* SESSION_STARTED */);
|
|
3452
|
+
if ("target" in options && !options.target) {
|
|
3453
|
+
logger10.warn("triggerReclaimFlow: target was provided but is null/undefined \u2014 falling back to default flow. Ensure the element exists in the DOM.");
|
|
3454
|
+
}
|
|
3455
|
+
if (options.target && mode === "portal") {
|
|
3456
|
+
yield this.embedPortalIframe(templateData, options.target);
|
|
3457
|
+
return {
|
|
3458
|
+
close: () => this.closeEmbeddedFlow(),
|
|
3459
|
+
iframe: this.portalIframe
|
|
3460
|
+
};
|
|
3461
|
+
}
|
|
2355
3462
|
if (deviceType === "desktop" /* DESKTOP */) {
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
3463
|
+
if ((_c = this.options) == null ? void 0 : _c.useBrowserExtension) {
|
|
3464
|
+
const extensionAvailable = yield this.isBrowserExtensionAvailable();
|
|
3465
|
+
if (extensionAvailable) {
|
|
3466
|
+
logger10.info("Triggering browser extension flow");
|
|
3467
|
+
this.triggerBrowserExtensionFlow();
|
|
3468
|
+
return {
|
|
3469
|
+
close: () => {
|
|
3470
|
+
this.clearInterval();
|
|
3471
|
+
}
|
|
3472
|
+
};
|
|
3473
|
+
}
|
|
3474
|
+
}
|
|
3475
|
+
if (mode === "portal") {
|
|
3476
|
+
yield this.openPortalTab(templateData);
|
|
2361
3477
|
} else {
|
|
2362
|
-
|
|
3478
|
+
logger10.info("Showing QR code modal with share page URL");
|
|
2363
3479
|
yield this.showQRCodeModal();
|
|
2364
3480
|
}
|
|
2365
3481
|
} else if (deviceType === "mobile" /* MOBILE */) {
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
3482
|
+
if (mode === "app") {
|
|
3483
|
+
if (((_d = this.options) == null ? void 0 : _d.useAppClip) && getMobileDeviceType() === "ios" /* IOS */) {
|
|
3484
|
+
logger10.info("Redirecting to iOS app clip");
|
|
3485
|
+
this.redirectToAppClip();
|
|
3486
|
+
} else {
|
|
3487
|
+
logger10.info("Redirecting to share page");
|
|
3488
|
+
yield this.redirectToInstantApp(options);
|
|
3489
|
+
}
|
|
3490
|
+
} else {
|
|
3491
|
+
yield this.openPortalTab(templateData);
|
|
2373
3492
|
}
|
|
2374
3493
|
}
|
|
3494
|
+
return {
|
|
3495
|
+
close: () => {
|
|
3496
|
+
var _a2;
|
|
3497
|
+
this.closePortalTab();
|
|
3498
|
+
this.closeEmbeddedFlow();
|
|
3499
|
+
(_a2 = this.modal) == null ? void 0 : _a2.close();
|
|
3500
|
+
},
|
|
3501
|
+
tab: (_e = this.portalTab) != null ? _e : void 0
|
|
3502
|
+
};
|
|
2375
3503
|
} catch (error) {
|
|
2376
|
-
|
|
3504
|
+
logger10.info("Error triggering Reclaim flow:", error);
|
|
2377
3505
|
throw error;
|
|
2378
3506
|
}
|
|
2379
3507
|
});
|
|
@@ -2421,7 +3549,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2421
3549
|
window.postMessage(message, "*");
|
|
2422
3550
|
});
|
|
2423
3551
|
} catch (error) {
|
|
2424
|
-
|
|
3552
|
+
logger10.info("Error checking Reclaim extension installed:", error);
|
|
2425
3553
|
return false;
|
|
2426
3554
|
}
|
|
2427
3555
|
});
|
|
@@ -2434,16 +3562,16 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2434
3562
|
extensionID: this.extensionID
|
|
2435
3563
|
};
|
|
2436
3564
|
window.postMessage(message, "*");
|
|
2437
|
-
|
|
3565
|
+
logger10.info("Browser extension flow triggered");
|
|
2438
3566
|
}
|
|
2439
3567
|
showQRCodeModal() {
|
|
2440
3568
|
return __async(this, null, function* () {
|
|
2441
3569
|
try {
|
|
2442
|
-
const requestUrl = yield createLinkWithTemplateData(this.templateData, this.
|
|
3570
|
+
const requestUrl = yield createLinkWithTemplateData(this.templateData, this.appSharePageUrl);
|
|
2443
3571
|
this.modal = new QRCodeModal(this.modalOptions);
|
|
2444
3572
|
yield this.modal.show(requestUrl);
|
|
2445
3573
|
} catch (error) {
|
|
2446
|
-
|
|
3574
|
+
logger10.info("Error showing QR code modal:", error);
|
|
2447
3575
|
throw error;
|
|
2448
3576
|
}
|
|
2449
3577
|
});
|
|
@@ -2452,11 +3580,9 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2452
3580
|
return __async(this, null, function* () {
|
|
2453
3581
|
var _a;
|
|
2454
3582
|
try {
|
|
2455
|
-
|
|
2456
|
-
template = replaceAll(template, "(", "%28");
|
|
2457
|
-
template = replaceAll(template, ")", "%29");
|
|
3583
|
+
const template = this.encodeTemplateData(this.templateData);
|
|
2458
3584
|
let instantAppUrl = this.buildSharePageUrl(template);
|
|
2459
|
-
|
|
3585
|
+
logger10.info("Redirecting to Android instant app: " + instantAppUrl);
|
|
2460
3586
|
const isDeferredDeeplinksFlowEnabled = (_a = options.canUseDeferredDeepLinksFlow) != null ? _a : false;
|
|
2461
3587
|
if (isDeferredDeeplinksFlowEnabled) {
|
|
2462
3588
|
instantAppUrl = instantAppUrl.replace("/verifier", "/link");
|
|
@@ -2506,40 +3632,58 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2506
3632
|
}
|
|
2507
3633
|
window.location.href = instantAppUrl;
|
|
2508
3634
|
} catch (error) {
|
|
2509
|
-
|
|
3635
|
+
logger10.info("Error redirecting to instant app:", error);
|
|
2510
3636
|
throw error;
|
|
2511
3637
|
}
|
|
2512
3638
|
});
|
|
2513
3639
|
}
|
|
2514
3640
|
redirectToAppClip() {
|
|
2515
3641
|
try {
|
|
2516
|
-
|
|
2517
|
-
template = replaceAll(template, "(", "%28");
|
|
2518
|
-
template = replaceAll(template, ")", "%29");
|
|
3642
|
+
const template = this.encodeTemplateData(this.templateData);
|
|
2519
3643
|
const appClipUrl = this.customAppClipUrl ? `${this.customAppClipUrl}&template=${template}` : `https://appclip.apple.com/id?p=org.reclaimprotocol.app.clip&template=${template}`;
|
|
2520
|
-
|
|
2521
|
-
const verifierUrl =
|
|
3644
|
+
logger10.info("Redirecting to iOS app clip: " + appClipUrl);
|
|
3645
|
+
const verifierUrl = `${this.appSharePageUrl}/?template=${template}`;
|
|
2522
3646
|
window.location.href = appClipUrl;
|
|
2523
3647
|
setTimeout(() => {
|
|
2524
3648
|
window.location.href = verifierUrl;
|
|
2525
3649
|
}, 5 * 1e3);
|
|
2526
3650
|
} catch (error) {
|
|
2527
|
-
|
|
3651
|
+
logger10.info("Error redirecting to app clip:", error);
|
|
2528
3652
|
throw error;
|
|
2529
3653
|
}
|
|
2530
3654
|
}
|
|
3655
|
+
/**
|
|
3656
|
+
* Returns the provider id and exact version of the provider that was used in the verification session of this request.
|
|
3657
|
+
*
|
|
3658
|
+
* This can be provided as a config parameter to the `verifyProof` function to verify the proof.
|
|
3659
|
+
*
|
|
3660
|
+
* See also:
|
|
3661
|
+
* * `verifyProof()` - Verifies a proof against the expected provider configuration.
|
|
3662
|
+
* * `getProviderHashRequirements()` - An alternative of this function to get the expected hashes for a provider version by providing providerId and exactProviderVersionString. The result can be provided in verifyProof function's `config` parameter for proof validation.
|
|
3663
|
+
* * `getProviderHashRequirementsFromSpec()` - An alternative of this function to get the expected hashes from a provider spec. The result can be provided in verifyProof function's `config` parameter for proof validation.
|
|
3664
|
+
*/
|
|
3665
|
+
getProviderVersion() {
|
|
3666
|
+
var _a, _b;
|
|
3667
|
+
const exactProviderVersionString = (_a = this.resolvedProviderVersion) != null ? _a : "";
|
|
3668
|
+
return {
|
|
3669
|
+
providerId: this.providerId,
|
|
3670
|
+
providerVersion: exactProviderVersionString,
|
|
3671
|
+
allowedTags: ((_b = this.options) == null ? void 0 : _b.acceptAiProviders) ? ["ai"] : []
|
|
3672
|
+
};
|
|
3673
|
+
}
|
|
2531
3674
|
/**
|
|
2532
3675
|
* Fetches the provider config that was used for this session and returns the hash requirements
|
|
2533
3676
|
*
|
|
2534
3677
|
* See also:
|
|
3678
|
+
* * `verifyProof()` - Verifies a proof against the expected provider configuration.
|
|
2535
3679
|
* * `fetchProviderHashRequirementsBy()` - An alternative of this function to get the expected hashes for a provider version by providing providerId and exactProviderVersionString. The result can be provided in verifyProof function's `config` parameter for proof validation.
|
|
2536
3680
|
* * `getProviderHashRequirementsFromSpec()` - An alternative of this function to get the expected hashes from a provider spec. The result can be provided in verifyProof function's `config` parameter for proof validation.
|
|
2537
3681
|
*
|
|
2538
|
-
* @returns A promise that resolves to a ProviderHashRequirementsConfig
|
|
3682
|
+
* @returns A promise that resolves to a `ProviderHashRequirementsConfig` or `ProviderHashRequirementsConfig[]`
|
|
2539
3683
|
*/
|
|
2540
|
-
getProviderHashRequirements() {
|
|
3684
|
+
getProviderHashRequirements(proofs, allowedTags) {
|
|
2541
3685
|
var _a;
|
|
2542
|
-
return fetchProviderHashRequirementsBy(this.providerId, (_a = this.resolvedProviderVersion) != null ? _a : "");
|
|
3686
|
+
return fetchProviderHashRequirementsBy(this.providerId, (_a = this.resolvedProviderVersion) != null ? _a : "", allowedTags, proofs);
|
|
2543
3687
|
}
|
|
2544
3688
|
/**
|
|
2545
3689
|
* Starts the proof request session and monitors for proof submission
|
|
@@ -2584,13 +3728,13 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2584
3728
|
return __async(this, arguments, function* ({ onSuccess, onError }) {
|
|
2585
3729
|
if (!this.sessionId) {
|
|
2586
3730
|
const message = "Session can't be started due to undefined value of sessionId";
|
|
2587
|
-
|
|
3731
|
+
logger10.info(message);
|
|
2588
3732
|
throw new SessionNotStartedError(message);
|
|
2589
3733
|
}
|
|
2590
|
-
|
|
3734
|
+
logger10.info("Starting session");
|
|
2591
3735
|
const sessionUpdatePollingInterval = 3 * 1e3;
|
|
2592
3736
|
const interval = setInterval(() => __async(this, null, function* () {
|
|
2593
|
-
var _a, _b, _c;
|
|
3737
|
+
var _a, _b, _c, _d, _e;
|
|
2594
3738
|
try {
|
|
2595
3739
|
const statusUrlResponse = yield fetchStatusUrl(this.sessionId);
|
|
2596
3740
|
if (!statusUrlResponse.session) return;
|
|
@@ -2602,7 +3746,8 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2602
3746
|
if (!this.lastFailureTime) {
|
|
2603
3747
|
this.lastFailureTime = currentTime;
|
|
2604
3748
|
} else if (currentTime - this.lastFailureTime >= this.FAILURE_TIMEOUT) {
|
|
2605
|
-
|
|
3749
|
+
const errorMessage = ((_a = statusUrlResponse.session.error) == null ? void 0 : _a.message) || "Proof generation failed - timeout reached";
|
|
3750
|
+
throw new ProviderFailedError(errorMessage);
|
|
2606
3751
|
}
|
|
2607
3752
|
return;
|
|
2608
3753
|
}
|
|
@@ -2614,9 +3759,9 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2614
3759
|
if (statusUrlResponse.session.proofs && statusUrlResponse.session.proofs.length > 0) {
|
|
2615
3760
|
const proofs = statusUrlResponse.session.proofs;
|
|
2616
3761
|
if (this.claimCreationType === "createClaim" /* STANDALONE */) {
|
|
2617
|
-
const verified = yield verifyProof(proofs,
|
|
3762
|
+
const { isVerified: verified } = yield verifyProof(proofs, this.getProviderVersion());
|
|
2618
3763
|
if (!verified) {
|
|
2619
|
-
|
|
3764
|
+
logger10.info(`Proofs not verified: count=${proofs == null ? void 0 : proofs.length}`);
|
|
2620
3765
|
throw new ProofNotVerifiedError();
|
|
2621
3766
|
}
|
|
2622
3767
|
}
|
|
@@ -2626,18 +3771,23 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2626
3771
|
onSuccess(proofs);
|
|
2627
3772
|
}
|
|
2628
3773
|
this.clearInterval();
|
|
2629
|
-
(
|
|
3774
|
+
(_b = this.modal) == null ? void 0 : _b.close();
|
|
3775
|
+
this.closePortalTab();
|
|
3776
|
+
this.closeEmbeddedFlow();
|
|
2630
3777
|
}
|
|
2631
3778
|
} else {
|
|
2632
3779
|
if (statusUrlResponse.session.statusV2 === "PROOF_SUBMISSION_FAILED" /* PROOF_SUBMISSION_FAILED */) {
|
|
2633
|
-
|
|
3780
|
+
const errorMessage = ((_c = statusUrlResponse.session.error) == null ? void 0 : _c.message) || "Proof submission failed";
|
|
3781
|
+
throw new ProofSubmissionFailedError(errorMessage);
|
|
2634
3782
|
}
|
|
2635
3783
|
if (statusUrlResponse.session.statusV2 === "PROOF_SUBMITTED" /* PROOF_SUBMITTED */ || statusUrlResponse.session.statusV2 === "AI_PROOF_SUBMITTED" /* AI_PROOF_SUBMITTED */) {
|
|
2636
3784
|
if (onSuccess) {
|
|
2637
3785
|
onSuccess([]);
|
|
2638
3786
|
}
|
|
2639
3787
|
this.clearInterval();
|
|
2640
|
-
(
|
|
3788
|
+
(_d = this.modal) == null ? void 0 : _d.close();
|
|
3789
|
+
this.closePortalTab();
|
|
3790
|
+
this.closeEmbeddedFlow();
|
|
2641
3791
|
}
|
|
2642
3792
|
}
|
|
2643
3793
|
} catch (e) {
|
|
@@ -2645,7 +3795,9 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2645
3795
|
onError(e);
|
|
2646
3796
|
}
|
|
2647
3797
|
this.clearInterval();
|
|
2648
|
-
(
|
|
3798
|
+
(_e = this.modal) == null ? void 0 : _e.close();
|
|
3799
|
+
this.closePortalTab();
|
|
3800
|
+
this.closeEmbeddedFlow();
|
|
2649
3801
|
}
|
|
2650
3802
|
}), sessionUpdatePollingInterval);
|
|
2651
3803
|
this.intervals.set(this.sessionId, interval);
|
|
@@ -2667,7 +3819,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2667
3819
|
closeModal() {
|
|
2668
3820
|
if (this.modal) {
|
|
2669
3821
|
this.modal.close();
|
|
2670
|
-
|
|
3822
|
+
logger10.info("Modal closed by user");
|
|
2671
3823
|
}
|
|
2672
3824
|
}
|
|
2673
3825
|
/**
|
|
@@ -2688,14 +3840,16 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2688
3840
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2689
3841
|
0 && (module.exports = {
|
|
2690
3842
|
ReclaimProofRequest,
|
|
3843
|
+
TeeVerificationError,
|
|
2691
3844
|
assertValidProofsByHash,
|
|
2692
3845
|
assertValidateProof,
|
|
2693
3846
|
assertVerifiedProof,
|
|
2694
3847
|
clearDeviceCache,
|
|
2695
3848
|
createLinkWithTemplateData,
|
|
2696
|
-
|
|
3849
|
+
fetchProviderConfigs,
|
|
2697
3850
|
fetchProviderHashRequirementsBy,
|
|
2698
3851
|
fetchStatusUrl,
|
|
3852
|
+
generateSpecsFromRequestSpecTemplate,
|
|
2699
3853
|
getAttestors,
|
|
2700
3854
|
getDeviceType,
|
|
2701
3855
|
getHttpProviderClaimParamsFromProof,
|
|
@@ -2708,8 +3862,11 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2708
3862
|
isHttpProviderClaimParams,
|
|
2709
3863
|
isMobileDevice,
|
|
2710
3864
|
recoverSignersOfSignedClaim,
|
|
3865
|
+
takePairsWhereValueIsArray,
|
|
3866
|
+
takeTemplateParametersFromProofs,
|
|
2711
3867
|
transformForOnchain,
|
|
2712
3868
|
updateSession,
|
|
2713
|
-
verifyProof
|
|
3869
|
+
verifyProof,
|
|
3870
|
+
verifyTeeAttestation
|
|
2714
3871
|
});
|
|
2715
3872
|
//# sourceMappingURL=index.js.map
|