@reclaimprotocol/attestor-core 3.1.1 → 4.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.
Files changed (110) hide show
  1. package/lib/avs/contracts/index.js +18 -8
  2. package/lib/avs/tests/test.operator.js +4 -4
  3. package/lib/avs/utils/tasks.d.ts +1 -1
  4. package/lib/client/create-claim.d.ts +2 -2
  5. package/lib/client/create-claim.js +100 -34
  6. package/lib/client/tunnels/make-rpc-tcp-tunnel.js +3 -3
  7. package/lib/client/tunnels/make-rpc-tls-tunnel.js +3 -3
  8. package/lib/client/utils/client-socket.d.ts +3 -1
  9. package/lib/client/utils/client-socket.js +25 -8
  10. package/lib/client/utils/message-handler.js +2 -2
  11. package/lib/config/index.d.ts +9 -2
  12. package/lib/config/index.js +10 -4
  13. package/lib/index.js +18 -8
  14. package/lib/proto/api.d.ts +81 -2
  15. package/lib/proto/api.js +859 -101
  16. package/lib/providers/http/index.js +220 -116
  17. package/lib/providers/http/utils.d.ts +3 -6
  18. package/lib/providers/http/utils.js +13 -11
  19. package/lib/providers/index.js +1 -3
  20. package/lib/scripts/check-avs-registration.js +2 -2
  21. package/lib/scripts/generate-provider-types.js +2 -2
  22. package/lib/scripts/generate-receipt.js +6 -3
  23. package/lib/scripts/generate-toprf-keys.d.ts +1 -0
  24. package/lib/scripts/generate-toprf-keys.js +23 -0
  25. package/lib/scripts/register-avs-operator.js +2 -2
  26. package/lib/scripts/start-server.js +10 -3
  27. package/lib/scripts/update-avs-metadata.js +2 -2
  28. package/lib/scripts/verify-root-ca.js +2 -2
  29. package/lib/scripts/whitelist-operator.js +2 -2
  30. package/lib/server/create-server.js +14 -7
  31. package/lib/server/handlers/claimTunnel.js +34 -11
  32. package/lib/server/handlers/createTunnel.js +45 -9
  33. package/lib/server/handlers/disconnectTunnel.js +2 -2
  34. package/lib/server/handlers/index.js +4 -2
  35. package/lib/server/handlers/init.js +17 -2
  36. package/lib/server/handlers/toprf.d.ts +2 -0
  37. package/lib/server/handlers/toprf.js +21 -0
  38. package/lib/server/socket.d.ts +5 -3
  39. package/lib/server/socket.js +28 -8
  40. package/lib/server/tunnels/make-tcp-tunnel.js +22 -29
  41. package/lib/server/utils/apm.js +9 -5
  42. package/lib/server/utils/assert-valid-claim-request.d.ts +3 -3
  43. package/lib/server/utils/assert-valid-claim-request.js +27 -16
  44. package/lib/server/utils/dns.d.ts +1 -0
  45. package/lib/server/utils/dns.js +22 -0
  46. package/lib/server/utils/generics.d.ts +1 -1
  47. package/lib/tests/describe-with-server.d.ts +0 -2
  48. package/lib/tests/describe-with-server.js +1 -4
  49. package/lib/tests/mock-provider-server.d.ts +1 -1
  50. package/lib/tests/test.auth.d.ts +1 -0
  51. package/lib/tests/test.auth.js +75 -0
  52. package/lib/tests/test.bgp-listener.d.ts +1 -0
  53. package/lib/tests/test.bgp-listener.js +169 -0
  54. package/lib/tests/test.claim-creation.js +101 -8
  55. package/lib/tests/test.http-parser.d.ts +1 -1
  56. package/lib/tests/test.http-parser.js +7 -5
  57. package/lib/tests/test.http-provider-utils.js +489 -211
  58. package/lib/tests/test.http-provider.js +77 -6
  59. package/lib/tests/test.rpc-tunnel.js +10 -6
  60. package/lib/tests/test.zk.d.ts +1 -1
  61. package/lib/tests/test.zk.js +180 -12
  62. package/lib/tests/utils.d.ts +6 -0
  63. package/lib/tests/utils.js +16 -1
  64. package/lib/types/bgp.d.ts +11 -0
  65. package/lib/types/bgp.js +3 -0
  66. package/lib/types/claims.d.ts +14 -5
  67. package/lib/types/client.d.ts +30 -3
  68. package/lib/types/general.d.ts +12 -0
  69. package/lib/types/handlers.d.ts +4 -4
  70. package/lib/types/index.d.ts +1 -0
  71. package/lib/types/index.js +2 -1
  72. package/lib/types/providers.d.ts +25 -10
  73. package/lib/types/providers.gen.d.ts +14 -155
  74. package/lib/types/providers.gen.js +2 -6
  75. package/lib/types/tunnel.d.ts +2 -2
  76. package/lib/types/zk.d.ts +11 -3
  77. package/lib/utils/auth.d.ts +7 -0
  78. package/lib/utils/auth.js +64 -0
  79. package/lib/utils/b64-json.d.ts +2 -0
  80. package/lib/utils/b64-json.js +23 -0
  81. package/lib/utils/bgp-listener.d.ts +7 -0
  82. package/lib/utils/bgp-listener.js +126 -0
  83. package/lib/utils/claims.js +3 -3
  84. package/lib/utils/generics.d.ts +5 -5
  85. package/lib/utils/generics.js +3 -3
  86. package/lib/utils/http-parser.d.ts +4 -0
  87. package/lib/utils/http-parser.js +4 -2
  88. package/lib/utils/index.d.ts +2 -0
  89. package/lib/utils/index.js +3 -1
  90. package/lib/utils/redactions.d.ts +19 -6
  91. package/lib/utils/redactions.js +41 -4
  92. package/lib/utils/socket-base.d.ts +3 -2
  93. package/lib/utils/socket-base.js +7 -2
  94. package/lib/utils/ws.d.ts +5 -5
  95. package/lib/utils/ws.js +27 -10
  96. package/lib/utils/zk.d.ts +12 -7
  97. package/lib/utils/zk.js +261 -67
  98. package/lib/window-rpc/setup-window-rpc.js +29 -8
  99. package/lib/window-rpc/types.d.ts +16 -21
  100. package/lib/window-rpc/utils.d.ts +2 -1
  101. package/lib/window-rpc/utils.js +28 -2
  102. package/lib/window-rpc/window-rpc-zk.d.ts +8 -3
  103. package/lib/window-rpc/window-rpc-zk.js +58 -45
  104. package/package.json +25 -22
  105. package/lib/providers/httpb64/index.d.ts +0 -3
  106. package/lib/providers/httpb64/index.js +0 -209
  107. package/lib/providers/httpb64/utils.d.ts +0 -77
  108. package/lib/providers/httpb64/utils.js +0 -358
  109. package/lib/server/utils/verify-server-certificates.d.ts +0 -7
  110. package/lib/server/utils/verify-server-certificates.js +0 -101
