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

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 (145) hide show
  1. package/browser/resources/attestor-browser.min.mjs +4512 -0
  2. package/lib/avs/abis/avsDirectoryABI.js +338 -341
  3. package/lib/avs/abis/delegationABI.js +1 -4
  4. package/lib/avs/abis/registryABI.js +719 -722
  5. package/lib/avs/client/create-claim-on-avs.js +129 -157
  6. package/lib/avs/config.js +18 -24
  7. package/lib/avs/contracts/ReclaimServiceManager.js +1 -0
  8. package/lib/avs/contracts/common.js +1 -0
  9. package/lib/avs/contracts/factories/ReclaimServiceManager__factory.js +1139 -1156
  10. package/lib/avs/contracts/factories/index.js +4 -4
  11. package/lib/avs/contracts/index.js +2 -6
  12. package/lib/avs/types/index.js +1 -0
  13. package/lib/avs/utils/contracts.js +30 -50
  14. package/lib/avs/utils/register.js +75 -70
  15. package/lib/avs/utils/tasks.js +38 -45
  16. package/lib/client/create-claim.js +402 -431
  17. package/lib/client/tunnels/make-rpc-tcp-tunnel.js +46 -48
  18. package/lib/client/tunnels/make-rpc-tls-tunnel.js +125 -121
  19. package/lib/client/utils/attestor-pool.js +23 -22
  20. package/lib/client/utils/client-socket.js +86 -109
  21. package/lib/client/utils/message-handler.js +79 -89
  22. package/lib/config/index.js +40 -58
  23. package/lib/external-rpc/benchmark.js +61 -74
  24. package/lib/external-rpc/event-bus.js +12 -15
  25. package/lib/external-rpc/handle-incoming-msg.js +216 -225
  26. package/lib/external-rpc/jsc-polyfills/1.js +70 -68
  27. package/lib/external-rpc/jsc-polyfills/2.js +17 -12
  28. package/lib/external-rpc/jsc-polyfills/event.js +10 -15
  29. package/lib/external-rpc/jsc-polyfills/index.js +2 -2
  30. package/lib/external-rpc/jsc-polyfills/ws.js +77 -79
  31. package/lib/external-rpc/setup-browser.js +28 -28
  32. package/lib/external-rpc/setup-jsc.js +17 -17
  33. package/lib/external-rpc/types.js +1 -0
  34. package/lib/external-rpc/utils.js +89 -89
  35. package/lib/external-rpc/zk.js +55 -50
  36. package/lib/index.js +2 -6
  37. package/lib/mechain/abis/governanceABI.js +457 -460
  38. package/lib/mechain/abis/taskABI.js +502 -505
  39. package/lib/mechain/client/create-claim-on-mechain.js +24 -29
  40. package/lib/mechain/constants/index.js +3 -8
  41. package/lib/mechain/types/index.js +1 -0
  42. package/lib/proto/api.js +4200 -4087
  43. package/lib/proto/tee-bundle.js +1261 -1241
  44. package/lib/providers/http/index.js +616 -603
  45. package/lib/providers/http/patch-parse5-tree.js +27 -29
  46. package/lib/providers/http/utils.js +289 -248
  47. package/lib/providers/index.js +3 -6
  48. package/lib/server/create-server.js +89 -91
  49. package/lib/server/handlers/claimTeeBundle.js +231 -211
  50. package/lib/server/handlers/claimTunnel.js +66 -73
  51. package/lib/server/handlers/completeClaimOnChain.js +20 -25
  52. package/lib/server/handlers/createClaimOnChain.js +21 -27
  53. package/lib/server/handlers/createTaskOnMechain.js +40 -50
  54. package/lib/server/handlers/createTunnel.js +85 -90
  55. package/lib/server/handlers/disconnectTunnel.js +4 -7
  56. package/lib/server/handlers/fetchCertificateBytes.js +37 -53
  57. package/lib/server/handlers/index.js +21 -24
  58. package/lib/server/handlers/init.js +27 -28
  59. package/lib/server/handlers/toprf.js +13 -16
  60. package/lib/server/socket.js +97 -100
  61. package/lib/server/tunnels/make-tcp-tunnel.js +161 -186
  62. package/lib/server/utils/apm.js +32 -25
  63. package/lib/server/utils/assert-valid-claim-request.js +305 -334
  64. package/lib/server/utils/config-env.js +2 -2
  65. package/lib/server/utils/dns.js +12 -18
  66. package/lib/server/utils/gcp-attestation.js +233 -181
  67. package/lib/server/utils/generics.d.ts +1 -1
  68. package/lib/server/utils/generics.js +43 -37
  69. package/lib/server/utils/iso.js +253 -256
  70. package/lib/server/utils/keep-alive.js +36 -36
  71. package/lib/server/utils/nitro-attestation.js +295 -220
  72. package/lib/server/utils/oprf-raw.js +48 -55
  73. package/lib/server/utils/process-handshake.js +200 -218
  74. package/lib/server/utils/proxy-session.js +5 -5
  75. package/lib/server/utils/tee-oprf-mpc-verification.js +82 -78
  76. package/lib/server/utils/tee-oprf-verification.js +165 -142
  77. package/lib/server/utils/tee-transcript-reconstruction.js +176 -129
  78. package/lib/server/utils/tee-verification.js +397 -334
  79. package/lib/server/utils/validation.js +30 -37
  80. package/lib/types/bgp.js +1 -0
  81. package/lib/types/claims.js +1 -0
  82. package/lib/types/client.js +1 -0
  83. package/lib/types/general.js +1 -0
  84. package/lib/types/handlers.js +1 -0
  85. package/lib/types/providers.d.ts +3 -2
  86. package/lib/types/providers.gen.js +9 -15
  87. package/lib/types/providers.js +1 -0
  88. package/lib/types/rpc.js +1 -0
  89. package/lib/types/signatures.d.ts +1 -2
  90. package/lib/types/signatures.js +1 -0
  91. package/lib/types/tunnel.js +1 -0
  92. package/lib/types/zk.js +1 -0
  93. package/lib/utils/auth.js +54 -66
  94. package/lib/utils/b64-json.js +15 -15
  95. package/lib/utils/bgp-listener.js +107 -111
  96. package/lib/utils/claims.js +89 -80
  97. package/lib/utils/env.js +13 -17
  98. package/lib/utils/error.js +43 -47
  99. package/lib/utils/generics.js +284 -235
  100. package/lib/utils/http-parser.js +232 -187
  101. package/lib/utils/logger.js +80 -71
  102. package/lib/utils/prepare-packets.js +69 -67
  103. package/lib/utils/redactions.js +163 -121
  104. package/lib/utils/retries.js +22 -24
  105. package/lib/utils/signatures/eth.js +29 -28
  106. package/lib/utils/signatures/index.js +5 -10
  107. package/lib/utils/socket-base.js +84 -88
  108. package/lib/utils/tls.js +28 -28
  109. package/lib/utils/ws.js +19 -19
  110. package/lib/utils/zk.js +542 -582
  111. package/package.json +12 -5
  112. package/lib/external-rpc/global.d.js +0 -0
  113. package/lib/scripts/build-browser.d.ts +0 -1
  114. package/lib/scripts/build-jsc.d.ts +0 -1
  115. package/lib/scripts/build-lib.d.ts +0 -1
  116. package/lib/scripts/check-avs-registration.d.ts +0 -1
  117. package/lib/scripts/check-avs-registration.js +0 -28
  118. package/lib/scripts/fallbacks/crypto.d.ts +0 -1
  119. package/lib/scripts/fallbacks/crypto.js +0 -4
  120. package/lib/scripts/fallbacks/empty.d.ts +0 -3
  121. package/lib/scripts/fallbacks/empty.js +0 -4
  122. package/lib/scripts/fallbacks/re2.d.ts +0 -1
  123. package/lib/scripts/fallbacks/re2.js +0 -7
  124. package/lib/scripts/fallbacks/snarkjs.d.ts +0 -1
  125. package/lib/scripts/fallbacks/snarkjs.js +0 -10
  126. package/lib/scripts/fallbacks/stwo.d.ts +0 -6
  127. package/lib/scripts/fallbacks/stwo.js +0 -159
  128. package/lib/scripts/generate-provider-types.d.ts +0 -5
  129. package/lib/scripts/generate-provider-types.js +0 -101
  130. package/lib/scripts/generate-receipt.d.ts +0 -9
  131. package/lib/scripts/generate-receipt.js +0 -101
  132. package/lib/scripts/generate-toprf-keys.d.ts +0 -1
  133. package/lib/scripts/generate-toprf-keys.js +0 -24
  134. package/lib/scripts/jsc-cli-rpc.d.ts +0 -1
  135. package/lib/scripts/jsc-cli-rpc.js +0 -35
  136. package/lib/scripts/register-avs-operator.d.ts +0 -1
  137. package/lib/scripts/register-avs-operator.js +0 -3
  138. package/lib/scripts/start-server.d.ts +0 -1
  139. package/lib/scripts/start-server.js +0 -11
  140. package/lib/scripts/update-avs-metadata.d.ts +0 -1
  141. package/lib/scripts/update-avs-metadata.js +0 -20
  142. package/lib/scripts/utils.d.ts +0 -1
  143. package/lib/scripts/utils.js +0 -10
  144. package/lib/scripts/whitelist-operator.d.ts +0 -1
  145. package/lib/scripts/whitelist-operator.js +0 -16
