@reclaimprotocol/js-sdk 5.1.0 → 5.3.0-dev.1

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.3.0-dev.1",
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,309 +1688,313 @@ 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
- MIIGjzCCBD6gAwIBAgIDAQEBMEYGCSqGSIb3DQEBCjA5oA8wDQYJYIZIAWUDBAIC
1683
- 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
- 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
- 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
- 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
- MjI0NTI0WjCBgDEUMBIGA1UECwwLRW5naW5lZXJpbmcxCzAJBgNVBAYTAlVTMRQw
1688
- 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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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
- KDZ3LpZt9/Crg6zyPpXDLR/tLHHpSaPRj7CTzHieKMTz+Q6RrCCQcHGfaAD/ETNY
1698
- 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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
- MIIGjzCCBD6gAwIBAgIDAgEBMEYGCSqGSIb3DQEBCjA5oA8wDQYJYIZIAWUDBAIC
1758
- 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
- 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
- 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
- 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
- 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
- EgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExHzAdBgNVBAoMFkFkdmFu
1764
- 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
- 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
- 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
- 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
- s8C0WwW/IWY9j6pNbEA1SnUvVg6t89zfE+AcB5UDCKq09x7qw+rPt9pTpEch0f1b
1769
- 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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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
- AQEKMDmgDzANBglghkgBZQMEAgIFAKEcMBoGCSqGSIb3DQEBCDANBglghkgBZQME
1781
- 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
- 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
- +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
- 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
- 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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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
- 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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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
- tz4oMxq8JKWJ8Po1CXLzKcfrTphjlbkh8AVKMXeBd2SpM33B1YP4g1BOdk013kqb
1822
- 7bRHZ1iB2JHG5cMKKbwRCSAAGHLTzASgDcXr9Fp7Z3liDhGu/ci1opGmkp12QNiJ
1823
- uBbkTU+xDZHm5X8Jm99BX7NEpzlOwIVR8ClgBDyuBkBC2ljtr3ZSaUIYj2xuyWN9
1824
- 5KFY49nWxcz90CFa3Hzmy4zMQmBe9dVyls5eL5p9bkXcgRMDTbgmVZiAf4afe8DL
1825
- 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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 SUPPORTED_PROOF_VERSIONS = ["v2", "v3"];
1698
+ var TOKEN_CLOCK_SKEW_S = 60;
1699
+ var NONCE_TIMESTAMP_MAX_SKEW_MS = 10 * 60 * 1e3;
1700
+ var BROWSER_ENVIRONMENT_ERROR = "TEE attestation verification is only supported in non-browser environments. Run verifyTeeAttestation on your server or API route.";
1701
+ function assert(condition, message) {
1702
+ if (!condition) {
1703
+ throw new Error(message);
1839
1704
  }
1840
- if (input instanceof Uint8Array) {
1841
- return new Uint8Array(input);
1705
+ }
1706
+ function isBrowserEnvironment() {
1707
+ if (typeof window !== "undefined" || typeof document !== "undefined") {
1708
+ return true;
1842
1709
  }
1843
- if (typeof ArrayBuffer !== "undefined" && input instanceof ArrayBuffer) {
1844
- return new Uint8Array(input);
1710
+ if (typeof navigator !== "undefined" && typeof process === "undefined") {
1711
+ return true;
1845
1712
  }
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);
1713
+ const workerGlobalScope = globalThis.WorkerGlobalScope;
1714
+ if (typeof workerGlobalScope !== "undefined" && typeof self !== "undefined" && self instanceof workerGlobalScope) {
1715
+ return true;
1854
1716
  }
1855
- return result;
1717
+ return false;
1856
1718
  }
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);
1719
+ function assertNonBrowserEnvironment() {
1720
+ if (isBrowserEnvironment()) {
1721
+ throw new Error(BROWSER_ENVIRONMENT_ERROR);
1861
1722
  }
1862
- return result;
1863
1723
  }
