@reclaimprotocol/js-sdk 5.1.0 → 5.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -84,7 +84,7 @@ var require_package = __commonJS({
84
84
  "package.json"(exports2, module2) {
85
85
  module2.exports = {
86
86
  name: "@reclaimprotocol/js-sdk",
87
- version: "5.1.0",
87
+ version: "5.2.0",
88
88
  description: "Designed to request proofs from the Reclaim protocol and manage the flow of claims and witness interactions.",
89
89
  main: "dist/index.js",
90
90
  types: "dist/index.d.ts",
@@ -220,6 +220,7 @@ __export(index_exports, {
220
220
  isHttpProviderClaimParams: () => isHttpProviderClaimParams,
221
221
  isMobileDevice: () => isMobileDevice,
222
222
  recoverSignersOfSignedClaim: () => recoverSignersOfSignedClaim,
223
+ runTeeVerification: () => runTeeVerification,
223
224
  takePairsWhereValueIsArray: () => takePairsWhereValueIsArray,
224
225
  takeTemplateParametersFromProofs: () => takeTemplateParametersFromProofs,
225
226
  transformForOnchain: () => transformForOnchain,
@@ -238,7 +239,7 @@ var RECLAIM_EXTENSION_ACTIONS = {
238
239
  };
239
240
 
240
241
  // src/Reclaim.ts
241
- var import_ethers5 = require("ethers");
242
+ var import_ethers6 = require("ethers");
242
243
  var import_canonicalize3 = __toESM(require("canonicalize"));
243
244
 
244
245
  // src/utils/errors.ts
@@ -560,19 +561,19 @@ function scheduleIntervalEndingTask(sessionId, intervals, onFailureCallback, tim
560
561
  }
561
562
  }, timeout);
562
563
  }
563
- var createVerifyProofResultSuccess = (proofs, isTeeVerified) => {
564
+ var createVerifyProofResultSuccess = (proofs, isTeeAttestationVerified) => {
564
565
  return {
565
566
  isVerified: true,
566
- isTeeVerified,
567
+ isTeeAttestationVerified,
567
568
  error: void 0,
568
569
  data: proofs.map(createTrustedDataFromProofData),
569
570
  publicData: getPublicDataFromProofs(proofs)
570
571
  };
571
572
  };
572
- var createVerifyProofResultFailure = (error, isTeeVerified) => {
573
+ var createVerifyProofResultFailure = (error, isTeeAttestationVerified) => {
573
574
  return {
574
575
  isVerified: false,
575
- isTeeVerified,
576
+ isTeeAttestationVerified,
576
577
  error,
577
578
  data: [],
578
579
  publicData: []
@@ -1446,6 +1447,20 @@ function clearDeviceCache() {
1446
1447
  cachedMobileType = null;
1447
1448
  }
1448
1449
 
1450
+ // src/utils/attestationNonce.ts
1451
+ var import_ethers4 = require("ethers");
1452
+ var ATTESTATION_NONCE_DOMAIN = "RECLAIM_TEE_NONCE_V1";
1453
+ function generateAttestationNonce(appSecret, applicationId, sessionId, timestamp) {
1454
+ const noncePayload = [
1455
+ ATTESTATION_NONCE_DOMAIN,
1456
+ applicationId,
1457
+ sessionId,
1458
+ timestamp,
1459
+ appSecret
1460
+ ].join(":");
1461
+ return import_ethers4.ethers.keccak256(import_ethers4.ethers.toUtf8Bytes(noncePayload)).replace(/^0x/i, "");
1462
+ }
1463
+
1449
1464
  // src/utils/providerUtils.ts
1450
1465
  var logger7 = logger_default.logger;
1451
1466
  function fetchProviderHashRequirementsBy(providerId, exactProviderVersionString, allowedTags, proofs) {
@@ -1673,724 +1688,336 @@ function assertValidateProof(proofs, config) {
1673
1688
  }
1674
1689
 
1675
1690
  // src/utils/verifyTee.ts
1676
- var import_node_forge = __toESM(require("node-forge"));
1677
- var import_ethers4 = require("ethers");
1678
-
1679
- // src/utils/amdCerts.ts
1680
- var AMD_CERTS = {
1681
- "Milan": `-----BEGIN CERTIFICATE-----
1682
- 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
- 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
- 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
- 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
- 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
- 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
- EgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExHzAdBgNVBAoMFkFkdmFu
1689
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
1717
- 0YPk
1718
- -----END CERTIFICATE-----
1719
- -----BEGIN CERTIFICATE-----
1720
- MIIGYzCCBBKgAwIBAgIDAQAAMEYGCSqGSIb3DQEBCjA5oA8wDQYJYIZIAWUDBAIC
1721
- BQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAICBQCiAwIBMKMDAgEBMHsxFDAS
1722
- BgNVBAsMC0VuZ2luZWVyaW5nMQswCQYDVQQGEwJVUzEUMBIGA1UEBwwLU2FudGEg
1723
- Q2xhcmExCzAJBgNVBAgMAkNBMR8wHQYDVQQKDBZBZHZhbmNlZCBNaWNybyBEZXZp
1724
- Y2VzMRIwEAYDVQQDDAlBUkstTWlsYW4wHhcNMjAxMDIyMTcyMzA1WhcNNDUxMDIy
1725
- MTcyMzA1WjB7MRQwEgYDVQQLDAtFbmdpbmVlcmluZzELMAkGA1UEBhMCVVMxFDAS
1726
- BgNVBAcMC1NhbnRhIENsYXJhMQswCQYDVQQIDAJDQTEfMB0GA1UECgwWQWR2YW5j
1727
- ZWQgTWljcm8gRGV2aWNlczESMBAGA1UEAwwJQVJLLU1pbGFuMIICIjANBgkqhkiG
1728
- 9w0BAQEFAAOCAg8AMIICCgKCAgEA0Ld52RJOdeiJlqK2JdsVmD7FktuotWwX1fNg
1729
- W41XY9Xz1HEhSUmhLz9Cu9DHRlvgJSNxbeYYsnJfvyjx1MfU0V5tkKiU1EesNFta
1730
- 1kTA0szNisdYc9isqk7mXT5+KfGRbfc4V/9zRIcE8jlHN61S1ju8X93+6dxDUrG2
1731
- SzxqJ4BhqyYmUDruPXJSX4vUc01P7j98MpqOS95rORdGHeI52Naz5m2B+O+vjsC0
1732
- 60d37jY9LFeuOP4Meri8qgfi2S5kKqg/aF6aPtuAZQVR7u3KFYXP59XmJgtcog05
1733
- gmI0T/OitLhuzVvpZcLph0odh/1IPXqx3+MnjD97A7fXpqGd/y8KxX7jksTEzAOg
1734
- bKAeam3lm+3yKIcTYMlsRMXPcjNbIvmsBykD//xSniusuHBkgnlENEWx1UcbQQrs
1735
- +gVDkuVPhsnzIRNgYvM48Y+7LGiJYnrmE8xcrexekBxrva2V9TJQqnN3Q53kt5vi
1736
- Qi3+gCfmkwC0F0tirIZbLkXPrPwzZ0M9eNxhIySb2npJfgnqz55I0u33wh4r0ZNQ
1737
- eTGfw03MBUtyuzGesGkcw+loqMaq1qR4tjGbPYxCvpCq7+OgpCCoMNit2uLo9M18
1738
- fHz10lOMT8nWAUvRZFzteXCm+7PHdYPlmQwUw3LvenJ/ILXoQPHfbkH0CyPfhl1j
1739
- WhJFZasCAwEAAaN+MHwwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSFrBrRQ/fI
1740
- rFXUxR1BSKvVeErUUzAPBgNVHRMBAf8EBTADAQH/MDoGA1UdHwQzMDEwL6AtoCuG
1741
- KWh0dHBzOi8va2RzaW50Zi5hbWQuY29tL3ZjZWsvdjEvTWlsYW4vY3JsMEYGCSqG
1742
- SIb3DQEBCjA5oA8wDQYJYIZIAWUDBAICBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZI
1743
- AWUDBAICBQCiAwIBMKMDAgEBA4ICAQC6m0kDp6zv4Ojfgy+zleehsx6ol0ocgVel
1744
- ETobpx+EuCsqVFRPK1jZ1sp/lyd9+0fQ0r66n7kagRk4Ca39g66WGTJMeJdqYriw
1745
- STjjDCKVPSesWXYPVAyDhmP5n2v+BYipZWhpvqpaiO+EGK5IBP+578QeW/sSokrK
1746
- dHaLAxG2LhZxj9aF73fqC7OAJZ5aPonw4RE299FVarh1Tx2eT3wSgkDgutCTB1Yq
1747
- zT5DuwvAe+co2CIVIzMDamYuSFjPN0BCgojl7V+bTou7dMsqIu/TW/rPCX9/EUcp
1748
- KGKqPQ3P+N9r1hjEFY1plBg93t53OOo49GNI+V1zvXPLI6xIFVsh+mto2RtgEX/e
1749
- pmMKTNN6psW88qg7c1hTWtN6MbRuQ0vm+O+/2tKBF2h8THb94OvvHHoFDpbCELlq
1750
- HnIYhxy0YKXGyaW1NjfULxrrmxVW4wcn5E8GddmvNa6yYm8scJagEi13mhGu4Jqh
1751
- 3QU3sf8iUSUr09xQDwHtOQUVIqx4maBZPBtSMf+qUDtjXSSq8lfWcd8bLr9mdsUn
1752
- JZJ0+tuPMKmBnSH860llKk+VpVQsgqbzDIvOLvD6W1Umq25boxCYJ+TuBoa4s+HH
1753
- CViAvgT9kf/rBq1d+ivj6skkHxuzcxbk1xv6ZGxrteJxVH7KlX7YRdZ6eARKwLe4
1754
- AFZEAwoKCQ==
1755
- -----END CERTIFICATE-----`,
1756
- "Genoa": `-----BEGIN CERTIFICATE-----
1757
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- kPnKgcNs5U1Le441ypen2n7BOnRyhmwyAUBGk3OcMXHsJ6KGpDJyTVCaC3fWX3ex
1773
- 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
- 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
- fAXF9sgvYtQjcaR9wlGr8ySRtZ2YJWofuR7zgYFJPEXRwAnbAR/05hBmog7CMt1F
1776
- 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
- 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
- BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQQwOgYDVR0fBDMwMTAvoC2gK4YpaHR0
1779
- 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
- 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
- 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
- 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
- +PzbTa0EwUkq1u6oezhTHywX1PilNRc4EjWgQ6ba/z4BBxO3P10tW/C39VS0Cv8S
1784
- N5G2bfZrPkjy6LBjGiaT4MBcsN+SM2o5QgKRG0qqn+edegHMmTPBDV2qCKbe5CBs
1785
- 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
- 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
- yCsTLyh13YsYBww5eW4DBREd/vCAS7F1JQUZ4twQy/jqBAJhcDyGuRnnwrRevGdW
1788
- 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
- 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
- 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
- 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
1792
- 2cko
1793
- -----END CERTIFICATE-----
1794
- -----BEGIN CERTIFICATE-----
1795
- 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
- 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
- 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
- Q2xhcmExCzAJBgNVBAgMAkNBMR8wHQYDVQQKDBZBZHZhbmNlZCBNaWNybyBEZXZp
1799
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- c3iUMyhNeGToOvgx/iUo4gGpG61NDpkEUvIzuKcaMx8IdTpWg2DF6SwF0IgVMffn
1808
- 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
- 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
- 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
- xHGRdTBkylungrkXJGYiwGrR8kaiqv7NN8QhOBMqYjcbrkEr0f8QMKklIS5ruOfq
1812
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 7SgFjMC9rR07292GQCA7Z7Ulq97JQaWeD2ofGGse5swj4OQfKfVv/zaJUFjvosZO
1820
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
1829
- /wMz1R1BHg==
1830
- -----END CERTIFICATE-----`
1831
- };
1832
-
1833
- // src/utils/verifyTee.ts
1834
- var crlCache = {};
1691
+ var import_ethers5 = require("ethers");
1835
1692
  var logger9 = logger_default.logger;
1836
- function toUint8Array(input) {
1837
- if (typeof Buffer !== "undefined" && typeof Buffer.isBuffer === "function" && Buffer.isBuffer(input)) {
1838
- return new Uint8Array(input);
1693
+ var EXPECTED_ISSUER = "https://confidentialcomputing.googleapis.com";
1694
+ var EXPECTED_HW_MODEL = "GCP_AMD_SEV";
1695
+ var EXPECTED_TEE_PROVIDER = "gcp";
1696
+ var EXPECTED_TEE_TECHNOLOGY = "amd-sev";
1697
+ var TOKEN_CLOCK_SKEW_S = 60;
1698
+ var NONCE_TIMESTAMP_MAX_SKEW_MS = 10 * 60 * 1e3;
1699
+ var BROWSER_ENVIRONMENT_ERROR = "TEE attestation verification is only supported in non-browser environments. Run verifyTeeAttestation on your server or API route.";
1700
+ function assert(condition, message) {
1701
+ if (!condition) {
1702
+ throw new Error(message);
1839
1703
  }
1840
- if (input instanceof Uint8Array) {
1841
- return new Uint8Array(input);
1704
+ }
1705
+ function isBrowserEnvironment() {
1706
+ if (typeof window !== "undefined" || typeof document !== "undefined") {
1707
+ return true;
1842
1708
  }
1843
- if (typeof ArrayBuffer !== "undefined" && input instanceof ArrayBuffer) {
1844
- return new Uint8Array(input);
1709
+ if (typeof navigator !== "undefined" && typeof process === "undefined") {
1710
+ return true;
1845
1711
  }
1846
- throw new Error("Unsupported binary data type");
1847
- }
1848
- function uint8ArrayToBinaryString(bytes) {
1849
- let result = "";
1850
- const chunkSize = 32768;
1851
- for (let i = 0; i < bytes.length; i += chunkSize) {
1852
- const chunk = bytes.subarray(i, i + chunkSize);
1853
- result += String.fromCharCode(...chunk);
1712
+ const workerGlobalScope = globalThis.WorkerGlobalScope;
1713
+ if (typeof workerGlobalScope !== "undefined" && typeof self !== "undefined" && self instanceof workerGlobalScope) {
1714
+ return true;
1854
1715
  }
1855
- return result;
1716
+ return false;
1856
1717
  }
1857
- function binaryStringToUint8Array(binary) {
1858
- const result = new Uint8Array(binary.length);
1859
- for (let i = 0; i < binary.length; i++) {
1860
- result[i] = binary.charCodeAt(i);
1718
+ function assertNonBrowserEnvironment() {
1719
+ if (isBrowserEnvironment()) {
1720
+ throw new Error(BROWSER_ENVIRONMENT_ERROR);
1861
1721
  }
1862
- return result;
1863
1722
  }
1864
- function base64ToUint8Array(base64) {
1865
- if (typeof atob === "function") {
1866
- const binary = atob(base64);
1867
- return binaryStringToUint8Array(binary);
1868
- }
1869
- if (typeof Buffer !== "undefined") {
1870
- return new Uint8Array(Buffer.from(base64, "base64"));
1871
- }
1872
- throw new Error("Base64 decoding is not supported in this environment");
1723
+ function normalizeHex(value) {
1724
+ return (value || "").trim().replace(/^0x/i, "").toLowerCase();
1873
1725
  }
1874
- function arrayBufferToHex(buffer) {
1875
- const view = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
1876
- let hex = "";
1877
- for (let i = 0; i < view.length; i++) {
1878
- hex += view[i].toString(16).padStart(2, "0");
1879
- }
1880
- return hex;
1726
+ function isHex(value) {
1727
+ return /^[0-9a-f]+$/i.test(value);
1881
1728
  }
1882
- function concatUint8Arrays(parts) {
1883
- const totalLength = parts.reduce((sum, arr) => sum + arr.length, 0);
1884
- const result = new Uint8Array(totalLength);
1885
- let offset = 0;
1886
- for (const arr of parts) {
1887
- result.set(arr, offset);
1888
- offset += arr.length;
1729
+ function decodeBase64Url(input) {
1730
+ const normalized = input.replace(/-/g, "+").replace(/_/g, "/");
1731
+ const padded = normalized + "=".repeat((4 - normalized.length % 4) % 4);
1732
+ if (typeof Buffer !== "undefined") {
1733
+ return new Uint8Array(Buffer.from(padded, "base64"));
1889
1734
  }
1890
- return result;
1891
- }
1892
- function reverseBytes(bytes) {
1893
- const copy = Uint8Array.from(bytes);
1894
- copy.reverse();
1895
- return copy;
1735
+ if (typeof atob === "function") {
1736
+ const binary = atob(padded);
1737
+ const bytes = new Uint8Array(binary.length);
1738
+ for (let i = 0; i < binary.length; i += 1) {
1739
+ bytes[i] = binary.charCodeAt(i);
1740
+ }
1741
+ return bytes;
1742
+ }
1743
+ throw new Error("Base64 decoding is not supported in this environment");
1896
1744
  }
1897
- function normalizeSerial(s) {
1898
- let cleaned = s.toLowerCase().replace(/[^a-f0-9]/g, "");
1899
- while (cleaned.startsWith("0") && cleaned.length > 1) cleaned = cleaned.substring(1);
1900
- return cleaned;
1745
+ function decodeUtf8(bytes) {
1746
+ return new TextDecoder().decode(bytes);
1901
1747
  }
1902
- var isNode = typeof process !== "undefined" && process.versions && process.versions.node;
1903
- var getSubtleCrypto = () => {
1904
- var _a;
1905
- if (typeof window !== "undefined" && ((_a = window.crypto) == null ? void 0 : _a.subtle)) return window.crypto.subtle;
1906
- if (isNode) return require("crypto").webcrypto.subtle;
1907
- throw new Error("No WebCrypto subtle implementation found in this environment");
1908
- };
1909
- function parseCert(buffer) {
1910
- const bytes = toUint8Array(buffer);
1911
- const asn1 = import_node_forge.default.asn1.fromDer(uint8ArrayToBinaryString(bytes));
1912
- const certSeq = asn1.value;
1913
- const tbsAsn1 = certSeq[0];
1914
- const sigAlgAsn1 = certSeq[1];
1915
- const sigValueAsn1 = certSeq[2];
1916
- const tbsFields = tbsAsn1.value;
1917
- let idx = 0;
1918
- if (tbsFields[idx].tagClass === 128) idx++;
1919
- const serialAsn1 = tbsFields[idx++];
1920
- const serialNumber = import_node_forge.default.util.bytesToHex(serialAsn1.value);
1921
- idx++;
1922
- idx++;
1923
- const validityAsn1 = tbsFields[idx++];
1924
- idx++;
1925
- const spkiAsn1 = tbsFields[idx];
1926
- if (!validityAsn1 || !Array.isArray(validityAsn1.value) || validityAsn1.value.length < 2) {
1927
- throw new Error("Certificate validity window is malformed");
1928
- }
1929
- const notBeforeNode = validityAsn1.value[0];
1930
- const notAfterNode = validityAsn1.value[1];
1931
- const notBefore = notBeforeNode ? parseAsn1Time(notBeforeNode) : void 0;
1932
- const notAfter = notAfterNode ? parseAsn1Time(notAfterNode) : void 0;
1933
- const sigRaw = typeof sigValueAsn1.value === "string" ? sigValueAsn1.value : "";
1934
- const signature = binaryStringToUint8Array(sigRaw.substring(1));
1935
- const sigAlgOid = import_node_forge.default.asn1.derToOid(sigAlgAsn1.value[0].value);
1748
+ function decodeJwt(token) {
1749
+ const parts = token.split(".");
1750
+ assert(parts.length === 3, "attestation token is not a JWT");
1936
1751
  return {
1937
- serialNumber: normalizeSerial(serialNumber),
1938
- tbsDer: binaryStringToUint8Array(import_node_forge.default.asn1.toDer(tbsAsn1).getBytes()),
1939
- signature,
1940
- sigAlgOid,
1941
- spkiDer: binaryStringToUint8Array(import_node_forge.default.asn1.toDer(spkiAsn1).getBytes()),
1942
- notBefore,
1943
- notAfter
1752
+ header: JSON.parse(decodeUtf8(decodeBase64Url(parts[0]))),
1753
+ payload: JSON.parse(decodeUtf8(decodeBase64Url(parts[1]))),
1754
+ signingInput: `${parts[0]}.${parts[1]}`,
1755
+ signature: decodeBase64Url(parts[2])
1944
1756
  };
1945
1757
  }
1946
- function verifySignature(publicKeyPem, data, signature, sigAlgOid) {
1758
+ function getFetch() {
1759
+ const fetchFn = globalThis.fetch;
1760
+ assert(fetchFn, "fetch is not available in this environment");
1761
+ return fetchFn.bind(globalThis);
1762
+ }
1763
+ function getSubtleCrypto() {
1764
+ var _a, _b, _c;
1765
+ if ((_a = globalThis.crypto) == null ? void 0 : _a.subtle) {
1766
+ return globalThis.crypto.subtle;
1767
+ }
1768
+ const nodeCrypto = typeof process !== "undefined" && ((_b = process.versions) == null ? void 0 : _b.node) ? require("crypto") : void 0;
1769
+ if ((_c = nodeCrypto == null ? void 0 : nodeCrypto.webcrypto) == null ? void 0 : _c.subtle) {
1770
+ return nodeCrypto.webcrypto.subtle;
1771
+ }
1772
+ throw new Error("WebCrypto subtle is not available in this environment");
1773
+ }
1774
+ function fetchJson(url) {
1947
1775
  return __async(this, null, function* () {
1948
- const cryptoSubtle = getSubtleCrypto();
1949
- const forgeCert = import_node_forge.default.pki.certificateFromPem(publicKeyPem);
1950
- const spkiBuf = binaryStringToUint8Array(import_node_forge.default.asn1.toDer(import_node_forge.default.pki.publicKeyToAsn1(forgeCert.publicKey)).getBytes());
1951
- let importParams;
1952
- let verifyParams;
1953
- if (sigAlgOid === "1.2.840.113549.1.1.10") {
1954
- importParams = { name: "RSA-PSS", hash: "SHA-384" };
1955
- verifyParams = { name: "RSA-PSS", saltLength: 48 };
1956
- } 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") {
1957
- importParams = { name: "RSASSA-PKCS1-v1_5", hash: sigAlgOid === "1.2.840.113549.1.1.12" ? "SHA-384" : "SHA-256" };
1958
- verifyParams = { name: "RSASSA-PKCS1-v1_5" };
1959
- } else if (sigAlgOid === "1.2.840.10045.4.3.3") {
1960
- importParams = { name: "ECDSA", namedCurve: "P-384" };
1961
- verifyParams = { name: "ECDSA", hash: "SHA-384" };
1962
- } else {
1963
- importParams = { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" };
1964
- verifyParams = { name: "RSASSA-PKCS1-v1_5" };
1776
+ const response = yield getFetch()(url);
1777
+ if (!response.ok) {
1778
+ throw new Error(`GET ${url} returned ${response.status} ${response.statusText}`);
1965
1779
  }
1966
- const key = yield cryptoSubtle.importKey("spki", spkiBuf, importParams, false, ["verify"]);
1967
- const isValid = yield cryptoSubtle.verify(verifyParams, key, signature, data);
1968
- if (!isValid) throw new Error(`Signature verification failed (OID: ${sigAlgOid}, ImportParams: ${JSON.stringify(importParams)})`);
1780
+ return response.json();
1969
1781
  });
1970
1782
  }
1971
- var COSIGN_PUBLIC_KEY = `-----BEGIN PUBLIC KEY-----
1972
- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEjiL30OjPuxa+GC1I7SAcBv2u2pMt
1973
- h9WbP33IvB3eFww+C1hoW0fwdZPiq4FxBtKNiZuFpmYuFngW/nJteBu9kQ==
1974
- -----END PUBLIC KEY-----
1975
- `;
1976
- function verifyTeeAttestation(proof, expectedApplicationId) {
1783
+ function sha256Hex(input) {
1977
1784
  return __async(this, null, function* () {
1978
- try {
1979
- let teeAttestation = proof.teeAttestation;
1980
- if (!teeAttestation) {
1981
- throw new Error("Missing teeAttestation in proof");
1982
- }
1983
- if (typeof teeAttestation === "string") {
1984
- teeAttestation = JSON.parse(teeAttestation);
1985
- }
1986
- let expectedNonceSignature;
1987
- let nonceDataObj;
1988
- try {
1989
- const context = JSON.parse(proof.claimData.context);
1990
- expectedNonceSignature = context.attestationNonce;
1991
- nonceDataObj = context.attestationNonceData;
1992
- } catch (e) {
1993
- throw new Error("Failed to parse proof context to extract attestationNonce");
1994
- }
1995
- if (!expectedNonceSignature || !nonceDataObj) {
1996
- throw new Error("Proof context is missing attestationNonce or attestationNonceData");
1997
- }
1998
- if (teeAttestation.nonce !== expectedNonceSignature) {
1999
- throw new Error(`Nonce Mismatch! Expected signature ${expectedNonceSignature}, got ${teeAttestation.nonce}`);
2000
- }
2001
- const { applicationId, sessionId, timestamp } = nonceDataObj;
2002
- if (expectedApplicationId && applicationId.toLowerCase() !== expectedApplicationId.toLowerCase()) {
2003
- throw new Error(`Application ID Mismatch! Expected ${expectedApplicationId}, but proof context contains ${applicationId}`);
2004
- }
2005
- const expectedNonceData = `${applicationId}:${sessionId}:${timestamp}`;
2006
- const nonceMsg = import_ethers4.ethers.getBytes(import_ethers4.ethers.keccak256(new TextEncoder().encode(expectedNonceData)));
2007
- const recoveredAddress = import_ethers4.ethers.verifyMessage(nonceMsg, expectedNonceSignature);
2008
- if (recoveredAddress.toLowerCase() !== applicationId.toLowerCase()) {
2009
- throw new Error(`Nonce signature verification failed: recovered ${recoveredAddress}, expected ${applicationId}`);
2010
- }
2011
- try {
2012
- const context = JSON.parse(proof.claimData.context);
2013
- const paramSessionId = context.attestationNonceData.sessionId;
2014
- if (!paramSessionId) {
2015
- throw new Error(`Proof parameters are missing proxySessionId or sessionId`);
2016
- }
2017
- if (paramSessionId.toString() !== sessionId.toString()) {
2018
- throw new Error(`Session ID Mismatch! Expected ${sessionId}, but proof parameters contain ${paramSessionId}`);
2019
- }
2020
- const claimTimestampMs = proof.claimData.timestampS * 1e3;
2021
- const nonceTimestampMs = parseInt(timestamp, 10);
2022
- const diffMs = Math.abs(claimTimestampMs - nonceTimestampMs);
2023
- const TEN_MINUTES_MS = 10 * 60 * 1e3;
2024
- if (diffMs > TEN_MINUTES_MS) {
2025
- throw new Error(`Timestamp Skew Too Large! claimData.timestampS and attestationNonce timestamp differ by ${Math.round(diffMs / 1e3)}s (limit: 600s)`);
2026
- }
2027
- } catch (e) {
2028
- if (e instanceof Error && (e.message.includes("Session ID Mismatch!") || e.message.includes("Timestamp Skew"))) {
2029
- throw e;
2030
- }
2031
- throw new Error(`Failed to cross-verify session ID: ${e.message}`);
2032
- }
2033
- const reportBuffer = base64ToUint8Array(teeAttestation.snp_report);
2034
- const report = parseAttestationReport(reportBuffer);
2035
- if (report.isDebugEnabled) {
2036
- throw new Error("POLICY CHECK FAILED: Debug mode is ALLOWED. Environment is compromised.");
2037
- }
2038
- const certBuffer = base64ToUint8Array(teeAttestation.vlek_cert);
2039
- yield verifyAMDChain(certBuffer);
2040
- verifyTCB(certBuffer, report);
2041
- yield verifyHardwareSignature(reportBuffer, certBuffer);
2042
- yield verifyReportData(teeAttestation, proof.claimData.context, report);
2043
- return true;
2044
- } catch (error) {
2045
- logger9.error("TEE attestation verification failed:", error);
2046
- return false;
2047
- }
1785
+ const digest = yield getSubtleCrypto().digest("SHA-256", new TextEncoder().encode(input));
1786
+ return Array.from(new Uint8Array(digest), (value) => value.toString(16).padStart(2, "0")).join("");
2048
1787
  });
2049
1788
  }
2050
- function parseAttestationReport(buffer) {
2051
- if (buffer.length < 1e3) {
2052
- throw new Error(`Report buffer is too small: ${buffer.length} bytes`);
2053
- }
2054
- const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
2055
- const policy = view.getBigUint64(8, true);
2056
- const isDebugEnabled = (policy & BigInt(1) << BigInt(19)) !== BigInt(0);
2057
- const reported_tcb = {
2058
- bootloader: buffer[56],
2059
- tee: buffer[57],
2060
- snp: buffer[62],
2061
- microcode: buffer[63]
2062
- };
2063
- const reportData = arrayBufferToHex(buffer.subarray(80, 144));
2064
- return { policy, isDebugEnabled, reported_tcb, reportData };
2065
- }
2066
- function getExtValue(certAsn1, oidString) {
2067
- const tbsCert = certAsn1.value[0];
2068
- if (!tbsCert || !tbsCert.value) return null;
2069
- const extBlockWrapper = tbsCert.value.find((node) => node.tagClass === import_node_forge.default.asn1.Class.CONTEXT_SPECIFIC && node.type === 3);
2070
- if (!extBlockWrapper || !extBlockWrapper.value || !extBlockWrapper.value.length) return null;
2071
- const extSequence = extBlockWrapper.value[0];
2072
- for (const ext of extSequence.value) {
2073
- const extIdAsn1 = ext.value[0];
2074
- const extIdStr = import_node_forge.default.asn1.derToOid(extIdAsn1.value);
2075
- if (extIdStr === oidString) {
2076
- const extValueAsn1 = ext.value[ext.value.length - 1];
2077
- const rawOctetStringBytes = extValueAsn1.value;
2078
- try {
2079
- const innerAsn1 = import_node_forge.default.asn1.fromDer(import_node_forge.default.util.createBuffer(rawOctetStringBytes));
2080
- if (innerAsn1.type === 2) {
2081
- const bytes = innerAsn1.value;
2082
- if (typeof bytes === "string" && bytes.length > 0) {
2083
- return bytes.charCodeAt(bytes.length - 1);
2084
- } else {
2085
- throw new Error(`Extension ${oidString} INTEGER value is empty or invalid`);
2086
- }
2087
- } else {
2088
- throw new Error(`Extension ${oidString} does not contain an INTEGER, found type ${innerAsn1.type}`);
2089
- }
2090
- } catch (e) {
2091
- throw new Error(`Failed to strictly parse AMD TCB extension ${oidString}: ${e.message}`);
2092
- }
2093
- }
2094
- }
2095
- return null;
2096
- }
2097
- function verifyTCB(vlekCertBuffer, report) {
2098
- const certAsn1 = import_node_forge.default.asn1.fromDer(import_node_forge.default.util.createBuffer(uint8ArrayToBinaryString(vlekCertBuffer)));
2099
- const OID_BOOTLOADER = "1.3.6.1.4.1.3704.1.3.1";
2100
- const OID_TEE = "1.3.6.1.4.1.3704.1.3.2";
2101
- const OID_SNP = "1.3.6.1.4.1.3704.1.3.3";
2102
- const OID_MICROCODE = "1.3.6.1.4.1.3704.1.3.8";
2103
- const certTcb = {
2104
- bootloader: getExtValue(certAsn1, OID_BOOTLOADER),
2105
- tee: getExtValue(certAsn1, OID_TEE),
2106
- snp: getExtValue(certAsn1, OID_SNP),
2107
- microcode: getExtValue(certAsn1, OID_MICROCODE)
2108
- };
2109
- if (certTcb.bootloader !== null && report.reported_tcb.bootloader < certTcb.bootloader) {
2110
- throw new Error(`TCB Downgrade! Bootloader reported ${report.reported_tcb.bootloader}, but certificate requires ${certTcb.bootloader}`);
2111
- }
2112
- if (certTcb.tee !== null && report.reported_tcb.tee < certTcb.tee) {
2113
- throw new Error(`TCB Downgrade! TEE reported ${report.reported_tcb.tee}, but certificate requires ${certTcb.tee}`);
2114
- }
2115
- if (certTcb.snp !== null && report.reported_tcb.snp < certTcb.snp) {
2116
- throw new Error(`TCB Downgrade! SNP reported ${report.reported_tcb.snp}, but certificate requires ${certTcb.snp}`);
2117
- }
2118
- if (certTcb.microcode !== null && report.reported_tcb.microcode < certTcb.microcode) {
2119
- throw new Error(`TCB Downgrade! Microcode reported ${report.reported_tcb.microcode}, but certificate requires ${certTcb.microcode}`);
2120
- }
2121
- }
2122
- function parseAsn1Time(node) {
2123
- const s = node.value;
2124
- if (node.type === import_node_forge.default.asn1.Type.UTCTIME) {
2125
- const yr = parseInt(s.substring(0, 2), 10);
2126
- return new Date(Date.UTC(
2127
- yr >= 50 ? 1900 + yr : 2e3 + yr,
2128
- parseInt(s.substring(2, 4), 10) - 1,
2129
- parseInt(s.substring(4, 6), 10),
2130
- parseInt(s.substring(6, 8), 10),
2131
- parseInt(s.substring(8, 10), 10),
2132
- parseInt(s.substring(10, 12), 10)
2133
- ));
2134
- } else {
2135
- return new Date(Date.UTC(
2136
- parseInt(s.substring(0, 4), 10),
2137
- parseInt(s.substring(4, 6), 10) - 1,
2138
- parseInt(s.substring(6, 8), 10),
2139
- parseInt(s.substring(8, 10), 10),
2140
- parseInt(s.substring(10, 12), 10),
2141
- parseInt(s.substring(12, 14), 10)
2142
- ));
2143
- }
2144
- }
2145
- function verifyCRL(crlBuf, arkPem, vlekSerial) {
1789
+ var JWKS_CACHE_TTL_MS = 5 * 60 * 1e3;
1790
+ var cachedJwksUri = null;
1791
+ var cachedJwksKeys = null;
1792
+ var cachedJwksAt = 0;
1793
+ function verifyJwtSignature(token, issuer) {
2146
1794
  return __async(this, null, function* () {
2147
- const crlAsn1 = import_node_forge.default.asn1.fromDer(import_node_forge.default.util.createBuffer(uint8ArrayToBinaryString(crlBuf)));
2148
- if (!Array.isArray(crlAsn1.value) || crlAsn1.value.length < 3) {
2149
- throw new Error("CRL ASN.1 structure is invalid: expected SEQUENCE with TBSCertList, AlgorithmIdentifier, BIT STRING");
2150
- }
2151
- const tbsAsn1 = crlAsn1.value[0];
2152
- const sigBitsAsn1 = crlAsn1.value[2];
2153
- if (!Array.isArray(tbsAsn1.value)) {
2154
- throw new Error("CRL TBSCertList is not a valid SEQUENCE");
2155
- }
2156
- const tbsFields = tbsAsn1.value;
2157
- let fi = 0;
2158
- if (fi < tbsFields.length && tbsFields[fi].tagClass === import_node_forge.default.asn1.Class.UNIVERSAL && tbsFields[fi].type === import_node_forge.default.asn1.Type.INTEGER) {
2159
- fi++;
2160
- }
2161
- if (fi < tbsFields.length) fi++;
2162
- if (fi >= tbsFields.length) throw new Error("CRL TBSCertList missing issuer");
2163
- const issuerAsn1 = tbsFields[fi++];
2164
- if (fi >= tbsFields.length) throw new Error("CRL TBSCertList missing thisUpdate");
2165
- const thisUpdateAsn1 = tbsFields[fi++];
2166
- let nextUpdateAsn1 = null;
2167
- 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)) {
2168
- nextUpdateAsn1 = tbsFields[fi++];
2169
- }
2170
- let revokedSeq = null;
2171
- if (fi < tbsFields.length && tbsFields[fi].tagClass === import_node_forge.default.asn1.Class.UNIVERSAL && tbsFields[fi].type === import_node_forge.default.asn1.Type.SEQUENCE) {
2172
- revokedSeq = tbsFields[fi];
2173
- }
2174
- const now = /* @__PURE__ */ new Date();
2175
- const thisUpdate = parseAsn1Time(thisUpdateAsn1);
2176
- if (thisUpdate > now) {
2177
- throw new Error(`CRL is not yet valid: thisUpdate is ${thisUpdate.toISOString()}`);
2178
- }
2179
- if (nextUpdateAsn1) {
2180
- const nextUpdate = parseAsn1Time(nextUpdateAsn1);
2181
- if (nextUpdate < now) {
2182
- throw new Error(`CRL has expired: nextUpdate was ${nextUpdate.toISOString()}`);
2183
- }
2184
- }
2185
- const crlIssuerDer = import_node_forge.default.asn1.toDer(issuerAsn1).getBytes();
2186
- const arkForgeCert = import_node_forge.default.pki.certificateFromPem(arkPem);
2187
- const arkCertAsn1 = import_node_forge.default.pki.certificateToAsn1(arkForgeCert);
2188
- const arkSubjectAsn1 = arkCertAsn1.value[0].value[5];
2189
- const arkSubjectDer = import_node_forge.default.asn1.toDer(arkSubjectAsn1).getBytes();
2190
- if (crlIssuerDer !== arkSubjectDer) {
2191
- throw new Error("CRL issuer does not match AMD ARK certificate subject \u2014 chain mismatch");
2192
- }
2193
- const tbsDerBuf = binaryStringToUint8Array(import_node_forge.default.asn1.toDer(tbsAsn1).getBytes());
2194
- const sigRaw = typeof sigBitsAsn1.value === "string" ? sigBitsAsn1.value : "";
2195
- const sigBuf = binaryStringToUint8Array(sigRaw.substring(1));
2196
- const cryptoSubtle = getSubtleCrypto();
2197
- const spkiBuf = binaryStringToUint8Array(
2198
- import_node_forge.default.asn1.toDer(import_node_forge.default.pki.publicKeyToAsn1(arkForgeCert.publicKey)).getBytes()
2199
- );
2200
- const arkCryptoKey = yield cryptoSubtle.importKey(
2201
- "spki",
2202
- spkiBuf,
2203
- { name: "RSA-PSS", hash: "SHA-384" },
1795
+ const { header, payload, signingInput, signature } = decodeJwt(token);
1796
+ assert(header.alg === "RS256", `unexpected attestation signing algorithm: ${header.alg}`);
1797
+ assert(typeof header.kid === "string" && header.kid.length > 0, "attestation token kid is missing");
1798
+ const isCacheFresh = cachedJwksKeys && Date.now() - cachedJwksAt < JWKS_CACHE_TTL_MS;
1799
+ if (!isCacheFresh) {
1800
+ const oidc = yield fetchJson(`${issuer}/.well-known/openid-configuration`);
1801
+ assert(typeof (oidc == null ? void 0 : oidc.jwks_uri) === "string" && oidc.jwks_uri.length > 0, "issuer JWKS URI is missing");
1802
+ cachedJwksUri = oidc.jwks_uri;
1803
+ const jwks = yield fetchJson(cachedJwksUri);
1804
+ cachedJwksKeys = (jwks == null ? void 0 : jwks.keys) || [];
1805
+ cachedJwksAt = Date.now();
1806
+ }
1807
+ const jwk = cachedJwksKeys.find((key) => key.kid === header.kid);
1808
+ assert(jwk, `no JWKS key found for kid ${header.kid}`);
1809
+ const cryptoKey = yield getSubtleCrypto().importKey(
1810
+ "jwk",
1811
+ jwk,
1812
+ { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" },
2204
1813
  false,
2205
1814
  ["verify"]
2206
1815
  );
2207
- const isValid = yield cryptoSubtle.verify(
2208
- { name: "RSA-PSS", saltLength: 48 },
2209
- // SHA-384 salt length is 48
2210
- arkCryptoKey,
2211
- sigBuf,
2212
- tbsDerBuf
1816
+ const isValid = yield getSubtleCrypto().verify(
1817
+ "RSASSA-PKCS1-v1_5",
1818
+ cryptoKey,
1819
+ signature,
1820
+ new TextEncoder().encode(signingInput)
2213
1821
  );
2214
- if (!isValid) {
2215
- throw new Error("CRL signature is INVALID \u2014 the CRL may be tampered or forged");
2216
- }
2217
- const targetSerial = normalizeSerial(vlekSerial);
2218
- if (revokedSeq && Array.isArray(revokedSeq.value)) {
2219
- for (const entry of revokedSeq.value) {
2220
- if (!Array.isArray(entry.value) || entry.value.length < 2) continue;
2221
- const serialAsn1 = entry.value[0];
2222
- if (serialAsn1.type !== import_node_forge.default.asn1.Type.INTEGER || typeof serialAsn1.value !== "string") continue;
2223
- const serialHex = import_node_forge.default.util.bytesToHex(serialAsn1.value);
2224
- if (normalizeSerial(serialHex) === targetSerial) {
2225
- throw new Error("\u{1F6A8} VLEK Certificate is REVOKED per AMD CRL! This hardware may be compromised.");
2226
- }
2227
- }
2228
- }
1822
+ assert(isValid, "JWT signature verification failed");
1823
+ return payload;
2229
1824
  });
2230
1825
  }
2231
- function assertCertValidity(label, cert) {
2232
- const now = Date.now();
2233
- if (cert.notBefore && now < cert.notBefore.getTime()) {
2234
- throw new Error(`${label} certificate is not yet valid (notBefore: ${cert.notBefore.toISOString()})`);
1826
+ function isNonceContextData(obj) {
1827
+ if (!obj || typeof obj !== "object") return false;
1828
+ const o = obj;
1829
+ return typeof o.applicationId === "string" && o.applicationId.length > 0 && typeof o.sessionId === "string" && o.sessionId.length > 0 && typeof o.timestamp === "string" && o.timestamp.length > 0;
1830
+ }
1831
+ function parseProofContext(proof) {
1832
+ let parsedContext;
1833
+ try {
1834
+ parsedContext = JSON.parse(proof.claimData.context);
1835
+ } catch (e) {
1836
+ throw new Error("Malformed proof: claimData.context is not valid JSON");
2235
1837
  }
2236
- if (cert.notAfter && now > cert.notAfter.getTime()) {
2237
- throw new Error(`${label} certificate expired on ${cert.notAfter.toISOString()}`);
1838
+ if (!parsedContext || typeof parsedContext !== "object") {
1839
+ throw new Error("Malformed proof: claimData.context is not a JSON object");
2238
1840
  }
1841
+ const ctx = parsedContext;
1842
+ const expectedNonce = ctx.attestationNonce;
1843
+ assert(typeof expectedNonce === "string" && expectedNonce.length > 0, "Proof context is missing attestationNonce");
1844
+ const nonceDataObj = ctx.attestationNonceData;
1845
+ assert(isNonceContextData(nonceDataObj), "Proof context is missing or has invalid attestationNonceData (requires applicationId, sessionId, timestamp)");
1846
+ return { parsedContext: ctx, nonceDataObj, expectedNonce };
2239
1847
  }
2240
- function verifyAMDChain(vlekCertBuffer) {
2241
- return __async(this, null, function* () {
2242
- const processors = ["Milan", "Genoa"];
2243
- let chainVerified = false;
2244
- const vlek = parseCert(vlekCertBuffer);
2245
- assertCertValidity("VLEK", vlek);
2246
- for (const processor of processors) {
2247
- let matchedChain = false;
2248
- try {
2249
- const chainPem = AMD_CERTS[processor];
2250
- if (!chainPem) continue;
2251
- const certs = chainPem.split("-----END CERTIFICATE-----").map((c) => c.trim()).filter((c) => c.length > 0).map((c) => c + "\n-----END CERTIFICATE-----\n");
2252
- const askCert = import_node_forge.default.pki.certificateFromPem(certs[0]);
2253
- const arkCert = import_node_forge.default.pki.certificateFromPem(certs[1]);
2254
- const askDer = import_node_forge.default.asn1.toDer(import_node_forge.default.pki.certificateToAsn1(askCert)).getBytes();
2255
- const arkDer = import_node_forge.default.asn1.toDer(import_node_forge.default.pki.certificateToAsn1(arkCert)).getBytes();
2256
- const ask = parseCert(binaryStringToUint8Array(askDer));
2257
- const ark = parseCert(binaryStringToUint8Array(arkDer));
2258
- assertCertValidity("ASK", ask);
2259
- assertCertValidity("ARK", ark);
2260
- try {
2261
- yield verifySignature(certs[1], ark.tbsDer, ark.signature, ark.sigAlgOid);
2262
- } catch (e) {
2263
- throw new Error(`AMD ARK self-signature verification failed: ${e.message}`);
2264
- }
2265
- try {
2266
- yield verifySignature(certs[1], ask.tbsDer, ask.signature, ask.sigAlgOid);
2267
- } catch (e) {
2268
- throw new Error(`AMD ASK-by-ARK signature verification failed: ${e.message}`);
2269
- }
2270
- try {
2271
- yield verifySignature(certs[0], vlek.tbsDer, vlek.signature, vlek.sigAlgOid);
2272
- } catch (e) {
2273
- throw new Error(`VLEK-by-ASK signature verification failed: ${e.message}`);
2274
- }
2275
- matchedChain = true;
2276
- let crlBuf;
2277
- const now = Date.now();
2278
- if (crlCache[processor] && now - crlCache[processor].fetchedAt < 36e5) {
2279
- crlBuf = crlCache[processor].buffer;
2280
- } else {
2281
- const crlUrl = `https://kdsintf.amd.com/vlek/v1/${processor}/crl`;
2282
- const controller = new AbortController();
2283
- const timeoutId = setTimeout(() => controller.abort(), 5e3);
2284
- const crlResp = yield fetch(crlUrl, { signal: controller.signal });
2285
- clearTimeout(timeoutId);
2286
- if (!crlResp.ok) continue;
2287
- crlBuf = new Uint8Array(yield crlResp.arrayBuffer());
2288
- crlCache[processor] = { buffer: crlBuf, fetchedAt: now };
2289
- }
2290
- if (vlek.serialNumber && crlBuf) {
2291
- yield verifyCRL(crlBuf, certs[1], vlek.serialNumber);
2292
- }
2293
- chainVerified = true;
2294
- break;
2295
- } catch (e) {
2296
- if (matchedChain) {
2297
- throw e;
2298
- }
2299
- continue;
2300
- }
2301
- }
2302
- if (!chainVerified) {
2303
- throw new Error("VLEK Certificate failed verification against all known AMD Root of Trust chains!");
1848
+ function verifyApplicationAndSessionBinding(proof, parsedContext, nonceDataObj, expectedApplicationId) {
1849
+ var _a;
1850
+ const { applicationId, sessionId, timestamp } = nonceDataObj;
1851
+ if (expectedApplicationId) {
1852
+ assert(
1853
+ applicationId.toLowerCase() === expectedApplicationId.toLowerCase(),
1854
+ `Application ID Mismatch! Expected ${expectedApplicationId}, but proof context contains ${applicationId}`
1855
+ );
1856
+ }
1857
+ let parsedParameters = {};
1858
+ if (proof.claimData.parameters) {
1859
+ try {
1860
+ const parsed = JSON.parse(proof.claimData.parameters);
1861
+ parsedParameters = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
1862
+ } catch (e) {
1863
+ throw new Error("Malformed proof: claimData.parameters is not valid JSON");
2304
1864
  }
2305
- });
1865
+ }
1866
+ const contextSessionId = parsedContext == null ? void 0 : parsedContext.reclaimSessionId;
1867
+ const parameterSessionId = (_a = parsedParameters == null ? void 0 : parsedParameters.proxySessionId) != null ? _a : parsedParameters == null ? void 0 : parsedParameters.sessionId;
1868
+ if (contextSessionId && contextSessionId.toString() !== sessionId.toString()) {
1869
+ throw new Error(`Session ID Mismatch! Expected ${sessionId}, but proof context contains reclaimSessionId=${contextSessionId}`);
1870
+ }
1871
+ if (parameterSessionId && parameterSessionId.toString() !== sessionId.toString()) {
1872
+ throw new Error(`Session ID Mismatch! Expected ${sessionId}, but proof parameters contain ${parameterSessionId}`);
1873
+ }
1874
+ if (!contextSessionId && !parameterSessionId) {
1875
+ throw new Error("Proof is missing reclaimSessionId and proxySessionId/sessionId for attestation nonce verification");
1876
+ }
1877
+ const claimTimestampMs = proof.claimData.timestampS * 1e3;
1878
+ const nonceTimestampMs = parseInt(timestamp, 10);
1879
+ const diffMs = Math.abs(claimTimestampMs - nonceTimestampMs);
1880
+ if (diffMs > NONCE_TIMESTAMP_MAX_SKEW_MS) {
1881
+ throw new Error(`Timestamp Skew Too Large! claimData.timestampS and attestationNonce timestamp differ by ${Math.round(diffMs / 1e3)}s (limit: 600s)`);
1882
+ }
2306
1883
  }
2307
- function verifyHardwareSignature(reportBytes, certBytes) {
2308
- return __async(this, null, function* () {
2309
- const vlek = parseCert(certBytes);
2310
- const sigOffset = 672;
2311
- const rLE = reportBytes.subarray(sigOffset, sigOffset + 72);
2312
- const sLE = reportBytes.subarray(sigOffset + 72, sigOffset + 144);
2313
- const rBE = reverseBytes(rLE);
2314
- const sBE = reverseBytes(sLE);
2315
- const signedData = reportBytes.subarray(0, 672);
2316
- const cryptoSubtle = getSubtleCrypto();
2317
- const importedKey = yield cryptoSubtle.importKey(
2318
- "spki",
2319
- vlek.spkiDer,
2320
- { name: "ECDSA", namedCurve: "P-384" },
2321
- false,
2322
- ["verify"]
1884
+ function verifyNonceMaterial(expectedNonce, nonceDataObj, expectedAppSecret) {
1885
+ const cleanExpectedNonce = normalizeHex(expectedNonce);
1886
+ const { applicationId, sessionId, timestamp } = nonceDataObj;
1887
+ assert(cleanExpectedNonce.length > 0, "Proof context attestationNonce is empty");
1888
+ assert(isHex(cleanExpectedNonce), "Proof context attestationNonce is not valid hex");
1889
+ if (expectedAppSecret) {
1890
+ const recomputedNonce = generateAttestationNonce(expectedAppSecret, applicationId, sessionId, timestamp);
1891
+ assert(
1892
+ recomputedNonce === cleanExpectedNonce,
1893
+ "Attestation nonce verification failed: app secret, application ID, session ID, or timestamp do not match"
1894
+ );
1895
+ return;
1896
+ }
1897
+ if (cleanExpectedNonce.length > 74) {
1898
+ const legacyNonceData = `${applicationId}:${sessionId}:${timestamp}`;
1899
+ const nonceMsg = import_ethers5.ethers.getBytes(import_ethers5.ethers.keccak256(new TextEncoder().encode(legacyNonceData)));
1900
+ const recoveredAddress = import_ethers5.ethers.verifyMessage(
1901
+ nonceMsg,
1902
+ expectedNonce.startsWith("0x") ? expectedNonce : `0x${expectedNonce}`
1903
+ );
1904
+ assert(
1905
+ recoveredAddress.toLowerCase() === applicationId.toLowerCase(),
1906
+ `Nonce signature verification failed: recovered ${recoveredAddress}, expected ${applicationId}`
2323
1907
  );
2324
- const rPadding = rBE.subarray(0, rBE.length - 48);
2325
- const sPadding = sBE.subarray(0, sBE.length - 48);
2326
- if (!rPadding.every((b) => b === 0) || !sPadding.every((b) => b === 0)) {
2327
- throw new Error("Hardware ECDSA signature is malformed: non-zero padding bytes detected in the structural signature coordinates.");
2328
- }
2329
- const r48 = rBE.subarray(rBE.length - 48);
2330
- const s48 = sBE.subarray(sBE.length - 48);
2331
- const rawSignature = concatUint8Arrays([r48, s48]);
2332
- const isValid = yield cryptoSubtle.verify(
2333
- { name: "ECDSA", hash: { name: "SHA-384" } },
2334
- importedKey,
2335
- rawSignature,
2336
- signedData
1908
+ return;
1909
+ }
1910
+ throw new Error("App secret is required to verify hash-based attestation nonces");
1911
+ }
1912
+ function assertTokenFresh(claims) {
1913
+ const now = Math.floor(Date.now() / 1e3);
1914
+ if (typeof claims.nbf === "number" && now + TOKEN_CLOCK_SKEW_S < claims.nbf) {
1915
+ throw new Error(`Attestation token is not valid before ${claims.nbf}`);
1916
+ }
1917
+ if (typeof claims.exp === "number" && now - TOKEN_CLOCK_SKEW_S > claims.exp) {
1918
+ throw new Error(`Attestation token expired at ${claims.exp}`);
1919
+ }
1920
+ if (typeof claims.iat === "number" && claims.iat > now + TOKEN_CLOCK_SKEW_S) {
1921
+ throw new Error(`Attestation token issued-at ${claims.iat} is in the future`);
1922
+ }
1923
+ }
1924
+ function assertAudienceClaim(aud) {
1925
+ if (typeof aud === "string") {
1926
+ assert(aud.length > 0, "attestation token audience is empty");
1927
+ return;
1928
+ }
1929
+ if (Array.isArray(aud)) {
1930
+ assert(aud.length > 0, "attestation token audience is empty");
1931
+ assert(aud.every((entry) => typeof entry === "string" && entry.length > 0), "attestation token audience contains invalid entries");
1932
+ return;
1933
+ }
1934
+ throw new Error("attestation token audience is missing");
1935
+ }
1936
+ function assertProofShape(teeAttestation) {
1937
+ var _a, _b, _c;
1938
+ if (teeAttestation.error) {
1939
+ throw new Error(`${teeAttestation.error.code}: ${teeAttestation.error.message}`);
1940
+ }
1941
+ assert(teeAttestation.proof_version === "v2", `unexpected proof version: ${teeAttestation.proof_version}`);
1942
+ assert(teeAttestation.tee_provider === EXPECTED_TEE_PROVIDER, `unexpected tee provider: ${teeAttestation.tee_provider}`);
1943
+ assert(teeAttestation.tee_technology === EXPECTED_TEE_TECHNOLOGY, `unexpected tee technology: ${teeAttestation.tee_technology}`);
1944
+ assert(typeof teeAttestation.nonce === "string" && teeAttestation.nonce.length > 0, "tee attestation nonce missing");
1945
+ assert(typeof teeAttestation.timestamp === "string" && teeAttestation.timestamp.length > 0, "tee attestation timestamp missing");
1946
+ assert(!Number.isNaN(Date.parse(teeAttestation.timestamp)), "tee attestation timestamp is invalid");
1947
+ assert(typeof ((_a = teeAttestation.workload) == null ? void 0 : _a.image_digest) === "string" && teeAttestation.workload.image_digest.length > 0, "workload image digest missing");
1948
+ assert(typeof ((_b = teeAttestation.verifier) == null ? void 0 : _b.image_digest) === "string" && teeAttestation.verifier.image_digest.length > 0, "verifier image digest missing");
1949
+ assert(typeof ((_c = teeAttestation.attestation) == null ? void 0 : _c.token) === "string" && teeAttestation.attestation.token.length > 0, "attestation token missing");
1950
+ }
1951
+ function verifyGcpClaims(teeAttestation, expectedNonce) {
1952
+ return __async(this, null, function* () {
1953
+ var _a;
1954
+ const claims = yield verifyJwtSignature(teeAttestation.attestation.token, EXPECTED_ISSUER);
1955
+ assert(claims.iss === EXPECTED_ISSUER, `unexpected issuer: ${claims.iss}`);
1956
+ assertAudienceClaim(claims.aud);
1957
+ assert(Array.isArray(claims.eat_nonce), "eat_nonce claim missing");
1958
+ const digestBinding = yield sha256Hex(
1959
+ `${teeAttestation.workload.image_digest}
1960
+ ${teeAttestation.verifier.image_digest}`
2337
1961
  );
2338
- if (!isValid) {
2339
- throw new Error("Hardware ECDSA signature is completely invalid!");
1962
+ assert(claims.eat_nonce.includes(expectedNonce), "request nonce is not present in attestation token");
1963
+ assert(claims.eat_nonce.includes(digestBinding), "digest-binding nonce is not present in attestation token");
1964
+ assert(claims.hwmodel === EXPECTED_HW_MODEL, `unexpected hwmodel: ${claims.hwmodel}`);
1965
+ assert(claims.secboot === true, "secure boot claim is not true");
1966
+ assert((_a = claims.submods) == null ? void 0 : _a.gce, "gce submod claim missing");
1967
+ assertTokenFresh(claims);
1968
+ });
1969
+ }
1970
+ function verifyTeeAttestation(proof, appSecret) {
1971
+ return __async(this, null, function* () {
1972
+ assertNonBrowserEnvironment();
1973
+ try {
1974
+ const appId = new import_ethers5.ethers.Wallet(appSecret).address;
1975
+ let teeAttestation = proof.teeAttestation;
1976
+ if (!teeAttestation) {
1977
+ throw new Error("Missing teeAttestation in proof");
1978
+ }
1979
+ if (typeof teeAttestation === "string") {
1980
+ teeAttestation = JSON.parse(teeAttestation);
1981
+ }
1982
+ assertProofShape(teeAttestation);
1983
+ const { parsedContext, nonceDataObj, expectedNonce } = parseProofContext(proof);
1984
+ verifyApplicationAndSessionBinding(proof, parsedContext, nonceDataObj, appId);
1985
+ verifyNonceMaterial(expectedNonce, nonceDataObj, appSecret);
1986
+ const cleanExpectedNonce = normalizeHex(expectedNonce);
1987
+ const cleanTeeNonce = normalizeHex(teeAttestation.nonce);
1988
+ assert(cleanTeeNonce.length > 0, "TEE attestation nonce is empty");
1989
+ assert(isHex(cleanTeeNonce), "TEE attestation nonce is not valid hex");
1990
+ assert(cleanTeeNonce === cleanExpectedNonce, `Nonce Mismatch! Expected ${cleanExpectedNonce}, got ${cleanTeeNonce}`);
1991
+ yield verifyGcpClaims(teeAttestation, cleanExpectedNonce);
1992
+ return { isVerified: true };
1993
+ } catch (error) {
1994
+ logger9.error("TEE attestation verification failed:", error);
1995
+ return {
1996
+ isVerified: false,
1997
+ error: error instanceof Error ? error.message : String(error)
1998
+ };
2340
1999
  }
2341
2000
  });
2342
2001
  }
2343
- function verifyReportData(teeAttestation, proofContext, report) {
2002
+ function runTeeVerification(proofs, config) {
2344
2003
  return __async(this, null, function* () {
2345
- if (!teeAttestation.workload_digest || !teeAttestation.verifier_digest) {
2346
- throw new Error("POLICY CHECK FAILED: Missing workload_digest or verifier_digest in TEE attestation.");
2347
- }
2348
- const { attestationNonce: nonce } = JSON.parse(proofContext);
2349
- const cryptoSubtle = getSubtleCrypto();
2350
- const extractDigestBytes = (imageRef) => {
2351
- const marker = "@sha256:";
2352
- const idx = imageRef.lastIndexOf(marker);
2353
- if (idx < 0) throw new Error(`Image ref missing @sha256: digest: ${imageRef}`);
2354
- const hexDigest = imageRef.substring(idx + marker.length);
2355
- if (hexDigest.length !== 64) throw new Error(`SHA256 digest must be 64 hex chars, got ${hexDigest.length} in: ${imageRef}`);
2356
- const bytes = new Uint8Array(32);
2357
- for (let i = 0; i < 32; i++) bytes[i] = parseInt(hexDigest.substring(i * 2, i * 2 + 2), 16);
2358
- return bytes;
2359
- };
2360
- const importedCosignKey = yield cryptoSubtle.importKey(
2361
- "spki",
2362
- base64ToUint8Array(
2363
- COSIGN_PUBLIC_KEY.replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", "").replace(/\s+/g, "")
2364
- ),
2365
- { name: "ECDSA", namedCurve: "P-256" },
2366
- true,
2367
- ["verify"]
2368
- );
2369
- const pubKeySpkiDer = yield cryptoSubtle.exportKey("spki", importedCosignKey);
2370
- const pubKeyHashBuffer = yield cryptoSubtle.digest("SHA-256", pubKeySpkiDer);
2371
- const pubKeyHashBytes = new Uint8Array(pubKeyHashBuffer);
2372
- const nonceHex = (teeAttestation.nonce || nonce).replace(/^0x/i, "");
2373
- const nonceBytes = new Uint8Array(nonceHex.length / 2);
2374
- for (let i = 0; i < nonceBytes.length; i++) nonceBytes[i] = parseInt(nonceHex.substring(i * 2, i * 2 + 2), 16);
2375
- const workloadBytes = extractDigestBytes(teeAttestation.workload_digest);
2376
- const verifierBytes = extractDigestBytes(teeAttestation.verifier_digest);
2377
- const domainSep = new TextEncoder().encode("POPCORN_TEE_REPORT_DATA_V1");
2378
- const version = new Uint8Array([1]);
2379
- const payload = new Uint8Array(
2380
- domainSep.length + version.length + workloadBytes.length + verifierBytes.length + pubKeyHashBytes.length + nonceBytes.length
2004
+ const hasTeeData = proofs.every((proof) => {
2005
+ if (proof.teeAttestation) return true;
2006
+ try {
2007
+ const context = JSON.parse(proof.claimData.context);
2008
+ return !!(context == null ? void 0 : context.attestationNonce);
2009
+ } catch (e) {
2010
+ return false;
2011
+ }
2012
+ });
2013
+ if (!hasTeeData) {
2014
+ throw new TeeVerificationError("TEE verification requested but one or more proofs are missing TEE attestation data");
2015
+ }
2016
+ const teeResults = yield Promise.all(
2017
+ proofs.map((proof) => verifyTeeAttestation(proof, config.appSecret))
2381
2018
  );
2382
- let offset = 0;
2383
- for (const chunk of [domainSep, version, workloadBytes, verifierBytes, pubKeyHashBytes, nonceBytes]) {
2384
- payload.set(chunk, offset);
2385
- offset += chunk.length;
2386
- }
2387
- const hashBuffer = yield cryptoSubtle.digest("SHA-256", payload);
2388
- const hashHex = arrayBufferToHex(hashBuffer);
2389
- const expected64ByteHex = hashHex + hashHex;
2390
- if (report.reportData !== expected64ByteHex) {
2391
- throw new Error(`REPORT_DATA Mismatch! Hardware report is not bound to these image digests or nonce.
2392
- Expected: ${expected64ByteHex}
2393
- Got: ${report.reportData}`);
2019
+ if (!teeResults.every((r) => r.isVerified)) {
2020
+ throw new TeeVerificationError("TEE attestation verification failed for one or more proofs");
2394
2021
  }
2395
2022
  });
2396
2023
  }
@@ -2413,29 +2040,15 @@ function verifyProof(proofOrProofs, config) {
2413
2040
  yield assertVerifiedProof(proof, attestors);
2414
2041
  }
2415
2042
  yield assertValidateProof(proofs, config);
2416
- let isTeeVerified = void 0;
2417
- if (config.verifyTEE) {
2418
- const hasTeeData = proofs.every((proof) => proof.teeAttestation || JSON.parse(proof.claimData.context).attestationNonce);
2419
- if (!hasTeeData) {
2420
- const teeError = new TeeVerificationError("TEE verification requested but one or more proofs are missing TEE attestation data");
2421
- logger10.error(teeError.message);
2422
- return createVerifyProofResultFailure(teeError, false);
2423
- }
2424
- try {
2425
- const teeResults = yield Promise.all(proofs.map((proof) => verifyTeeAttestation(proof)));
2426
- isTeeVerified = teeResults.every((r) => r === true);
2427
- if (!isTeeVerified) {
2428
- const teeError = new TeeVerificationError("TEE attestation verification failed for one or more proofs");
2429
- logger10.error(teeError.message);
2430
- return createVerifyProofResultFailure(teeError, false);
2431
- }
2432
- } catch (error) {
2433
- const teeError = new TeeVerificationError("Error verifying TEE attestation", error);
2434
- logger10.error(teeError.message);
2435
- return createVerifyProofResultFailure(teeError, false);
2436
- }
2043
+ let isTeeAttestationVerified;
2044
+ if (config.teeAttestation && "dangerouslyDisableContentValidation" in config && config.dangerouslyDisableContentValidation) {
2045
+ logger10.warn("teeAttestation is enabled but content validation is disabled \u2014 TEE attestation alone does not guarantee proof contents are valid");
2437
2046
  }
2438
- return createVerifyProofResultSuccess(proofs, isTeeVerified);
2047
+ if (config.teeAttestation) {
2048
+ yield runTeeVerification(proofs, config.teeAttestation);
2049
+ isTeeAttestationVerified = true;
2050
+ }
2051
+ return createVerifyProofResultSuccess(proofs, isTeeAttestationVerified);
2439
2052
  } catch (error) {
2440
2053
  logger10.error("Error in validating proof:", error);
2441
2054
  const _error = error instanceof Error ? error : new Error(String(error));
@@ -2698,11 +2311,13 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
2698
2311
  proofRequestInstance.resolvedProviderVersion = data.resolvedProviderVersion;
2699
2312
  proofRequestInstance.context.reclaimSessionId = data.sessionId;
2700
2313
  if (options == null ? void 0 : options.acceptTeeAttestation) {
2701
- const wallet = new import_ethers5.ethers.Wallet(appSecret);
2702
- const nonceData = `${applicationId}:${data.sessionId}:${proofRequestInstance.timeStamp}`;
2703
- const nonceMsg = import_ethers5.ethers.getBytes(import_ethers5.ethers.keccak256(new TextEncoder().encode(nonceData)));
2704
- const nonceSignature = yield wallet.signMessage(nonceMsg);
2705
- proofRequestInstance.setAttestationContext(nonceSignature, {
2314
+ const attestationNonce = generateAttestationNonce(
2315
+ appSecret,
2316
+ applicationId,
2317
+ data.sessionId,
2318
+ proofRequestInstance.timeStamp
2319
+ );
2320
+ proofRequestInstance.setAttestationContext(attestationNonce, {
2706
2321
  applicationId,
2707
2322
  sessionId: data.sessionId,
2708
2323
  timestamp: proofRequestInstance.timeStamp
@@ -3223,13 +2838,13 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
3223
2838
  generateSignature(applicationSecret) {
3224
2839
  return __async(this, null, function* () {
3225
2840
  try {
3226
- const wallet = new import_ethers5.ethers.Wallet(applicationSecret);
2841
+ const wallet = new import_ethers6.ethers.Wallet(applicationSecret);
3227
2842
  const canonicalData = (0, import_canonicalize3.default)({ providerId: this.providerId, timestamp: this.timeStamp });
3228
2843
  if (!canonicalData) {
3229
2844
  throw new SignatureGeneratingError("Failed to canonicalize data for signing.");
3230
2845
  }
3231
- const messageHash = import_ethers5.ethers.keccak256(new TextEncoder().encode(canonicalData));
3232
- return yield wallet.signMessage(import_ethers5.ethers.getBytes(messageHash));
2846
+ const messageHash = import_ethers6.ethers.keccak256(new TextEncoder().encode(canonicalData));
2847
+ return yield wallet.signMessage(import_ethers6.ethers.getBytes(messageHash));
3233
2848
  } catch (err) {
3234
2849
  logger10.info(`Error generating proof request for applicationId: ${this.applicationId}, providerId: ${this.providerId}, timeStamp: ${this.timeStamp}`);
3235
2850
  throw new SignatureGeneratingError(`Error generating signature for applicationId: ${this.applicationId}`);
@@ -3917,6 +3532,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
3917
3532
  isHttpProviderClaimParams,
3918
3533
  isMobileDevice,
3919
3534
  recoverSignersOfSignedClaim,
3535
+ runTeeVerification,
3920
3536
  takePairsWhereValueIsArray,
3921
3537
  takeTemplateParametersFromProofs,
3922
3538
  transformForOnchain,