@@ -1,268 +1,317 @@
1
- import {
2
- areUint8ArraysEqual,
3
- CONTENT_TYPE_MAP,
4
- crypto,
5
- decryptWrappedRecord,
6
- PACKET_TYPE,
7
- SUPPORTED_CIPHER_SUITE_MAP,
8
- uint8ArrayToBinaryStr,
9
- uint8ArrayToDataView
10
- } from "@reclaimprotocol/tls";
11
- import { REDACTION_CHAR_CODE } from "@reclaimprotocol/zk-symmetric-crypto";
1
+ import { areUint8ArraysEqual, CONTENT_TYPE_MAP, crypto, decryptWrappedRecord, PACKET_TYPE, SUPPORTED_CIPHER_SUITE_MAP, uint8ArrayToBinaryStr, uint8ArrayToDataView } from '@reclaimprotocol/tls';
2
+ import { REDACTION_CHAR_CODE } from '@reclaimprotocol/zk-symmetric-crypto';
12
3
  import { RPCMessage, RPCMessages } from "../proto/api.js";
13
- const DEFAULT_REDACTION_DATA = new Uint8Array(4).fill(REDACTION_CHAR_CODE);
14
- function uint8ArrayToStr(arr) {
15
- return new TextDecoder().decode(arr);
4
+ const DEFAULT_REDACTION_DATA = new Uint8Array(4)
5
+ .fill(REDACTION_CHAR_CODE);
6
+ export { uint8ArrayToBinaryStr };
7
+ /**
8
+ * Decodes a Uint8Array to a UTF-8 string.
9
+ */
10
+ export function uint8ArrayToStr(arr) {
11
+ return new TextDecoder().decode(arr);
16
12
  }
17
- function strToUint8Array(str) {
18
- return new TextEncoder().encode(str);
13
+ /**
14
+ * Encodes a UTF-8 string to a Uint8Array.
15
+ */
16
+ export function strToUint8Array(str) {
17
+ return new TextEncoder().encode(str);
19
18
  }
20
- function getTranscriptString(receipt) {
21
- const applMsgs = extractApplicationDataFromTranscript(receipt);
22
- const strList = [];
23
- for (const { message, sender } of applMsgs) {
24
- const content = uint8ArrayToStr(message);
25
- if (strList[strList.length - 1]?.startsWith(sender)) {
26
- strList[strList.length - 1] += content;
27
- } else {
28
- strList.push(`${sender}: ${content}`);
19
+ export function getTranscriptString(receipt) {
20
+ const applMsgs = extractApplicationDataFromTranscript(receipt);
21
+ const strList = [];
22
+ for (const { message, sender } of applMsgs) {
23
+ const content = uint8ArrayToStr(message);
24
+ if (strList[strList.length - 1]?.startsWith(sender)) {
25
+ strList[strList.length - 1] += content;
26
+ }
27
+ else {
28
+ strList.push(`${sender}: ${content}`);
29
+ }
29
30
  }
30
- }
31
- return strList.join("\n");
31
+ return strList.join('\n');
32
32
  }
33
- const unixTimestampSeconds = () => Math.floor(Date.now() / 1e3);
34
- function findIndexInUint8Array(haystack, needle) {
35
- for (let i = 0; i < haystack.length; i++) {
36
- if (areUint8ArraysEqual(haystack.slice(i, i + needle.length), needle)) {
37
- return i;
33
+ export const unixTimestampSeconds = () => Math.floor(Date.now() / 1000);
34
+ /**
35
+ * Find index of needle in haystack
36
+ */
37
+ export function findIndexInUint8Array(haystack, needle) {
38
+ for (let i = 0; i < haystack.length; i++) {
39
+ if (areUint8ArraysEqual(haystack.slice(i, i + needle.length), needle)) {
40
+ return i;
41
+ }
38
42
  }
39
- }
40
- return -1;
41
- }
42
- function getZkAlgorithmForCipherSuite(cipherSuite) {
43
- if (cipherSuite.includes("CHACHA20")) {
44
- return "chacha20";
45
- }
46
- if (cipherSuite.includes("AES_256_GCM")) {
47
- return "aes-256-ctr";
48
- }
49
- if (cipherSuite.includes("AES_128_GCM")) {
50
- return "aes-128-ctr";
51
- }
52
- throw new Error(`${cipherSuite} not supported for ZK ops`);
43
+ return -1;
53
44
  }
54
- function getPureCiphertext(content, cipherSuite) {
55
- getZkAlgorithmForCipherSuite(cipherSuite);
56
- content = content.slice(0, -16);
57
- const {
58
- ivLength: fixedIvLength
59
- } = SUPPORTED_CIPHER_SUITE_MAP[cipherSuite];
60
- const recordIvLength = 12 - fixedIvLength;
61
- content = content.slice(recordIvLength);
62
- return content;
45
+ /**
46
+ * Fetch the ZK algorithm for the specified cipher suite
47
+ */
48
+ export function getZkAlgorithmForCipherSuite(cipherSuite) {
49
+ if (cipherSuite.includes('CHACHA20')) {
50
+ return 'chacha20';
51
+ }
52
+ if (cipherSuite.includes('AES_256_GCM')) {
53
+ return 'aes-256-ctr';
54
+ }
55
+ if (cipherSuite.includes('AES_128_GCM')) {
56
+ return 'aes-128-ctr';
57
+ }
58
+ throw new Error(`${cipherSuite} not supported for ZK ops`);
63
59
  }
64
- function getRecordIV(content, cipherSuite) {
65
- getZkAlgorithmForCipherSuite(cipherSuite);
66
- const {
67
- ivLength: fixedIvLength
68
- } = SUPPORTED_CIPHER_SUITE_MAP[cipherSuite];
69
- const recordIvLength = 12 - fixedIvLength;
70
- return content.slice(0, recordIvLength);
60
+ /**
61
+ * Get the pure ciphertext without any MAC,
62
+ * or authentication tag,
63
+ * @param content content w/o header
64
+ * @param cipherSuite
65
+ */
66
+ export function getPureCiphertext(content, cipherSuite) {
67
+ // assert that the cipher suite is supported
68
+ getZkAlgorithmForCipherSuite(cipherSuite);
69
+ // 16 => auth tag length
70
+ content = content.slice(0, -16);
71
+ const { ivLength: fixedIvLength, } = SUPPORTED_CIPHER_SUITE_MAP[cipherSuite];
72
+ // 12 => total IV length
73
+ const recordIvLength = 12 - fixedIvLength;
74
+ // record IV is prefixed to the ciphertext
75
+ content = content.slice(recordIvLength);
76
+ return content;
71
77
  }
72
- function getProviderValue(params, fn, secretParams) {
73
- return typeof fn === "function" ? fn(params, secretParams) : fn;
78
+ /**
79
+ * Get the 8 byte IV part that's stored in the record for some cipher suites
80
+ * @param content content w/o header
81
+ * @param cipherSuite
82
+ */
83
+ export function getRecordIV(content, cipherSuite) {
84
+ // assert that the cipher suite is supported
85
+ getZkAlgorithmForCipherSuite(cipherSuite);
86
+ const { ivLength: fixedIvLength, } = SUPPORTED_CIPHER_SUITE_MAP[cipherSuite];
87
+ // 12 => total IV length
88
+ const recordIvLength = 12 - fixedIvLength;
89
+ return content.slice(0, recordIvLength);
74
90
  }
75
- function generateRpcMessageId() {
76
- return uint8ArrayToDataView(crypto.randomBytes(4)).getUint32(0);
91
+ export function getProviderValue(params, fn, secretParams) {
92
+ return typeof fn === 'function'
93
+ // @ts-ignore
94
+ ? fn(params, secretParams)
95
+ : fn;
77
96
  }
78
- function generateSessionId() {
79
- return generateRpcMessageId();
97
+ export function generateRpcMessageId() {
98
+ return uint8ArrayToDataView(crypto.randomBytes(4)).getUint32(0);
80
99
  }
81
- function generateTunnelId() {
82
- return generateRpcMessageId();
100
+ /**
101
+ * Random session ID for a WebSocket client.
102
+ */
103
+ export function generateSessionId() {
104
+ return generateRpcMessageId();
83
105
  }
84
- function makeRpcEvent(type, data) {
85
- const ev = new Event(type);
86
- ev.data = data;
87
- return ev;
106
+ /**
107
+ * Random ID for a tunnel.
108
+ */
109
+ export function generateTunnelId() {
110
+ return generateRpcMessageId();
88
111
  }
89
- function getRpcTypeFromKey(key) {
90
- if (key.endsWith("Request")) {
91
- return {
92
- type: key.slice(0, -7),
93
- direction: "request"
94
- };
95
- }
96
- if (key.endsWith("Response")) {
97
- return {
98
- type: key.slice(0, -8),
99
- direction: "response"
100
- };
101
- }
112
+ export function makeRpcEvent(type, data) {
113
+ const ev = new Event(type);
114
+ ev.data = data;
115
+ return ev;
102
116
  }
103
- function getRpcResponseType(type) {
104
- return `${type}Response`;
117
+ /**
118
+ * Get the RPC type from the key.
119
+ * For eg. "claimTunnelRequest" ->
120
+ * { type: 'claimTunnel', direction: 'request' }
121
+ */
122
+ export function getRpcTypeFromKey(key) {
123
+ if (key.endsWith('Request')) {
124
+ return {
125
+ type: key.slice(0, -7),
126
+ direction: 'request'
127
+ };
128
+ }
129
+ if (key.endsWith('Response')) {
130
+ return {
131
+ type: key.slice(0, -8),
132
+ direction: 'response'
133
+ };
134
+ }
105
135
  }
106
- function getRpcRequestType(type) {
107
- return `${type}Request`;
136
+ /**
137
+ * Get the RPC response type from the RPC type.
138
+ * For eg. "claimTunnel" -> "claimTunnelResponse"
139
+ */
140
+ export function getRpcResponseType(type) {
141
+ return `${type}Response`;
108
142
  }
109
- function isApplicationData(packet, tlsVersion) {
110
- return packet.type === "ciphertext" && (packet.contentType === "APPLICATION_DATA" || packet.data[0] === PACKET_TYPE.WRAPPED_RECORD && tlsVersion === "TLS1_2");
143
+ /**
144
+ * Get the RPC request type from the RPC type.
145
+ * For eg. "claimTunnel" -> "claimTunnelRequest"
146
+ */
147
+ export function getRpcRequestType(type) {
148
+ return `${type}Request`;
111
149
  }
112
- async function extractArrayBufferFromWsData(data) {
113
- if (data instanceof ArrayBuffer) {
114
- return new Uint8Array(data);
115
- }
116
- if (data instanceof Uint8Array || typeof data === "object" && data && "buffer" in data) {
117
- return data;
118
- }
119
- if (typeof data === "string") {
120
- return strToUint8Array(data);
121
- }
122
- if (typeof Blob !== "undefined" && data instanceof Blob) {
123
- return new Uint8Array(await data.arrayBuffer());
124
- }
125
- throw new Error("unsupported data: " + String(data));
150
+ export function isApplicationData(packet, tlsVersion) {
151
+ return packet.type === 'ciphertext'
152
+ && (packet.contentType === 'APPLICATION_DATA'
153
+ || (packet.data[0] === PACKET_TYPE.WRAPPED_RECORD
154
+ && tlsVersion === 'TLS1_2'));
126
155
  }
127
- function getRpcRequest(msg) {
128
- if (msg.requestError) {
129
- return {
130
- direction: "response",
131
- type: "error"
132
- };
133
- }
134
- for (const key in msg) {
135
- if (!msg[key]) {
136
- continue;
156
+ /**
157
+ * Convert the received data from a WS to a Uint8Array
158
+ */
159
+ export async function extractArrayBufferFromWsData(data) {
160
+ if (data instanceof ArrayBuffer) {
161
+ return new Uint8Array(data);
137
162
  }
138
- const rpcType = getRpcTypeFromKey(key);
139
- if (!rpcType) {
140
- continue;
163
+ // uint8array/Buffer
164
+ if (data instanceof Uint8Array
165
+ || (typeof data === 'object' && data && 'buffer' in data)) {
166
+ return data;
141
167
  }
142
- return rpcType;
143
- }
144
- }
145
- function extractApplicationDataFromTranscript({ transcript, tlsVersion }) {
146
- const msgs = [];
147
- for (const m of transcript) {
148
- let message;
149
- if (m.redacted) {
150
- if (!m.plaintextLength) {
151
- message = DEFAULT_REDACTION_DATA;
152
- } else {
153
- const len = tlsVersion === "TLS1_3" ? m.plaintextLength - 1 : m.plaintextLength;
154
- message = new Uint8Array(len).fill(REDACTION_CHAR_CODE);
155
- }
156
- } else if (tlsVersion === "TLS1_3") {
157
- const contentType = m.message[m.message.length - 1];
158
- if (contentType !== CONTENT_TYPE_MAP["APPLICATION_DATA"]) {
159
- continue;
160
- }
161
- message = m.message.slice(0, -1);
162
- } else if (m.recordHeader[0] === PACKET_TYPE.WRAPPED_RECORD) {
163
- message = m.message;
164
- } else {
165
- continue;
168
+ if (typeof data === 'string') {
169
+ return strToUint8Array(data);
166
170
  }
167
- msgs.push({ message, sender: m.sender });
168
- }
169
- return msgs;
171
+ if (typeof Blob !== 'undefined' && data instanceof Blob) {
172
+ return new Uint8Array(await data.arrayBuffer());
173
+ }
174
+ throw new Error('unsupported data: ' + String(data));
170
175
  }
171
- function extractHandshakeFromTranscript({ transcript, tlsVersion }) {
172
- const msgs = [];
173
- for (const [i, m] of transcript.entries()) {
174
- if (m.redacted) {
175
- break;
176
+ /**
177
+ * Check if the RPC message is a request or a response.
178
+ */
179
+ export function getRpcRequest(msg) {
180
+ if (msg.requestError) {
181
+ return {
182
+ direction: 'response',
183
+ type: 'error'
184
+ };
176
185
  }
177
- let message;
178
- if (m.recordHeader[0] === PACKET_TYPE.HELLO) {
179
- message = m.message;
180
- } else if (m.recordHeader[0] === PACKET_TYPE.WRAPPED_RECORD) {
181
- if (tlsVersion === "TLS1_3") {
182
- const contentType = m.message[m.message.length - 1];
183
- if (contentType !== CONTENT_TYPE_MAP["HANDSHAKE"]) {
184
- break;
186
+ for (const key in msg) {
187
+ if (!msg[key]) {
188
+ continue;
189
+ }
190
+ const rpcType = getRpcTypeFromKey(key);
191
+ if (!rpcType) {
192
+ continue;
185
193
  }
186
- message = m.message.slice(0, -1);
187
- } else {
188
- break;
189
- }
190
- } else {
191
- continue;
194
+ return rpcType;
192
195
  }
193
- if (!message.length) {
194
- throw new Error("unsupported handshake message");
196
+ }
197
+ /**
198
+ * Finds all application data messages in a transcript
199
+ * and returns them. Removes the "contentType" suffix from the message.
200
+ * in TLS 1.3
201
+ */
202
+ export function extractApplicationDataFromTranscript({ transcript, tlsVersion }) {
203
+ const msgs = [];
204
+ for (const m of transcript) {
205
+ let message;
206
+ // redacted msgs but with a valid packet header
207
+ // can be considered application data messages
208
+ if (m.redacted) {
209
+ if (!m.plaintextLength) {
210
+ message = DEFAULT_REDACTION_DATA;
211
+ }
212
+ else {
213
+ const len = tlsVersion === 'TLS1_3'
214
+ // remove content type suffix
215
+ ? m.plaintextLength - 1
216
+ : m.plaintextLength;
217
+ message = new Uint8Array(len)
218
+ .fill(REDACTION_CHAR_CODE);
219
+ }
220
+ // otherwise, we need to check the content type
221
+ }
222
+ else if (tlsVersion === 'TLS1_3') {
223
+ const contentType = m.message[m.message.length - 1];
224
+ if (contentType !== CONTENT_TYPE_MAP['APPLICATION_DATA']) {
225
+ continue;
226
+ }
227
+ message = m.message.slice(0, -1);
228
+ }
229
+ else if (m.recordHeader[0] === PACKET_TYPE.WRAPPED_RECORD) {
230
+ message = m.message;
231
+ }
232
+ else {
233
+ continue;
234
+ }
235
+ msgs.push({ message, sender: m.sender });
195
236
  }
196
- msgs.push({ message, sender: m.sender, index: i });
197
- }
198
- return msgs;
237
+ return msgs;
199
238
  }
200
- async function decryptDirect(directReveal, cipherSuite, recordHeader, serverTlsVersion, content) {
201
- const { key, iv, recordNumber } = directReveal;
202
- const { cipher } = SUPPORTED_CIPHER_SUITE_MAP[cipherSuite];
203
- const importedKey = await crypto.importKey(cipher, key);
204
- return await decryptWrappedRecord(
205
- content,
206
- {
207
- iv,
208
- key: importedKey,
209
- recordHeader,
210
- recordNumber,
211
- version: serverTlsVersion,
212
- cipherSuite
239
+ export function extractHandshakeFromTranscript({ transcript, tlsVersion }) {
240
+ const msgs = [];
241
+ for (const [i, m] of transcript.entries()) {
242
+ if (m.redacted) {
243
+ break; // stop at first encrypted message
244
+ }
245
+ let message;
246
+ if (m.recordHeader[0] === PACKET_TYPE.HELLO) {
247
+ message = m.message;
248
+ }
249
+ else if (m.recordHeader[0] === PACKET_TYPE.WRAPPED_RECORD) {
250
+ if (tlsVersion === 'TLS1_3') {
251
+ const contentType = m.message[m.message.length - 1];
252
+ if (contentType !== CONTENT_TYPE_MAP['HANDSHAKE']) {
253
+ break;
254
+ }
255
+ message = m.message.slice(0, -1);
256
+ }
257
+ else {
258
+ break;
259
+ }
260
+ }
261
+ else {
262
+ continue;
263
+ }
264
+ if (!message.length) {
265
+ throw new Error('unsupported handshake message');
266
+ }
267
+ msgs.push({ message, sender: m.sender, index: i });
213
268
  }
214
- );
269
+ return msgs;
270
+ }
271
+ export async function decryptDirect(directReveal, cipherSuite, recordHeader, serverTlsVersion, content) {
272
+ const { key, iv, recordNumber } = directReveal;
273
+ const { cipher } = SUPPORTED_CIPHER_SUITE_MAP[cipherSuite];
274
+ const importedKey = await crypto.importKey(cipher, key);
275
+ return await decryptWrappedRecord(content, {
276
+ iv,
277
+ key: importedKey,
278
+ recordHeader,
279
+ recordNumber,
280
+ version: serverTlsVersion,
281
+ cipherSuite,
282
+ });
215
283
  }
216
- function packRpcMessages(...msgs) {
217
- return RPCMessages.create({
218
- messages: msgs.map((msg) => RPCMessage.create({
219
- ...msg,
220
- id: msg.id || generateRpcMessageId()
221
- }))
222
- });
284
+ export function packRpcMessages(...msgs) {
285
+ return RPCMessages.create({
286
+ messages: msgs.map(msg => (RPCMessage.create({
287
+ ...msg,
288
+ id: msg.id || generateRpcMessageId()
289
+ })))
290
+ });
223
291
  }
224
- function ethersStructToPlainObject(struct) {
225
- if (!Array.isArray(struct)) {
226
- return struct;
227
- }
228
- const namedKeys = Object.keys(struct).filter((key) => isNaN(Number(key)));
229
- if (!namedKeys.length) {
230
- return struct.map(ethersStructToPlainObject);
231
- }
232
- const obj = {};
233
- for (const key of namedKeys) {
234
- obj[key] = ethersStructToPlainObject(struct[key]);
235
- }
236
- return obj;
292
+ /**
293
+ * Converts an Ethers struct (an array w named keys) to
294
+ * a plain object. Recursively converts all structs inside.
295
+ * Required to correctly JSON.stringify the struct.
296
+ */
297
+ export function ethersStructToPlainObject(struct) {
298
+ if (!Array.isArray(struct)) {
299
+ return struct;
300
+ }
301
+ const namedKeys = Object.keys(struct)
302
+ .filter(key => isNaN(Number(key)));
303
+ // seems to be an actual array
304
+ if (!namedKeys.length) {
305
+ return struct.map(ethersStructToPlainObject);
306
+ }
307
+ const obj = {};
308
+ for (const key of namedKeys) {
309
+ obj[key] = ethersStructToPlainObject(struct[key]);
310
+ }
311
+ return obj;
237
312
  }
238
- function isTls13Suite(suite) {
239
- return suite === "TLS_AES_128_GCM_SHA256" || suite === "TLS_AES_256_GCM_SHA384" || suite === "TLS_CHACHA20_POLY1305_SHA256";
313
+ export function isTls13Suite(suite) {
314
+ return suite === 'TLS_AES_128_GCM_SHA256'
315
+ || suite === 'TLS_AES_256_GCM_SHA384'
316
+ || suite === 'TLS_CHACHA20_POLY1305_SHA256';
240
317
  }
241
- export {
242
- decryptDirect,
243
- ethersStructToPlainObject,
244
- extractApplicationDataFromTranscript,
245
- extractArrayBufferFromWsData,
246
- extractHandshakeFromTranscript,
247
- findIndexInUint8Array,
248
- generateRpcMessageId,
249
- generateSessionId,
250
- generateTunnelId,
251
- getProviderValue,
252
- getPureCiphertext,
253
- getRecordIV,
254
- getRpcRequest,
255
- getRpcRequestType,
256
- getRpcResponseType,
257
- getRpcTypeFromKey,
258
- getTranscriptString,
259
- getZkAlgorithmForCipherSuite,
260
- isApplicationData,
261
- isTls13Suite,
262
- makeRpcEvent,
263
- packRpcMessages,
264
- strToUint8Array,
265
- uint8ArrayToBinaryStr,
266
- uint8ArrayToStr,
267
- unixTimestampSeconds
268
- };