1864
- function base64ToUint8Array(base64) {
1865
- if (typeof atob === "function") {
1866
- const binary = atob(base64);
1867
- return binaryStringToUint8Array(binary);
1868
- }
1724
+ function normalizeHex(value) {
1725
+ return (value || "").trim().replace(/^0x/i, "").toLowerCase();
1726
+ }
1727
+ function isHex(value) {
1728
+ return /^[0-9a-f]+$/i.test(value);
1729
+ }
1730
+ function decodeBase64Url(input) {
1731
+ const normalized = input.replace(/-/g, "+").replace(/_/g, "/");
1732
+ const padded = normalized + "=".repeat((4 - normalized.length % 4) % 4);
1869
1733
  if (typeof Buffer !== "undefined") {
1870
- return new Uint8Array(Buffer.from(base64, "base64"));
1734
+ return new Uint8Array(Buffer.from(padded, "base64"));
1735
+ }
1736
+ if (typeof atob === "function") {
1737
+ const binary = atob(padded);
1738
+ const bytes = new Uint8Array(binary.length);
1739
+ for (let i = 0; i < binary.length; i += 1) {
1740
+ bytes[i] = binary.charCodeAt(i);
1741
+ }
1742
+ return bytes;
1871
1743
  }
1872
1744
  throw new Error("Base64 decoding is not supported in this environment");
1873
1745
  }
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");
1746
+ function decodeUtf8(bytes) {
1747
+ return new TextDecoder().decode(bytes);
1748
+ }
1749
+ function decodeJwt(token) {
1750
+ const parts = token.split(".");
1751
+ assert(parts.length === 3, "attestation token is not a JWT");
1752
+ return {
1753
+ header: JSON.parse(decodeUtf8(decodeBase64Url(parts[0]))),
1754
+ payload: JSON.parse(decodeUtf8(decodeBase64Url(parts[1]))),
1755
+ signingInput: `${parts[0]}.${parts[1]}`,
1756
+ signature: decodeBase64Url(parts[2])
1757
+ };
1758
+ }
1759
+ function getFetch() {
1760
+ const fetchFn = globalThis.fetch;
1761
+ assert(fetchFn, "fetch is not available in this environment");
1762
+ return fetchFn.bind(globalThis);
1763
+ }
1764
+ function getSubtleCrypto() {
1765
+ var _a, _b, _c;
1766
+ if ((_a = globalThis.crypto) == null ? void 0 : _a.subtle) {
1767
+ return globalThis.crypto.subtle;
1768
+ }
1769
+ const nodeCrypto = typeof process !== "undefined" && ((_b = process.versions) == null ? void 0 : _b.node) ? require("crypto") : void 0;
1770
+ if ((_c = nodeCrypto == null ? void 0 : nodeCrypto.webcrypto) == null ? void 0 : _c.subtle) {
1771
+ return nodeCrypto.webcrypto.subtle;
1772
+ }
1773
+ throw new Error("WebCrypto subtle is not available in this environment");
1774
+ }
1775
+ function fetchJson(url) {
1776
+ return __async(this, null, function* () {
1777
+ const response = yield getFetch()(url);
1778
+ if (!response.ok) {
1779
+ throw new Error(`GET ${url} returned ${response.status} ${response.statusText}`);
1780
+ }
1781
+ return response.json();
1782
+ });
1783
+ }
1784
+ function sha256Hex(input) {
1785
+ return __async(this, null, function* () {
1786
+ const digest = yield getSubtleCrypto().digest("SHA-256", new TextEncoder().encode(input));
1787
+ return Array.from(new Uint8Array(digest), (value) => value.toString(16).padStart(2, "0")).join("");
1788
+ });
1789
+ }
1790
+ var JWKS_CACHE_TTL_MS = 5 * 60 * 1e3;
1791
+ var cachedJwksUri = null;
1792
+ var cachedJwksKeys = null;
1793
+ var cachedJwksAt = 0;
1794
+ function verifyJwtSignature(token, issuer) {
1795
+ return __async(this, null, function* () {
1796
+ const { header, payload, signingInput, signature } = decodeJwt(token);
1797
+ assert(header.alg === "RS256", `unexpected attestation signing algorithm: ${header.alg}`);
1798
+ assert(typeof header.kid === "string" && header.kid.length > 0, "attestation token kid is missing");
1799
+ const isCacheFresh = cachedJwksKeys && Date.now() - cachedJwksAt < JWKS_CACHE_TTL_MS;
1800
+ if (!isCacheFresh) {
1801
+ const oidc = yield fetchJson(`${issuer}/.well-known/openid-configuration`);
1802
+ assert(typeof (oidc == null ? void 0 : oidc.jwks_uri) === "string" && oidc.jwks_uri.length > 0, "issuer JWKS URI is missing");
1803
+ cachedJwksUri = oidc.jwks_uri;
1804
+ const jwks = yield fetchJson(cachedJwksUri);
1805
+ cachedJwksKeys = (jwks == null ? void 0 : jwks.keys) || [];
1806
+ cachedJwksAt = Date.now();
1807
+ }
1808
+ const jwk = cachedJwksKeys.find((key) => key.kid === header.kid);
1809
+ assert(jwk, `no JWKS key found for kid ${header.kid}`);
1810
+ const cryptoKey = yield getSubtleCrypto().importKey(
1811
+ "jwk",
1812
+ jwk,
1813
+ { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" },
1814
+ false,
1815
+ ["verify"]
1816
+ );
1817
+ const isValid = yield getSubtleCrypto().verify(
1818
+ "RSASSA-PKCS1-v1_5",
1819
+ cryptoKey,
1820
+ signature,
1821
+ new TextEncoder().encode(signingInput)
1822
+ );
1823
+ assert(isValid, "JWT signature verification failed");
1824
+ return payload;
1825
+ });
1826
+ }
1827
+ function isNonceContextData(obj) {
1828
+ if (!obj || typeof obj !== "object") return false;
1829
+ const o = obj;
1830
+ 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;
1831
+ }
1832
+ function parseProofContext(proof) {
1833
+ let parsedContext;
1834
+ try {
1835
+ parsedContext = JSON.parse(proof.claimData.context);
1836
+ } catch (e) {
1837
+ throw new Error("Malformed proof: claimData.context is not valid JSON");
1838
+ }
1839
+ if (!parsedContext || typeof parsedContext !== "object") {
1840
+ throw new Error("Malformed proof: claimData.context is not a JSON object");
1841
+ }
1842
+ const ctx = parsedContext;
1843
+ const expectedNonce = ctx.attestationNonce;
1844
+ assert(typeof expectedNonce === "string" && expectedNonce.length > 0, "Proof context is missing attestationNonce");
1845
+ const nonceDataObj = ctx.attestationNonceData;
1846
+ assert(isNonceContextData(nonceDataObj), "Proof context is missing or has invalid attestationNonceData (requires applicationId, sessionId, timestamp)");
1847
+ return { parsedContext: ctx, nonceDataObj, expectedNonce };
1848
+ }
1849
+ function verifyApplicationAndSessionBinding(proof, parsedContext, nonceDataObj, expectedApplicationId) {
1850
+ var _a;
1851
+ const { applicationId, sessionId, timestamp } = nonceDataObj;
1852
+ if (expectedApplicationId) {
1853
+ assert(
1854
+ applicationId.toLowerCase() === expectedApplicationId.toLowerCase(),
1855
+ `Application ID Mismatch! Expected ${expectedApplicationId}, but proof context contains ${applicationId}`
1856
+ );
1857
+ }
1858
+ let parsedParameters = {};
1859
+ if (proof.claimData.parameters) {
1860
+ try {
1861
+ const parsed = JSON.parse(proof.claimData.parameters);
1862
+ parsedParameters = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
1863
+ } catch (e) {
1864
+ throw new Error("Malformed proof: claimData.parameters is not valid JSON");
1865
+ }
1866
+ }
1867
+ const contextSessionId = parsedContext == null ? void 0 : parsedContext.reclaimSessionId;
1868
+ const parameterSessionId = (_a = parsedParameters == null ? void 0 : parsedParameters.proxySessionId) != null ? _a : parsedParameters == null ? void 0 : parsedParameters.sessionId;
1869
+ if (contextSessionId && contextSessionId.toString() !== sessionId.toString()) {
1870
+ throw new Error(`Session ID Mismatch! Expected ${sessionId}, but proof context contains reclaimSessionId=${contextSessionId}`);
1871
+ }
1872
+ if (parameterSessionId && parameterSessionId.toString() !== sessionId.toString()) {
1873
+ throw new Error(`Session ID Mismatch! Expected ${sessionId}, but proof parameters contain ${parameterSessionId}`);
1874
+ }
1875
+ if (!contextSessionId && !parameterSessionId) {
1876
+ throw new Error("Proof is missing reclaimSessionId and proxySessionId/sessionId for attestation nonce verification");
1877
+ }
1878
+ const claimTimestampMs = proof.claimData.timestampS * 1e3;
1879
+ const nonceTimestampMs = parseInt(timestamp, 10);
1880
+ const diffMs = Math.abs(claimTimestampMs - nonceTimestampMs);
1881
+ if (diffMs > NONCE_TIMESTAMP_MAX_SKEW_MS) {
1882
+ throw new Error(`Timestamp Skew Too Large! claimData.timestampS and attestationNonce timestamp differ by ${Math.round(diffMs / 1e3)}s (limit: 600s)`);
1879
1883
  }
1880
- return hex;
1881
1884
  }
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;
1885
+ function verifyNonceMaterial(expectedNonce, nonceDataObj, expectedAppSecret) {
1886
+ const cleanExpectedNonce = normalizeHex(expectedNonce);
1887
+ const { applicationId, sessionId, timestamp } = nonceDataObj;
1888
+ assert(cleanExpectedNonce.length > 0, "Proof context attestationNonce is empty");
1889
+ assert(isHex(cleanExpectedNonce), "Proof context attestationNonce is not valid hex");
1890
+ if (expectedAppSecret) {
1891
+ const recomputedNonce = generateAttestationNonce(expectedAppSecret, applicationId, sessionId, timestamp);
1892
+ assert(
1893
+ recomputedNonce === cleanExpectedNonce,
1894
+ "Attestation nonce verification failed: app secret, application ID, session ID, or timestamp do not match"
1895
+ );
1896
+ return;
1897
+ }
1898
+ if (cleanExpectedNonce.length > 74) {
1899
+ const legacyNonceData = `${applicationId}:${sessionId}:${timestamp}`;
1900
+ const nonceMsg = import_ethers5.ethers.getBytes(import_ethers5.ethers.keccak256(new TextEncoder().encode(legacyNonceData)));
1901
+ const recoveredAddress = import_ethers5.ethers.verifyMessage(
1902
+ nonceMsg,
1903
+ expectedNonce.startsWith("0x") ? expectedNonce : `0x${expectedNonce}`
1904
+ );
1905
+ assert(
1906
+ recoveredAddress.toLowerCase() === applicationId.toLowerCase(),
1907
+ `Nonce signature verification failed: recovered ${recoveredAddress}, expected ${applicationId}`
1908
+ );
1909
+ return;
1889
1910
  }
1890
- return result;
1911
+ throw new Error("App secret is required to verify hash-based attestation nonces");
1891
1912
  }
1892
- function reverseBytes(bytes) {
1893
- const copy = Uint8Array.from(bytes);
1894
- copy.reverse();
1895
- return copy;
1913
+ function assertTokenFresh(claims) {
1914
+ const now = Math.floor(Date.now() / 1e3);
1915
+ if (typeof claims.nbf === "number" && now + TOKEN_CLOCK_SKEW_S < claims.nbf) {
1916
+ throw new Error(`Attestation token is not valid before ${claims.nbf}`);
1917
+ }
1918
+ if (typeof claims.exp === "number" && now - TOKEN_CLOCK_SKEW_S > claims.exp) {
1919
+ throw new Error(`Attestation token expired at ${claims.exp}`);
1920
+ }
1921
+ if (typeof claims.iat === "number" && claims.iat > now + TOKEN_CLOCK_SKEW_S) {
1922
+ throw new Error(`Attestation token issued-at ${claims.iat} is in the future`);
1923
+ }
1896
1924
  }
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;
1925
+ function assertAudienceClaim(aud) {
1926
+ if (typeof aud === "string") {
1927
+ assert(aud.length > 0, "attestation token audience is empty");
1928
+ return;
1929
+ }
1930
+ if (Array.isArray(aud)) {
1931
+ assert(aud.length > 0, "attestation token audience is empty");
1932
+ assert(aud.every((entry) => typeof entry === "string" && entry.length > 0), "attestation token audience contains invalid entries");
1933
+ return;
1934
+ }
1935
+ throw new Error("attestation token audience is missing");
1901
1936
  }
1902
- var isNode = typeof process !== "undefined" && process.versions && process.versions.node;
1903
- var getSubtleCrypto = () => {
1937
+ function getProofVersion(teeAttestation) {
1904
1938
  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);
1936
- 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
1944
- };
1939
+ return (_a = teeAttestation.proof_version) != null ? _a : teeAttestation.proofVersion;
1940
+ }
1941
+ function assertProofShape(teeAttestation) {
1942
+ var _a, _b, _c;
1943
+ if (teeAttestation.error) {
1944
+ throw new Error(`${teeAttestation.error.code}: ${teeAttestation.error.message}`);
1945
+ }
1946
+ const proofVersion = getProofVersion(teeAttestation);
1947
+ assert(typeof proofVersion === "string" && SUPPORTED_PROOF_VERSIONS.includes(proofVersion), `unexpected proof version: ${proofVersion}`);
1948
+ assert(teeAttestation.tee_provider === EXPECTED_TEE_PROVIDER, `unexpected tee provider: ${teeAttestation.tee_provider}`);
1949
+ assert(teeAttestation.tee_technology === EXPECTED_TEE_TECHNOLOGY, `unexpected tee technology: ${teeAttestation.tee_technology}`);
1950
+ assert(typeof teeAttestation.nonce === "string" && teeAttestation.nonce.length > 0, "tee attestation nonce missing");
1951
+ assert(typeof teeAttestation.timestamp === "string" && teeAttestation.timestamp.length > 0, "tee attestation timestamp missing");
1952
+ assert(!Number.isNaN(Date.parse(teeAttestation.timestamp)), "tee attestation timestamp is invalid");
1953
+ assert(typeof ((_a = teeAttestation.workload) == null ? void 0 : _a.image_digest) === "string" && teeAttestation.workload.image_digest.length > 0, "workload image digest missing");
1954
+ assert(typeof ((_b = teeAttestation.verifier) == null ? void 0 : _b.image_digest) === "string" && teeAttestation.verifier.image_digest.length > 0, "verifier image digest missing");
1955
+ assert(typeof ((_c = teeAttestation.attestation) == null ? void 0 : _c.token) === "string" && teeAttestation.attestation.token.length > 0, "attestation token missing");
1956
+ }
1957
+ function computeDigestBinding(teeAttestation) {
1958
+ return __async(this, null, function* () {
1959
+ const proofVersion = getProofVersion(teeAttestation);
1960
+ if (proofVersion === "v3") {
1961
+ assert(typeof teeAttestation.workload.container_name === "string" && teeAttestation.workload.container_name.length > 0, "workload container name missing");
1962
+ assert(typeof teeAttestation.verifier.container_name === "string" && teeAttestation.verifier.container_name.length > 0, "verifier container name missing");
1963
+ return sha256Hex([
1964
+ "v3",
1965
+ `workload.container_name=${teeAttestation.workload.container_name}`,
1966
+ `workload.image_digest=${teeAttestation.workload.image_digest}`,
1967
+ `verifier.container_name=${teeAttestation.verifier.container_name}`,
1968
+ `verifier.image_digest=${teeAttestation.verifier.image_digest}`
1969
+ ].join("\n"));
1970
+ }
1971
+ return sha256Hex(
1972
+ `${teeAttestation.workload.image_digest}
1973
+ ${teeAttestation.verifier.image_digest}`
1974
+ );
1975
+ });
1945
1976
  }
1946
- function verifySignature(publicKeyPem, data, signature, sigAlgOid) {
1977
+ function verifyGcpClaims(teeAttestation, expectedNonce) {
1947
1978
  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" };
1965
- }
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)})`);
1979
+ var _a;
1980
+ const claims = yield verifyJwtSignature(teeAttestation.attestation.token, EXPECTED_ISSUER);
1981
+ assert(claims.iss === EXPECTED_ISSUER, `unexpected issuer: ${claims.iss}`);
1982
+ assertAudienceClaim(claims.aud);
1983
+ assert(Array.isArray(claims.eat_nonce), "eat_nonce claim missing");
1984
+ const digestBinding = yield computeDigestBinding(teeAttestation);
1985
+ assert(claims.eat_nonce.includes(expectedNonce), "request nonce is not present in attestation token");
1986
+ assert(claims.eat_nonce.includes(digestBinding), "digest-binding nonce is not present in attestation token");
1987
+ assert(claims.hwmodel === EXPECTED_HW_MODEL, `unexpected hwmodel: ${claims.hwmodel}`);
1988
+ assert(claims.secboot === true, "secure boot claim is not true");
1989
+ assert((_a = claims.submods) == null ? void 0 : _a.gce, "gce submod claim missing");
1990
+ assertTokenFresh(claims);
1969
1991
  });
1970
1992
  }
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) {
1993
+ function verifyTeeAttestation(proof, appSecret) {
1977
1994
  return __async(this, null, function* () {
1995
+ assertNonBrowserEnvironment();
1978
1996
  try {
1997
+ const appId = new import_ethers5.ethers.Wallet(appSecret).address;
1979
1998
  let teeAttestation = proof.teeAttestation;
1980
1999
  if (!teeAttestation) {
1981
2000
  throw new Error("Missing teeAttestation in proof");
@@ -1983,414 +2002,45 @@ function verifyTeeAttestation(proof, expectedApplicationId) {
1983
2002
  if (typeof teeAttestation === "string") {
1984
2003
  teeAttestation = JSON.parse(teeAttestation);
1985
2004
  }
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;
2005
+ assertProofShape(teeAttestation);
2006
+ const { parsedContext, nonceDataObj, expectedNonce } = parseProofContext(proof);
2007
+ verifyApplicationAndSessionBinding(proof, parsedContext, nonceDataObj, appId);
2008
+ verifyNonceMaterial(expectedNonce, nonceDataObj, appSecret);
2009
+ const cleanExpectedNonce = normalizeHex(expectedNonce);
2010
+ const cleanTeeNonce = normalizeHex(teeAttestation.nonce);
2011
+ assert(cleanTeeNonce.length > 0, "TEE attestation nonce is empty");
2012
+ assert(isHex(cleanTeeNonce), "TEE attestation nonce is not valid hex");
2013
+ assert(cleanTeeNonce === cleanExpectedNonce, `Nonce Mismatch! Expected ${cleanExpectedNonce}, got ${cleanTeeNonce}`);
2014
+ yield verifyGcpClaims(teeAttestation, cleanExpectedNonce);
2015
+ return { isVerified: true };
2044
2016
  } catch (error) {
2045
2017
  logger9.error("TEE attestation verification failed:", error);
2046
- return false;
2047
- }
2048
- });
2049
- }
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) {
2146
- 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" },
2204
- false,
2205
- ["verify"]
2206
- );
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
2213
- );
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
- }
2018
+ return {
2019
+ isVerified: false,
2020
+ error: error instanceof Error ? error.message : String(error)
2021
+ };
2228
2022
  }
2229
2023
  });
2230
2024
  }
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()})`);
2235
- }
2236
- if (cert.notAfter && now > cert.notAfter.getTime()) {
2237
- throw new Error(`${label} certificate expired on ${cert.notAfter.toISOString()}`);
2238
- }
2239
- }
2240
- function verifyAMDChain(vlekCertBuffer) {
2025
+ function runTeeVerification(proofs, config) {
2241
2026
  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;
2027
+ const hasTeeData = proofs.every((proof) => {
2028
+ if (proof.teeAttestation) return true;
2248
2029
  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;
2030
+ const context = JSON.parse(proof.claimData.context);
2031
+ return !!(context == null ? void 0 : context.attestationNonce);
2295
2032
  } catch (e) {
2296
- if (matchedChain) {
2297
- throw e;
2298
- }
2299
- continue;
2033
+ return false;
2300
2034
  }
2035
+ });
2036
+ if (!hasTeeData) {
2037
+ throw new TeeVerificationError("TEE verification requested but one or more proofs are missing TEE attestation data");
2301
2038
  }
2302
- if (!chainVerified) {
2303
- throw new Error("VLEK Certificate failed verification against all known AMD Root of Trust chains!");
2304
- }
2305
- });
2306
- }
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"]
2323
- );
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
2337
- );
2338
- if (!isValid) {
2339
- throw new Error("Hardware ECDSA signature is completely invalid!");
2340
- }
2341
- });
2342
- }
2343
- function verifyReportData(teeAttestation, proofContext, report) {
2344
- 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"]
2039
+ const teeResults = yield Promise.all(
2040
+ proofs.map((proof) => verifyTeeAttestation(proof, config.appSecret))
2368
2041
  );
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
2381
- );
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}`);
2042
+ if (!teeResults.every((r) => r.isVerified)) {
2043
+ throw new TeeVerificationError("TEE attestation verification failed for one or more proofs");
2394
2044
  }
2395
2045
  });
2396
2046
  }
@@ -2398,6 +2048,7 @@ Got: ${report.reportData}`);
2398
2048
  // src/Reclaim.ts
