@reclaimprotocol/attestor-core 5.0.1-beta.9 → 5.0.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/browser/resources/attestor-browser.min.mjs +4512 -0
- package/lib/client/tunnels/make-rpc-tls-tunnel.d.ts +1 -1
- package/lib/external-rpc/index.js +10399 -3
- package/lib/index.js +8323 -10
- package/lib/server/utils/proxy-session.d.ts +1 -1
- package/lib/types/general.d.ts +0 -1
- package/lib/utils/generics.d.ts +1 -6
- package/lib/utils/index.d.ts +0 -1
- package/package.json +8 -10
- package/lib/avs/abis/avsDirectoryABI.js +0 -343
- package/lib/avs/abis/delegationABI.js +0 -4
- package/lib/avs/abis/registryABI.js +0 -728
- package/lib/avs/client/create-claim-on-avs.js +0 -168
- package/lib/avs/config.js +0 -26
- package/lib/avs/contracts/ReclaimServiceManager.js +0 -0
- package/lib/avs/contracts/common.js +0 -0
- package/lib/avs/contracts/factories/ReclaimServiceManager__factory.js +0 -1183
- package/lib/avs/contracts/factories/index.js +0 -4
- package/lib/avs/contracts/index.js +0 -6
- package/lib/avs/types/index.js +0 -0
- package/lib/avs/utils/contracts.js +0 -53
- package/lib/avs/utils/register.js +0 -74
- package/lib/avs/utils/tasks.js +0 -48
- package/lib/browser/avs/abis/avsDirectoryABI.d.ts +0 -60
- package/lib/browser/avs/abis/avsDirectoryABI.js +0 -343
- package/lib/browser/avs/abis/delegationABI.d.ts +0 -126
- package/lib/browser/avs/abis/delegationABI.js +0 -4
- package/lib/browser/avs/abis/registryABI.d.ts +0 -136
- package/lib/browser/avs/abis/registryABI.js +0 -728
- package/lib/browser/avs/client/create-claim-on-avs.d.ts +0 -12
- package/lib/browser/avs/client/create-claim-on-avs.js +0 -168
- package/lib/browser/avs/config.d.ts +0 -7
- package/lib/browser/avs/config.js +0 -26
- package/lib/browser/avs/contracts/ReclaimServiceManager.d.ts +0 -601
- package/lib/browser/avs/contracts/ReclaimServiceManager.js +0 -0
- package/lib/browser/avs/contracts/common.d.ts +0 -50
- package/lib/browser/avs/contracts/common.js +0 -0
- package/lib/browser/avs/contracts/factories/ReclaimServiceManager__factory.d.ts +0 -890
- package/lib/browser/avs/contracts/factories/ReclaimServiceManager__factory.js +0 -1183
- package/lib/browser/avs/contracts/factories/index.d.ts +0 -1
- package/lib/browser/avs/contracts/factories/index.js +0 -4
- package/lib/browser/avs/contracts/index.d.ts +0 -3
- package/lib/browser/avs/contracts/index.js +0 -6
- package/lib/browser/avs/types/index.d.ts +0 -55
- package/lib/browser/avs/types/index.js +0 -0
- package/lib/browser/avs/utils/contracts.d.ts +0 -21
- package/lib/browser/avs/utils/contracts.js +0 -53
- package/lib/browser/avs/utils/register.d.ts +0 -27
- package/lib/browser/avs/utils/register.js +0 -74
- package/lib/browser/avs/utils/tasks.d.ts +0 -22
- package/lib/browser/avs/utils/tasks.js +0 -48
- package/lib/browser/client/create-claim.d.ts +0 -5
- package/lib/browser/client/create-claim.js +0 -461
- package/lib/browser/client/index.d.ts +0 -3
- package/lib/browser/client/index.js +0 -3
- package/lib/browser/client/tunnels/make-rpc-tcp-tunnel.d.ts +0 -16
- package/lib/browser/client/tunnels/make-rpc-tcp-tunnel.js +0 -53
- package/lib/browser/client/tunnels/make-rpc-tls-tunnel.d.ts +0 -26
- package/lib/browser/client/tunnels/make-rpc-tls-tunnel.js +0 -127
- package/lib/browser/client/utils/attestor-pool.d.ts +0 -8
- package/lib/browser/client/utils/attestor-pool.js +0 -24
- package/lib/browser/client/utils/client-socket.d.ts +0 -11
- package/lib/browser/client/utils/client-socket.js +0 -120
- package/lib/browser/client/utils/message-handler.d.ts +0 -4
- package/lib/browser/client/utils/message-handler.js +0 -97
- package/lib/browser/config/index.d.ts +0 -31
- package/lib/browser/config/index.js +0 -62
- package/lib/browser/external-rpc/benchmark.d.ts +0 -1
- package/lib/browser/external-rpc/benchmark.js +0 -82
- package/lib/browser/external-rpc/event-bus.d.ts +0 -7
- package/lib/browser/external-rpc/event-bus.js +0 -17
- package/lib/browser/external-rpc/global.d.js +0 -0
- package/lib/browser/external-rpc/handle-incoming-msg.d.ts +0 -2
- package/lib/browser/external-rpc/handle-incoming-msg.js +0 -241
- package/lib/browser/external-rpc/index.d.ts +0 -3
- package/lib/browser/external-rpc/index.js +0 -3
- package/lib/browser/external-rpc/jsc-polyfills/1.d.ts +0 -14
- package/lib/browser/external-rpc/jsc-polyfills/1.js +0 -80
- package/lib/browser/external-rpc/jsc-polyfills/2.d.ts +0 -1
- package/lib/browser/external-rpc/jsc-polyfills/2.js +0 -15
- package/lib/browser/external-rpc/jsc-polyfills/event.d.ts +0 -10
- package/lib/browser/external-rpc/jsc-polyfills/event.js +0 -19
- package/lib/browser/external-rpc/jsc-polyfills/index.d.ts +0 -2
- package/lib/browser/external-rpc/jsc-polyfills/index.js +0 -2
- package/lib/browser/external-rpc/jsc-polyfills/ws.d.ts +0 -21
- package/lib/browser/external-rpc/jsc-polyfills/ws.js +0 -83
- package/lib/browser/external-rpc/setup-browser.d.ts +0 -6
- package/lib/browser/external-rpc/setup-browser.js +0 -33
- package/lib/browser/external-rpc/setup-jsc.d.ts +0 -24
- package/lib/browser/external-rpc/setup-jsc.js +0 -22
- package/lib/browser/external-rpc/types.d.ts +0 -213
- package/lib/browser/external-rpc/types.js +0 -0
- package/lib/browser/external-rpc/utils.d.ts +0 -20
- package/lib/browser/external-rpc/utils.js +0 -100
- package/lib/browser/external-rpc/zk.d.ts +0 -14
- package/lib/browser/external-rpc/zk.js +0 -58
- package/lib/browser/index.browser.js +0 -13
- package/lib/browser/index.d.ts +0 -9
- package/lib/browser/index.js +0 -13
- package/lib/browser/mechain/abis/governanceABI.d.ts +0 -50
- package/lib/browser/mechain/abis/governanceABI.js +0 -461
- package/lib/browser/mechain/abis/taskABI.d.ts +0 -157
- package/lib/browser/mechain/abis/taskABI.js +0 -512
- package/lib/browser/mechain/client/create-claim-on-mechain.d.ts +0 -10
- package/lib/browser/mechain/client/create-claim-on-mechain.js +0 -33
- package/lib/browser/mechain/client/index.d.ts +0 -1
- package/lib/browser/mechain/client/index.js +0 -1
- package/lib/browser/mechain/constants/index.d.ts +0 -3
- package/lib/browser/mechain/constants/index.js +0 -8
- package/lib/browser/mechain/index.d.ts +0 -2
- package/lib/browser/mechain/index.js +0 -2
- package/lib/browser/mechain/types/index.d.ts +0 -23
- package/lib/browser/mechain/types/index.js +0 -0
- package/lib/browser/proto/api.d.ts +0 -651
- package/lib/browser/proto/api.js +0 -4250
- package/lib/browser/proto/tee-bundle.d.ts +0 -156
- package/lib/browser/proto/tee-bundle.js +0 -1296
- package/lib/browser/providers/http/index.d.ts +0 -18
- package/lib/browser/providers/http/index.js +0 -640
- package/lib/browser/providers/http/patch-parse5-tree.d.ts +0 -6
- package/lib/browser/providers/http/patch-parse5-tree.js +0 -34
- package/lib/browser/providers/http/utils.d.ts +0 -77
- package/lib/browser/providers/http/utils.js +0 -283
- package/lib/browser/providers/index.d.ts +0 -4
- package/lib/browser/providers/index.js +0 -7
- package/lib/browser/types/bgp.d.ts +0 -11
- package/lib/browser/types/bgp.js +0 -0
- package/lib/browser/types/claims.d.ts +0 -70
- package/lib/browser/types/claims.js +0 -0
- package/lib/browser/types/client.d.ts +0 -163
- package/lib/browser/types/client.js +0 -0
- package/lib/browser/types/general.d.ts +0 -77
- package/lib/browser/types/general.js +0 -0
- package/lib/browser/types/handlers.d.ts +0 -10
- package/lib/browser/types/handlers.js +0 -0
- package/lib/browser/types/index.d.ts +0 -10
- package/lib/browser/types/index.js +0 -10
- package/lib/browser/types/providers.d.ts +0 -161
- package/lib/browser/types/providers.gen.d.ts +0 -443
- package/lib/browser/types/providers.gen.js +0 -16
- package/lib/browser/types/providers.js +0 -0
- package/lib/browser/types/rpc.d.ts +0 -35
- package/lib/browser/types/rpc.js +0 -0
- package/lib/browser/types/signatures.d.ts +0 -28
- package/lib/browser/types/signatures.js +0 -0
- package/lib/browser/types/tunnel.d.ts +0 -18
- package/lib/browser/types/tunnel.js +0 -0
- package/lib/browser/types/zk.d.ts +0 -38
- package/lib/browser/types/zk.js +0 -0
- package/lib/browser/utils/auth.d.ts +0 -8
- package/lib/browser/utils/auth.js +0 -71
- package/lib/browser/utils/b64-json.d.ts +0 -2
- package/lib/browser/utils/b64-json.js +0 -17
- package/lib/browser/utils/claims.d.ts +0 -33
- package/lib/browser/utils/claims.js +0 -89
- package/lib/browser/utils/env.d.ts +0 -3
- package/lib/browser/utils/env.js +0 -19
- package/lib/browser/utils/error.d.ts +0 -26
- package/lib/browser/utils/error.js +0 -54
- package/lib/browser/utils/generics.d.ts +0 -119
- package/lib/browser/utils/generics.js +0 -272
- package/lib/browser/utils/http-parser.d.ts +0 -59
- package/lib/browser/utils/http-parser.js +0 -201
- package/lib/browser/utils/index.browser.js +0 -13
- package/lib/browser/utils/index.d.ts +0 -13
- package/lib/browser/utils/index.js +0 -13
- package/lib/browser/utils/logger.browser.js +0 -88
- package/lib/browser/utils/logger.d.ts +0 -14
- package/lib/browser/utils/logger.js +0 -88
- package/lib/browser/utils/prepare-packets.d.ts +0 -16
- package/lib/browser/utils/prepare-packets.js +0 -69
- package/lib/browser/utils/redactions.d.ts +0 -73
- package/lib/browser/utils/redactions.js +0 -135
- package/lib/browser/utils/retries.d.ts +0 -12
- package/lib/browser/utils/retries.js +0 -26
- package/lib/browser/utils/signatures/eth.d.ts +0 -2
- package/lib/browser/utils/signatures/eth.js +0 -31
- package/lib/browser/utils/signatures/index.d.ts +0 -5
- package/lib/browser/utils/signatures/index.js +0 -12
- package/lib/browser/utils/socket-base.d.ts +0 -23
- package/lib/browser/utils/socket-base.js +0 -96
- package/lib/browser/utils/tls-imports.d.ts +0 -21
- package/lib/browser/utils/tls-imports.js +0 -71
- package/lib/browser/utils/tls.d.ts +0 -2
- package/lib/browser/utils/tls.js +0 -58
- package/lib/browser/utils/ws.d.ts +0 -7
- package/lib/browser/utils/ws.js +0 -22
- package/lib/browser/utils/zk.d.ts +0 -71
- package/lib/browser/utils/zk.js +0 -625
- package/lib/client/create-claim.js +0 -461
- package/lib/client/index.js +0 -3
- package/lib/client/tunnels/make-rpc-tcp-tunnel.js +0 -53
- package/lib/client/tunnels/make-rpc-tls-tunnel.js +0 -127
- package/lib/client/utils/attestor-pool.js +0 -24
- package/lib/client/utils/client-socket.js +0 -120
- package/lib/client/utils/message-handler.js +0 -97
- package/lib/config/index.js +0 -62
- package/lib/external-rpc/benchmark.js +0 -82
- package/lib/external-rpc/event-bus.js +0 -17
- package/lib/external-rpc/global.d.js +0 -0
- package/lib/external-rpc/handle-incoming-msg.js +0 -241
- package/lib/external-rpc/jsc-polyfills/1.js +0 -80
- package/lib/external-rpc/jsc-polyfills/2.js +0 -15
- package/lib/external-rpc/jsc-polyfills/event.js +0 -19
- package/lib/external-rpc/jsc-polyfills/index.js +0 -2
- package/lib/external-rpc/jsc-polyfills/ws.js +0 -83
- package/lib/external-rpc/setup-browser.js +0 -33
- package/lib/external-rpc/setup-jsc.js +0 -22
- package/lib/external-rpc/types.js +0 -0
- package/lib/external-rpc/utils.js +0 -100
- package/lib/external-rpc/zk.js +0 -58
- package/lib/index.browser.d.ts +0 -9
- package/lib/mechain/abis/governanceABI.js +0 -461
- package/lib/mechain/abis/taskABI.js +0 -512
- package/lib/mechain/client/create-claim-on-mechain.js +0 -33
- package/lib/mechain/client/index.js +0 -1
- package/lib/mechain/constants/index.js +0 -8
- package/lib/mechain/index.js +0 -2
- package/lib/mechain/types/index.js +0 -0
- package/lib/proto/api.js +0 -4250
- package/lib/proto/tee-bundle.js +0 -1296
- package/lib/providers/http/index.js +0 -640
- package/lib/providers/http/patch-parse5-tree.js +0 -34
- package/lib/providers/http/utils.js +0 -283
- package/lib/providers/index.js +0 -7
- package/lib/scripts/check-avs-registration.js +0 -28
- package/lib/scripts/fallbacks/crypto.js +0 -4
- package/lib/scripts/fallbacks/empty.js +0 -4
- package/lib/scripts/fallbacks/re2.js +0 -7
- package/lib/scripts/fallbacks/snarkjs.js +0 -10
- package/lib/scripts/fallbacks/stwo.js +0 -159
- package/lib/scripts/generate-provider-types.js +0 -101
- package/lib/scripts/generate-receipt.js +0 -101
- package/lib/scripts/generate-toprf-keys.js +0 -24
- package/lib/scripts/jsc-cli-rpc.js +0 -35
- package/lib/scripts/register-avs-operator.js +0 -3
- package/lib/scripts/start-server.js +0 -11
- package/lib/scripts/update-avs-metadata.js +0 -20
- package/lib/scripts/utils.js +0 -10
- package/lib/scripts/whitelist-operator.js +0 -16
- package/lib/server/create-server.js +0 -105
- package/lib/server/handlers/claimTeeBundle.js +0 -232
- package/lib/server/handlers/claimTunnel.js +0 -80
- package/lib/server/handlers/completeClaimOnChain.js +0 -29
- package/lib/server/handlers/createClaimOnChain.js +0 -32
- package/lib/server/handlers/createTaskOnMechain.js +0 -57
- package/lib/server/handlers/createTunnel.js +0 -98
- package/lib/server/handlers/disconnectTunnel.js +0 -8
- package/lib/server/handlers/fetchCertificateBytes.js +0 -57
- package/lib/server/handlers/index.js +0 -25
- package/lib/server/handlers/init.js +0 -33
- package/lib/server/handlers/toprf.js +0 -19
- package/lib/server/index.js +0 -4
- package/lib/server/socket.js +0 -112
- package/lib/server/tunnels/make-tcp-tunnel.js +0 -202
- package/lib/server/utils/apm.js +0 -29
- package/lib/server/utils/assert-valid-claim-request.js +0 -354
- package/lib/server/utils/config-env.js +0 -4
- package/lib/server/utils/dns.js +0 -24
- package/lib/server/utils/gcp-attestation.js +0 -237
- package/lib/server/utils/generics.js +0 -45
- package/lib/server/utils/iso.js +0 -259
- package/lib/server/utils/keep-alive.js +0 -38
- package/lib/server/utils/nitro-attestation.js +0 -249
- package/lib/server/utils/oprf-raw.js +0 -61
- package/lib/server/utils/process-handshake.js +0 -233
- package/lib/server/utils/proxy-session.js +0 -4
- package/lib/server/utils/tee-oprf-mpc-verification.js +0 -86
- package/lib/server/utils/tee-oprf-verification.js +0 -151
- package/lib/server/utils/tee-transcript-reconstruction.js +0 -140
- package/lib/server/utils/tee-verification.js +0 -358
- package/lib/server/utils/validation.js +0 -45
- package/lib/types/bgp.js +0 -0
- package/lib/types/claims.js +0 -0
- package/lib/types/client.js +0 -0
- package/lib/types/general.js +0 -0
- package/lib/types/handlers.js +0 -0
- package/lib/types/index.js +0 -10
- package/lib/types/providers.gen.js +0 -16
- package/lib/types/providers.js +0 -0
- package/lib/types/rpc.js +0 -0
- package/lib/types/signatures.js +0 -0
- package/lib/types/tunnel.js +0 -0
- package/lib/types/zk.js +0 -0
- package/lib/utils/auth.js +0 -71
- package/lib/utils/b64-json.js +0 -17
- package/lib/utils/bgp-listener.js +0 -123
- package/lib/utils/claims.js +0 -89
- package/lib/utils/env.js +0 -19
- package/lib/utils/error.js +0 -54
- package/lib/utils/generics.js +0 -272
- package/lib/utils/http-parser.js +0 -201
- package/lib/utils/index.browser.d.ts +0 -13
- package/lib/utils/index.js +0 -14
- package/lib/utils/logger.browser.d.ts +0 -14
- package/lib/utils/logger.js +0 -82
- package/lib/utils/prepare-packets.js +0 -69
- package/lib/utils/redactions.js +0 -135
- package/lib/utils/retries.js +0 -26
- package/lib/utils/signatures/eth.js +0 -31
- package/lib/utils/signatures/index.js +0 -12
- package/lib/utils/socket-base.js +0 -96
- package/lib/utils/tls-imports.d.ts +0 -21
- package/lib/utils/tls-imports.js +0 -71
- package/lib/utils/tls.js +0 -58
- package/lib/utils/ws.js +0 -22
- package/lib/utils/zk.js +0 -625
|
@@ -1,354 +0,0 @@
|
|
|
1
|
-
import { areUint8ArraysEqual, concatenateUint8Arrays } from "@reclaimprotocol/tls";
|
|
2
|
-
import { ClaimTunnelRequest, TranscriptMessageSenderType } from "../../proto/api.js";
|
|
3
|
-
import { providers } from "../../providers/index.js";
|
|
4
|
-
import { niceParseJsonObject } from "../../server/utils/generics.js";
|
|
5
|
-
import { computeOPRFRaw } from "../../server/utils/oprf-raw.js";
|
|
6
|
-
import { processHandshake } from "../../server/utils/process-handshake.js";
|
|
7
|
-
import { assertValidateProviderParams } from "../../server/utils/validation.js";
|
|
8
|
-
import {
|
|
9
|
-
AttestorError,
|
|
10
|
-
binaryHashToStr,
|
|
11
|
-
canonicalStringify,
|
|
12
|
-
decryptDirect,
|
|
13
|
-
extractApplicationDataFromTranscript,
|
|
14
|
-
hashProviderParams,
|
|
15
|
-
SIGNATURES,
|
|
16
|
-
verifyZkPacket
|
|
17
|
-
} from "../../utils/index.js";
|
|
18
|
-
import { getEngineString } from "../../utils/zk.js";
|
|
19
|
-
async function assertValidClaimRequest(request, metadata, logger) {
|
|
20
|
-
const {
|
|
21
|
-
data,
|
|
22
|
-
signatures: { requestSignature } = {},
|
|
23
|
-
zkEngine,
|
|
24
|
-
fixedServerIV,
|
|
25
|
-
fixedClientIV
|
|
26
|
-
} = request;
|
|
27
|
-
if (!data) {
|
|
28
|
-
throw new AttestorError(
|
|
29
|
-
"ERROR_INVALID_CLAIM",
|
|
30
|
-
"No info provided on claim request"
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
if (!requestSignature?.length) {
|
|
34
|
-
throw new AttestorError(
|
|
35
|
-
"ERROR_INVALID_CLAIM",
|
|
36
|
-
"No signature provided on claim request"
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
const serialisedReq = ClaimTunnelRequest.encode({ ...request, signatures: void 0 }).finish();
|
|
40
|
-
const { verify: verifySig } = SIGNATURES[metadata.signatureType];
|
|
41
|
-
const verified = await verifySig(serialisedReq, requestSignature, data.owner);
|
|
42
|
-
if (!verified) {
|
|
43
|
-
throw new AttestorError(
|
|
44
|
-
"ERROR_INVALID_CLAIM",
|
|
45
|
-
"Invalid signature on claim request"
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
const receipt = await decryptTranscript(
|
|
49
|
-
request.transcript,
|
|
50
|
-
logger,
|
|
51
|
-
getEngineString(zkEngine),
|
|
52
|
-
fixedServerIV,
|
|
53
|
-
fixedClientIV
|
|
54
|
-
);
|
|
55
|
-
const reqHost = request.request?.host;
|
|
56
|
-
if (receipt.hostname !== reqHost) {
|
|
57
|
-
throw new Error(
|
|
58
|
-
`Expected server name ${reqHost}, got ${receipt.hostname}`
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
const applData = extractApplicationDataFromTranscript(receipt);
|
|
62
|
-
const newData = await assertValidProviderTranscript(
|
|
63
|
-
applData,
|
|
64
|
-
data,
|
|
65
|
-
logger,
|
|
66
|
-
{ version: metadata.clientVersion },
|
|
67
|
-
receipt.oprfRawReplacements
|
|
68
|
-
);
|
|
69
|
-
if (newData !== data) {
|
|
70
|
-
logger.info({ newData }, "updated claim info");
|
|
71
|
-
}
|
|
72
|
-
return newData;
|
|
73
|
-
}
|
|
74
|
-
async function assertValidProviderTranscript(applData, info, logger, providerCtx, oprfRawReplacements) {
|
|
75
|
-
const providerName = info.provider;
|
|
76
|
-
const provider = providers[providerName];
|
|
77
|
-
if (!provider) {
|
|
78
|
-
throw new AttestorError(
|
|
79
|
-
"ERROR_INVALID_CLAIM",
|
|
80
|
-
`Unsupported provider: ${providerName}`
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
|
-
let params = niceParseJsonObject(info.parameters, "params");
|
|
84
|
-
const ctx = niceParseJsonObject(info.context, "context");
|
|
85
|
-
if (oprfRawReplacements?.length) {
|
|
86
|
-
let strParams = canonicalStringify(params) ?? "{}";
|
|
87
|
-
for (const { originalText, nullifierText } of oprfRawReplacements) {
|
|
88
|
-
strParams = strParams.replaceAll(originalText, nullifierText);
|
|
89
|
-
}
|
|
90
|
-
params = JSON.parse(strParams);
|
|
91
|
-
info.parameters = strParams;
|
|
92
|
-
logger.debug(
|
|
93
|
-
{ replacements: oprfRawReplacements.length },
|
|
94
|
-
"applied oprf-raw parameter replacements"
|
|
95
|
-
);
|
|
96
|
-
}
|
|
97
|
-
assertValidateProviderParams(providerName, params);
|
|
98
|
-
const rslt = await provider.assertValidProviderReceipt({
|
|
99
|
-
receipt: applData,
|
|
100
|
-
params,
|
|
101
|
-
logger,
|
|
102
|
-
ctx: providerCtx
|
|
103
|
-
});
|
|
104
|
-
ctx.providerHash = hashProviderParams(params);
|
|
105
|
-
const extractedParameters = rslt?.extractedParameters || {};
|
|
106
|
-
if (Object.keys(extractedParameters).length) {
|
|
107
|
-
ctx.extractedParameters = extractedParameters;
|
|
108
|
-
}
|
|
109
|
-
info.context = canonicalStringify(ctx) ?? "";
|
|
110
|
-
return info;
|
|
111
|
-
}
|
|
112
|
-
function assertTranscriptsMatch(clientTranscript, tunnelTranscript) {
|
|
113
|
-
const clientSends = concatenateUint8Arrays(
|
|
114
|
-
clientTranscript.filter((m) => m.sender === TranscriptMessageSenderType.TRANSCRIPT_MESSAGE_SENDER_TYPE_CLIENT).map((m) => m.message)
|
|
115
|
-
);
|
|
116
|
-
const tunnelSends = concatenateUint8Arrays(
|
|
117
|
-
tunnelTranscript.filter((m) => m.sender === "client").map((m) => m.message)
|
|
118
|
-
);
|
|
119
|
-
if (!areUint8ArraysEqual(clientSends, tunnelSends)) {
|
|
120
|
-
throw AttestorError.badRequest(
|
|
121
|
-
"Outgoing messages from client do not match the tunnel transcript"
|
|
122
|
-
);
|
|
123
|
-
}
|
|
124
|
-
const clientRecvs = concatenateUint8Arrays(
|
|
125
|
-
clientTranscript.filter((m) => m.sender === TranscriptMessageSenderType.TRANSCRIPT_MESSAGE_SENDER_TYPE_SERVER).map((m) => m.message)
|
|
126
|
-
);
|
|
127
|
-
const tunnelRecvs = concatenateUint8Arrays(
|
|
128
|
-
tunnelTranscript.filter((m) => m.sender === "server").map((m) => m.message)
|
|
129
|
-
).slice(0, clientRecvs.length);
|
|
130
|
-
if (!areUint8ArraysEqual(clientRecvs, tunnelRecvs)) {
|
|
131
|
-
throw AttestorError.badRequest(
|
|
132
|
-
"Incoming messages from server do not match the tunnel transcript"
|
|
133
|
-
);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
async function decryptTranscript(transcript, logger, zkEngine, serverIV, clientIV) {
|
|
137
|
-
const {
|
|
138
|
-
tlsVersion,
|
|
139
|
-
cipherSuite,
|
|
140
|
-
hostname,
|
|
141
|
-
nextMsgIndex
|
|
142
|
-
} = await processHandshake(transcript, logger);
|
|
143
|
-
let clientRecordNumber = tlsVersion === "TLS1_3" ? -1 : 0;
|
|
144
|
-
let serverRecordNumber = clientRecordNumber;
|
|
145
|
-
transcript = transcript.slice(nextMsgIndex);
|
|
146
|
-
const overshotMap = {};
|
|
147
|
-
const decryptedTranscript = [];
|
|
148
|
-
const oprfRawReplacements = [];
|
|
149
|
-
const pendingOprfRaw = {};
|
|
150
|
-
for (const [i, {
|
|
151
|
-
sender,
|
|
152
|
-
message,
|
|
153
|
-
reveal: { zkReveal, directReveal } = {}
|
|
154
|
-
}] of transcript.entries()) {
|
|
155
|
-
try {
|
|
156
|
-
await decryptMessage(sender, message, directReveal, zkReveal, i);
|
|
157
|
-
} catch (error) {
|
|
158
|
-
const err = new AttestorError(
|
|
159
|
-
"ERROR_INVALID_CLAIM",
|
|
160
|
-
`error in handling packet at idx ${i}: ${error}`,
|
|
161
|
-
{ packetIdx: i, error }
|
|
162
|
-
);
|
|
163
|
-
if (error.stack) {
|
|
164
|
-
err.stack = error.stack;
|
|
165
|
-
}
|
|
166
|
-
throw err;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
const remainingPending = Object.keys(pendingOprfRaw);
|
|
170
|
-
if (remainingPending.length) {
|
|
171
|
-
throw new AttestorError(
|
|
172
|
-
"ERROR_INVALID_CLAIM",
|
|
173
|
-
`oprf-raw cross-block markers incomplete: pending for packets ${remainingPending.join(", ")}`
|
|
174
|
-
);
|
|
175
|
-
}
|
|
176
|
-
return {
|
|
177
|
-
transcript: decryptedTranscript,
|
|
178
|
-
hostname,
|
|
179
|
-
tlsVersion,
|
|
180
|
-
oprfRawReplacements: oprfRawReplacements.length ? oprfRawReplacements : void 0
|
|
181
|
-
};
|
|
182
|
-
async function decryptMessage(sender, message, directReveal, zkReveal, i) {
|
|
183
|
-
const isServer = sender === TranscriptMessageSenderType.TRANSCRIPT_MESSAGE_SENDER_TYPE_SERVER;
|
|
184
|
-
const recordHeader = message.slice(0, 5);
|
|
185
|
-
const content = getWithoutHeader(message);
|
|
186
|
-
if (isServer) {
|
|
187
|
-
serverRecordNumber++;
|
|
188
|
-
} else {
|
|
189
|
-
clientRecordNumber++;
|
|
190
|
-
}
|
|
191
|
-
let redacted = true;
|
|
192
|
-
let plaintext = void 0;
|
|
193
|
-
let plaintextLength;
|
|
194
|
-
if (directReveal?.key?.length) {
|
|
195
|
-
const result = await decryptDirect(
|
|
196
|
-
directReveal,
|
|
197
|
-
cipherSuite,
|
|
198
|
-
recordHeader,
|
|
199
|
-
tlsVersion,
|
|
200
|
-
content
|
|
201
|
-
);
|
|
202
|
-
plaintext = result.plaintext;
|
|
203
|
-
redacted = false;
|
|
204
|
-
plaintextLength = plaintext.length;
|
|
205
|
-
} else if (zkReveal?.proofs?.length) {
|
|
206
|
-
const iv = sender === TranscriptMessageSenderType.TRANSCRIPT_MESSAGE_SENDER_TYPE_SERVER ? serverIV : clientIV;
|
|
207
|
-
const recordNumber = isServer ? serverRecordNumber : clientRecordNumber;
|
|
208
|
-
const result = await verifyZkPacket(
|
|
209
|
-
{
|
|
210
|
-
ciphertext: content,
|
|
211
|
-
zkReveal,
|
|
212
|
-
iv,
|
|
213
|
-
recordNumber,
|
|
214
|
-
toprfOvershotNullifier: overshotMap[i]?.data,
|
|
215
|
-
getNextPacket(overshot) {
|
|
216
|
-
const nextIdx = transcript.findIndex((t, j) => t.sender === sender && j > i);
|
|
217
|
-
if (nextIdx < 0) {
|
|
218
|
-
return;
|
|
219
|
-
}
|
|
220
|
-
overshotMap[nextIdx] = { data: overshot };
|
|
221
|
-
return getWithoutHeader(transcript[nextIdx].message);
|
|
222
|
-
},
|
|
223
|
-
logger,
|
|
224
|
-
cipherSuite,
|
|
225
|
-
zkEngine
|
|
226
|
-
}
|
|
227
|
-
);
|
|
228
|
-
plaintext = result.redactedPlaintext;
|
|
229
|
-
const pendingForThis = pendingOprfRaw[i];
|
|
230
|
-
if (pendingForThis && zkReveal?.overshotOprfRawLength) {
|
|
231
|
-
const overshootLen = zkReveal.overshotOprfRawLength;
|
|
232
|
-
const overshootData = plaintext.slice(0, overshootLen);
|
|
233
|
-
const fullData = concatenateUint8Arrays([
|
|
234
|
-
pendingForThis.partialData,
|
|
235
|
-
overshootData
|
|
236
|
-
]);
|
|
237
|
-
const expectedLen = pendingForThis.dataLocation.length;
|
|
238
|
-
if (fullData.length !== expectedLen) {
|
|
239
|
-
throw new AttestorError(
|
|
240
|
-
"ERROR_INVALID_CLAIM",
|
|
241
|
-
`oprf-raw cross-block length mismatch: got ${fullData.length}, expected ${expectedLen}`
|
|
242
|
-
);
|
|
243
|
-
}
|
|
244
|
-
const oprfResults = await computeOPRFRaw(
|
|
245
|
-
fullData,
|
|
246
|
-
[{ dataLocation: { fromIndex: 0, length: fullData.length } }],
|
|
247
|
-
logger
|
|
248
|
-
);
|
|
249
|
-
if (oprfResults.length) {
|
|
250
|
-
const { nullifier } = oprfResults[0];
|
|
251
|
-
const originalText = new TextDecoder().decode(fullData);
|
|
252
|
-
const nullifierStr = binaryHashToStr(nullifier, fullData.length);
|
|
253
|
-
oprfRawReplacements.push({ originalText, nullifierText: nullifierStr });
|
|
254
|
-
const nullifierBytes = new TextEncoder().encode(nullifierStr);
|
|
255
|
-
const overshootNullifier = nullifierBytes.slice(pendingForThis.partialData.length);
|
|
256
|
-
plaintext.set(overshootNullifier, 0);
|
|
257
|
-
const prevPkt = decryptedTranscript[pendingForThis.originPktIdx];
|
|
258
|
-
if (prevPkt) {
|
|
259
|
-
const firstPartNullifier = nullifierBytes.slice(0, pendingForThis.partialData.length);
|
|
260
|
-
prevPkt.message.set(firstPartNullifier, pendingForThis.dataLocation.fromIndex);
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
delete pendingOprfRaw[i];
|
|
264
|
-
}
|
|
265
|
-
if (result.oprfRawMarkers?.length) {
|
|
266
|
-
const { markersThisPacket, pendingMarker } = separateOprfRawMarkers(
|
|
267
|
-
result.oprfRawMarkers,
|
|
268
|
-
plaintext.length,
|
|
269
|
-
() => transcript.findIndex((t, j) => t.sender === sender && j > i),
|
|
270
|
-
decryptedTranscript.length,
|
|
271
|
-
logger
|
|
272
|
-
);
|
|
273
|
-
if (pendingMarker) {
|
|
274
|
-
pendingMarker.pending.partialData.set(
|
|
275
|
-
plaintext.slice(pendingMarker.pending.dataLocation.fromIndex)
|
|
276
|
-
);
|
|
277
|
-
pendingOprfRaw[pendingMarker.nextIdx] = pendingMarker.pending;
|
|
278
|
-
}
|
|
279
|
-
if (markersThisPacket.length) {
|
|
280
|
-
const pt = plaintext;
|
|
281
|
-
const oprfResults = await computeOPRFRaw(pt, markersThisPacket, logger);
|
|
282
|
-
const originalTexts = oprfResults.map(({ dataLocation }) => new TextDecoder().decode(
|
|
283
|
-
pt.slice(dataLocation.fromIndex, dataLocation.fromIndex + dataLocation.length)
|
|
284
|
-
));
|
|
285
|
-
for (const [idx, { dataLocation, nullifier }] of oprfResults.entries()) {
|
|
286
|
-
const originalText = originalTexts[idx];
|
|
287
|
-
const nullifierStr = binaryHashToStr(nullifier, dataLocation.length);
|
|
288
|
-
oprfRawReplacements.push({ originalText, nullifierText: nullifierStr });
|
|
289
|
-
const nullifierBytes = new TextEncoder().encode(nullifierStr);
|
|
290
|
-
pt.set(nullifierBytes, dataLocation.fromIndex);
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
redacted = false;
|
|
295
|
-
plaintextLength = plaintext.length;
|
|
296
|
-
} else {
|
|
297
|
-
plaintext = content;
|
|
298
|
-
plaintextLength = plaintext.length;
|
|
299
|
-
}
|
|
300
|
-
decryptedTranscript.push({
|
|
301
|
-
sender: sender === TranscriptMessageSenderType.TRANSCRIPT_MESSAGE_SENDER_TYPE_CLIENT ? "client" : "server",
|
|
302
|
-
redacted,
|
|
303
|
-
message: plaintext,
|
|
304
|
-
recordHeader,
|
|
305
|
-
plaintextLength
|
|
306
|
-
});
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
function getWithoutHeader(message) {
|
|
310
|
-
return message.slice(5);
|
|
311
|
-
}
|
|
312
|
-
function separateOprfRawMarkers(markers, plaintextLength, findNextPacketIdx, currentTranscriptLength, logger) {
|
|
313
|
-
const markersThisPacket = [];
|
|
314
|
-
let pendingMarker;
|
|
315
|
-
for (const marker of markers) {
|
|
316
|
-
const dataLocation = marker.dataLocation;
|
|
317
|
-
if (!dataLocation) {
|
|
318
|
-
continue;
|
|
319
|
-
}
|
|
320
|
-
const { fromIndex, length } = dataLocation;
|
|
321
|
-
const endInPacket = fromIndex + length;
|
|
322
|
-
if (endInPacket <= plaintextLength) {
|
|
323
|
-
markersThisPacket.push({ dataLocation });
|
|
324
|
-
continue;
|
|
325
|
-
}
|
|
326
|
-
const nextIdx = findNextPacketIdx();
|
|
327
|
-
if (nextIdx < 0) {
|
|
328
|
-
throw new AttestorError(
|
|
329
|
-
"ERROR_INVALID_CLAIM",
|
|
330
|
-
"oprf-raw marker spans packets but no next packet found"
|
|
331
|
-
);
|
|
332
|
-
}
|
|
333
|
-
pendingMarker = {
|
|
334
|
-
nextIdx,
|
|
335
|
-
pending: {
|
|
336
|
-
partialData: new Uint8Array(plaintextLength - fromIndex),
|
|
337
|
-
dataLocation: { fromIndex, length },
|
|
338
|
-
originPktIdx: currentTranscriptLength
|
|
339
|
-
}
|
|
340
|
-
};
|
|
341
|
-
logger.debug(
|
|
342
|
-
{ fromIndex, length, partialLen: plaintextLength - fromIndex, nextIdx },
|
|
343
|
-
"oprf-raw marker spans packets, storing partial data"
|
|
344
|
-
);
|
|
345
|
-
}
|
|
346
|
-
return { markersThisPacket, pendingMarker };
|
|
347
|
-
}
|
|
348
|
-
export {
|
|
349
|
-
assertTranscriptsMatch,
|
|
350
|
-
assertValidClaimRequest,
|
|
351
|
-
assertValidProviderTranscript,
|
|
352
|
-
decryptTranscript,
|
|
353
|
-
getWithoutHeader
|
|
354
|
-
};
|
package/lib/server/utils/dns.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { resolve, setServers } from "dns";
|
|
2
|
-
import { DNS_SERVERS } from "../../config/index.js";
|
|
3
|
-
setDnsServers();
|
|
4
|
-
async function resolveHostnames(hostname) {
|
|
5
|
-
return new Promise((_resolve, reject) => {
|
|
6
|
-
resolve(hostname, (err, addresses) => {
|
|
7
|
-
if (err) {
|
|
8
|
-
reject(
|
|
9
|
-
new Error(
|
|
10
|
-
`Could not resolve hostname: ${hostname}, ${err.message}`
|
|
11
|
-
)
|
|
12
|
-
);
|
|
13
|
-
} else {
|
|
14
|
-
_resolve(addresses);
|
|
15
|
-
}
|
|
16
|
-
});
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
function setDnsServers() {
|
|
20
|
-
setServers(DNS_SERVERS);
|
|
21
|
-
}
|
|
22
|
-
export {
|
|
23
|
-
resolveHostnames
|
|
24
|
-
};
|
|
@@ -1,237 +0,0 @@
|
|
|
1
|
-
import crypto, { X509Certificate } from "crypto";
|
|
2
|
-
let gcpKeysCache = null;
|
|
3
|
-
let gcpKeysCacheTime = 0;
|
|
4
|
-
const GCP_KEYS_CACHE_TTL = 36e5;
|
|
5
|
-
const GCP_CONFIDENTIAL_SPACE_ROOT_CA = `-----BEGIN CERTIFICATE-----
|
|
6
|
-
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
-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
-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
-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
-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
-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
-
BgNVBAoTCkdvb2dsZSBMTEMxFTATBgNVBAsTDEdvb2dsZSBDbG91ZDEjMCEGA1UE
|
|
13
|
-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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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
-
uiHvXeSJBRlRxQ8Vu+t6J7hBdl0etWBKAu9Vti46af5cjC03dspkHR3MAUGcrLWE
|
|
23
|
-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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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
|
|
38
|
-
uyT5CnJulxSC5CT1
|
|
39
|
-
-----END CERTIFICATE-----`;
|
|
40
|
-
function base64urlDecode(input) {
|
|
41
|
-
let base64 = input.replace(/-/g, "+").replace(/_/g, "/");
|
|
42
|
-
while (base64.length % 4) {
|
|
43
|
-
base64 += "=";
|
|
44
|
-
}
|
|
45
|
-
return Buffer.from(base64, "base64");
|
|
46
|
-
}
|
|
47
|
-
async function fetchGooglePublicKeys(logger) {
|
|
48
|
-
const now = Date.now();
|
|
49
|
-
if (gcpKeysCache && now - gcpKeysCacheTime < GCP_KEYS_CACHE_TTL) {
|
|
50
|
-
if (logger) {
|
|
51
|
-
logger.debug("Using cached Google public keys");
|
|
52
|
-
}
|
|
53
|
-
return gcpKeysCache;
|
|
54
|
-
}
|
|
55
|
-
if (logger) {
|
|
56
|
-
logger.info("Fetching Google public keys from https://www.googleapis.com/oauth2/v3/certs");
|
|
57
|
-
}
|
|
58
|
-
const response = await fetch("https://www.googleapis.com/oauth2/v3/certs");
|
|
59
|
-
if (!response.ok) {
|
|
60
|
-
throw new Error(`Failed to fetch Google keys: ${response.status} ${response.statusText}`);
|
|
61
|
-
}
|
|
62
|
-
const keys = await response.json();
|
|
63
|
-
gcpKeysCache = keys;
|
|
64
|
-
gcpKeysCacheTime = now;
|
|
65
|
-
if (logger) {
|
|
66
|
-
logger.info(`Fetched ${keys.keys.length} Google public keys`);
|
|
67
|
-
}
|
|
68
|
-
return keys;
|
|
69
|
-
}
|
|
70
|
-
function jwkToPublicKey(jwk) {
|
|
71
|
-
return crypto.createPublicKey({
|
|
72
|
-
key: {
|
|
73
|
-
kty: "RSA",
|
|
74
|
-
n: jwk.n,
|
|
75
|
-
e: jwk.e
|
|
76
|
-
},
|
|
77
|
-
format: "jwk"
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
function verifyX5cChain(x5cChain, logger) {
|
|
81
|
-
if (!x5cChain || x5cChain.length === 0) {
|
|
82
|
-
throw new Error("Empty x5c certificate chain");
|
|
83
|
-
}
|
|
84
|
-
const leafCertPem = `-----BEGIN CERTIFICATE-----
|
|
85
|
-
${x5cChain[0]}
|
|
86
|
-
-----END CERTIFICATE-----`;
|
|
87
|
-
const leafCert = new X509Certificate(leafCertPem);
|
|
88
|
-
if (logger) {
|
|
89
|
-
logger.info(`x5c leaf certificate: subject=${leafCert.subject}, issuer=${leafCert.issuer}`);
|
|
90
|
-
}
|
|
91
|
-
const rootCert = new X509Certificate(GCP_CONFIDENTIAL_SPACE_ROOT_CA);
|
|
92
|
-
let currentCert = leafCert;
|
|
93
|
-
for (let i = 1; i < x5cChain.length; i++) {
|
|
94
|
-
const intermediatePem = `-----BEGIN CERTIFICATE-----
|
|
95
|
-
${x5cChain[i]}
|
|
96
|
-
-----END CERTIFICATE-----`;
|
|
97
|
-
const intermediateCert = new X509Certificate(intermediatePem);
|
|
98
|
-
const isValid = currentCert.verify(intermediateCert.publicKey);
|
|
99
|
-
if (!isValid) {
|
|
100
|
-
throw new Error(`Certificate chain verification failed at level ${i}`);
|
|
101
|
-
}
|
|
102
|
-
if (logger) {
|
|
103
|
-
logger.debug(`Verified cert level ${i}: ${intermediateCert.subject}`);
|
|
104
|
-
}
|
|
105
|
-
currentCert = intermediateCert;
|
|
106
|
-
}
|
|
107
|
-
const isRootValid = currentCert.verify(rootCert.publicKey);
|
|
108
|
-
if (!isRootValid) {
|
|
109
|
-
throw new Error("Certificate chain does not root to GCP Confidential Space Root CA");
|
|
110
|
-
}
|
|
111
|
-
if (logger) {
|
|
112
|
-
logger.info("x5c certificate chain verified successfully");
|
|
113
|
-
}
|
|
114
|
-
return leafCert.publicKey;
|
|
115
|
-
}
|
|
116
|
-
async function validateGcpAttestationAndExtractKey(attestationBytes, logger) {
|
|
117
|
-
const errors = [];
|
|
118
|
-
try {
|
|
119
|
-
const jwtString = Buffer.from(attestationBytes).toString("utf8");
|
|
120
|
-
const parts = jwtString.split(".");
|
|
121
|
-
if (parts.length !== 3) {
|
|
122
|
-
errors.push("Invalid JWT format: expected 3 parts");
|
|
123
|
-
return { isValid: false, errors };
|
|
124
|
-
}
|
|
125
|
-
const [headerB64, payloadB64, signatureB64] = parts;
|
|
126
|
-
const headerJson = base64urlDecode(headerB64).toString("utf8");
|
|
127
|
-
const payloadJson = base64urlDecode(payloadB64).toString("utf8");
|
|
128
|
-
const header = JSON.parse(headerJson);
|
|
129
|
-
const payload = JSON.parse(payloadJson);
|
|
130
|
-
if (logger) {
|
|
131
|
-
logger.info(`GCP JWT header: kid=${header.kid}, alg=${header.alg}`);
|
|
132
|
-
logger.info(`GCP JWT payload: iss=${payload.iss}, aud=${payload.aud}`);
|
|
133
|
-
}
|
|
134
|
-
const now = Math.floor(Date.now() / 1e3);
|
|
135
|
-
const validIssuers = [
|
|
136
|
-
"https://accounts.google.com",
|
|
137
|
-
"https://confidentialcomputing.googleapis.com"
|
|
138
|
-
];
|
|
139
|
-
if (!validIssuers.includes(payload.iss)) {
|
|
140
|
-
errors.push(`Invalid issuer: expected one of ${validIssuers.join(", ")}, got "${payload.iss}"`);
|
|
141
|
-
}
|
|
142
|
-
if (payload.exp <= now) {
|
|
143
|
-
errors.push(`Token expired: exp=${payload.exp}, now=${now}`);
|
|
144
|
-
}
|
|
145
|
-
if (payload.iat > now + 60) {
|
|
146
|
-
errors.push(`Token issued in future: iat=${payload.iat}, now=${now}`);
|
|
147
|
-
}
|
|
148
|
-
const hasReclaimAudience = payload.aud?.includes("reclaimprotocol.org");
|
|
149
|
-
const hasGcpStsAudience = payload.aud?.includes("sts.googleapis.com");
|
|
150
|
-
if (!hasReclaimAudience && !hasGcpStsAudience) {
|
|
151
|
-
errors.push(`Invalid audience: expected "reclaimprotocol.org" or "sts.googleapis.com", got "${payload.aud}"`);
|
|
152
|
-
}
|
|
153
|
-
if (errors.length > 0) {
|
|
154
|
-
return { isValid: false, errors };
|
|
155
|
-
}
|
|
156
|
-
let publicKey;
|
|
157
|
-
if (header.x5c && header.x5c.length > 0) {
|
|
158
|
-
if (logger) {
|
|
159
|
-
logger.info(`Using x5c certificate chain (${header.x5c.length} certificates)`);
|
|
160
|
-
}
|
|
161
|
-
publicKey = verifyX5cChain(header.x5c, logger);
|
|
162
|
-
} else if (header.kid) {
|
|
163
|
-
if (logger) {
|
|
164
|
-
logger.info(`Using OIDC token with kid: ${header.kid}`);
|
|
165
|
-
}
|
|
166
|
-
const jwks = await fetchGooglePublicKeys(logger);
|
|
167
|
-
const jwk = jwks.keys.find((k) => k.kid === header.kid);
|
|
168
|
-
if (!jwk) {
|
|
169
|
-
errors.push(`No public key found for kid: ${header.kid}`);
|
|
170
|
-
return { isValid: false, errors };
|
|
171
|
-
}
|
|
172
|
-
publicKey = jwkToPublicKey(jwk);
|
|
173
|
-
} else {
|
|
174
|
-
errors.push("JWT header must contain either x5c or kid field");
|
|
175
|
-
return { isValid: false, errors };
|
|
176
|
-
}
|
|
177
|
-
const signedData = `${headerB64}.${payloadB64}`;
|
|
178
|
-
const signature = base64urlDecode(signatureB64);
|
|
179
|
-
const verify = crypto.createVerify("RSA-SHA256");
|
|
180
|
-
verify.update(signedData);
|
|
181
|
-
const isSignatureValid = verify.verify(publicKey, signature);
|
|
182
|
-
if (!isSignatureValid) {
|
|
183
|
-
errors.push("Signature verification failed");
|
|
184
|
-
return { isValid: false, errors };
|
|
185
|
-
}
|
|
186
|
-
if (logger) {
|
|
187
|
-
logger.info("GCP JWT signature verified successfully");
|
|
188
|
-
}
|
|
189
|
-
if (!payload.eat_nonce) {
|
|
190
|
-
errors.push("No eat_nonce field found in JWT payload");
|
|
191
|
-
return { isValid: false, errors };
|
|
192
|
-
}
|
|
193
|
-
const match = payload.eat_nonce.match(/^(tee_[kt])_public_key:0x([0-9a-fA-F]{40})$/);
|
|
194
|
-
if (!match) {
|
|
195
|
-
errors.push(`Invalid eat_nonce format: ${payload.eat_nonce}`);
|
|
196
|
-
return { isValid: false, errors };
|
|
197
|
-
}
|
|
198
|
-
const userDataType = match[1];
|
|
199
|
-
const hexAddress = match[2];
|
|
200
|
-
const ethAddress = new Uint8Array(Buffer.from(hexAddress, "hex"));
|
|
201
|
-
if (logger) {
|
|
202
|
-
logger.info(`Extracted address from eat_nonce: ${payload.eat_nonce}`);
|
|
203
|
-
}
|
|
204
|
-
let pcr0 = "gcp-no-digest";
|
|
205
|
-
if (payload.google?.compute_engine?.image_digest) {
|
|
206
|
-
pcr0 = payload.google.compute_engine.image_digest;
|
|
207
|
-
} else if (payload.submods?.container?.image_digest) {
|
|
208
|
-
pcr0 = payload.submods.container.image_digest;
|
|
209
|
-
}
|
|
210
|
-
if (payload.dbgstat === "enabled" && pcr0.startsWith("sha256:")) {
|
|
211
|
-
pcr0 = "debug_" + pcr0;
|
|
212
|
-
}
|
|
213
|
-
const envVars = payload.submods?.container?.env || {};
|
|
214
|
-
if (logger) {
|
|
215
|
-
const hexAddr = Buffer.from(ethAddress).toString("hex");
|
|
216
|
-
logger.info(`Extracted ETH address from GCP attestation: 0x${hexAddr}, type: ${userDataType}, pcr0: ${pcr0}`);
|
|
217
|
-
if (Object.keys(envVars).length > 0) {
|
|
218
|
-
logger.debug(`Environment variables: ${Object.keys(envVars).join(", ")}`);
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
return {
|
|
222
|
-
isValid: true,
|
|
223
|
-
errors: [],
|
|
224
|
-
ethAddress,
|
|
225
|
-
userDataType,
|
|
226
|
-
pcr0,
|
|
227
|
-
envVars
|
|
228
|
-
};
|
|
229
|
-
} catch (error) {
|
|
230
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
231
|
-
errors.push(`GCP attestation validation error: ${errorMsg}`);
|
|
232
|
-
return { isValid: false, errors };
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
export {
|
|
236
|
-
validateGcpAttestationAndExtractKey
|
|
237
|
-
};
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { RPCMessages } from "../../proto/api.js";
|
|
2
|
-
import { getEnvVariable } from "../../utils/env.js";
|
|
3
|
-
import { AttestorError, strToUint8Array } from "../../utils/index.js";
|
|
4
|
-
import { SIGNATURES } from "../../utils/signatures/index.js";
|
|
5
|
-
const PRIVATE_KEY = getEnvVariable("PRIVATE_KEY");
|
|
6
|
-
function signAsAttestor(data, scheme) {
|
|
7
|
-
const { sign } = SIGNATURES[scheme];
|
|
8
|
-
return sign(
|
|
9
|
-
typeof data === "string" ? strToUint8Array(data) : data,
|
|
10
|
-
PRIVATE_KEY
|
|
11
|
-
);
|
|
12
|
-
}
|
|
13
|
-
function getAttestorAddress(scheme) {
|
|
14
|
-
const { getAddress, getPublicKey } = SIGNATURES[scheme];
|
|
15
|
-
const publicKey = getPublicKey(PRIVATE_KEY);
|
|
16
|
-
return getAddress(publicKey);
|
|
17
|
-
}
|
|
18
|
-
function niceParseJsonObject(data, key) {
|
|
19
|
-
if (!data) {
|
|
20
|
-
return {};
|
|
21
|
-
}
|
|
22
|
-
try {
|
|
23
|
-
return JSON.parse(data);
|
|
24
|
-
} catch (e) {
|
|
25
|
-
throw AttestorError.badRequest(
|
|
26
|
-
`Invalid JSON in ${key}: ${e.message}`
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
function getInitialMessagesFromQuery(req) {
|
|
31
|
-
const url = new URL(req.url, "http://localhost");
|
|
32
|
-
const messagesB64 = url.searchParams.get("messages");
|
|
33
|
-
if (!messagesB64?.length) {
|
|
34
|
-
return [];
|
|
35
|
-
}
|
|
36
|
-
const msgsBytes = Buffer.from(messagesB64, "base64");
|
|
37
|
-
const msgs = RPCMessages.decode(msgsBytes);
|
|
38
|
-
return msgs.messages;
|
|
39
|
-
}
|
|
40
|
-
export {
|
|
41
|
-
getAttestorAddress,
|
|
42
|
-
getInitialMessagesFromQuery,
|
|
43
|
-
niceParseJsonObject,
|
|
44
|
-
signAsAttestor
|
|
45
|
-
};
|