package/lib/utils/zk.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { CipherSuite } from '@reclaimprotocol/tls';
2
- import { EncryptionAlgorithm, PrivateInput, PublicInput, ZKEngine, ZKOperator } from '@reclaimprotocol/zk-symmetric-crypto';
3
- import { MessageReveal_MessageRevealZk as ZKReveal, MessageReveal_ZKProof as ZKProof } from '../proto/api';
4
- import { CompleteTLSPacket, Logger, PrepareZKProofsBaseOpts, ZKOperators, ZKRevealInfo } from '../types';
2
+ import { EncryptionAlgorithm, OPRFOperator, PrivateInput, PublicInput, ZKEngine, ZKOperator } from '@reclaimprotocol/zk-symmetric-crypto';
3
+ import { MessageReveal_MessageRevealZk as ZKReveal, MessageReveal_ZKProof as ZKProof, ZKProofEngine } from '../proto/api';
4
+ import { CompleteTLSPacket, Logger, OPRFOperators, PrepareZKProofsBaseOpts, TOPRFProofParams, ZKOperators, ZKRevealInfo } from '../types';
5
5
  type PrepareZKProofsOpts = {
6
6
  logger?: Logger;
7
7
  cipherSuite: CipherSuite;
@@ -13,6 +13,7 @@ type ZKVerifyOpts = {
13
13
  logger?: Logger;
14
14
  /** get ZK operator for specified algorithm */
15
15
  zkOperators?: ZKOperators;
16
+ oprfOperators?: OPRFOperators;
16
17
  zkEngine?: ZKEngine;
17
18
  iv: Uint8Array;
18
19
  recordNumber: number;
@@ -22,6 +23,7 @@ type ZKProofToGenerate = {
22
23
  redactedPlaintext: Uint8Array;
23
24
  privateInput: PrivateInput;
24
25
  publicInput: PublicInput;
26
+ toprf?: TOPRFProofParams;
25
27
  };
26
28
  type ZKPacketToProve = {
27
29
  onGeneratedProofs(proofs: ZKProof[]): void;
@@ -29,22 +31,25 @@ type ZKPacketToProve = {
29
31
  proofsToGenerate: ZKProofToGenerate[];
30
32
  iv: Uint8Array;
31
33
  };
32
- export declare function makeZkProofGenerator({ zkOperators, logger, zkProofConcurrency, maxZkChunks, cipherSuite, zkEngine }: PrepareZKProofsOpts): Promise<{
34
+ export declare function makeZkProofGenerator({ zkOperators, oprfOperators, logger, zkProofConcurrency, cipherSuite, zkEngine }: PrepareZKProofsOpts): Promise<{
33
35
  /**
34
36
  * Adds the given packet to the list of packets to
35
37
  * generate ZK proofs for.
36
38
  *
37
39
  * Call `generateProofs()` to finally generate the proofs
38
40
  */
39
- addPacketToProve(packet: CompleteTLSPacket, reveal: ZKRevealInfo, onGeneratedProofs: ZKPacketToProve["onGeneratedProofs"]): Promise<void>;
41
+ addPacketToProve(packet: CompleteTLSPacket, { redactedPlaintext, toprfs }: ZKRevealInfo, onGeneratedProofs: ZKPacketToProve["onGeneratedProofs"]): Promise<void>;
40
42
  getTotalChunksToProve(): number;
41
43
  generateProofs(onChunkDone?: () => void): Promise<void>;
42
44
  }>;
43
45
  /**
44
46
  * Verify the given ZK proof
45
47
  */
46
- export declare function verifyZkPacket({ cipherSuite, ciphertext, zkReveal, zkOperators, logger, zkEngine, iv, recordNumber }: ZKVerifyOpts): Promise<{
47
- redactedPlaintext: Uint8Array;
48
+ export declare function verifyZkPacket({ cipherSuite, ciphertext, zkReveal, zkOperators, oprfOperators, logger, zkEngine, iv, recordNumber }: ZKVerifyOpts): Promise<{
49
+ redactedPlaintext: Uint8Array<ArrayBuffer>;
48
50
  }>;
49
51
  export declare function makeDefaultZkOperator(algorithm: EncryptionAlgorithm, zkEngine: ZKEngine, logger: Logger): ZKOperator;
52
+ export declare function makeDefaultOPRFOperator(algorithm: EncryptionAlgorithm, zkEngine: ZKEngine, logger: Logger): OPRFOperator;
53
+ export declare function getEngineString(engine: ZKProofEngine): "snarkjs" | "gnark";
54
+ export declare function getEngineProto(engine: ZKEngine): ZKProofEngine.ZK_ENGINE_SNARKJS | ZKProofEngine.ZK_ENGINE_GNARK;
50
55
  export {};
package/lib/utils/zk.js CHANGED
@@ -3,16 +3,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.makeZkProofGenerator = makeZkProofGenerator;
4
4
  exports.verifyZkPacket = verifyZkPacket;
5
5
  exports.makeDefaultZkOperator = makeDefaultZkOperator;
6
+ exports.makeDefaultOPRFOperator = makeDefaultOPRFOperator;
7
+ exports.getEngineString = getEngineString;
8
+ exports.getEngineProto = getEngineProto;
6
9
  const tls_1 = require("@reclaimprotocol/tls");
7
10
  const zk_symmetric_crypto_1 = require("@reclaimprotocol/zk-symmetric-crypto");
8
11
  const config_1 = require("../config");
12
+ const api_1 = require("../proto/api");
9
13
  const env_1 = require("../utils/env");
14
+ const error_1 = require("../utils/error");
10
15
  const generics_1 = require("../utils/generics");
11
16
  const logger_1 = require("../utils/logger");
12
17
  const redactions_1 = require("../utils/redactions");
13
18
  const ZK_CONCURRENCY = +((0, env_1.getEnvVariable)('ZK_CONCURRENCY')
14
19
  || config_1.DEFAULT_ZK_CONCURRENCY);
15
- async function makeZkProofGenerator({ zkOperators, logger = logger_1.logger, zkProofConcurrency = ZK_CONCURRENCY, maxZkChunks = config_1.MAX_ZK_CHUNKS, cipherSuite, zkEngine = 'snarkjs' }) {
20
+ async function makeZkProofGenerator({ zkOperators, oprfOperators, logger = logger_1.logger, zkProofConcurrency = ZK_CONCURRENCY, cipherSuite, zkEngine = 'snarkjs' }) {
16
21
  const { default: PQueue } = await import('p-queue');
17
22
  const zkQueue = new PQueue({
18
23
  concurrency: zkProofConcurrency,
@@ -20,7 +25,7 @@ async function makeZkProofGenerator({ zkOperators, logger = logger_1.logger, zkP
20
25
  });
21
26
  const packetsToProve = [];
22
27
  logger = (logger || logger_1.logger).child({ module: 'zk', zkEngine: zkEngine });
23
- let zkChunksToProve = 0;
28
+ let zkProofsToGen = 0;
24
29
  return {
25
30
  /**
26
31
  * Adds the given packet to the list of packets to
@@ -28,44 +33,97 @@ async function makeZkProofGenerator({ zkOperators, logger = logger_1.logger, zkP
28
33
  *
29
34
  * Call `generateProofs()` to finally generate the proofs
30
35
  */
31
- async addPacketToProve(packet, reveal, onGeneratedProofs) {
36
+ async addPacketToProve(packet, { redactedPlaintext, toprfs }, onGeneratedProofs) {
32
37
  if (packet.type === 'plaintext') {
33
38
  throw new Error('Cannot generate proof for plaintext');
34
39
  }
35
40
  const alg = (0, generics_1.getZkAlgorithmForCipherSuite)(cipherSuite);
36
41
  const chunkSizeBytes = getChunkSizeBytes(alg);
37
- const { redactedPlaintext } = reveal;
38
42
  const key = await tls_1.crypto.exportKey(packet.encKey);
39
43
  const iv = packet.iv;
40
44
  const ciphertext = (0, generics_1.getPureCiphertext)(packet.ciphertext, cipherSuite);
41
- const chunks = Math.ceil(ciphertext.length / chunkSizeBytes);
42
45
  const packetToProve = {
43
46
  onGeneratedProofs,
44
47
  algorithm: alg,
45
48
  proofsToGenerate: [],
46
- iv: packet.fixedIv
49
+ iv: packet.fixedIv,
47
50
  };
48
- for (let i = 0; i < chunks; i++) {
49
- const proof = getProofGenerationParamsForChunk(alg, {
50
- key,
51
- iv,
52
- ciphertext,
53
- redactedPlaintext,
54
- offsetChunks: i,
51
+ const slicesDone = [];
52
+ // first we'll handle all TOPRF blocks
53
+ // we do these first, because they can span multiple chunks
54
+ // & we need to be able to span the right chunks
55
+ for (const toprf of toprfs || []) {
56
+ const fromIndex = getIdealOffsetForToprfBlock(alg, toprf);
57
+ const toIndex = Math.min(fromIndex + chunkSizeBytes, ciphertext.length);
58
+ // ensure this OPRF block doesn't overlap with any other OPRF block
59
+ const slice = { fromIndex, toIndex };
60
+ assertNoOverlapOprf(slice);
61
+ addProofsToGenerate(slice, {
62
+ ...toprf,
63
+ dataLocation: {
64
+ ...toprf.dataLocation,
65
+ fromIndex: toprf.dataLocation.fromIndex - fromIndex
66
+ }
55
67
  });
56
- if (!proof) {
57
- continue;
58
- }
59
- packetToProve.proofsToGenerate.push(proof);
60
- zkChunksToProve += 1;
61
- if (zkChunksToProve > maxZkChunks) {
62
- throw new Error(`Too many chunks to prove: ${zkChunksToProve} > ${maxZkChunks}`);
68
+ }
69
+ // now we'll go through the rest of the ciphertext, and add proofs
70
+ // for the sections that haven't been covered by the TOPRF blocks
71
+ const slicesCp = sortSlices(slicesDone.slice());
72
+ let fromIndex = 0;
73
+ for (const done of slicesCp) {
74
+ if (done.fromIndex > fromIndex) {
75
+ addProofsToGenerate({
76
+ fromIndex,
77
+ toIndex: done.fromIndex
78
+ });
63
79
  }
80
+ fromIndex = done.toIndex;
81
+ }
82
+ if (fromIndex < ciphertext.length) {
83
+ addProofsToGenerate({
84
+ fromIndex,
85
+ toIndex: ciphertext.length
86
+ });
64
87
  }
88
+ // generate proofs in order of start index
89
+ packetToProve.proofsToGenerate
90
+ .sort((a, b) => a.startIdx - b.startIdx);
65
91
  packetsToProve.push(packetToProve);
92
+ function assertNoOverlapOprf(slice) {
93
+ for (const done of slicesDone) {
94
+ if (
95
+ // 1d box overlap
96
+ slice.fromIndex < done.toIndex
97
+ && slice.toIndex > done.fromIndex) {
98
+ throw new error_1.AttestorError('ERROR_BAD_REQUEST', 'Single chunk has multiple OPRFs');
99
+ }
100
+ }
101
+ }
102
+ function addProofsToGenerate({ fromIndex, toIndex }, toprf) {
103
+ for (let i = fromIndex; i < toIndex; i += chunkSizeBytes) {
104
+ const slice = {
105
+ fromIndex: i,
106
+ toIndex: Math.min(i + chunkSizeBytes, toIndex)
107
+ };
108
+ slicesDone.push(slice);
109
+ const proofParams = getProofGenerationParamsForSlice({
110
+ key,
111
+ iv,
112
+ ciphertext,
113
+ redactedPlaintext,
114
+ slice,
115
+ toprf,
116
+ });
117
+ if (!proofParams) {
118
+ continue;
119
+ }
120
+ packetToProve.proofsToGenerate.push(proofParams);
121
+ zkProofsToGen += 1;
122
+ }
123
+ }
66
124
  },
67
125
  getTotalChunksToProve() {
68
- return zkChunksToProve;
126
+ return zkProofsToGen;
69
127
  },
70
128
  async generateProofs(onChunkDone) {
71
129
  var _a;
@@ -90,52 +148,70 @@ async function makeZkProofGenerator({ zkOperators, logger = logger_1.logger, zkP
90
148
  }
91
149
  }
92
150
  await Promise.all(tasks);
93
- logger === null || logger === void 0 ? void 0 : logger.info({
94
- durationMs: Date.now() - start,
95
- chunks: zkChunksToProve,
96
- }, 'generated ZK proofs');
151
+ logger === null || logger === void 0 ? void 0 : logger.info({ durationMs: Date.now() - start, zkProofsToGen }, 'generated ZK proofs');
97
152
  // reset the packets to prove
98
153
  packetsToProve.splice(0, packetsToProve.length);
99
- zkChunksToProve = 0;
154
+ zkProofsToGen = 0;
100
155
  // release ZK resources to free up memory
101
156
  const alg = (0, generics_1.getZkAlgorithmForCipherSuite)(cipherSuite);
102
157
  const zkOperator = await getZkOperatorForAlgorithm(alg);
103
158
  (_a = zkOperator.release) === null || _a === void 0 ? void 0 : _a.call(zkOperator);
104
159
  },
105
160
  };
106
- async function generateProofForChunk(algorithm, { startIdx, redactedPlaintext, privateInput, publicInput }) {
107
- const operator = await getZkOperatorForAlgorithm(algorithm);
161
+ async function generateProofForChunk(algorithm, { startIdx, redactedPlaintext, privateInput, publicInput, toprf, }) {
162
+ const operator = toprf
163
+ ? getOprfOperatorForAlgorithm(algorithm)
164
+ : getZkOperatorForAlgorithm(algorithm);
108
165
  const proof = await (0, zk_symmetric_crypto_1.generateProof)({
109
166
  algorithm,
110
167
  privateInput,
111
168
  publicInput,
112
169
  operator,
113
- logger
170
+ logger,
171
+ ...(toprf
172
+ ? {
173
+ toprf: {
174
+ pos: toprf.dataLocation.fromIndex,
175
+ len: toprf.dataLocation.length,
176
+ output: toprf.nullifier,
177
+ responses: toprf.responses,
178
+ domainSeparator: config_1.TOPRF_DOMAIN_SEPARATOR
179
+ },
180
+ mask: toprf.mask,
181
+ }
182
+ : {})
114
183
  });
115
184
  logger === null || logger === void 0 ? void 0 : logger.debug({ startIdx }, 'generated proof for chunk');
116
185
  return {
117
- proofJson: proof.proofJson,
186
+ // backwards compatibility
187
+ proofJson: '',
188
+ proofData: typeof proof.proofData === 'string'
189
+ ? (0, tls_1.strToUint8Array)(proof.proofData)
190
+ : proof.proofData,
191
+ toprf,
118
192
  decryptedRedactedCiphertext: proof.plaintext,
119
193
  redactedPlaintext,
120
194
  startIdx
121
195
  };
122
196
  }
123
- async function getZkOperatorForAlgorithm(algorithm) {
197
+ function getZkOperatorForAlgorithm(algorithm) {
124
198
  return (zkOperators === null || zkOperators === void 0 ? void 0 : zkOperators[algorithm])
125
- || await makeDefaultZkOperator(algorithm, zkEngine, logger);
199
+ || makeDefaultZkOperator(algorithm, zkEngine, logger);
200
+ }
201
+ function getOprfOperatorForAlgorithm(algorithm) {
202
+ return (oprfOperators === null || oprfOperators === void 0 ? void 0 : oprfOperators[algorithm])
203
+ || makeDefaultOPRFOperator(algorithm, zkEngine, logger);
126
204
  }
127
205
  }
128
206
  /**
129
207
  * Verify the given ZK proof
130
208
  */
131
- async function verifyZkPacket({ cipherSuite, ciphertext, zkReveal, zkOperators, logger = logger_1.logger, zkEngine = 'snarkjs', iv, recordNumber }) {
209
+ async function verifyZkPacket({ cipherSuite, ciphertext, zkReveal, zkOperators, oprfOperators, logger = logger_1.logger, zkEngine = 'snarkjs', iv, recordNumber }) {
132
210
  if (!zkReveal) {
133
211
  throw new Error('No ZK reveal');
134
212
  }
135
213
  const { proofs } = zkReveal;
136
214
  const algorithm = (0, generics_1.getZkAlgorithmForCipherSuite)(cipherSuite);
137
- const operator = (zkOperators === null || zkOperators === void 0 ? void 0 : zkOperators[algorithm])
138
- || await makeDefaultZkOperator(algorithm, zkEngine, logger);
139
215
  const recordIV = (0, generics_1.getRecordIV)(ciphertext, cipherSuite);
140
216
  ciphertext = (0, generics_1.getPureCiphertext)(ciphertext, cipherSuite);
141
217
  /**
@@ -146,10 +222,18 @@ async function verifyZkPacket({ cipherSuite, ciphertext, zkReveal, zkOperators,
146
222
  * in the proofs
147
223
  */
148
224
  const realRedactedPlaintext = new Uint8Array(ciphertext.length).fill(redactions_1.REDACTION_CHAR_CODE);
149
- const alg = (0, generics_1.getZkAlgorithmForCipherSuite)(cipherSuite);
150
- const chunkSizeBytes = getChunkSizeBytes(alg);
151
- const { blocksPerChunk } = zk_symmetric_crypto_1.CONFIG[algorithm];
152
- await Promise.all(proofs.map(async ({ proofJson, decryptedRedactedCiphertext, redactedPlaintext, startIdx }, i) => {
225
+ await Promise.all(proofs.map(async (proof, i) => {
226
+ try {
227
+ await verifyProofPacket(proof);
228
+ }
229
+ catch (e) {
230
+ e.message += ` (chunk ${i}, startIdx ${proof.startIdx})`;
231
+ throw e;
232
+ }
233
+ }));
234
+ return { redactedPlaintext: realRedactedPlaintext };
235
+ async function verifyProofPacket({ proofData, proofJson, decryptedRedactedCiphertext, redactedPlaintext, startIdx, toprf, }) {
236
+ var _a, _b, _c;
153
237
  // get the ciphertext chunk we received from the server
154
238
  // the ZK library, will verify that the decrypted redacted
155
239
  // ciphertext matches the ciphertext received from the server
@@ -163,10 +247,29 @@ async function verifyZkPacket({ cipherSuite, ciphertext, zkReveal, zkOperators,
163
247
  ciphertextChunk[i] = redactions_1.REDACTION_CHAR_CODE;
164
248
  }
165
249
  }
166
- if (!(0, redactions_1.isRedactionCongruent)(redactedPlaintext, decryptedRedactedCiphertext)) {
167
- throw new Error(`redacted ciphertext (${i}) not congruent`);
250
+ // redact OPRF indices -- because they'll incorrectly
251
+ // be marked as incongruent
252
+ let comparePlaintext = redactedPlaintext;
253
+ if (toprf) {
254
+ comparePlaintext = new Uint8Array(redactedPlaintext);
255
+ for (let i = 0; i < toprf.dataLocation.length; i++) {
256
+ comparePlaintext[i + toprf.dataLocation.fromIndex] = redactions_1.REDACTION_CHAR_CODE;
257
+ }
258
+ // the transcript will contain only the stringified
259
+ // nullifier. So here, we'll compare the provable
260
+ // binary nullifier with the stringified nullifier
261
+ // that the user has provided
262
+ const nulliferStr = (0, redactions_1.binaryHashToStr)(toprf.nullifier, toprf.dataLocation.length);
263
+ const txtHash = redactedPlaintext.slice((_a = toprf.dataLocation) === null || _a === void 0 ? void 0 : _a.fromIndex, ((_b = toprf.dataLocation) === null || _b === void 0 ? void 0 : _b.fromIndex)
264
+ + ((_c = toprf.dataLocation) === null || _c === void 0 ? void 0 : _c.length));
265
+ if ((0, generics_1.uint8ArrayToStr)(txtHash) !== nulliferStr
266
+ .slice(0, txtHash.length)) {
267
+ throw new Error('OPRF nullifier not congruent');
268
+ }
269
+ }
270
+ if (!(0, redactions_1.isRedactionCongruent)(comparePlaintext, decryptedRedactedCiphertext)) {
271
+ throw new Error('redacted ciphertext not congruent');
168
272
  }
169
- const chunkIndex = startIdx / chunkSizeBytes * blocksPerChunk;
170
273
  let nonce = (0, tls_1.concatenateUint8Arrays)([iv, recordIV]);
171
274
  if (!recordIV.length) {
172
275
  nonce = (0, tls_1.generateIV)(nonce, recordNumber);
@@ -174,26 +277,56 @@ async function verifyZkPacket({ cipherSuite, ciphertext, zkReveal, zkOperators,
174
277
  await (0, zk_symmetric_crypto_1.verifyProof)({
175
278
  proof: {
176
279
  algorithm,
177
- proofJson,
280
+ proofData: proofData.length
281
+ ? proofData
282
+ : (0, tls_1.strToUint8Array)(proofJson),
178
283
  plaintext: decryptedRedactedCiphertext,
179
284
  },
180
- publicInput: { ciphertext: ciphertextChunk, iv: nonce, offset: chunkIndex },
181
- operator,
285
+ publicInput: {
286
+ ciphertext: ciphertextChunk,
287
+ iv: nonce,
288
+ offsetBytes: startIdx
289
+ },
182
290
  logger,
291
+ ...(toprf
292
+ ? {
293
+ operator: getOprfOperator(),
294
+ toprf: {
295
+ pos: toprf.dataLocation.fromIndex,
296
+ len: toprf.dataLocation.length,
297
+ domainSeparator: config_1.TOPRF_DOMAIN_SEPARATOR,
298
+ output: toprf.nullifier,
299
+ responses: toprf.responses,
300
+ }
301
+ }
302
+ : { operator: getZkOperator() })
183
303
  });
184
304
  logger === null || logger === void 0 ? void 0 : logger.debug({ startIdx, endIdx: startIdx + redactedPlaintext.length }, 'verified proof');
185
305
  realRedactedPlaintext.set(redactedPlaintext, startIdx);
186
- }));
187
- return { redactedPlaintext: realRedactedPlaintext };
306
+ }
307
+ function getZkOperator() {
308
+ return (zkOperators === null || zkOperators === void 0 ? void 0 : zkOperators[algorithm])
309
+ || makeDefaultZkOperator(algorithm, zkEngine, logger);
310
+ }
311
+ function getOprfOperator() {
312
+ return (oprfOperators === null || oprfOperators === void 0 ? void 0 : oprfOperators[algorithm])
313
+ || makeDefaultOPRFOperator(algorithm, zkEngine, logger);
314
+ }
188
315
  }
316
+ // the chunk size of the ZK circuit in bytes
317
+ // this will be >= the block size
189
318
  function getChunkSizeBytes(alg) {
190
319
  const { chunkSize, bitsPerWord } = zk_symmetric_crypto_1.CONFIG[alg];
191
320
  return chunkSize * bitsPerWord / 8;
192
321
  }
193
322
  const zkEngines = {};
323
+ const oprfEngines = {};
194
324
  const operatorMakers = {
195
325
  'snarkjs': zk_symmetric_crypto_1.makeSnarkJsZKOperator,
196
- 'gnark': zk_symmetric_crypto_1.makeGnarkZkOperator
326
+ 'gnark': zk_symmetric_crypto_1.makeGnarkZkOperator,
327
+ };
328
+ const OPRF_OPERATOR_MAKERS = {
329
+ 'gnark': zk_symmetric_crypto_1.makeGnarkOPRFOperator
197
330
  };
198
331
  function makeDefaultZkOperator(algorithm, zkEngine, logger) {
199
332
  let zkOperators = zkEngines[zkEngine];
@@ -204,30 +337,64 @@ function makeDefaultZkOperator(algorithm, zkEngine, logger) {
204
337
  if (!zkOperators[algorithm]) {
205
338
  const isNode = (0, env_1.detectEnvironment)() === 'node';
206
339
  const opType = isNode ? 'local' : 'remote';
207
- logger === null || logger === void 0 ? void 0 : logger.info({
208
- type: opType,
209
- algorithm
210
- }, 'fetching zk operator');
340
+ logger === null || logger === void 0 ? void 0 : logger.info({ type: opType, algorithm }, 'fetching zk operator');
211
341
  const fetcher = opType === 'local'
212
342
  ? (0, zk_symmetric_crypto_1.makeLocalFileFetch)()
213
343
  : (0, zk_symmetric_crypto_1.makeRemoteFileFetch)({
214
344
  baseUrl: config_1.DEFAULT_REMOTE_FILE_FETCH_BASE_URL,
215
345
  });
216
- zkOperators[algorithm] = operatorMakers[zkEngine]({
217
- algorithm,
218
- fetcher
219
- });
346
+ const maker = operatorMakers[zkEngine];
347
+ if (!maker) {
348
+ throw new Error(`No ZK operator maker for ${zkEngine}`);
349
+ }
350
+ zkOperators[algorithm] = maker({ algorithm, fetcher });
220
351
  }
221
352
  return zkOperators[algorithm];
222
353
  }
223
- function getProofGenerationParamsForChunk(algorithm, { key, iv, ciphertext, redactedPlaintext, offsetChunks, }) {
224
- const chunkSize = getChunkSizeBytes(algorithm);
225
- const startIdx = offsetChunks * chunkSize;
226
- const endIdx = (offsetChunks + 1) * chunkSize;
227
- const ciphertextChunk = ciphertext
228
- .slice(startIdx, endIdx);
229
- const plaintextChunk = redactedPlaintext
230
- .slice(startIdx, endIdx);
354
+ function makeDefaultOPRFOperator(algorithm, zkEngine, logger) {
355
+ let operators = oprfEngines[zkEngine];
356
+ if (!operators) {
357
+ oprfEngines[zkEngine] = {};
358
+ operators = oprfEngines[zkEngine];
359
+ }
360
+ if (!operators[algorithm]) {
361
+ const isNode = (0, env_1.detectEnvironment)() === 'node';
362
+ const type = isNode ? 'local' : 'remote';
363
+ logger === null || logger === void 0 ? void 0 : logger.info({ type, algorithm }, 'fetching oprf operator');
364
+ const fetcher = type === 'local'
365
+ ? (0, zk_symmetric_crypto_1.makeLocalFileFetch)()
366
+ : (0, zk_symmetric_crypto_1.makeRemoteFileFetch)({
367
+ baseUrl: config_1.DEFAULT_REMOTE_FILE_FETCH_BASE_URL,
368
+ });
369
+ const maker = OPRF_OPERATOR_MAKERS[zkEngine];
370
+ if (!maker) {
371
+ throw new Error(`No OPRF operator maker for ${zkEngine}`);
372
+ }
373
+ operators[algorithm] = maker({ algorithm, fetcher });
374
+ }
375
+ return operators[algorithm];
376
+ }
377
+ function getEngineString(engine) {
378
+ if (engine === api_1.ZKProofEngine.ZK_ENGINE_GNARK) {
379
+ return 'gnark';
380
+ }
381
+ if (engine === api_1.ZKProofEngine.ZK_ENGINE_SNARKJS) {
382
+ return 'snarkjs';
383
+ }
384
+ throw new Error(`Unknown ZK engine: ${engine}`);
385
+ }
386
+ function getEngineProto(engine) {
387
+ if (engine === 'gnark') {
388
+ return api_1.ZKProofEngine.ZK_ENGINE_GNARK;
389
+ }
390
+ if (engine === 'snarkjs') {
391
+ return api_1.ZKProofEngine.ZK_ENGINE_SNARKJS;
392
+ }
393
+ throw new Error(`Unknown ZK engine: ${engine}`);
394
+ }
395
+ function getProofGenerationParamsForSlice({ key, iv, ciphertext, redactedPlaintext, slice: { fromIndex, toIndex }, toprf, }) {
396
+ const ciphertextChunk = ciphertext.slice(fromIndex, toIndex);
397
+ const plaintextChunk = redactedPlaintext.slice(fromIndex, toIndex);
231
398
  if ((0, redactions_1.isFullyRedacted)(plaintextChunk)) {
232
399
  return;
233
400
  }
@@ -241,10 +408,37 @@ function getProofGenerationParamsForChunk(algorithm, { key, iv, ciphertext, reda
241
408
  }
242
409
  }
243
410
  return {
244
- startIdx,
411
+ startIdx: fromIndex,
245
412
  redactedPlaintext: plaintextChunk,
246
413
  privateInput: { key },
247
- publicInput: { ciphertext: ciphertextChunk, iv, offset: offsetChunks }
414
+ publicInput: { ciphertext: ciphertextChunk, iv, offsetBytes: fromIndex },
415
+ toprf
248
416
  };
249
417
  }
250
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiemsuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMvemsudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUF1RUEsb0RBMEtDO0FBS0Qsd0NBc0dDO0FBb0JELHNEQW1DQztBQW5aRCw4Q0FBOEY7QUFDOUYsOEVBYXlEO0FBQ3pELHVDQUFzRztBQUd0Ryx1Q0FBaUU7QUFDakUsaURBQWlHO0FBQ2pHLDZDQUFtRDtBQUNuRCxxREFBaUc7QUE2Q2pHLE1BQU0sY0FBYyxHQUFHLENBQUMsQ0FDdkIsSUFBQSxvQkFBYyxFQUFDLGdCQUFnQixDQUFDO09BQzdCLCtCQUFzQixDQUN6QixDQUFBO0FBRU0sS0FBSyxVQUFVLG9CQUFvQixDQUN6QyxFQUNDLFdBQVcsRUFDWCxNQUFNLEdBQUcsZUFBTSxFQUNmLGtCQUFrQixHQUFHLGNBQWMsRUFDbkMsV0FBVyxHQUFHLHNCQUFhLEVBQzNCLFdBQVcsRUFDWCxRQUFRLEdBQUcsU0FBUyxFQUNDO0lBR3RCLE1BQU0sRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLEdBQUcsTUFBTSxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUE7SUFDbkQsTUFBTSxPQUFPLEdBQUcsSUFBSSxNQUFNLENBQUM7UUFDMUIsV0FBVyxFQUFFLGtCQUFrQjtRQUMvQixTQUFTLEVBQUUsSUFBSTtLQUNmLENBQUMsQ0FBQTtJQUVGLE1BQU0sY0FBYyxHQUFzQixFQUFFLENBQUE7SUFFNUMsTUFBTSxHQUFHLENBQUMsTUFBTSxJQUFJLGVBQU0sQ0FBQyxDQUFDLEtBQUssQ0FBQyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUE7SUFDdkUsSUFBSSxlQUFlLEdBQUcsQ0FBQyxDQUFBO0lBRXZCLE9BQU87UUFDTjs7Ozs7V0FLRztRQUNILEtBQUssQ0FBQyxnQkFBZ0IsQ0FDckIsTUFBeUIsRUFDekIsTUFBb0IsRUFDcEIsaUJBQXVEO1lBRXZELElBQUcsTUFBTSxDQUFDLElBQUksS0FBSyxXQUFXLEVBQUUsQ0FBQztnQkFDaEMsTUFBTSxJQUFJLEtBQUssQ0FBQyxxQ0FBcUMsQ0FBQyxDQUFBO1lBQ3ZELENBQUM7WUFFRCxNQUFNLEdBQUcsR0FBRyxJQUFBLHVDQUE0QixFQUFDLFdBQVcsQ0FBQyxDQUFBO1lBQ3JELE1BQU0sY0FBYyxHQUFHLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxDQUFBO1lBRTdDLE1BQU0sRUFBRSxpQkFBaUIsRUFBRSxHQUFHLE1BQU0sQ0FBQTtZQUNwQyxNQUFNLEdBQUcsR0FBRyxNQUFNLFlBQU0sQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFBO1lBQ2pELE1BQU0sRUFBRSxHQUFHLE1BQU0sQ0FBQyxFQUFFLENBQUE7WUFDcEIsTUFBTSxVQUFVLEdBQUcsSUFBQSw0QkFBaUIsRUFDbkMsTUFBTSxDQUFDLFVBQVUsRUFDakIsV0FBVyxDQUNYLENBQUE7WUFDRCxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEdBQUcsY0FBYyxDQUFDLENBQUE7WUFDNUQsTUFBTSxhQUFhLEdBQW9CO2dCQUN0QyxpQkFBaUI7Z0JBQ2pCLFNBQVMsRUFBRSxHQUFHO2dCQUNkLGdCQUFnQixFQUFFLEVBQUU7Z0JBQ3BCLEVBQUUsRUFBRSxNQUFNLENBQUMsT0FBTzthQUNsQixDQUFBO1lBRUQsS0FBSSxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUMsQ0FBQyxHQUFHLE1BQU0sRUFBQyxDQUFDLEVBQUUsRUFBRSxDQUFDO2dCQUM5QixNQUFNLEtBQUssR0FBRyxnQ0FBZ0MsQ0FDN0MsR0FBRyxFQUNIO29CQUNDLEdBQUc7b0JBQ0gsRUFBRTtvQkFDRixVQUFVO29CQUNWLGlCQUFpQjtvQkFDakIsWUFBWSxFQUFFLENBQUM7aUJBQ2YsQ0FDRCxDQUFBO2dCQUNELElBQUcsQ0FBQyxLQUFLLEVBQUUsQ0FBQztvQkFDWCxTQUFRO2dCQUNULENBQUM7Z0JBRUQsYUFBYSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQTtnQkFDMUMsZUFBZSxJQUFJLENBQUMsQ0FBQTtnQkFFcEIsSUFBRyxlQUFlLEdBQUcsV0FBVyxFQUFFLENBQUM7b0JBQ2xDLE1BQU0sSUFBSSxLQUFLLENBQ2QsNkJBQTZCLGVBQWUsTUFBTSxXQUFXLEVBQUUsQ0FDL0QsQ0FBQTtnQkFDRixDQUFDO1lBQ0YsQ0FBQztZQUVELGNBQWMsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUE7UUFDbkMsQ0FBQztRQUNELHFCQUFxQjtZQUNwQixPQUFPLGVBQWUsQ0FBQTtRQUN2QixDQUFDO1FBQ0QsS0FBSyxDQUFDLGNBQWMsQ0FBQyxXQUF3Qjs7WUFDNUMsSUFBRyxDQUFDLGNBQWMsQ0FBQyxNQUFNLEVBQUUsQ0FBQztnQkFDM0IsT0FBTTtZQUNQLENBQUM7WUFFRCxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUE7WUFDeEIsTUFBTSxLQUFLLEdBQW9CLEVBQUUsQ0FBQTtZQUNqQyxLQUFJLE1BQU0sRUFBRSxpQkFBaUIsRUFBRSxTQUFTLEVBQUUsZ0JBQWdCLEVBQUUsSUFBSSxjQUFjLEVBQUUsQ0FBQztnQkFDaEYsTUFBTSxNQUFNLEdBQWMsRUFBRSxDQUFBO2dCQUU1QixJQUFJLFVBQVUsR0FBRyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUE7Z0JBQ3hDLEtBQUksTUFBTSxVQUFVLElBQUksZ0JBQWdCLEVBQUUsQ0FBQztvQkFDMUMsS0FBSyxDQUFDLElBQUksQ0FDVCxPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssSUFBRyxFQUFFO3dCQUNyQixNQUFNLEtBQUssR0FBRyxNQUFNLHFCQUFxQixDQUN4QyxTQUFTLEVBQ1QsVUFBVSxDQUNWLENBQUE7d0JBRUQsV0FBVyxhQUFYLFdBQVcsdUJBQVgsV0FBVyxFQUFJLENBQUE7d0JBQ2YsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQTt3QkFFbEIsVUFBVSxJQUFJLENBQUMsQ0FBQTt3QkFDZixJQUFHLFVBQVUsS0FBSyxDQUFDLEVBQUUsQ0FBQzs0QkFDckIsaUJBQWlCLENBQUMsTUFBTSxDQUFDLENBQUE7d0JBQzFCLENBQUM7b0JBQ0YsQ0FBQyxFQUFFLEVBQUUsY0FBYyxFQUFFLElBQUksRUFBRSxDQUFDLENBQzVCLENBQUE7Z0JBQ0YsQ0FBQztZQUNGLENBQUM7WUFFRCxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUE7WUFFeEIsTUFBTSxhQUFOLE1BQU0sdUJBQU4sTUFBTSxDQUFFLElBQUksQ0FDWDtnQkFDQyxVQUFVLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLEtBQUs7Z0JBQzlCLE1BQU0sRUFBRSxlQUFlO2FBQ3ZCLEVBQ0QscUJBQXFCLENBQ3JCLENBQUE7WUFFRCw2QkFBNkI7WUFDN0IsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFBO1lBQy9DLGVBQWUsR0FBRyxDQUFDLENBQUE7WUFFbkIseUNBQXlDO1lBQ3pDLE1BQU0sR0FBRyxHQUFHLElBQUEsdUNBQTRCLEVBQUMsV0FBVyxDQUFDLENBQUE7WUFDckQsTUFBTSxVQUFVLEdBQUcsTUFBTSx5QkFBeUIsQ0FBQyxHQUFHLENBQUMsQ0FBQTtZQUN2RCxNQUFBLFVBQVUsQ0FBQyxPQUFPLDBEQUFJLENBQUE7UUFDdkIsQ0FBQztLQUNELENBQUE7SUFFRCxLQUFLLFVBQVUscUJBQXFCLENBQ25DLFNBQThCLEVBQzlCLEVBQ0MsUUFBUSxFQUFFLGlCQUFpQixFQUMzQixZQUFZLEVBQUUsV0FBVyxFQUNOO1FBRXBCLE1BQU0sUUFBUSxHQUFHLE1BQU0seUJBQXlCLENBQUMsU0FBUyxDQUFDLENBQUE7UUFFM0QsTUFBTSxLQUFLLEdBQUcsTUFBTSxJQUFBLG1DQUFhLEVBQ2hDO1lBQ0MsU0FBUztZQUNULFlBQVk7WUFDWixXQUFXO1lBQ1gsUUFBUTtZQUNSLE1BQU07U0FDTixDQUNELENBQUE7UUFFRCxNQUFNLGFBQU4sTUFBTSx1QkFBTixNQUFNLENBQUUsS0FBSyxDQUFDLEVBQUUsUUFBUSxFQUFFLEVBQUUsMkJBQTJCLENBQUMsQ0FBQTtRQUN4RCxPQUFPO1lBQ04sU0FBUyxFQUFFLEtBQUssQ0FBQyxTQUFTO1lBQzFCLDJCQUEyQixFQUFFLEtBQUssQ0FBQyxTQUFTO1lBQzVDLGlCQUFpQjtZQUNqQixRQUFRO1NBQ1IsQ0FBQTtJQUNGLENBQUM7SUFFRCxLQUFLLFVBQVUseUJBQXlCLENBQUMsU0FBOEI7UUFDdEUsT0FBTyxDQUFBLFdBQVcsYUFBWCxXQUFXLHVCQUFYLFdBQVcsQ0FBRyxTQUFTLENBQUM7ZUFDM0IsTUFBTSxxQkFBcUIsQ0FBQyxTQUFTLEVBQUUsUUFBUSxFQUFFLE1BQU0sQ0FBQyxDQUFBO0lBQzdELENBQUM7QUFDRixDQUFDO0FBRUQ7O0dBRUc7QUFDSSxLQUFLLFVBQVUsY0FBYyxDQUNuQyxFQUNDLFdBQVcsRUFDWCxVQUFVLEVBQ1YsUUFBUSxFQUNSLFdBQVcsRUFDWCxNQUFNLEdBQUcsZUFBTSxFQUNmLFFBQVEsR0FBRyxTQUFTLEVBQ3BCLEVBQUUsRUFDRixZQUFZLEVBQ0U7SUFFZixJQUFHLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDZCxNQUFNLElBQUksS0FBSyxDQUFDLGNBQWMsQ0FBQyxDQUFBO0lBQ2hDLENBQUM7SUFFRCxNQUFNLEVBQUUsTUFBTSxFQUFFLEdBQUcsUUFBUSxDQUFBO0lBQzNCLE1BQU0sU0FBUyxHQUFHLElBQUEsdUNBQTRCLEVBQUMsV0FBVyxDQUFDLENBQUE7SUFDM0QsTUFBTSxRQUFRLEdBQUcsQ0FBQSxXQUFXLGFBQVgsV0FBVyx1QkFBWCxXQUFXLENBQUcsU0FBUyxDQUFDO1dBQ3JDLE1BQU0scUJBQXFCLENBQUMsU0FBUyxFQUFFLFFBQVEsRUFBRSxNQUFNLENBQUMsQ0FBQTtJQUU1RCxNQUFNLFFBQVEsR0FBRyxJQUFBLHNCQUFXLEVBQUMsVUFBVSxFQUFFLFdBQVcsQ0FBQyxDQUFBO0lBQ3JELFVBQVUsR0FBRyxJQUFBLDRCQUFpQixFQUFDLFVBQVUsRUFBRSxXQUFXLENBQUMsQ0FBQTtJQUN2RDs7Ozs7O09BTUc7SUFDSCxNQUFNLHFCQUFxQixHQUFHLElBQUksVUFBVSxDQUMzQyxVQUFVLENBQUMsTUFBTSxDQUNqQixDQUFDLElBQUksQ0FBQyxnQ0FBbUIsQ0FBQyxDQUFBO0lBRTNCLE1BQU0sR0FBRyxHQUFHLElBQUEsdUNBQTRCLEVBQUMsV0FBVyxDQUFDLENBQUE7SUFDckQsTUFBTSxjQUFjLEdBQUcsaUJBQWlCLENBQUMsR0FBRyxDQUFDLENBQUE7SUFDN0MsTUFBTSxFQUFFLGNBQWMsRUFBRSxHQUFHLDRCQUFTLENBQUMsU0FBUyxDQUFDLENBQUE7SUFFL0MsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUNoQixNQUFNLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBQyxFQUNoQixTQUFTLEVBQ1QsMkJBQTJCLEVBQzNCLGlCQUFpQixFQUNqQixRQUFRLEVBQ1IsRUFBRSxDQUFDLEVBQUUsRUFBRTtRQUNQLHVEQUF1RDtRQUN2RCwwREFBMEQ7UUFDMUQsNkRBQTZEO1FBQzdELE1BQU0sZUFBZSxHQUFHLFVBQVUsQ0FBQyxLQUFLLENBQ3ZDLFFBQVEsRUFDUixRQUFRLEdBQUcsaUJBQWlCLENBQUMsTUFBTSxDQUNuQyxDQUFBO1FBQ0QsNkNBQTZDO1FBQzdDLDBDQUEwQztRQUMxQyx1REFBdUQ7UUFDdkQsNkNBQTZDO1FBQzdDLEtBQUksSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFDLENBQUMsR0FBRyxlQUFlLENBQUMsTUFBTSxFQUFDLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDOUMsSUFBRyxpQkFBaUIsQ0FBQyxDQUFDLENBQUMsS0FBSyxnQ0FBbUIsRUFBRSxDQUFDO2dCQUNqRCxlQUFlLENBQUMsQ0FBQyxDQUFDLEdBQUcsZ0NBQW1CLENBQUE7WUFDekMsQ0FBQztRQUNGLENBQUM7UUFFRCxJQUFHLENBQUMsSUFBQSxpQ0FBb0IsRUFDdkIsaUJBQWlCLEVBQ2pCLDJCQUEyQixDQUMzQixFQUFFLENBQUM7WUFDSCxNQUFNLElBQUksS0FBSyxDQUFDLHdCQUF3QixDQUFDLGlCQUFpQixDQUFDLENBQUE7UUFDNUQsQ0FBQztRQUVELE1BQU0sVUFBVSxHQUFHLFFBQVEsR0FBRyxjQUFjLEdBQUcsY0FBYyxDQUFBO1FBQzdELElBQUksS0FBSyxHQUFHLElBQUEsNEJBQXNCLEVBQUMsQ0FBQyxFQUFFLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQTtRQUVsRCxJQUFHLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ3JCLEtBQUssR0FBRyxJQUFBLGdCQUFVLEVBQUMsS0FBSyxFQUFFLFlBQVksQ0FBQyxDQUFBO1FBQ3hDLENBQUM7UUFFRCxNQUFNLElBQUEsaUNBQVcsRUFDaEI7WUFDQyxLQUFLLEVBQUU7Z0JBQ04sU0FBUztnQkFDVCxTQUFTO2dCQUNULFNBQVMsRUFBRSwyQkFBMkI7YUFDdEM7WUFDRCxXQUFXLEVBQUUsRUFBRSxVQUFVLEVBQUUsZUFBZSxFQUFFLEVBQUUsRUFBQyxLQUFLLEVBQUUsTUFBTSxFQUFDLFVBQVUsRUFBRTtZQUN6RSxRQUFRO1lBQ1IsTUFBTTtTQUNOLENBQ0QsQ0FBQTtRQUVELE1BQU0sYUFBTixNQUFNLHVCQUFOLE1BQU0sQ0FBRSxLQUFLLENBQ1osRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLFFBQVEsR0FBRyxpQkFBaUIsQ0FBQyxNQUFNLEVBQUUsRUFDekQsZ0JBQWdCLENBQ2hCLENBQUE7UUFFRCxxQkFBcUIsQ0FBQyxHQUFHLENBQ3hCLGlCQUFpQixFQUNqQixRQUFRLENBQ1IsQ0FBQTtJQUNGLENBQUMsQ0FBQyxDQUNGLENBQUE7SUFFRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUscUJBQXFCLEVBQUUsQ0FBQTtBQUNwRCxDQUFDO0FBRUQsU0FBUyxpQkFBaUIsQ0FBQyxHQUF3QjtJQUNsRCxNQUFNLEVBQ0wsU0FBUyxFQUNULFdBQVcsRUFDWCxHQUFHLDRCQUFTLENBQUMsR0FBRyxDQUFDLENBQUE7SUFFbEIsT0FBTyxTQUFTLEdBQUcsV0FBVyxHQUFHLENBQUMsQ0FBQTtBQUNuQyxDQUFDO0FBRUQsTUFBTSxTQUFTLEdBRVgsRUFBRSxDQUFBO0FBRU4sTUFBTSxjQUFjLEdBQXNFO0lBQ3pGLFNBQVMsRUFBRSwyQ0FBcUI7SUFDaEMsT0FBTyxFQUFFLHlDQUFtQjtDQUM1QixDQUFBO0FBRUQsU0FBZ0IscUJBQXFCLENBQ3BDLFNBQThCLEVBQzlCLFFBQWtCLEVBQ2xCLE1BQWM7SUFFZCxJQUFJLFdBQVcsR0FBRyxTQUFTLENBQUMsUUFBUSxDQUFDLENBQUE7SUFDckMsSUFBRyxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ2pCLFNBQVMsQ0FBQyxRQUFRLENBQUMsR0FBRyxFQUFFLENBQUE7UUFDeEIsV0FBVyxHQUFHLFNBQVMsQ0FBQyxRQUFRLENBQUMsQ0FBQTtJQUNsQyxDQUFDO0lBRUQsSUFBRyxDQUFDLFdBQVcsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO1FBQzVCLE1BQU0sTUFBTSxHQUFHLElBQUEsdUJBQWlCLEdBQUUsS0FBSyxNQUFNLENBQUE7UUFDN0MsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQTtRQUMxQyxNQUFNLGFBQU4sTUFBTSx1QkFBTixNQUFNLENBQUUsSUFBSSxDQUNYO1lBQ0MsSUFBSSxFQUFFLE1BQU07WUFDWixTQUFTO1NBQ1QsRUFDRCxzQkFBc0IsQ0FDdEIsQ0FBQTtRQUVELE1BQU0sT0FBTyxHQUFHLE1BQU0sS0FBSyxPQUFPO1lBQ2pDLENBQUMsQ0FBQyxJQUFBLHdDQUFrQixHQUFFO1lBQ3RCLENBQUMsQ0FBQyxJQUFBLHlDQUFtQixFQUFDO2dCQUNyQixPQUFPLEVBQUUsMkNBQWtDO2FBQzNDLENBQUMsQ0FBQTtRQUVILFdBQVcsQ0FBQyxTQUFTLENBQUMsR0FBRyxjQUFjLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDakQsU0FBUztZQUNULE9BQU87U0FDUCxDQUFDLENBQUE7SUFDSCxDQUFDO0lBRUQsT0FBTyxXQUFXLENBQUMsU0FBUyxDQUFDLENBQUE7QUFDOUIsQ0FBQztBQUVELFNBQVMsZ0NBQWdDLENBQ3hDLFNBQThCLEVBQzlCLEVBQ0MsR0FBRyxFQUNILEVBQUUsRUFDRixVQUFVLEVBQ1YsaUJBQWlCLEVBQ2pCLFlBQVksR0FDYztJQUUzQixNQUFNLFNBQVMsR0FBRyxpQkFBaUIsQ0FBQyxTQUFTLENBQUMsQ0FBQTtJQUU5QyxNQUFNLFFBQVEsR0FBRyxZQUFZLEdBQUcsU0FBUyxDQUFBO0lBQ3pDLE1BQU0sTUFBTSxHQUFHLENBQUMsWUFBWSxHQUFHLENBQUMsQ0FBQyxHQUFHLFNBQVMsQ0FBQTtJQUM3QyxNQUFNLGVBQWUsR0FBRyxVQUFVO1NBQ2hDLEtBQUssQ0FBQyxRQUFRLEVBQUUsTUFBTSxDQUFDLENBQUE7SUFDekIsTUFBTSxjQUFjLEdBQUcsaUJBQWlCO1NBQ3RDLEtBQUssQ0FBQyxRQUFRLEVBQUUsTUFBTSxDQUFDLENBQUE7SUFDekIsSUFBRyxJQUFBLDRCQUFlLEVBQUMsY0FBYyxDQUFDLEVBQUUsQ0FBQztRQUNwQyxPQUFNO0lBQ1AsQ0FBQztJQUVELDZDQUE2QztJQUM3QywwQ0FBMEM7SUFDMUMsdURBQXVEO0lBQ3ZELDZDQUE2QztJQUM3QyxLQUFJLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBQyxDQUFDLEdBQUcsZUFBZSxDQUFDLE1BQU0sRUFBQyxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBQzlDLElBQUcsY0FBYyxDQUFDLENBQUMsQ0FBQyxLQUFLLGdDQUFtQixFQUFFLENBQUM7WUFDOUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxHQUFHLGdDQUFtQixDQUFBO1FBQ3pDLENBQUM7SUFDRixDQUFDO0lBRUQsT0FBTztRQUNOLFFBQVE7UUFDUixpQkFBaUIsRUFBRSxjQUFjO1FBQ2pDLFlBQVksRUFBRSxFQUFFLEdBQUcsRUFBRTtRQUNyQixXQUFXLEVBQUUsRUFBRSxVQUFVLEVBQUUsZUFBZSxFQUFFLEVBQUUsRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUFFO0tBQ3RFLENBQUE7QUFDRixDQUFDIn0=
418
+ /**
419
+ * Get the ideal location to generate a ZK proof for a TOPRF block.
420
+ * Ideally it should be put into a slice that's a divisor of the chunk size,
421
+ * as that'll minimize the number of proofs that need to be generated.
422
+ * @returns the offset in bytes
423
+ */
424
+ function getIdealOffsetForToprfBlock(alg, { dataLocation }) {
425
+ const chunkSizeBytes = getChunkSizeBytes(alg);
426
+ const offsetChunks = Math.floor(dataLocation.fromIndex / chunkSizeBytes) * chunkSizeBytes;
427
+ const endOffsetChunks = Math.floor((dataLocation.fromIndex + dataLocation.length) / chunkSizeBytes);
428
+ // happy case -- the OPRF block fits into a single chunk, that's a
429
+ // divisor of the chunk size
430
+ if (endOffsetChunks === offsetChunks) {
431
+ return offsetChunks * chunkSizeBytes;
432
+ }
433
+ const blockSizeBytes = (0, zk_symmetric_crypto_1.getBlockSizeBytes)(alg);
434
+ const offsetBytes = Math.floor(dataLocation.fromIndex / blockSizeBytes) * blockSizeBytes;
435
+ if ((dataLocation.fromIndex + dataLocation.length) - offsetBytes
436
+ > chunkSizeBytes) {
437
+ throw new error_1.AttestorError('ERROR_BAD_REQUEST', 'OPRF data cannot fit into a single chunk');
438
+ }
439
+ return offsetBytes;
440
+ }
441
+ function sortSlices(slices) {
442
+ return slices.sort((a, b) => a.fromIndex - b.fromIndex);
443
+ }
444
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiemsuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMvemsudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUErRUEsb0RBZ1FDO0FBS0Qsd0NBc0tDO0FBMEJELHNEQThCQztBQUVELDBEQThCQztBQUVELDBDQVVDO0FBR0Qsd0NBVUM7QUEzbUJELDhDQUErRztBQUMvRyw4RUFleUQ7QUFDekQsdUNBQStHO0FBQy9HLHVDQUEwSDtBQUUxSCx1Q0FBaUU7QUFDakUsMkNBQStDO0FBQy9DLGlEQUFrSDtBQUNsSCw2Q0FBbUQ7QUFDbkQscURBQWtIO0FBa0RsSCxNQUFNLGNBQWMsR0FBRyxDQUFDLENBQ3ZCLElBQUEsb0JBQWMsRUFBQyxnQkFBZ0IsQ0FBQztPQUM3QiwrQkFBc0IsQ0FDekIsQ0FBQTtBQUVNLEtBQUssVUFBVSxvQkFBb0IsQ0FDekMsRUFDQyxXQUFXLEVBQ1gsYUFBYSxFQUNiLE1BQU0sR0FBRyxlQUFNLEVBQ2Ysa0JBQWtCLEdBQUcsY0FBYyxFQUNuQyxXQUFXLEVBQ1gsUUFBUSxHQUFHLFNBQVMsRUFDQztJQUd0QixNQUFNLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxHQUFHLE1BQU0sTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFBO0lBQ25ELE1BQU0sT0FBTyxHQUFHLElBQUksTUFBTSxDQUFDO1FBQzFCLFdBQVcsRUFBRSxrQkFBa0I7UUFDL0IsU0FBUyxFQUFFLElBQUk7S0FDZixDQUFDLENBQUE7SUFFRixNQUFNLGNBQWMsR0FBc0IsRUFBRSxDQUFBO0lBRTVDLE1BQU0sR0FBRyxDQUFDLE1BQU0sSUFBSSxlQUFNLENBQUMsQ0FBQyxLQUFLLENBQUMsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFBO0lBQ3ZFLElBQUksYUFBYSxHQUFHLENBQUMsQ0FBQTtJQUVyQixPQUFPO1FBQ047Ozs7O1dBS0c7UUFDSCxLQUFLLENBQUMsZ0JBQWdCLENBQ3JCLE1B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