2399
2049
  var logger10 = logger_default.logger;
2400
2050
  var sdkVersion = require_package().version;
2051
+ var SDK_TEE_ATTESTATION_VERSION = "v3";
2401
2052
  function verifyProof(proofOrProofs, config) {
2402
2053
  return __async(this, null, function* () {
2403
2054
  const proofs = Array.isArray(proofOrProofs) ? proofOrProofs : [proofOrProofs];
@@ -2413,29 +2064,15 @@ function verifyProof(proofOrProofs, config) {
2413
2064
  yield assertVerifiedProof(proof, attestors);
2414
2065
  }
2415
2066
  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
- }
2067
+ let isTeeAttestationVerified;
2068
+ if (config.teeAttestation && "dangerouslyDisableContentValidation" in config && config.dangerouslyDisableContentValidation) {
2069
+ logger10.warn("teeAttestation is enabled but content validation is disabled \u2014 TEE attestation alone does not guarantee proof contents are valid");
2437
2070
  }
2438
- return createVerifyProofResultSuccess(proofs, isTeeVerified);
2071
+ if (config.teeAttestation) {
2072
+ yield runTeeVerification(proofs, config.teeAttestation);
2073
+ isTeeAttestationVerified = true;
2074
+ }
2075
+ return createVerifyProofResultSuccess(proofs, isTeeAttestationVerified);
2439
2076
  } catch (error) {
2440
2077
  logger10.error("Error in validating proof:", error);
2441
2078
  const _error = error instanceof Error ? error : new Error(String(error));
@@ -2498,7 +2135,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
2498
2135
  * @returns
2499
2136
  */
2500
2137
  this.getTemplateData = () => {
2501
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
2138
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
2502
2139
  if (!this.signature) {
2503
2140
  throw new SignatureNotFoundError("Signature is not set.");
2504
2141
  }
@@ -2538,7 +2175,9 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
2538
2175
  log: (_h = (_g = this.options) == null ? void 0 : _g.log) != null ? _h : false,
2539
2176
  canAutoSubmit: (_j = (_i = this.options) == null ? void 0 : _i.canAutoSubmit) != null ? _j : true,
2540
2177
  metadata: (_k = this.options) == null ? void 0 : _k.metadata,
2541
- preferredLocale: (_l = this.options) == null ? void 0 : _l.preferredLocale
2178
+ preferredLocale: (_l = this.options) == null ? void 0 : _l.preferredLocale,
2179
+ acceptTeeAttestation: (_m = this.options) == null ? void 0 : _m.acceptTeeAttestation,
2180
+ teeAttestationVersion: (_o = (_n = this.context.attestationNonceData) == null ? void 0 : _n.attestationVersion) != null ? _o : SDK_TEE_ATTESTATION_VERSION
2542
2181
  };
2543
2182
  return templateData;
2544
2183
  };
@@ -2609,6 +2248,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
2609
2248
  */
2610
2249
  static init(applicationId, appSecret, providerId, options) {
2611
2250
  return __async(this, null, function* () {
2251
+ var _a;
2612
2252
  try {
2613
2253
  validateFunctionParams([
2614
2254
  { paramName: "applicationId", input: applicationId, isString: true },
@@ -2690,22 +2330,28 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
2690
2330
  }, "the constructor");
2691
2331
  }
2692
2332
  }
2693
- const proofRequestInstance = new _ReclaimProofRequest(applicationId, providerId, options);
2333
+ const proofRequestOptions = __spreadProps(__spreadValues({}, options), {
2334
+ acceptTeeAttestation: (_a = options == null ? void 0 : options.acceptTeeAttestation) != null ? _a : true
2335
+ });
2336
+ const proofRequestInstance = new _ReclaimProofRequest(applicationId, providerId, proofRequestOptions);
2694
2337
  const signature = yield proofRequestInstance.generateSignature(appSecret);
2695
2338
  proofRequestInstance.setSignature(signature);
2696
2339
  const data = yield initSession(providerId, applicationId, proofRequestInstance.timeStamp, signature, options == null ? void 0 : options.providerVersion);
2697
2340
  proofRequestInstance.sessionId = data.sessionId;
2698
2341
  proofRequestInstance.resolvedProviderVersion = data.resolvedProviderVersion;
2699
2342
  proofRequestInstance.context.reclaimSessionId = data.sessionId;
2700
- 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, {
2343
+ if (proofRequestOptions.acceptTeeAttestation) {
2344
+ const attestationNonce = generateAttestationNonce(
2345
+ appSecret,
2346
+ applicationId,
2347
+ data.sessionId,
2348
+ proofRequestInstance.timeStamp
2349
+ );
2350
+ proofRequestInstance.setAttestationContext(attestationNonce, {
2706
2351
  applicationId,
2707
2352
  sessionId: data.sessionId,
2708
- timestamp: proofRequestInstance.timeStamp
2353
+ timestamp: proofRequestInstance.timeStamp,
2354
+ attestationVersion: SDK_TEE_ATTESTATION_VERSION
2709
2355
  });
2710
2356
  }
2711
2357
  return proofRequestInstance;
@@ -3223,13 +2869,13 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
3223
2869
  generateSignature(applicationSecret) {
3224
2870
  return __async(this, null, function* () {
3225
2871
  try {
3226
- const wallet = new import_ethers5.ethers.Wallet(applicationSecret);
2872
+ const wallet = new import_ethers6.ethers.Wallet(applicationSecret);
3227
2873
  const canonicalData = (0, import_canonicalize3.default)({ providerId: this.providerId, timestamp: this.timeStamp });
3228
2874
  if (!canonicalData) {
3229
2875
  throw new SignatureGeneratingError("Failed to canonicalize data for signing.");
3230
2876
  }
3231
- const messageHash = import_ethers5.ethers.keccak256(new TextEncoder().encode(canonicalData));
3232
- return yield wallet.signMessage(import_ethers5.ethers.getBytes(messageHash));
2877
+ const messageHash = import_ethers6.ethers.keccak256(new TextEncoder().encode(canonicalData));
2878
+ return yield wallet.signMessage(import_ethers6.ethers.getBytes(messageHash));
3233
2879
  } catch (err) {
3234
2880
  logger10.info(`Error generating proof request for applicationId: ${this.applicationId}, providerId: ${this.providerId}, timeStamp: ${this.timeStamp}`);
3235
2881
  throw new SignatureGeneratingError(`Error generating signature for applicationId: ${this.applicationId}`);
@@ -3917,6 +3563,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
3917
3563
  isHttpProviderClaimParams,
3918
3564
  isMobileDevice,
3919
3565
  recoverSignersOfSignedClaim,
3566
+ runTeeVerification,
3920
3567
  takePairsWhereValueIsArray,
3921
3568
  takeTemplateParametersFromProofs,
3922
3569
  transformForOnchain,