@reclaimprotocol/attestor-core 5.0.1-beta.1 → 5.0.1-beta.2
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/lib/avs/abis/avsDirectoryABI.d.ts +60 -0
- package/lib/avs/abis/avsDirectoryABI.js +343 -0
- package/lib/avs/abis/delegationABI.d.ts +126 -0
- package/lib/avs/abis/delegationABI.js +4 -0
- package/lib/avs/abis/registryABI.d.ts +136 -0
- package/lib/avs/abis/registryABI.js +728 -0
- package/lib/avs/client/create-claim-on-avs.d.ts +12 -0
- package/lib/avs/client/create-claim-on-avs.js +168 -0
- package/lib/avs/config.d.ts +7 -0
- package/lib/avs/config.js +26 -0
- package/lib/avs/contracts/ReclaimServiceManager.d.ts +601 -0
- package/lib/avs/contracts/ReclaimServiceManager.js +0 -0
- package/lib/avs/contracts/common.d.ts +50 -0
- package/lib/avs/contracts/common.js +0 -0
- package/lib/avs/contracts/factories/ReclaimServiceManager__factory.d.ts +890 -0
- package/lib/avs/contracts/factories/ReclaimServiceManager__factory.js +1183 -0
- package/lib/avs/contracts/factories/index.d.ts +1 -0
- package/lib/avs/contracts/factories/index.js +4 -0
- package/lib/avs/contracts/index.d.ts +3 -0
- package/lib/avs/contracts/index.js +6 -0
- package/lib/avs/types/index.d.ts +55 -0
- package/lib/avs/types/index.js +0 -0
- package/lib/avs/utils/contracts.d.ts +21 -0
- package/lib/avs/utils/contracts.js +53 -0
- package/lib/avs/utils/register.d.ts +27 -0
- package/lib/avs/utils/register.js +74 -0
- package/lib/avs/utils/tasks.d.ts +22 -0
- package/lib/avs/utils/tasks.js +48 -0
- package/lib/client/create-claim.d.ts +5 -0
- package/lib/client/create-claim.js +461 -0
- package/lib/client/index.d.ts +3 -0
- package/lib/client/index.js +3 -0
- package/lib/client/tunnels/make-rpc-tcp-tunnel.d.ts +16 -0
- package/lib/client/tunnels/make-rpc-tcp-tunnel.js +53 -0
- package/lib/client/tunnels/make-rpc-tls-tunnel.d.ts +26 -0
- package/lib/client/tunnels/make-rpc-tls-tunnel.js +127 -0
- package/lib/client/utils/attestor-pool.d.ts +8 -0
- package/lib/client/utils/attestor-pool.js +24 -0
- package/lib/client/utils/client-socket.d.ts +11 -0
- package/lib/client/utils/client-socket.js +120 -0
- package/lib/client/utils/message-handler.d.ts +4 -0
- package/lib/client/utils/message-handler.js +97 -0
- package/lib/config/index.d.ts +31 -0
- package/lib/config/index.js +62 -0
- package/lib/external-rpc/benchmark.d.ts +1 -0
- package/lib/external-rpc/benchmark.js +82 -0
- package/lib/external-rpc/event-bus.d.ts +7 -0
- package/lib/external-rpc/event-bus.js +17 -0
- package/lib/external-rpc/global.d.js +0 -0
- package/lib/external-rpc/handle-incoming-msg.d.ts +2 -0
- package/lib/external-rpc/handle-incoming-msg.js +241 -0
- package/lib/external-rpc/index.d.ts +3 -0
- package/lib/external-rpc/index.js +3 -0
- package/lib/external-rpc/jsc-polyfills/1.d.ts +14 -0
- package/lib/external-rpc/jsc-polyfills/1.js +80 -0
- package/lib/external-rpc/jsc-polyfills/2.d.ts +1 -0
- package/lib/external-rpc/jsc-polyfills/2.js +15 -0
- package/lib/external-rpc/jsc-polyfills/event.d.ts +10 -0
- package/lib/external-rpc/jsc-polyfills/event.js +19 -0
- package/lib/external-rpc/jsc-polyfills/index.d.ts +2 -0
- package/lib/external-rpc/jsc-polyfills/index.js +2 -0
- package/lib/external-rpc/jsc-polyfills/ws.d.ts +21 -0
- package/lib/external-rpc/jsc-polyfills/ws.js +83 -0
- package/lib/external-rpc/setup-browser.d.ts +6 -0
- package/lib/external-rpc/setup-browser.js +33 -0
- package/lib/external-rpc/setup-jsc.d.ts +24 -0
- package/lib/external-rpc/setup-jsc.js +22 -0
- package/lib/external-rpc/types.d.ts +213 -0
- package/lib/external-rpc/types.js +0 -0
- package/lib/external-rpc/utils.d.ts +20 -0
- package/lib/external-rpc/utils.js +100 -0
- package/lib/external-rpc/zk.d.ts +14 -0
- package/lib/external-rpc/zk.js +58 -0
- package/lib/index.d.ts +9 -0
- package/lib/index.js +13 -0
- package/lib/mechain/abis/governanceABI.d.ts +50 -0
- package/lib/mechain/abis/governanceABI.js +461 -0
- package/lib/mechain/abis/taskABI.d.ts +157 -0
- package/lib/mechain/abis/taskABI.js +512 -0
- package/lib/mechain/client/create-claim-on-mechain.d.ts +10 -0
- package/lib/mechain/client/create-claim-on-mechain.js +33 -0
- package/lib/mechain/client/index.d.ts +1 -0
- package/lib/mechain/client/index.js +1 -0
- package/lib/mechain/constants/index.d.ts +3 -0
- package/lib/mechain/constants/index.js +8 -0
- package/lib/mechain/index.d.ts +2 -0
- package/lib/mechain/index.js +2 -0
- package/lib/mechain/types/index.d.ts +23 -0
- package/lib/mechain/types/index.js +0 -0
- package/lib/proto/api.d.ts +651 -0
- package/lib/proto/api.js +4250 -0
- package/lib/proto/tee-bundle.d.ts +156 -0
- package/lib/proto/tee-bundle.js +1296 -0
- package/lib/providers/http/index.d.ts +18 -0
- package/lib/providers/http/index.js +640 -0
- package/lib/providers/http/patch-parse5-tree.d.ts +6 -0
- package/lib/providers/http/patch-parse5-tree.js +34 -0
- package/lib/providers/http/utils.d.ts +77 -0
- package/lib/providers/http/utils.js +283 -0
- package/lib/providers/index.d.ts +4 -0
- package/lib/providers/index.js +7 -0
- package/lib/scripts/build-browser.d.ts +1 -0
- package/lib/scripts/build-jsc.d.ts +1 -0
- package/lib/scripts/build-lib.d.ts +1 -0
- package/lib/scripts/check-avs-registration.d.ts +1 -0
- package/lib/scripts/check-avs-registration.js +28 -0
- package/lib/scripts/fallbacks/crypto.d.ts +1 -0
- package/lib/scripts/fallbacks/crypto.js +4 -0
- package/lib/scripts/fallbacks/empty.d.ts +3 -0
- package/lib/scripts/fallbacks/empty.js +4 -0
- package/lib/scripts/fallbacks/re2.d.ts +1 -0
- package/lib/scripts/fallbacks/re2.js +7 -0
- package/lib/scripts/fallbacks/snarkjs.d.ts +1 -0
- package/lib/scripts/fallbacks/snarkjs.js +10 -0
- package/lib/scripts/fallbacks/stwo.d.ts +6 -0
- package/lib/scripts/fallbacks/stwo.js +159 -0
- package/lib/scripts/generate-provider-types.d.ts +5 -0
- package/lib/scripts/generate-provider-types.js +101 -0
- package/lib/scripts/generate-receipt.d.ts +9 -0
- package/lib/scripts/generate-receipt.js +101 -0
- package/lib/scripts/generate-toprf-keys.d.ts +1 -0
- package/lib/scripts/generate-toprf-keys.js +24 -0
- package/lib/scripts/jsc-cli-rpc.d.ts +1 -0
- package/lib/scripts/jsc-cli-rpc.js +35 -0
- package/lib/scripts/register-avs-operator.d.ts +1 -0
- package/lib/scripts/register-avs-operator.js +3 -0
- package/lib/scripts/start-server.d.ts +1 -0
- package/lib/scripts/start-server.js +11 -0
- package/lib/scripts/update-avs-metadata.d.ts +1 -0
- package/lib/scripts/update-avs-metadata.js +20 -0
- package/lib/scripts/utils.d.ts +1 -0
- package/lib/scripts/utils.js +10 -0
- package/lib/scripts/whitelist-operator.d.ts +1 -0
- package/lib/scripts/whitelist-operator.js +16 -0
- package/lib/server/create-server.d.ts +8 -0
- package/lib/server/create-server.js +105 -0
- package/lib/server/handlers/claimTeeBundle.d.ts +6 -0
- package/lib/server/handlers/claimTeeBundle.js +232 -0
- package/lib/server/handlers/claimTunnel.d.ts +2 -0
- package/lib/server/handlers/claimTunnel.js +80 -0
- package/lib/server/handlers/completeClaimOnChain.d.ts +2 -0
- package/lib/server/handlers/completeClaimOnChain.js +29 -0
- package/lib/server/handlers/createClaimOnChain.d.ts +2 -0
- package/lib/server/handlers/createClaimOnChain.js +32 -0
- package/lib/server/handlers/createTaskOnMechain.d.ts +2 -0
- package/lib/server/handlers/createTaskOnMechain.js +57 -0
- package/lib/server/handlers/createTunnel.d.ts +2 -0
- package/lib/server/handlers/createTunnel.js +98 -0
- package/lib/server/handlers/disconnectTunnel.d.ts +2 -0
- package/lib/server/handlers/disconnectTunnel.js +8 -0
- package/lib/server/handlers/fetchCertificateBytes.d.ts +2 -0
- package/lib/server/handlers/fetchCertificateBytes.js +57 -0
- package/lib/server/handlers/index.d.ts +4 -0
- package/lib/server/handlers/index.js +25 -0
- package/lib/server/handlers/init.d.ts +2 -0
- package/lib/server/handlers/init.js +33 -0
- package/lib/server/handlers/toprf.d.ts +2 -0
- package/lib/server/handlers/toprf.js +19 -0
- package/lib/server/index.d.ts +4 -0
- package/lib/server/index.js +4 -0
- package/lib/server/socket.d.ts +13 -0
- package/lib/server/socket.js +112 -0
- package/lib/server/tunnels/make-tcp-tunnel.d.ts +22 -0
- package/lib/server/tunnels/make-tcp-tunnel.js +202 -0
- package/lib/server/utils/apm.d.ts +11 -0
- package/lib/server/utils/apm.js +29 -0
- package/lib/server/utils/assert-valid-claim-request.d.ts +31 -0
- package/lib/server/utils/assert-valid-claim-request.js +354 -0
- package/lib/server/utils/config-env.d.ts +1 -0
- package/lib/server/utils/config-env.js +4 -0
- package/lib/server/utils/dns.d.ts +1 -0
- package/lib/server/utils/dns.js +24 -0
- package/lib/server/utils/gcp-attestation.d.ts +17 -0
- package/lib/server/utils/gcp-attestation.js +237 -0
- package/lib/server/utils/generics.d.ts +22 -0
- package/lib/server/utils/generics.js +45 -0
- package/lib/server/utils/iso.d.ts +1 -0
- package/lib/server/utils/iso.js +259 -0
- package/lib/server/utils/keep-alive.d.ts +7 -0
- package/lib/server/utils/keep-alive.js +38 -0
- package/lib/server/utils/nitro-attestation.d.ts +33 -0
- package/lib/server/utils/nitro-attestation.js +249 -0
- package/lib/server/utils/oprf-raw.d.ts +21 -0
- package/lib/server/utils/oprf-raw.js +61 -0
- package/lib/server/utils/process-handshake.d.ts +13 -0
- package/lib/server/utils/process-handshake.js +233 -0
- package/lib/server/utils/proxy-session.d.ts +1 -0
- package/lib/server/utils/proxy-session.js +6 -0
- package/lib/server/utils/tee-oprf-mpc-verification.d.ts +16 -0
- package/lib/server/utils/tee-oprf-mpc-verification.js +86 -0
- package/lib/server/utils/tee-oprf-verification.d.ts +24 -0
- package/lib/server/utils/tee-oprf-verification.js +151 -0
- package/lib/server/utils/tee-transcript-reconstruction.d.ts +24 -0
- package/lib/server/utils/tee-transcript-reconstruction.js +140 -0
- package/lib/server/utils/tee-verification.d.ts +28 -0
- package/lib/server/utils/tee-verification.js +358 -0
- package/lib/server/utils/validation.d.ts +2 -0
- package/lib/server/utils/validation.js +45 -0
- package/lib/types/bgp.d.ts +11 -0
- package/lib/types/bgp.js +0 -0
- package/lib/types/claims.d.ts +70 -0
- package/lib/types/claims.js +0 -0
- package/lib/types/client.d.ts +163 -0
- package/lib/types/client.js +0 -0
- package/lib/types/general.d.ts +76 -0
- package/lib/types/general.js +0 -0
- package/lib/types/handlers.d.ts +10 -0
- package/lib/types/handlers.js +0 -0
- package/lib/types/index.d.ts +10 -0
- package/lib/types/index.js +10 -0
- package/lib/types/providers.d.ts +161 -0
- package/lib/types/providers.gen.d.ts +443 -0
- package/lib/types/providers.gen.js +16 -0
- package/lib/types/providers.js +0 -0
- package/lib/types/rpc.d.ts +35 -0
- package/lib/types/rpc.js +0 -0
- package/lib/types/signatures.d.ts +28 -0
- package/lib/types/signatures.js +0 -0
- package/lib/types/tunnel.d.ts +18 -0
- package/lib/types/tunnel.js +0 -0
- package/lib/types/zk.d.ts +38 -0
- package/lib/types/zk.js +0 -0
- package/lib/utils/auth.d.ts +8 -0
- package/lib/utils/auth.js +71 -0
- package/lib/utils/b64-json.d.ts +2 -0
- package/lib/utils/b64-json.js +17 -0
- package/lib/utils/bgp-listener.d.ts +7 -0
- package/lib/utils/bgp-listener.js +123 -0
- package/lib/utils/claims.d.ts +33 -0
- package/lib/utils/claims.js +89 -0
- package/lib/utils/env.d.ts +3 -0
- package/lib/utils/env.js +19 -0
- package/lib/utils/error.d.ts +26 -0
- package/lib/utils/error.js +54 -0
- package/lib/utils/generics.d.ts +114 -0
- package/lib/utils/generics.js +268 -0
- package/lib/utils/http-parser.d.ts +59 -0
- package/lib/utils/http-parser.js +201 -0
- package/lib/utils/index.d.ts +13 -0
- package/lib/utils/index.js +13 -0
- package/lib/utils/logger.d.ts +13 -0
- package/lib/utils/logger.js +82 -0
- package/lib/utils/prepare-packets.d.ts +16 -0
- package/lib/utils/prepare-packets.js +69 -0
- package/lib/utils/redactions.d.ts +73 -0
- package/lib/utils/redactions.js +135 -0
- package/lib/utils/retries.d.ts +12 -0
- package/lib/utils/retries.js +26 -0
- package/lib/utils/signatures/eth.d.ts +2 -0
- package/lib/utils/signatures/eth.js +31 -0
- package/lib/utils/signatures/index.d.ts +5 -0
- package/lib/utils/signatures/index.js +12 -0
- package/lib/utils/socket-base.d.ts +23 -0
- package/lib/utils/socket-base.js +96 -0
- package/lib/utils/tls.d.ts +2 -0
- package/lib/utils/tls.js +58 -0
- package/lib/utils/ws.d.ts +7 -0
- package/lib/utils/ws.js +22 -0
- package/lib/utils/zk.d.ts +71 -0
- package/lib/utils/zk.js +625 -0
- package/package.json +2 -2
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { getBytes } from "ethers";
|
|
2
|
+
import { TOPRF_DOMAIN_SEPARATOR } from "../../config/index.js";
|
|
3
|
+
import { getEnvVariable } from "../../utils/env.js";
|
|
4
|
+
import { makeDefaultOPRFOperator } from "../../utils/zk.js";
|
|
5
|
+
async function computeOPRFRaw(plaintext, markers, logger) {
|
|
6
|
+
if (!markers.length) {
|
|
7
|
+
return [];
|
|
8
|
+
}
|
|
9
|
+
const PRIVATE_KEY_STR = getEnvVariable("TOPRF_SHARE_PRIVATE_KEY");
|
|
10
|
+
const PUBLIC_KEY_STR = getEnvVariable("TOPRF_SHARE_PUBLIC_KEY");
|
|
11
|
+
if (!PRIVATE_KEY_STR || !PUBLIC_KEY_STR) {
|
|
12
|
+
throw new Error("TOPRF keys not configured. Cannot compute oprf-raw.");
|
|
13
|
+
}
|
|
14
|
+
const privateKey = getBytes(PRIVATE_KEY_STR);
|
|
15
|
+
const publicKey = getBytes(PUBLIC_KEY_STR);
|
|
16
|
+
const operator = makeDefaultOPRFOperator("chacha20", "gnark", logger);
|
|
17
|
+
const results = [];
|
|
18
|
+
for (const marker of markers) {
|
|
19
|
+
const { dataLocation } = marker;
|
|
20
|
+
if (!dataLocation) {
|
|
21
|
+
logger.warn("oprf-raw marker missing dataLocation, skipping");
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
const { fromIndex, length } = dataLocation;
|
|
25
|
+
const endIndex = fromIndex + length;
|
|
26
|
+
if (endIndex > plaintext.length) {
|
|
27
|
+
throw new Error(
|
|
28
|
+
`oprf-raw marker out of bounds: fromIndex=${fromIndex}, length=${length}, plaintextLength=${plaintext.length}`
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
const data = plaintext.slice(fromIndex, endIndex);
|
|
32
|
+
const request = await operator.generateOPRFRequestData(
|
|
33
|
+
data,
|
|
34
|
+
TOPRF_DOMAIN_SEPARATOR,
|
|
35
|
+
logger
|
|
36
|
+
);
|
|
37
|
+
const response = await operator.evaluateOPRF(
|
|
38
|
+
privateKey,
|
|
39
|
+
request.maskedData,
|
|
40
|
+
logger
|
|
41
|
+
);
|
|
42
|
+
const nullifier = await operator.finaliseOPRF(
|
|
43
|
+
publicKey,
|
|
44
|
+
request,
|
|
45
|
+
[{ ...response, publicKeyShare: publicKey }],
|
|
46
|
+
logger
|
|
47
|
+
);
|
|
48
|
+
results.push({
|
|
49
|
+
dataLocation: { fromIndex, length },
|
|
50
|
+
nullifier
|
|
51
|
+
});
|
|
52
|
+
logger.debug(
|
|
53
|
+
{ fromIndex, length, nullifierHex: Buffer.from(nullifier).toString("hex").slice(0, 16) + "..." },
|
|
54
|
+
"computed oprf-raw nullifier"
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
return results;
|
|
58
|
+
}
|
|
59
|
+
export {
|
|
60
|
+
computeOPRFRaw
|
|
61
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ClaimTunnelRequest } from '#src/proto/api.ts';
|
|
2
|
+
import type { Logger } from '#src/types/index.ts';
|
|
3
|
+
/**
|
|
4
|
+
* Verifies server cert chain and removes handshake messages from transcript
|
|
5
|
+
* @param receipt
|
|
6
|
+
* @param logger
|
|
7
|
+
*/
|
|
8
|
+
export declare function processHandshake(receipt: ClaimTunnelRequest['transcript'], logger: Logger): Promise<{
|
|
9
|
+
tlsVersion: "TLS1_3" | "TLS1_2";
|
|
10
|
+
cipherSuite: "TLS_CHACHA20_POLY1305_SHA256" | "TLS_AES_256_GCM_SHA384" | "TLS_AES_128_GCM_SHA256" | "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" | "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" | "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" | "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" | "TLS_RSA_WITH_AES_128_GCM_SHA256" | "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" | "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" | "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA" | "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA";
|
|
11
|
+
hostname: string;
|
|
12
|
+
nextMsgIndex: number;
|
|
13
|
+
}>;
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import {
|
|
2
|
+
concatenateUint8Arrays,
|
|
3
|
+
getSignatureDataTls12,
|
|
4
|
+
getSignatureDataTls13,
|
|
5
|
+
PACKET_TYPE,
|
|
6
|
+
parseCertificates,
|
|
7
|
+
parseClientHello,
|
|
8
|
+
parseServerCertificateVerify,
|
|
9
|
+
parseServerHello,
|
|
10
|
+
processServerKeyShare,
|
|
11
|
+
SUPPORTED_RECORD_TYPE_MAP,
|
|
12
|
+
uint8ArrayToDataView,
|
|
13
|
+
verifyCertificateChain,
|
|
14
|
+
verifyCertificateSignature
|
|
15
|
+
} from "@reclaimprotocol/tls";
|
|
16
|
+
import { TranscriptMessageSenderType } from "../../proto/api.js";
|
|
17
|
+
import { decryptDirect } from "../../utils/index.js";
|
|
18
|
+
const RECORD_LENGTH_BYTES = 3;
|
|
19
|
+
async function processHandshake(receipt, logger) {
|
|
20
|
+
const certificates = [];
|
|
21
|
+
const handshakeRawMessages = [];
|
|
22
|
+
let currentPacketIdx = 0;
|
|
23
|
+
let cipherSuite = void 0;
|
|
24
|
+
let tlsVersion = void 0;
|
|
25
|
+
let serverRandom = void 0;
|
|
26
|
+
let clientRandom = void 0;
|
|
27
|
+
let serverFinishedIdx = -1;
|
|
28
|
+
let clientFinishedIdx = -1;
|
|
29
|
+
let certVerified = false;
|
|
30
|
+
let certVerifyHandled = false;
|
|
31
|
+
let hostname = void 0;
|
|
32
|
+
let clientChangeCipherSpecMsgIdx = -1;
|
|
33
|
+
let serverChangeCipherSpecMsgIdx = -1;
|
|
34
|
+
let incompletePkt = void 0;
|
|
35
|
+
while (serverFinishedIdx < 0 || clientFinishedIdx < 0) {
|
|
36
|
+
const packetIdx = currentPacketIdx++;
|
|
37
|
+
if (packetIdx >= receipt.length) {
|
|
38
|
+
throw new Error(
|
|
39
|
+
"Receipt over but server finish: " + serverFinishedIdx + ", client finish: " + clientFinishedIdx
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
const { message, reveal, sender } = receipt[packetIdx];
|
|
43
|
+
if (message[0] === PACKET_TYPE["CHANGE_CIPHER_SPEC"]) {
|
|
44
|
+
if (sender === TranscriptMessageSenderType.TRANSCRIPT_MESSAGE_SENDER_TYPE_CLIENT) {
|
|
45
|
+
clientChangeCipherSpecMsgIdx = packetIdx;
|
|
46
|
+
logger.trace("found client change cipher spec message");
|
|
47
|
+
} else {
|
|
48
|
+
serverChangeCipherSpecMsgIdx = packetIdx;
|
|
49
|
+
logger.trace("found server change cipher spec message");
|
|
50
|
+
}
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
let plaintext = getWithoutHeader(message);
|
|
54
|
+
if (!plaintext) {
|
|
55
|
+
throw new Error("incomplete TLS record encountered");
|
|
56
|
+
}
|
|
57
|
+
if (
|
|
58
|
+
// decrypt if wrapped record or after change cipher spec message,
|
|
59
|
+
// after which records are encrypted
|
|
60
|
+
message[0] === PACKET_TYPE["WRAPPED_RECORD"] || serverChangeCipherSpecMsgIdx > 0 && sender === TranscriptMessageSenderType.TRANSCRIPT_MESSAGE_SENDER_TYPE_SERVER || clientChangeCipherSpecMsgIdx > 0 && sender === TranscriptMessageSenderType.TRANSCRIPT_MESSAGE_SENDER_TYPE_CLIENT
|
|
61
|
+
) {
|
|
62
|
+
if (!tlsVersion || !cipherSuite) {
|
|
63
|
+
throw new Error("Could not find cipherSuite to use & got enc record");
|
|
64
|
+
}
|
|
65
|
+
if (!reveal?.directReveal?.key) {
|
|
66
|
+
throw new Error(
|
|
67
|
+
"no direct reveal for handshake packet: " + packetIdx
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
const recordHeader = message.slice(0, 5);
|
|
71
|
+
({ plaintext } = await decryptDirect(
|
|
72
|
+
reveal?.directReveal,
|
|
73
|
+
cipherSuite,
|
|
74
|
+
recordHeader,
|
|
75
|
+
tlsVersion,
|
|
76
|
+
plaintext
|
|
77
|
+
));
|
|
78
|
+
if (tlsVersion === "TLS1_3") {
|
|
79
|
+
plaintext = plaintext.slice(0, -1);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (incompletePkt) {
|
|
83
|
+
const incSender = receipt[incompletePkt.packetIdx].sender;
|
|
84
|
+
if (incSender !== sender) {
|
|
85
|
+
throw new Error(
|
|
86
|
+
"Missing follow up to incomplete packet at idx: " + incompletePkt.packetIdx
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
plaintext = concatenateUint8Arrays([
|
|
90
|
+
incompletePkt.remainingBytes,
|
|
91
|
+
plaintext
|
|
92
|
+
]);
|
|
93
|
+
incompletePkt = void 0;
|
|
94
|
+
}
|
|
95
|
+
const handshakeMessages = [];
|
|
96
|
+
for (let offset = 0; offset < plaintext.length; ) {
|
|
97
|
+
const type = plaintext[offset];
|
|
98
|
+
const content = readWithLength(plaintext.slice(offset + 1), RECORD_LENGTH_BYTES);
|
|
99
|
+
if (!content) {
|
|
100
|
+
incompletePkt = {
|
|
101
|
+
remainingBytes: plaintext.slice(offset),
|
|
102
|
+
packetIdx
|
|
103
|
+
};
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
handshakeMessages.push({
|
|
107
|
+
type,
|
|
108
|
+
content,
|
|
109
|
+
contentWithHeader: plaintext.slice(
|
|
110
|
+
offset,
|
|
111
|
+
offset + 1 + RECORD_LENGTH_BYTES + content.length
|
|
112
|
+
),
|
|
113
|
+
packetIdx
|
|
114
|
+
});
|
|
115
|
+
offset += 1 + RECORD_LENGTH_BYTES + content.length;
|
|
116
|
+
}
|
|
117
|
+
for (const msg of handshakeMessages) {
|
|
118
|
+
await processHandshakeMessage(msg);
|
|
119
|
+
handshakeRawMessages.push(msg.contentWithHeader);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (!certVerified) {
|
|
123
|
+
throw new Error("No provider certificates received");
|
|
124
|
+
}
|
|
125
|
+
if (tlsVersion === "TLS1_3" && serverFinishedIdx < 0) {
|
|
126
|
+
throw new Error("server finished message not found");
|
|
127
|
+
}
|
|
128
|
+
if (tlsVersion === "TLS1_3" && !certVerifyHandled) {
|
|
129
|
+
throw new Error("TLS1.3 cert verify packet not received");
|
|
130
|
+
}
|
|
131
|
+
if (tlsVersion === "TLS1_2" && (serverChangeCipherSpecMsgIdx < 0 || clientChangeCipherSpecMsgIdx < 0)) {
|
|
132
|
+
throw new Error("change cipher spec message not found");
|
|
133
|
+
}
|
|
134
|
+
const nextMsgIndex = Math.max(serverFinishedIdx, clientFinishedIdx) + 1;
|
|
135
|
+
return {
|
|
136
|
+
tlsVersion,
|
|
137
|
+
cipherSuite,
|
|
138
|
+
hostname,
|
|
139
|
+
nextMsgIndex
|
|
140
|
+
};
|
|
141
|
+
async function processHandshakeMessage({ type, content, contentWithHeader, packetIdx }) {
|
|
142
|
+
switch (type) {
|
|
143
|
+
case SUPPORTED_RECORD_TYPE_MAP.CLIENT_HELLO:
|
|
144
|
+
const clientHello = parseClientHello(contentWithHeader);
|
|
145
|
+
clientRandom = clientHello.serverRandom;
|
|
146
|
+
const { SERVER_NAME: sni } = clientHello.extensions;
|
|
147
|
+
hostname = sni?.serverName;
|
|
148
|
+
if (!hostname) {
|
|
149
|
+
throw new Error("client hello has no SNI");
|
|
150
|
+
}
|
|
151
|
+
break;
|
|
152
|
+
case SUPPORTED_RECORD_TYPE_MAP.SERVER_HELLO:
|
|
153
|
+
const serverHello = await parseServerHello(content);
|
|
154
|
+
cipherSuite = serverHello.cipherSuite;
|
|
155
|
+
tlsVersion = serverHello.serverTlsVersion;
|
|
156
|
+
serverRandom = serverHello.serverRandom;
|
|
157
|
+
logger.info(
|
|
158
|
+
{ serverTLSVersion: tlsVersion, cipherSuite },
|
|
159
|
+
"extracted server hello params"
|
|
160
|
+
);
|
|
161
|
+
break;
|
|
162
|
+
case SUPPORTED_RECORD_TYPE_MAP.CERTIFICATE:
|
|
163
|
+
const parseResult = parseCertificates(content, { version: tlsVersion });
|
|
164
|
+
certificates.push(...parseResult.certificates);
|
|
165
|
+
await verifyCertificateChain(certificates, hostname, logger);
|
|
166
|
+
logger.info({ hostname }, "verified provider certificate chain");
|
|
167
|
+
certVerified = true;
|
|
168
|
+
break;
|
|
169
|
+
case SUPPORTED_RECORD_TYPE_MAP.CERTIFICATE_VERIFY:
|
|
170
|
+
const signature = parseServerCertificateVerify(content);
|
|
171
|
+
if (!certificates?.length) {
|
|
172
|
+
throw new Error("No provider certificates received");
|
|
173
|
+
}
|
|
174
|
+
const signatureData = await getSignatureDataTls13(
|
|
175
|
+
handshakeRawMessages,
|
|
176
|
+
cipherSuite
|
|
177
|
+
);
|
|
178
|
+
await verifyCertificateSignature({
|
|
179
|
+
...signature,
|
|
180
|
+
publicKey: certificates[0].getPublicKey(),
|
|
181
|
+
signatureData
|
|
182
|
+
});
|
|
183
|
+
certVerifyHandled = true;
|
|
184
|
+
break;
|
|
185
|
+
case SUPPORTED_RECORD_TYPE_MAP.SERVER_KEY_SHARE:
|
|
186
|
+
if (!certificates?.length) {
|
|
187
|
+
throw new Error("No provider certificates received");
|
|
188
|
+
}
|
|
189
|
+
const keyShare = await processServerKeyShare(content);
|
|
190
|
+
const signatureData12 = await getSignatureDataTls12(
|
|
191
|
+
{
|
|
192
|
+
clientRandom,
|
|
193
|
+
serverRandom,
|
|
194
|
+
curveType: keyShare.publicKeyType,
|
|
195
|
+
publicKey: keyShare.publicKey
|
|
196
|
+
}
|
|
197
|
+
);
|
|
198
|
+
await verifyCertificateSignature({
|
|
199
|
+
signature: keyShare.signatureBytes,
|
|
200
|
+
algorithm: keyShare.signatureAlgorithm,
|
|
201
|
+
publicKey: certificates[0].getPublicKey(),
|
|
202
|
+
signatureData: signatureData12,
|
|
203
|
+
publicKeyType: keyShare.publicKeyType
|
|
204
|
+
});
|
|
205
|
+
await verifyCertificateChain(certificates, hostname, logger);
|
|
206
|
+
logger.info({ hostname }, "verified provider certificate chain");
|
|
207
|
+
certVerified = true;
|
|
208
|
+
break;
|
|
209
|
+
case SUPPORTED_RECORD_TYPE_MAP.FINISHED:
|
|
210
|
+
const packet = receipt[packetIdx];
|
|
211
|
+
if (packet.sender === TranscriptMessageSenderType.TRANSCRIPT_MESSAGE_SENDER_TYPE_CLIENT) {
|
|
212
|
+
clientFinishedIdx = packetIdx;
|
|
213
|
+
} else {
|
|
214
|
+
serverFinishedIdx = packetIdx;
|
|
215
|
+
}
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
function getWithoutHeader(message) {
|
|
221
|
+
return readWithLength(message.slice(3), 2);
|
|
222
|
+
}
|
|
223
|
+
function readWithLength(data, lengthBytes = 2) {
|
|
224
|
+
const dataView = uint8ArrayToDataView(data);
|
|
225
|
+
const length = lengthBytes === 1 ? dataView.getUint8(0) : dataView.getUint16(lengthBytes === 3 ? 1 : 0);
|
|
226
|
+
if (data.length < lengthBytes + length) {
|
|
227
|
+
return void 0;
|
|
228
|
+
}
|
|
229
|
+
return data.slice(lengthBytes, lengthBytes + length);
|
|
230
|
+
}
|
|
231
|
+
export {
|
|
232
|
+
processHandshake
|
|
233
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function isValidProxySessionId(sessionId: string): boolean;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TEE OPRF MPC Verification
|
|
3
|
+
* Verifies OPRF MPC outputs from TEE_K and TEE_T match
|
|
4
|
+
*
|
|
5
|
+
* Unlike ZK OPRF which requires proof verification, OPRF MPC outputs
|
|
6
|
+
* are already trusted because they are included in TEE-signed payloads.
|
|
7
|
+
* This module verifies that both TEEs computed identical outputs.
|
|
8
|
+
*/
|
|
9
|
+
import type { KOutputPayload, TOutputPayload } from '#src/proto/tee-bundle.ts';
|
|
10
|
+
import type { OprfVerificationResult } from '#src/server/utils/tee-oprf-verification.ts';
|
|
11
|
+
import type { Logger } from '#src/types/general.ts';
|
|
12
|
+
/**
|
|
13
|
+
* Verifies OPRF MPC outputs from TEE_K and TEE_T match
|
|
14
|
+
* Returns verified outputs for transcript replacement (same format as ZK OPRF)
|
|
15
|
+
*/
|
|
16
|
+
export declare function verifyOprfMpcOutputs(kPayload: KOutputPayload, tPayload: TOutputPayload, logger: Logger): OprfVerificationResult[];
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { AttestorError } from "../../utils/error.js";
|
|
2
|
+
function verifyOprfMpcOutputs(kPayload, tPayload, logger) {
|
|
3
|
+
const kOutputs = kPayload.oprfOutputs || [];
|
|
4
|
+
const tOutputs = tPayload.oprfOutputs || [];
|
|
5
|
+
if (kOutputs.length === 0 && tOutputs.length === 0) {
|
|
6
|
+
logger.debug("No OPRF MPC outputs to verify");
|
|
7
|
+
return [];
|
|
8
|
+
}
|
|
9
|
+
if (kOutputs.length !== tOutputs.length) {
|
|
10
|
+
throw new AttestorError(
|
|
11
|
+
"ERROR_INVALID_CLAIM",
|
|
12
|
+
`OPRF MPC count mismatch: TEE_K has ${kOutputs.length}, TEE_T has ${tOutputs.length}`
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
logger.info(`Verifying ${kOutputs.length} OPRF MPC outputs`);
|
|
16
|
+
const results = [];
|
|
17
|
+
for (const [i, kOut] of kOutputs.entries()) {
|
|
18
|
+
const tOut = tOutputs[i];
|
|
19
|
+
if (kOut.tlsStart < 0 || tOut.tlsStart < 0) {
|
|
20
|
+
throw new AttestorError(
|
|
21
|
+
"ERROR_INVALID_CLAIM",
|
|
22
|
+
`OPRF MPC invalid position at index ${i}: negative start position`
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
if (kOut.tlsLength <= 0 || kOut.tlsLength > 64 || tOut.tlsLength <= 0 || tOut.tlsLength > 64) {
|
|
26
|
+
throw new AttestorError(
|
|
27
|
+
"ERROR_INVALID_CLAIM",
|
|
28
|
+
`OPRF MPC invalid length at index ${i}: must be 1-64 bytes (TEE_K: ${kOut.tlsLength}, TEE_T: ${tOut.tlsLength})`
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
if (kOut.hashOutput.length !== 32 || tOut.hashOutput.length !== 32) {
|
|
32
|
+
throw new AttestorError(
|
|
33
|
+
"ERROR_INVALID_CLAIM",
|
|
34
|
+
`OPRF MPC invalid hash size at index ${i}: expected 32 bytes (TEE_K: ${kOut.hashOutput.length}, TEE_T: ${tOut.hashOutput.length})`
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
if (kOut.tlsStart !== tOut.tlsStart || kOut.tlsLength !== tOut.tlsLength) {
|
|
38
|
+
throw new AttestorError(
|
|
39
|
+
"ERROR_INVALID_CLAIM",
|
|
40
|
+
`OPRF MPC position mismatch at index ${i}: TEE_K [${kOut.tlsStart}:${kOut.tlsStart + kOut.tlsLength}] vs TEE_T [${tOut.tlsStart}:${tOut.tlsStart + tOut.tlsLength}]`
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
if (!buffersEqual(kOut.hashOutput, tOut.hashOutput)) {
|
|
44
|
+
throw new AttestorError(
|
|
45
|
+
"ERROR_INVALID_CLAIM",
|
|
46
|
+
`OPRF MPC hash mismatch at index ${i}: outputs differ between TEE_K and TEE_T`
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
const hashOutputHex = Buffer.from(kOut.hashOutput).toString("hex");
|
|
50
|
+
const hashOutputBase64 = Buffer.from(kOut.hashOutput).toString("base64");
|
|
51
|
+
logger.info(
|
|
52
|
+
{
|
|
53
|
+
index: i,
|
|
54
|
+
position: kOut.tlsStart,
|
|
55
|
+
length: kOut.tlsLength,
|
|
56
|
+
hashOutputLen: kOut.hashOutput.length,
|
|
57
|
+
hashOutputHex: hashOutputHex.substring(0, 32) + "...",
|
|
58
|
+
hashOutputBase64Preview: hashOutputBase64.substring(0, 20) + "..."
|
|
59
|
+
},
|
|
60
|
+
"OPRF MPC output verified"
|
|
61
|
+
);
|
|
62
|
+
results.push({
|
|
63
|
+
position: kOut.tlsStart,
|
|
64
|
+
length: kOut.tlsLength,
|
|
65
|
+
output: new Uint8Array(kOut.hashOutput),
|
|
66
|
+
// Use SHA256(CMAC) as the replacement value
|
|
67
|
+
isMPC: true
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
logger.info(`Successfully verified ${results.length} OPRF MPC outputs`);
|
|
71
|
+
return results;
|
|
72
|
+
}
|
|
73
|
+
function buffersEqual(a, b) {
|
|
74
|
+
if (a.length !== b.length) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
for (const [i, element] of a.entries()) {
|
|
78
|
+
if (element !== b[i]) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
export {
|
|
85
|
+
verifyOprfMpcOutputs
|
|
86
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TEE OPRF Verification and Replacement
|
|
3
|
+
* Verifies OPRF proofs and replaces ranges in reconstructed plaintext
|
|
4
|
+
*/
|
|
5
|
+
import type { OPRFVerificationData } from '#src/proto/tee-bundle.ts';
|
|
6
|
+
import type { TeeBundleData } from '#src/server/utils/tee-verification.ts';
|
|
7
|
+
import type { Logger } from '#src/types/general.ts';
|
|
8
|
+
export interface OprfVerificationResult {
|
|
9
|
+
position: number;
|
|
10
|
+
length: number;
|
|
11
|
+
output: Uint8Array;
|
|
12
|
+
isMPC?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Verifies all OPRF proofs in the bundle and returns replacement data
|
|
16
|
+
*/
|
|
17
|
+
export declare function verifyOprfProofs(bundleData: TeeBundleData & {
|
|
18
|
+
oprfVerifications?: OPRFVerificationData[];
|
|
19
|
+
}, logger: Logger): Promise<OprfVerificationResult[]>;
|
|
20
|
+
/**
|
|
21
|
+
* Replaces OPRF ranges in the reconstructed plaintext with verified outputs.
|
|
22
|
+
* Properly expands or contracts the transcript to fit replacement hashes.
|
|
23
|
+
*/
|
|
24
|
+
export declare function replaceOprfRanges(plaintext: Uint8Array, oprfResults: OprfVerificationResult[], logger: Logger): Uint8Array;
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import bs58 from "bs58";
|
|
2
|
+
import { AttestorError } from "../../utils/error.js";
|
|
3
|
+
import { makeDefaultOPRFOperator } from "../../utils/zk.js";
|
|
4
|
+
async function verifyOprfProofs(bundleData, logger) {
|
|
5
|
+
if (!bundleData.oprfVerifications || bundleData.oprfVerifications.length === 0) {
|
|
6
|
+
logger.debug("No OPRF verifications present in bundle");
|
|
7
|
+
return [];
|
|
8
|
+
}
|
|
9
|
+
const { tOutputPayload } = bundleData;
|
|
10
|
+
const consolidatedCiphertext = tOutputPayload.consolidatedResponseCiphertext;
|
|
11
|
+
if (!consolidatedCiphertext || consolidatedCiphertext.length === 0) {
|
|
12
|
+
throw new AttestorError("ERROR_INVALID_CLAIM", "No consolidated ciphertext for OPRF verification");
|
|
13
|
+
}
|
|
14
|
+
const results = [];
|
|
15
|
+
logger.info(`Verifying ${bundleData.oprfVerifications.length} OPRF proofs`);
|
|
16
|
+
for (const [idx, oprfData] of bundleData.oprfVerifications.entries()) {
|
|
17
|
+
try {
|
|
18
|
+
const result = await verifySingleOprfProof(
|
|
19
|
+
oprfData,
|
|
20
|
+
consolidatedCiphertext,
|
|
21
|
+
idx,
|
|
22
|
+
logger
|
|
23
|
+
);
|
|
24
|
+
results.push(result);
|
|
25
|
+
} catch (error) {
|
|
26
|
+
logger.error({ error, index: idx }, "OPRF proof verification failed");
|
|
27
|
+
throw new AttestorError(
|
|
28
|
+
"ERROR_INVALID_CLAIM",
|
|
29
|
+
`OPRF verification failed at index ${idx}: ${error.message}`
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
logger.info(`Successfully verified ${results.length} OPRF proofs`);
|
|
34
|
+
return results;
|
|
35
|
+
}
|
|
36
|
+
async function verifySingleOprfProof(oprfData, consolidatedCiphertext, index, logger) {
|
|
37
|
+
const publicSignalsJson = JSON.parse(new TextDecoder().decode(oprfData.publicSignalsJson));
|
|
38
|
+
const { proof, publicSignals, cipher } = publicSignalsJson;
|
|
39
|
+
if (!proof || !publicSignals) {
|
|
40
|
+
throw new Error("Missing proof or public signals in OPRF data");
|
|
41
|
+
}
|
|
42
|
+
const ciphertextChunk = consolidatedCiphertext.slice(
|
|
43
|
+
oprfData.streamPos,
|
|
44
|
+
oprfData.streamPos + oprfData.streamLength
|
|
45
|
+
);
|
|
46
|
+
const completePublicSignals = {
|
|
47
|
+
out: publicSignals.out || Uint8Array.from([]),
|
|
48
|
+
// Replace null input with extracted ciphertext
|
|
49
|
+
in: ciphertextChunk,
|
|
50
|
+
// Convert base64 nonces and counters
|
|
51
|
+
noncesAndCounters: publicSignals.blocks?.map((block) => ({
|
|
52
|
+
nonce: Buffer.from(block.nonce || "", "base64"),
|
|
53
|
+
counter: block.counter || 0,
|
|
54
|
+
boundary: block.boundary || ""
|
|
55
|
+
})) || [],
|
|
56
|
+
// Process TOPRF data
|
|
57
|
+
toprf: publicSignals.toprf ? {
|
|
58
|
+
...publicSignals.toprf,
|
|
59
|
+
// Convert domain separator from base64
|
|
60
|
+
domainSeparator: publicSignals.toprf.domainSeparator ? Buffer.from(publicSignals.toprf.domainSeparator, "base64").toString("utf8") : "reclaim",
|
|
61
|
+
// Convert output from base64
|
|
62
|
+
output: publicSignals.toprf.output ? Buffer.from(publicSignals.toprf.output, "base64") : new Uint8Array(),
|
|
63
|
+
// Convert response fields from base64
|
|
64
|
+
responses: publicSignals.toprf.responses?.map((resp) => ({
|
|
65
|
+
publicKeyShare: Buffer.from(resp.publicKeyShare || "", "base64"),
|
|
66
|
+
evaluated: Buffer.from(resp.evaluated || "", "base64"),
|
|
67
|
+
c: Buffer.from(resp.c || "", "base64"),
|
|
68
|
+
r: Buffer.from(resp.r || "", "base64")
|
|
69
|
+
})) || [],
|
|
70
|
+
// Locations are already in correct format
|
|
71
|
+
locations: publicSignals.toprf.locations || []
|
|
72
|
+
} : void 0
|
|
73
|
+
};
|
|
74
|
+
const algorithm = cipher.replace("-toprf", "");
|
|
75
|
+
const zkEngine = "gnark";
|
|
76
|
+
const oprfOperator = makeDefaultOPRFOperator(algorithm, zkEngine, logger);
|
|
77
|
+
const proofBytes = Buffer.from(proof, "base64");
|
|
78
|
+
const isValid = await oprfOperator.groth16Verify(
|
|
79
|
+
completePublicSignals,
|
|
80
|
+
proofBytes,
|
|
81
|
+
logger
|
|
82
|
+
);
|
|
83
|
+
if (!isValid) {
|
|
84
|
+
throw new Error("OPRF proof verification failed");
|
|
85
|
+
}
|
|
86
|
+
logger.debug(`OPRF ${index}: Proof verified successfully`);
|
|
87
|
+
const oprfOutput = completePublicSignals.toprf?.output;
|
|
88
|
+
if (!oprfOutput || oprfOutput.length === 0) {
|
|
89
|
+
throw new Error("No OPRF output found in verified proof");
|
|
90
|
+
}
|
|
91
|
+
const oprfLocation = completePublicSignals.toprf?.locations?.[0];
|
|
92
|
+
if (!oprfLocation) {
|
|
93
|
+
throw new Error("No OPRF location found in public signals");
|
|
94
|
+
}
|
|
95
|
+
logger.info(`OPRF #${index}: streamPos=${oprfData.streamPos}, locationPos=${oprfLocation.pos}, finalPos=${oprfData.streamPos + oprfLocation.pos}, len=${oprfLocation.len}`);
|
|
96
|
+
return {
|
|
97
|
+
// The position in the plaintext where to replace (stream position + OPRF location within chunk)
|
|
98
|
+
position: oprfData.streamPos + oprfLocation.pos,
|
|
99
|
+
length: oprfLocation.len,
|
|
100
|
+
output: oprfOutput
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
function replaceOprfRanges(plaintext, oprfResults, logger) {
|
|
104
|
+
if (oprfResults.length === 0) {
|
|
105
|
+
return plaintext;
|
|
106
|
+
}
|
|
107
|
+
const replacements = oprfResults.map((result) => {
|
|
108
|
+
let outputBytes;
|
|
109
|
+
let encodedOutput;
|
|
110
|
+
if (result.isMPC) {
|
|
111
|
+
encodedOutput = bs58.encode(result.output);
|
|
112
|
+
outputBytes = new TextEncoder().encode(encodedOutput);
|
|
113
|
+
} else {
|
|
114
|
+
encodedOutput = Buffer.from(result.output).toString("base64");
|
|
115
|
+
const truncated = encodedOutput.substring(0, result.length);
|
|
116
|
+
outputBytes = new TextEncoder().encode(truncated);
|
|
117
|
+
}
|
|
118
|
+
return { result, outputBytes, encodedOutput };
|
|
119
|
+
});
|
|
120
|
+
replacements.sort((a, b) => a.result.position - b.result.position);
|
|
121
|
+
let newSize = plaintext.length;
|
|
122
|
+
for (const { result, outputBytes } of replacements) {
|
|
123
|
+
const sizeDiff = outputBytes.length - result.length;
|
|
124
|
+
newSize += sizeDiff;
|
|
125
|
+
}
|
|
126
|
+
logger.info(`Transcript size: ${plaintext.length} -> ${newSize} (${newSize - plaintext.length >= 0 ? "+" : ""}${newSize - plaintext.length} bytes)`);
|
|
127
|
+
const newPlaintext = new Uint8Array(newSize);
|
|
128
|
+
let srcPos = 0;
|
|
129
|
+
let dstPos = 0;
|
|
130
|
+
for (const [idx, { result, outputBytes, encodedOutput }] of replacements.entries()) {
|
|
131
|
+
const segmentLength = result.position - srcPos;
|
|
132
|
+
if (segmentLength > 0) {
|
|
133
|
+
newPlaintext.set(plaintext.slice(srcPos, result.position), dstPos);
|
|
134
|
+
dstPos += segmentLength;
|
|
135
|
+
}
|
|
136
|
+
const currentContent = plaintext.slice(result.position, result.position + result.length);
|
|
137
|
+
logger.info(`OPRF #${idx} at pos ${result.position}: "${Buffer.from(currentContent).toString("utf8")}" (${result.length}b) -> "${encodedOutput}" (${outputBytes.length}b)${result.isMPC ? " [MPC/base58]" : ""}`);
|
|
138
|
+
newPlaintext.set(outputBytes, dstPos);
|
|
139
|
+
dstPos += outputBytes.length;
|
|
140
|
+
srcPos = result.position + result.length;
|
|
141
|
+
}
|
|
142
|
+
if (srcPos < plaintext.length) {
|
|
143
|
+
newPlaintext.set(plaintext.slice(srcPos), dstPos);
|
|
144
|
+
}
|
|
145
|
+
logger.info(`Replaced ${oprfResults.length} OPRF ranges in plaintext`);
|
|
146
|
+
return newPlaintext;
|
|
147
|
+
}
|
|
148
|
+
export {
|
|
149
|
+
replaceOprfRanges,
|
|
150
|
+
verifyOprfProofs
|
|
151
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TLS Transcript Reconstruction from TEE data
|
|
3
|
+
*/
|
|
4
|
+
import type { CertificateInfo } from '#src/proto/tee-bundle.ts';
|
|
5
|
+
import type { TeeBundleData } from '#src/server/utils/tee-verification.ts';
|
|
6
|
+
import type { Logger } from '#src/types/general.ts';
|
|
7
|
+
export interface TeeTranscriptData {
|
|
8
|
+
revealedRequest: Uint8Array;
|
|
9
|
+
reconstructedResponse: Uint8Array;
|
|
10
|
+
certificateInfo?: CertificateInfo;
|
|
11
|
+
responseTrimOffset?: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Reconstructs TLS transcript from TEE bundle data
|
|
15
|
+
* @param bundleData - Validated TEE bundle data
|
|
16
|
+
* @param logger - Logger instance
|
|
17
|
+
* @param oprfResults - Optional OPRF results to apply during reconstruction
|
|
18
|
+
* @returns Reconstructed transcript data
|
|
19
|
+
*/
|
|
20
|
+
export declare function reconstructTlsTranscript(bundleData: TeeBundleData, logger: Logger, oprfResults?: Array<{
|
|
21
|
+
position: number;
|
|
22
|
+
length: number;
|
|
23
|
+
output: Uint8Array;
|
|
24
|
+
}>): Promise<TeeTranscriptData>;
|