@reclaimprotocol/attestor-core 5.0.1-beta.2 → 5.0.1-beta.21

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.
Files changed (131) hide show
  1. package/browser/resources/attestor-browser.min.mjs +4512 -0
  2. package/lib/external-rpc/index.js +10399 -3
  3. package/lib/index.js +8323 -10
  4. package/package.json +9 -4
  5. package/lib/avs/abis/avsDirectoryABI.js +0 -343
  6. package/lib/avs/abis/delegationABI.js +0 -4
  7. package/lib/avs/abis/registryABI.js +0 -728
  8. package/lib/avs/client/create-claim-on-avs.js +0 -168
  9. package/lib/avs/config.js +0 -26
  10. package/lib/avs/contracts/ReclaimServiceManager.js +0 -0
  11. package/lib/avs/contracts/common.js +0 -0
  12. package/lib/avs/contracts/factories/ReclaimServiceManager__factory.js +0 -1183
  13. package/lib/avs/contracts/factories/index.js +0 -4
  14. package/lib/avs/contracts/index.js +0 -6
  15. package/lib/avs/types/index.js +0 -0
  16. package/lib/avs/utils/contracts.js +0 -53
  17. package/lib/avs/utils/register.js +0 -74
  18. package/lib/avs/utils/tasks.js +0 -48
  19. package/lib/client/create-claim.js +0 -461
  20. package/lib/client/index.js +0 -3
  21. package/lib/client/tunnels/make-rpc-tcp-tunnel.js +0 -53
  22. package/lib/client/tunnels/make-rpc-tls-tunnel.js +0 -127
  23. package/lib/client/utils/attestor-pool.js +0 -24
  24. package/lib/client/utils/client-socket.js +0 -120
  25. package/lib/client/utils/message-handler.js +0 -97
  26. package/lib/config/index.js +0 -62
  27. package/lib/external-rpc/benchmark.js +0 -82
  28. package/lib/external-rpc/event-bus.js +0 -17
  29. package/lib/external-rpc/global.d.js +0 -0
  30. package/lib/external-rpc/handle-incoming-msg.js +0 -241
  31. package/lib/external-rpc/jsc-polyfills/1.js +0 -80
  32. package/lib/external-rpc/jsc-polyfills/2.js +0 -15
  33. package/lib/external-rpc/jsc-polyfills/event.js +0 -19
  34. package/lib/external-rpc/jsc-polyfills/index.js +0 -2
  35. package/lib/external-rpc/jsc-polyfills/ws.js +0 -83
  36. package/lib/external-rpc/setup-browser.js +0 -33
  37. package/lib/external-rpc/setup-jsc.js +0 -22
  38. package/lib/external-rpc/types.js +0 -0
  39. package/lib/external-rpc/utils.js +0 -100
  40. package/lib/external-rpc/zk.js +0 -58
  41. package/lib/mechain/abis/governanceABI.js +0 -461
  42. package/lib/mechain/abis/taskABI.js +0 -512
  43. package/lib/mechain/client/create-claim-on-mechain.js +0 -33
  44. package/lib/mechain/client/index.js +0 -1
  45. package/lib/mechain/constants/index.js +0 -8
  46. package/lib/mechain/index.js +0 -2
  47. package/lib/mechain/types/index.js +0 -0
  48. package/lib/proto/api.js +0 -4250
  49. package/lib/proto/tee-bundle.js +0 -1296
  50. package/lib/providers/http/index.js +0 -640
  51. package/lib/providers/http/patch-parse5-tree.js +0 -34
  52. package/lib/providers/http/utils.js +0 -283
  53. package/lib/providers/index.js +0 -7
  54. package/lib/scripts/check-avs-registration.js +0 -28
  55. package/lib/scripts/fallbacks/crypto.js +0 -4
  56. package/lib/scripts/fallbacks/empty.js +0 -4
  57. package/lib/scripts/fallbacks/re2.js +0 -7
  58. package/lib/scripts/fallbacks/snarkjs.js +0 -10
  59. package/lib/scripts/fallbacks/stwo.js +0 -159
  60. package/lib/scripts/generate-provider-types.js +0 -101
  61. package/lib/scripts/generate-receipt.js +0 -101
  62. package/lib/scripts/generate-toprf-keys.js +0 -24
  63. package/lib/scripts/jsc-cli-rpc.js +0 -35
  64. package/lib/scripts/register-avs-operator.js +0 -3
  65. package/lib/scripts/start-server.js +0 -11
  66. package/lib/scripts/update-avs-metadata.js +0 -20
  67. package/lib/scripts/utils.js +0 -10
  68. package/lib/scripts/whitelist-operator.js +0 -16
  69. package/lib/server/create-server.js +0 -105
  70. package/lib/server/handlers/claimTeeBundle.js +0 -232
  71. package/lib/server/handlers/claimTunnel.js +0 -80
  72. package/lib/server/handlers/completeClaimOnChain.js +0 -29
  73. package/lib/server/handlers/createClaimOnChain.js +0 -32
  74. package/lib/server/handlers/createTaskOnMechain.js +0 -57
  75. package/lib/server/handlers/createTunnel.js +0 -98
  76. package/lib/server/handlers/disconnectTunnel.js +0 -8
  77. package/lib/server/handlers/fetchCertificateBytes.js +0 -57
  78. package/lib/server/handlers/index.js +0 -25
  79. package/lib/server/handlers/init.js +0 -33
  80. package/lib/server/handlers/toprf.js +0 -19
  81. package/lib/server/index.js +0 -4
  82. package/lib/server/socket.js +0 -112
  83. package/lib/server/tunnels/make-tcp-tunnel.js +0 -202
  84. package/lib/server/utils/apm.js +0 -29
  85. package/lib/server/utils/assert-valid-claim-request.js +0 -354
  86. package/lib/server/utils/config-env.js +0 -4
  87. package/lib/server/utils/dns.js +0 -24
  88. package/lib/server/utils/gcp-attestation.js +0 -237
  89. package/lib/server/utils/generics.js +0 -45
  90. package/lib/server/utils/iso.js +0 -259
  91. package/lib/server/utils/keep-alive.js +0 -38
  92. package/lib/server/utils/nitro-attestation.js +0 -249
  93. package/lib/server/utils/oprf-raw.js +0 -61
  94. package/lib/server/utils/process-handshake.js +0 -233
  95. package/lib/server/utils/proxy-session.js +0 -6
  96. package/lib/server/utils/tee-oprf-mpc-verification.js +0 -86
  97. package/lib/server/utils/tee-oprf-verification.js +0 -151
  98. package/lib/server/utils/tee-transcript-reconstruction.js +0 -140
  99. package/lib/server/utils/tee-verification.js +0 -358
  100. package/lib/server/utils/validation.js +0 -45
  101. package/lib/types/bgp.js +0 -0
  102. package/lib/types/claims.js +0 -0
  103. package/lib/types/client.js +0 -0
  104. package/lib/types/general.js +0 -0
  105. package/lib/types/handlers.js +0 -0
  106. package/lib/types/index.js +0 -10
  107. package/lib/types/providers.gen.js +0 -16
  108. package/lib/types/providers.js +0 -0
  109. package/lib/types/rpc.js +0 -0
  110. package/lib/types/signatures.js +0 -0
  111. package/lib/types/tunnel.js +0 -0
  112. package/lib/types/zk.js +0 -0
  113. package/lib/utils/auth.js +0 -71
  114. package/lib/utils/b64-json.js +0 -17
  115. package/lib/utils/bgp-listener.js +0 -123
  116. package/lib/utils/claims.js +0 -89
  117. package/lib/utils/env.js +0 -19
  118. package/lib/utils/error.js +0 -54
  119. package/lib/utils/generics.js +0 -268
  120. package/lib/utils/http-parser.js +0 -201
  121. package/lib/utils/index.js +0 -13
  122. package/lib/utils/logger.js +0 -82
  123. package/lib/utils/prepare-packets.js +0 -69
  124. package/lib/utils/redactions.js +0 -135
  125. package/lib/utils/retries.js +0 -26
  126. package/lib/utils/signatures/eth.js +0 -31
  127. package/lib/utils/signatures/index.js +0 -12
  128. package/lib/utils/socket-base.js +0 -96
  129. package/lib/utils/tls.js +0 -58
  130. package/lib/utils/ws.js +0 -22
  131. package/lib/utils/zk.js +0 -625
@@ -1,358 +0,0 @@
1
- import { ServiceSignatureType } from "../../proto/api.js";
2
- import { BodyType, KOutputPayload, TOutputPayload, VerificationBundle } from "../../proto/tee-bundle.js";
3
- import { validateGcpAttestationAndExtractKey } from "../../server/utils/gcp-attestation.js";
4
- import { validateNitroAttestationAndExtractKey } from "../../server/utils/nitro-attestation.js";
5
- import { AttestorError } from "../../utils/error.js";
6
- import { SIGNATURES } from "../../utils/signatures/index.js";
7
- async function verifyTeeBundle(bundleBytes, logger) {
8
- const bundle = parseVerificationBundle(bundleBytes);
9
- validateBundleCompleteness(bundle);
10
- const { teekKeyResult, teetKeyResult } = await extractPublicKeys(bundle, logger);
11
- await verifyTeeSignatures(bundle, teekKeyResult, teetKeyResult, logger);
12
- if (!bundle.teekSigned || !bundle.teetSigned) {
13
- throw new AttestorError("ERROR_INVALID_CLAIM", "Missing TEE signed messages");
14
- }
15
- const kOutputPayload = parseKOutputPayload(bundle.teekSigned);
16
- const tOutputPayload = parseTOutputPayload(bundle.teetSigned);
17
- validateTimestamps(kOutputPayload, tOutputPayload, logger);
18
- const teeSessionId = validateSessionIds(kOutputPayload, tOutputPayload, logger);
19
- logger.info("TEE bundle verification successful");
20
- return {
21
- teekSigned: bundle.teekSigned,
22
- teetSigned: bundle.teetSigned,
23
- kOutputPayload,
24
- tOutputPayload,
25
- teekPcr0: teekKeyResult.pcr0,
26
- teetPcr0: teetKeyResult.pcr0,
27
- teeSessionId
28
- };
29
- }
30
- function parseVerificationBundle(bundleBytes) {
31
- try {
32
- return VerificationBundle.decode(bundleBytes);
33
- } catch (error) {
34
- throw new Error(`Failed to parse verification bundle: ${error.message}`);
35
- }
36
- }
37
- function validateBundleCompleteness(bundle) {
38
- if (!bundle.teekSigned) {
39
- throw new Error("SECURITY ERROR: missing TEE_K signed message - verification bundle incomplete");
40
- }
41
- if (!bundle.teetSigned) {
42
- throw new Error("SECURITY ERROR: missing TEE_T signed message - verification bundle incomplete");
43
- }
44
- const hasAttestations = bundle.teekSigned.attestationReport?.report && bundle.teekSigned.attestationReport.report.length > 0 || bundle.teetSigned.attestationReport?.report && bundle.teetSigned.attestationReport.report.length > 0;
45
- const hasPublicKeys = bundle.teekSigned.ethAddress && bundle.teekSigned.ethAddress.length > 0 || bundle.teetSigned.ethAddress && bundle.teetSigned.ethAddress.length > 0;
46
- if (!hasAttestations && !hasPublicKeys) {
47
- throw new Error("SECURITY ERROR: bundle must have either Nitro attestations (production) or embedded public keys (development)");
48
- }
49
- if (bundle.teekSigned.bodyType !== BodyType.BODY_TYPE_K_OUTPUT) {
50
- throw new Error("Invalid TEE_K signed message: wrong body type");
51
- }
52
- if (bundle.teetSigned.bodyType !== BodyType.BODY_TYPE_T_OUTPUT) {
53
- throw new Error("Invalid TEE_T signed message: wrong body type");
54
- }
55
- if (!bundle.teekSigned.body || bundle.teekSigned.body.length === 0) {
56
- throw new Error("Invalid TEE_K signed message: empty body");
57
- }
58
- if (!bundle.teetSigned.body || bundle.teetSigned.body.length === 0) {
59
- throw new Error("Invalid TEE_T signed message: empty body");
60
- }
61
- if (!bundle.teekSigned.signature || bundle.teekSigned.signature.length === 0) {
62
- throw new Error("Invalid TEE_K signed message: missing signature");
63
- }
64
- if (!bundle.teetSigned.signature || bundle.teetSigned.signature.length === 0) {
65
- throw new Error("Invalid TEE_T signed message: missing signature");
66
- }
67
- }
68
- async function extractPublicKeys(bundle, logger) {
69
- const hasEmbeddedAttestations = bundle.teekSigned.attestationReport?.report && bundle.teekSigned.attestationReport.report.length > 0 && (bundle.teetSigned.attestationReport?.report && bundle.teetSigned.attestationReport.report.length > 0);
70
- let teekKeyResult;
71
- let teetKeyResult;
72
- if (hasEmbeddedAttestations) {
73
- logger.info("Using production mode: extracting keys from attestations");
74
- if (!bundle.teekSigned?.attestationReport?.report) {
75
- throw new Error("TEE_K embedded attestation report missing");
76
- }
77
- if (!bundle.teetSigned?.attestationReport?.report) {
78
- throw new Error("TEE_T embedded attestation report missing");
79
- }
80
- const teekAttestationType = bundle.teekSigned.attestationReport.type || "nitro";
81
- const teetAttestationType = bundle.teetSigned.attestationReport.type || "nitro";
82
- logger.info(`TEE_K attestation type: ${teekAttestationType}`);
83
- logger.info(`TEE_T attestation type: ${teetAttestationType}`);
84
- const teekAttestationBytes = bundle.teekSigned.attestationReport.report;
85
- const teetAttestationBytes = bundle.teetSigned.attestationReport.report;
86
- if (teekAttestationType === "gcp") {
87
- const gcpResult = await validateGcpAttestationAndExtractKey(teekAttestationBytes, logger);
88
- if (!gcpResult.isValid) {
89
- throw new Error(`TEE_K GCP attestation validation failed: ${gcpResult.errors.join(", ")}`);
90
- }
91
- if (!gcpResult.ethAddress) {
92
- throw new Error("TEE_K GCP attestation validation failed: no address");
93
- }
94
- if (gcpResult.userDataType !== "tee_k") {
95
- throw new Error(`TEE_K GCP attestation validation failed: wrong TEE type, expected tee_k, got ${gcpResult.userDataType}`);
96
- }
97
- teekKeyResult = {
98
- teeType: gcpResult.userDataType,
99
- ethAddress: "0x" + Buffer.from(gcpResult.ethAddress).toString("hex"),
100
- pcr0: gcpResult.pcr0 || "gcp-no-digest"
101
- };
102
- } else {
103
- const nitroResult = await validateNitroAttestationAndExtractKey(teekAttestationBytes);
104
- if (!nitroResult.isValid) {
105
- throw new Error(`TEE_K Nitro attestation validation failed: ${nitroResult.errors.join(", ")}`);
106
- }
107
- if (!nitroResult.ethAddress) {
108
- throw new Error("TEE_K Nitro attestation validation failed: no address");
109
- }
110
- if (nitroResult.userDataType !== "tee_k") {
111
- throw new Error(`TEE_K Nitro attestation validation failed: wrong TEE type, expected tee_k, got ${nitroResult.userDataType}`);
112
- }
113
- teekKeyResult = {
114
- teeType: nitroResult.userDataType,
115
- ethAddress: nitroResult.ethAddress,
116
- pcr0: nitroResult.pcr0
117
- };
118
- }
119
- if (teetAttestationType === "gcp") {
120
- const gcpResult = await validateGcpAttestationAndExtractKey(teetAttestationBytes, logger);
121
- if (!gcpResult.isValid) {
122
- throw new Error(`TEE_T GCP attestation validation failed: ${gcpResult.errors.join(", ")}`);
123
- }
124
- if (!gcpResult.ethAddress) {
125
- throw new Error("TEE_T GCP attestation validation failed: no address");
126
- }
127
- if (gcpResult.userDataType !== "tee_t") {
128
- throw new Error(`TEE_T GCP attestation validation failed: wrong TEE type, expected tee_t, got ${gcpResult.userDataType}`);
129
- }
130
- teetKeyResult = {
131
- teeType: gcpResult.userDataType,
132
- ethAddress: "0x" + Buffer.from(gcpResult.ethAddress).toString("hex"),
133
- pcr0: gcpResult.pcr0 || "gcp-no-digest"
134
- };
135
- if (!gcpResult.envVars?.EXPECTED_TEEK_PCR0) {
136
- throw new Error("TEE_T GCP attestation missing required EXPECTED_TEEK_PCR0 environment variable");
137
- }
138
- const expectedPcr0 = gcpResult.envVars.EXPECTED_TEEK_PCR0;
139
- const actualPcr0 = teekKeyResult.pcr0;
140
- logger.info(`Cross-validating TEE_K PCR0: expected=${expectedPcr0}, actual=${actualPcr0}`);
141
- if (expectedPcr0 !== actualPcr0) {
142
- throw new Error(`TEE cross-validation failed: TEE_T expects TEE_K PCR0 "${expectedPcr0}" but got "${actualPcr0}"`);
143
- }
144
- logger.info("TEE cross-validation successful: TEE_K PCR0 matches TEE_T expectation");
145
- } else {
146
- const nitroResult = await validateNitroAttestationAndExtractKey(teetAttestationBytes);
147
- if (!nitroResult.isValid) {
148
- throw new Error(`TEE_T Nitro attestation validation failed: ${nitroResult.errors.join(", ")}`);
149
- }
150
- if (!nitroResult.ethAddress) {
151
- throw new Error("TEE_T Nitro attestation validation failed: no address");
152
- }
153
- if (nitroResult.userDataType !== "tee_t") {
154
- throw new Error(`TEE_T Nitro attestation validation failed: wrong TEE type, expected tee_t, got ${nitroResult.userDataType}`);
155
- }
156
- teetKeyResult = {
157
- teeType: nitroResult.userDataType,
158
- ethAddress: nitroResult.ethAddress,
159
- pcr0: nitroResult.pcr0
160
- };
161
- }
162
- logger.info("Attestations validated successfully");
163
- } else {
164
- const standaloneEnabled = process.env.TEE_STANDALONE === "true" || process.env.TEE_STANDALONE === "1";
165
- if (!standaloneEnabled) {
166
- throw new Error("Missing attestation reports and standalone mode is not enabled (set TEE_STANDALONE=true to enable)");
167
- }
168
- const hasEmbeddedKeys = bundle.teekSigned.ethAddress && bundle.teekSigned.ethAddress.length > 0 && (bundle.teetSigned.ethAddress && bundle.teetSigned.ethAddress.length > 0);
169
- if (!hasEmbeddedKeys) {
170
- throw new Error("Missing attestation and no embedded ETH addresses for standalone mode");
171
- }
172
- logger.warn("STANDALONE MODE ENABLED: Using embedded ETH addresses without attestation verification");
173
- const teekAddress = Buffer.from(bundle.teekSigned.ethAddress).toString("utf8");
174
- teekKeyResult = {
175
- teeType: "tee_k",
176
- ethAddress: teekAddress,
177
- pcr0: "standalone-mode"
178
- // No PCR0 in standalone mode
179
- };
180
- logger.info(`TEE_K standalone address: ${teekAddress}`);
181
- const teetAddress = Buffer.from(bundle.teetSigned.ethAddress).toString("utf8");
182
- teetKeyResult = {
183
- teeType: "tee_t",
184
- ethAddress: teetAddress,
185
- pcr0: "standalone-mode"
186
- // No PCR0 in standalone mode
187
- };
188
- logger.info(`TEE_T standalone address: ${teetAddress}`);
189
- logger.info("Standalone mode key extraction successful");
190
- }
191
- return {
192
- teekKeyResult,
193
- teetKeyResult
194
- };
195
- }
196
- async function verifyTeeSignatures(bundle, teekKeyResult, teetKeyResult, logger) {
197
- if (!bundle.teekSigned) {
198
- throw new Error("TEE_K signed message is missing");
199
- }
200
- const teekResult = await verifyTeeSignature(
201
- bundle.teekSigned,
202
- teekKeyResult,
203
- "TEE_K",
204
- logger
205
- );
206
- if (!teekResult.isValid) {
207
- throw new Error(`TEE_K signature verification failed: ${teekResult.errors.join(", ")}`);
208
- }
209
- if (!bundle.teetSigned) {
210
- throw new Error("TEE_T signed message is missing");
211
- }
212
- const teetResult = await verifyTeeSignature(
213
- bundle.teetSigned,
214
- teetKeyResult,
215
- "TEE_T",
216
- logger
217
- );
218
- if (!teetResult.isValid) {
219
- throw new Error(`TEE_T signature verification failed: ${teetResult.errors.join(", ")}`);
220
- }
221
- logger.info("TEE signatures verified successfully");
222
- }
223
- async function verifyTeeSignature(signedMessage, extractedKey, teeType, logger) {
224
- const errors = [];
225
- if (!signedMessage) {
226
- return {
227
- isValid: false,
228
- errors: ["Signed message is null or undefined"]
229
- };
230
- }
231
- try {
232
- let ethAddress;
233
- if (extractedKey.ethAddress) {
234
- ethAddress = extractedKey.ethAddress;
235
- logger.debug(`${teeType} using ETH address from attestation: ${ethAddress}`);
236
- } else {
237
- return {
238
- isValid: false,
239
- errors: ["eth address is null"]
240
- };
241
- }
242
- const { verify: verifySig } = SIGNATURES[ServiceSignatureType.SERVICE_SIGNATURE_TYPE_ETH];
243
- const isValid = await verifySig(
244
- signedMessage.body,
245
- signedMessage.signature,
246
- ethAddress
247
- );
248
- if (!isValid) {
249
- errors.push(`${teeType} signature verification failed for address ${ethAddress}`);
250
- }
251
- logger.debug(`${teeType} signature verification result: ${isValid} for address ${ethAddress}`);
252
- return {
253
- isValid: errors.length === 0,
254
- errors,
255
- address: extractedKey.ethAddress
256
- };
257
- } catch (error) {
258
- errors.push(`${teeType} signature verification error: ${error.message}`);
259
- return {
260
- isValid: false,
261
- errors
262
- };
263
- }
264
- }
265
- function parseKOutputPayload(signedMessage) {
266
- const payload = KOutputPayload.decode(signedMessage.body);
267
- if (!payload.redactedRequest) {
268
- throw new Error("Missing redacted request in TEE_K payload");
269
- }
270
- if (!payload.consolidatedResponseKeystream || payload.consolidatedResponseKeystream.length === 0) {
271
- throw new Error("Missing consolidated response keystream in TEE_K payload");
272
- }
273
- if (!payload.certificateInfo) {
274
- throw new Error("Missing certificate info in TEE_K payload");
275
- }
276
- return payload;
277
- }
278
- function parseTOutputPayload(signedMessage) {
279
- const payload = TOutputPayload.decode(signedMessage.body);
280
- if (!payload.consolidatedResponseCiphertext || payload.consolidatedResponseCiphertext.length === 0) {
281
- throw new Error("Missing consolidated response ciphertext in TEE_T payload");
282
- }
283
- return payload;
284
- }
285
- function validateTimestamps(kPayload, tPayload, logger) {
286
- const now = Date.now();
287
- const kTimestamp = kPayload.timestampMs;
288
- const tTimestamp = tPayload.timestampMs;
289
- const kTimestampS = Math.floor(kTimestamp / 1e3);
290
- const tTimestampS = Math.floor(tTimestamp / 1e3);
291
- const nowS = Math.floor(now / 1e3);
292
- logger.info("Validating TEE timestamps", {
293
- kTimestampMs: kTimestamp,
294
- tTimestampMs: tTimestamp,
295
- kTimestampS,
296
- tTimestampS,
297
- nowS
298
- });
299
- const maxAgeMs = 10 * 60 * 1e3;
300
- const oldestAllowed = now - maxAgeMs;
301
- if (kTimestamp < oldestAllowed) {
302
- throw new Error(`TEE_K timestamp ${kTimestamp} is too old. Must be within 10 minutes of current time ${now}`);
303
- }
304
- if (tTimestamp < oldestAllowed) {
305
- throw new Error(`TEE_T timestamp ${tTimestamp} is too old. Must be within 10 minutes of current time ${now}`);
306
- }
307
- const maxFutureMs = 60 * 1e3;
308
- const maxAllowed = now + maxFutureMs;
309
- if (kTimestamp > maxAllowed) {
310
- throw new Error(`TEE_K timestamp ${kTimestamp} is in the future. Current time is ${now}`);
311
- }
312
- if (tTimestamp > maxAllowed) {
313
- throw new Error(`TEE_T timestamp ${tTimestamp} is in the future. Current time is ${now}`);
314
- }
315
- const timestampDiffMs = Math.abs(kTimestamp - tTimestamp);
316
- const maxDiffMs = 60 * 1e3;
317
- if (timestampDiffMs > maxDiffMs) {
318
- throw new Error(`TEE timestamps differ by ${timestampDiffMs}ms, which exceeds maximum allowed difference of ${maxDiffMs}ms (1 minute)`);
319
- }
320
- logger.info("TEE timestamp validation successful", {
321
- timestampDiffMs,
322
- ageKMs: now - kTimestamp,
323
- ageTMs: now - tTimestamp
324
- });
325
- }
326
- function validateSessionIds(kPayload, tPayload, logger) {
327
- const kSessionId = kPayload.sessionId;
328
- const tSessionId = tPayload.sessionId;
329
- logger.info("Validating TEE session IDs", {
330
- kSessionId,
331
- tSessionId
332
- });
333
- if (!kSessionId || kSessionId.length === 0) {
334
- throw new AttestorError(
335
- "ERROR_INVALID_CLAIM",
336
- "Missing session_id in TEE_K payload - required for cross-TEE binding"
337
- );
338
- }
339
- if (!tSessionId || tSessionId.length === 0) {
340
- throw new AttestorError(
341
- "ERROR_INVALID_CLAIM",
342
- "Missing session_id in TEE_T payload - required for cross-TEE binding"
343
- );
344
- }
345
- if (kSessionId !== tSessionId) {
346
- throw new AttestorError(
347
- "ERROR_INVALID_CLAIM",
348
- `Session ID mismatch: TEE_K session_id "${kSessionId}" does not match TEE_T session_id "${tSessionId}".`
349
- );
350
- }
351
- logger.info("TEE session ID validation successful", {
352
- sessionId: kSessionId
353
- });
354
- return kSessionId;
355
- }
356
- export {
357
- verifyTeeBundle
358
- };
@@ -1,45 +0,0 @@
1
- import { Ajv } from "ajv";
2
- import { PROVIDER_SCHEMAS } from "../../types/providers.gen.js";
3
- import { AttestorError } from "../../utils/error.js";
4
- const PROVIDER_VALIDATOR_MAP = {};
5
- const AJV = new Ajv({
6
- allErrors: true,
7
- strict: true,
8
- strictRequired: false,
9
- formats: {
10
- binary(data) {
11
- return data instanceof Uint8Array || typeof Buffer !== "undefined" && Buffer.isBuffer(data);
12
- },
13
- url(data) {
14
- try {
15
- new URL(data);
16
- return true;
17
- } catch {
18
- return false;
19
- }
20
- }
21
- }
22
- });
23
- function assertValidateProviderParams(name, params) {
24
- let validate = PROVIDER_VALIDATOR_MAP[name];
25
- if (!validate) {
26
- const schema = PROVIDER_SCHEMAS[name]?.parameters;
27
- if (!schema) {
28
- throw new AttestorError(
29
- "ERROR_BAD_REQUEST",
30
- `Invalid provider name "${String(name)}"`
31
- );
32
- }
33
- validate = AJV.compile(schema);
34
- }
35
- if (!validate?.(params)) {
36
- throw new AttestorError(
37
- "ERROR_BAD_REQUEST",
38
- "Params validation failed",
39
- { errors: JSON.stringify(validate.errors) }
40
- );
41
- }
42
- }
43
- export {
44
- assertValidateProviderParams
45
- };
package/lib/types/bgp.js DELETED
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -1,10 +0,0 @@
1
- export * from "./providers.js";
2
- export * from "./general.js";
3
- export * from "./signatures.js";
4
- export * from "./claims.js";
5
- export * from "./zk.js";
6
- export * from "./client.js";
7
- export * from "./rpc.js";
8
- export * from "./tunnel.js";
9
- export * from "./handlers.js";
10
- export * from "./bgp.js";
@@ -1,16 +0,0 @@
1
- const HttpProviderParametersJson = { "title": "HttpProviderParameters", "type": "object", "required": ["url", "method", "responseMatches"], "properties": { "url": { "type": "string", "format": "url", "description": "which URL does the request have to be made to Has to be a valid https URL for eg. https://amazon.in/orders?q=abcd" }, "method": { "type": "string", "enum": ["GET", "POST", "PUT", "PATCH"] }, "geoLocation": { "type": "string", "nullable": true, "description": "Specify the geographical location from where to proxy the request. 2-letter ISO country code or parameter (public or secret)" }, "proxySessionId": { "type": "string", "nullable": true, "description": 'Specify the unique session id for allowing use of same proxy ip across multiple requests. Can be a smallcase alphanumeric string of length 8-14 characters. eg. "mystring12345", "something1234".' }, "headers": { "type": "object", "description": "Any additional headers to be sent with the request Note: these will be revealed to the attestor & won't be redacted from the transcript. To add hidden headers, use 'secretParams.headers' instead", "additionalProperties": { "type": "string" } }, "body": { "description": "Body of the HTTP request", "oneOf": [{ "type": "string", "format": "binary" }, { "type": "string" }] }, "writeRedactionMode": { "type": "string", "description": `If the API doesn't perform well with the "key-update" method of redaction, you can switch to "zk" mode by setting this to "zk"`, "enum": ["zk", "key-update"] }, "additionalClientOptions": { "type": "object", "description": "Apply TLS configuration when creating the tunnel to the attestor.", "nullable": true, "properties": { "supportedProtocolVersions": { "type": "array", "minItems": 1, "uniqueItems": true, "items": { "type": "string", "enum": ["TLS1_2", "TLS1_3"] } } } }, "responseMatches": { "type": "array", "minItems": 1, "uniqueItems": true, "description": "The attestor will use this list to check that the redacted response does indeed match all the provided strings/regexes", "items": { "type": "object", "required": ["value", "type"], "properties": { "value": { "type": "string", "description": '"regex": the response must match the regex "contains": the response must contain the provided\n string exactly' }, "type": { "type": "string", "description": "The string/regex to match against", "enum": ["regex", "contains"] }, "invert": { "type": "boolean", "description": "Inverses the matching logic. Fail when match is found and proceed otherwise" } }, "additionalProperties": false } }, "responseRedactions": { "type": "array", "uniqueItems": true, "description": 'which portions to select from a response. These are selected in order, xpath => jsonPath => regex * These redactions are done client side and only the selected portions are sent to the attestor. The attestor will only be able to see the selected portions alongside the first line of the HTTP response (i.e. "HTTP/1.1 200 OK") * To disable any redactions, pass an empty array', "items": { "type": "object", "properties": { "xPath": { "type": "string", "nullable": true, "description": 'expect an HTML response, and to contain a certain xpath for eg. "/html/body/div.a1/div.a2/span.a5"' }, "jsonPath": { "type": "string", "nullable": true, "description": "expect a JSON response, retrieve the item at this path using dot notation for e.g. 'email.addresses.0'" }, "regex": { "type": "string", "nullable": true, "description": "select a regex match from the response" }, "hash": { "type": "string", "description": `If provided, the value inside will be hashed instead of being redacted. Useful for cases where the data inside is an identifiying piece of information that you don't want to reveal to the attestor, eg. an email address.
2
- If the hash function produces more bytes than the original value, the hash will be truncated.
3
- Eg. if hash is enabled, the original value is "hello", and hashed is "a1b2c", then the attestor will only see "a1b2c".
4
- Note: if a regex with named groups is provided, only the named groups will be hashed.`, "enum": ["oprf", "oprf-mpc", "oprf-raw"] } }, "additionalProperties": false } }, "paramValues": { "type": "object", "description": "A map of parameter values which are user in form of {{param}} in URL, responseMatches, responseRedactions, body, geolocation. Those in URL, responseMatches & geo will be put into context and signed This value will NOT be included in provider hash", "additionalProperties": { "type": "string" } } }, "additionalProperties": false };
5
- const HttpProviderSecretParametersJson = { "title": "HttpProviderSecretParameters", "type": "object", "description": "Secret parameters to be used with HTTP provider. None of the values in this object will be shown to the attestor", "properties": { "cookieStr": { "type": "string", "description": "cookie string for authorisation." }, "authorisationHeader": { "type": "string", "description": "authorisation header value" }, "headers": { "type": "object", "description": "Headers that need to be hidden from the attestor", "additionalProperties": { "type": "string" } }, "paramValues": { "type": "object", "description": "A map of parameter values which are user in form of {{param}} in body these parameters will NOT be shown to attestor and extracted", "additionalProperties": { "type": "string" } } }, "additionalProperties": false };
6
- const PROVIDER_SCHEMAS = {
7
- http: {
8
- parameters: HttpProviderParametersJson,
9
- secretParameters: HttpProviderSecretParametersJson
10
- }
11
- };
12
- export {
13
- HttpProviderParametersJson,
14
- HttpProviderSecretParametersJson,
15
- PROVIDER_SCHEMAS
16
- };
File without changes
package/lib/types/rpc.js DELETED
File without changes
File without changes
File without changes
package/lib/types/zk.js DELETED
File without changes
package/lib/utils/auth.js DELETED
@@ -1,71 +0,0 @@
1
- import { getBytes } from "ethers";
2
- import { DEFAULT_AUTH_EXPIRY_S } from "../config/index.js";
3
- import { AuthenticatedUserData } from "../proto/api.js";
4
- import { getEnvVariable } from "../utils/env.js";
5
- import { AttestorError } from "../utils/error.js";
6
- import { unixTimestampSeconds } from "../utils/generics.js";
7
- import { SelectedServiceSignature, SIGNATURES } from "../utils/signatures/index.js";
8
- async function assertValidAuthRequest(request, signatureType) {
9
- const publicKey = getEnvVariable("AUTHENTICATION_PUBLIC_KEY");
10
- if (!request) {
11
- if (publicKey) {
12
- throw new AttestorError(
13
- "ERROR_AUTHENTICATION_FAILED",
14
- "User must be authenticated"
15
- );
16
- }
17
- return;
18
- }
19
- if (!publicKey) {
20
- throw new AttestorError(
21
- "ERROR_BAD_REQUEST",
22
- "The attestor is not configured for authentication"
23
- );
24
- }
25
- const { signature, data } = request;
26
- if (!data) {
27
- throw new AttestorError(
28
- "ERROR_AUTHENTICATION_FAILED",
29
- "Missing data in auth request"
30
- );
31
- }
32
- if (data.expiresAt < unixTimestampSeconds()) {
33
- throw new AttestorError(
34
- "ERROR_AUTHENTICATION_FAILED",
35
- "Authentication request has expired"
36
- );
37
- }
38
- const proto = AuthenticatedUserData.encode(data).finish();
39
- const signatureAlg = SIGNATURES[signatureType];
40
- const address = signatureAlg.getAddress(
41
- getBytes(publicKey)
42
- );
43
- const verified = await signatureAlg.verify(proto, signature, address);
44
- if (!verified) {
45
- throw new AttestorError(
46
- "ERROR_AUTHENTICATION_FAILED",
47
- "Signature verification failed"
48
- );
49
- }
50
- }
51
- async function createAuthRequest(_data, privateKey) {
52
- const createdAt = unixTimestampSeconds();
53
- const data = {
54
- createdAt,
55
- expiresAt: createdAt + DEFAULT_AUTH_EXPIRY_S,
56
- id: "",
57
- hostWhitelist: [],
58
- ..._data
59
- };
60
- const proto = AuthenticatedUserData.encode(data).finish();
61
- const signature = await SelectedServiceSignature.sign(proto, privateKey);
62
- const request = {
63
- data,
64
- signature
65
- };
66
- return request;
67
- }
68
- export {
69
- assertValidAuthRequest,
70
- createAuthRequest
71
- };
@@ -1,17 +0,0 @@
1
- import { decodeBase64, encodeBase64 } from "ethers";
2
- const B64_JSON_REPLACER = (key, value) => {
3
- if (value instanceof Uint8Array || typeof value === "object" && value && "buffer" in value && value.buffer instanceof ArrayBuffer) {
4
- return { type: "uint8array", value: encodeBase64(value) };
5
- }
6
- return value;
7
- };
8
- const B64_JSON_REVIVER = (key, value) => {
9
- if (value?.type === "uint8array") {
10
- return decodeBase64(value.value);
11
- }
12
- return value;
13
- };
14
- export {
15
- B64_JSON_REPLACER,
16
- B64_JSON_REVIVER
17
- };
@@ -1,123 +0,0 @@
1
- import CIDR from "ip-cidr";
2
- import { BGP_WS_URL } from "../config/index.js";
3
- import { makeWebSocket } from "../utils/ws.js";
4
- const ANNOUNCEMENT_OVERLAP = "announcement-overlap";
5
- class BGPAnnouncementOverlapEvent extends Event {
6
- data;
7
- constructor(data) {
8
- super(ANNOUNCEMENT_OVERLAP);
9
- this.data = data;
10
- }
11
- }
12
- function createBgpListener(logger) {
13
- let ws;
14
- let closed = false;
15
- const targetIps = /* @__PURE__ */ new Set();
16
- const eventTarget = new EventTarget();
17
- openWs();
18
- return {
19
- onOverlap(ips, callback) {
20
- for (const ip of ips) {
21
- targetIps.add(ip);
22
- }
23
- eventTarget.addEventListener(
24
- ANNOUNCEMENT_OVERLAP,
25
- _callback
26
- );
27
- return () => {
28
- for (const ip of ips) {
29
- targetIps.delete(ip);
30
- }
31
- eventTarget.removeEventListener(
32
- ANNOUNCEMENT_OVERLAP,
33
- _callback
34
- );
35
- };
36
- function _callback(event) {
37
- callback(event.data);
38
- }
39
- },
40
- close() {
41
- ws.onclose = null;
42
- ws.onerror = null;
43
- ws.close();
44
- closed = true;
45
- }
46
- };
47
- function openWs() {
48
- logger.debug("connecting to BGP websocket");
49
- ws = makeWebSocket(BGP_WS_URL);
50
- ws.onopen = onOpen;
51
- ws.onerror = (ev) => onClose(ev);
52
- ws.onclose = () => onClose(new Error("Unexpected close"));
53
- ws.onmessage = ({ data }) => {
54
- const str = typeof data === "string" ? data : data.toString();
55
- try {
56
- onMessage(str);
57
- } catch (err) {
58
- logger.error({ data, err }, "error processing BGP message");
59
- }
60
- };
61
- }
62
- function onOpen() {
63
- const subscriptionMessage = {
64
- type: "ris_subscribe",
65
- data: {
66
- type: "UPDATE"
67
- }
68
- };
69
- ws.send(JSON.stringify(subscriptionMessage));
70
- logger.info("connected to BGP websocket");
71
- }
72
- function onClose(err) {
73
- if (closed) {
74
- return;
75
- }
76
- logger.info({ err }, "BGP websocket closed");
77
- if (!err) {
78
- return;
79
- }
80
- logger.info("reconnecting to BGP websocket");
81
- openWs();
82
- }
83
- function onMessage(message) {
84
- const data = JSON.parse(message);
85
- const announcements = data?.data?.announcements;
86
- logger.trace({ data }, "got BGP update");
87
- if (!Array.isArray(announcements)) {
88
- return;
89
- }
90
- const asPath = data?.data?.path;
91
- for (const announcement of announcements) {
92
- const prefixes = announcement?.prefixes;
93
- const nextHop = announcement?.["next_hop"];
94
- const hasPrefixes = prefixes?.length && (nextHop || asPath);
95
- if (!hasPrefixes) {
96
- return;
97
- }
98
- for (const prefix of prefixes) {
99
- if (!overlapsTargetIps(prefix)) {
100
- continue;
101
- }
102
- eventTarget.dispatchEvent(
103
- new BGPAnnouncementOverlapEvent({ prefix })
104
- );
105
- }
106
- }
107
- }
108
- function overlapsTargetIps(prefix) {
109
- if (prefix.endsWith("/0")) {
110
- return false;
111
- }
112
- const cidr = new CIDR(prefix);
113
- for (const ip of targetIps) {
114
- if (cidr.contains(ip)) {
115
- return true;
116
- }
117
- }
118
- return false;
119
- }
120
- }
121
- export {
122
- createBgpListener
123
- };