@arcium-hq/client 0.9.2 → 0.9.3

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 (92) hide show
  1. package/build/index.cjs +15 -3
  2. package/build/index.mjs +15 -4
  3. package/build/types/arcis/arcisModule.d.ts +26 -0
  4. package/build/types/arcis/arcisModule.d.ts.map +1 -0
  5. package/build/types/arcis/arcisType.d.ts +76 -0
  6. package/build/types/arcis/arcisType.d.ts.map +1 -0
  7. package/build/types/arcis/packer.d.ts +63 -0
  8. package/build/types/arcis/packer.d.ts.map +1 -0
  9. package/build/types/arcis/packing.d.ts +33 -0
  10. package/build/types/arcis/packing.d.ts.map +1 -0
  11. package/build/types/callback.d.ts +21 -0
  12. package/build/types/callback.d.ts.map +1 -0
  13. package/build/types/constants.d.ts +101 -0
  14. package/build/types/constants.d.ts.map +1 -0
  15. package/build/types/cryptography/aes128Cipher.d.ts +14 -0
  16. package/build/types/cryptography/aes128Cipher.d.ts.map +1 -0
  17. package/build/types/cryptography/aes192Cipher.d.ts +14 -0
  18. package/build/types/cryptography/aes192Cipher.d.ts.map +1 -0
  19. package/build/types/cryptography/aes256Cipher.d.ts +14 -0
  20. package/build/types/cryptography/aes256Cipher.d.ts.map +1 -0
  21. package/build/types/cryptography/aesCtrCipher.d.ts +36 -0
  22. package/build/types/cryptography/aesCtrCipher.d.ts.map +1 -0
  23. package/build/types/cryptography/arcisEd25519.d.ts +8 -0
  24. package/build/types/cryptography/arcisEd25519.d.ts.map +1 -0
  25. package/build/types/cryptography/cSplRescueCipher.d.ts +29 -0
  26. package/build/types/cryptography/cSplRescueCipher.d.ts.map +1 -0
  27. package/build/types/cryptography/cryptography.d.ts +38 -0
  28. package/build/types/cryptography/cryptography.d.ts.map +1 -0
  29. package/build/types/cryptography/hkdf.d.ts +37 -0
  30. package/build/types/cryptography/hkdf.d.ts.map +1 -0
  31. package/build/types/cryptography/hmac.d.ts +22 -0
  32. package/build/types/cryptography/hmac.d.ts.map +1 -0
  33. package/build/types/cryptography/rescueCipher.d.ts +29 -0
  34. package/build/types/cryptography/rescueCipher.d.ts.map +1 -0
  35. package/build/types/cryptography/rescueCipherCommon.d.ts +45 -0
  36. package/build/types/cryptography/rescueCipherCommon.d.ts.map +1 -0
  37. package/build/types/cryptography/rescueDesc.d.ts +80 -0
  38. package/build/types/cryptography/rescueDesc.d.ts.map +1 -0
  39. package/build/types/cryptography/rescuePrimeHash.d.ts +23 -0
  40. package/build/types/cryptography/rescuePrimeHash.d.ts.map +1 -0
  41. package/build/types/ctUtils.d.ts +50 -0
  42. package/build/types/ctUtils.d.ts.map +1 -0
  43. package/build/{index.d.ts → types/idl/arcium.d.ts} +5 -901
  44. package/build/types/idl/arcium.d.ts.map +1 -0
  45. package/build/types/idl/arcium_staking.d.ts +4589 -0
  46. package/build/types/idl/arcium_staking.d.ts.map +1 -0
  47. package/build/types/idl/index.d.ts +15 -0
  48. package/build/types/idl/index.d.ts.map +1 -0
  49. package/build/types/index.d.ts +33 -0
  50. package/build/types/index.d.ts.map +1 -0
  51. package/build/types/localEnv.d.ts +15 -0
  52. package/build/types/localEnv.d.ts.map +1 -0
  53. package/build/types/matrix.d.ts +39 -0
  54. package/build/types/matrix.d.ts.map +1 -0
  55. package/build/types/onchain.d.ts +223 -0
  56. package/build/types/onchain.d.ts.map +1 -0
  57. package/build/types/pda.d.ts +89 -0
  58. package/build/types/pda.d.ts.map +1 -0
  59. package/build/types/utils.d.ts +65 -0
  60. package/build/types/utils.d.ts.map +1 -0
  61. package/package.json +6 -6
  62. package/src/arcis/arcisModule.ts +39 -0
  63. package/src/arcis/arcisType.ts +303 -0
  64. package/src/arcis/packer.ts +152 -0
  65. package/src/arcis/packing.ts +115 -0
  66. package/src/callback.ts +101 -0
  67. package/src/constants.ts +104 -0
  68. package/src/cryptography/aes128Cipher.ts +16 -0
  69. package/src/cryptography/aes192Cipher.ts +16 -0
  70. package/src/cryptography/aes256Cipher.ts +16 -0
  71. package/src/cryptography/aesCtrCipher.ts +84 -0
  72. package/src/cryptography/arcisEd25519.ts +96 -0
  73. package/src/cryptography/cSplRescueCipher.ts +41 -0
  74. package/src/cryptography/cryptography.ts +82 -0
  75. package/src/cryptography/hkdf.ts +58 -0
  76. package/src/cryptography/hmac.ts +66 -0
  77. package/src/cryptography/rescueCipher.ts +41 -0
  78. package/src/cryptography/rescueCipherCommon.ts +211 -0
  79. package/src/cryptography/rescueDesc.ts +492 -0
  80. package/src/cryptography/rescuePrimeHash.ts +72 -0
  81. package/src/ctUtils.ts +124 -0
  82. package/src/idl/arcium.json +12281 -0
  83. package/src/idl/arcium.ts +12287 -0
  84. package/src/idl/arcium_staking.json +4582 -0
  85. package/src/idl/arcium_staking.ts +4588 -0
  86. package/src/idl/index.ts +20 -0
  87. package/src/index.ts +32 -0
  88. package/src/localEnv.ts +39 -0
  89. package/src/matrix.ts +215 -0
  90. package/src/onchain.ts +1020 -0
  91. package/src/pda.ts +203 -0
  92. package/src/utils.ts +126 -0
@@ -0,0 +1,58 @@
1
+ import { HMACRescuePrime } from './hmac.js';
2
+ import { FpField } from './rescueDesc.js';
3
+
4
+ /**
5
+ * HKDF (HMAC-based Extract-and-Expand Key Derivation Function) using the Rescue-Prime hash function.
6
+ * Follows RFC 5869. Only supports L = HashLen.
7
+ */
8
+ export class HKDFRescuePrime {
9
+ hmac: HMACRescuePrime;
10
+
11
+ /**
12
+ * Construct a new HKDFRescuePrime instance.
13
+ */
14
+ constructor(field: FpField) {
15
+ this.hmac = new HMACRescuePrime(field);
16
+ }
17
+
18
+ /**
19
+ * HKDF-Extract step: derive a pseudorandom key (PRK) from the input keying material (IKM) and salt.
20
+ * @param salt - Salt value as an array of bigints.
21
+ * @param ikm - Input keying material as an array of bigints.
22
+ * @returns Pseudorandom key (PRK) as an array of bigints.
23
+ */
24
+ extract(salt: bigint[], ikm: bigint[]): bigint[] {
25
+ // Create effective salt to avoid mutating input parameter
26
+ const effectiveSalt = salt.length === 0
27
+ ? Array(this.hmac.hasher.rate).fill(0n)
28
+ : salt;
29
+ return this.hmac.digest(effectiveSalt, ikm);
30
+ }
31
+
32
+ /**
33
+ * HKDF-Expand step: expand the pseudorandom key (PRK) with info to produce output keying material (OKM).
34
+ * Only supports L = HashLen = 5, i.e. N = 1.
35
+ * @param prk - Pseudorandom key as an array of bigints.
36
+ * @param info - Context and application specific information as an array of bigints.
37
+ * @returns Output keying material (OKM) as an array of bigints.
38
+ */
39
+ expand(prk: bigint[], info: bigint[]): bigint[] {
40
+ // we only support L = HashLen = 5, i.e. N = 1
41
+ // message = empty string | info | 0x01
42
+ // Create a copy to avoid mutating the input parameter
43
+ const infoWithCounter = [...info, 1n];
44
+ return this.hmac.digest(prk, infoWithCounter);
45
+ }
46
+
47
+ /**
48
+ * Perform the full HKDF (extract and expand) to derive output keying material (OKM).
49
+ * @param salt - Salt value as an array of bigints.
50
+ * @param ikm - Input keying material as an array of bigints.
51
+ * @param info - Context and application specific information as an array of bigints.
52
+ * @returns Output keying material (OKM) as an array of bigints.
53
+ */
54
+ okm(salt: bigint[], ikm: bigint[], info: bigint[]): bigint[] {
55
+ const prk = this.extract(salt, ikm);
56
+ return this.expand(prk, info);
57
+ }
58
+ }
@@ -0,0 +1,66 @@
1
+ import { deserializeLE } from './cryptography.js';
2
+ import { FpField } from './rescueDesc.js';
3
+ import { RescuePrimeHash } from './rescuePrimeHash.js';
4
+
5
+ /**
6
+ * HMAC inner padding constant (RFC 2104).
7
+ * Added to each key element for the inner hash computation.
8
+ * @see https://datatracker.ietf.org/doc/html/rfc2104
9
+ */
10
+ const HMAC_IPAD_BYTE = 0x36;
11
+
12
+ /**
13
+ * HMAC outer padding constant (RFC 2104).
14
+ * Added to each key element for the outer hash computation.
15
+ * @see https://datatracker.ietf.org/doc/html/rfc2104
16
+ */
17
+ const HMAC_OPAD_BYTE = 0x5c;
18
+
19
+ /**
20
+ * HMACRescuePrime provides a message authentication code (MAC) using the Rescue-Prime hash function.
21
+ * We refer to https://datatracker.ietf.org/doc/html/rfc2104 for more details.
22
+ */
23
+ export class HMACRescuePrime {
24
+ hasher: RescuePrimeHash;
25
+
26
+ /**
27
+ * Construct a new HMACRescuePrime instance.
28
+ */
29
+ constructor(field: FpField) {
30
+ this.hasher = new RescuePrimeHash(field);
31
+ }
32
+
33
+ /**
34
+ * Compute the HMAC digest of a message with a given key using Rescue-Prime.
35
+ * @param key - Key as an array of bigints.
36
+ * @param message - Message as an array of bigints.
37
+ * @returns HMAC digest as an array of bigints.
38
+ * @throws Error if the key is shorter than the hash function's digest length or longer than the hash function's rate.
39
+ */
40
+ digest(key: bigint[], message: bigint[]): bigint[] {
41
+ // We follow https://datatracker.ietf.org/doc/html/rfc2104, though since Rescue-Prime is not based
42
+ // on the Merkle-Damgard construction we cannot have an exact anology between the
43
+ // parameters. For our purpose, we set B = hasher.rate and L = hasher.digestLength.
44
+ if (key.length < this.hasher.digestLength || key.length > this.hasher.rate) {
45
+ throw Error(`length of key is supposed to be at least the hash function's digest length and at most the hash function's rate (found ${key.length}, ${this.hasher.digestLength} and ${this.hasher.rate})`);
46
+ }
47
+ // 32-byte array size is for field element deserialization, not HMAC block size
48
+ const ipad = deserializeLE(new Uint8Array(32).fill(HMAC_IPAD_BYTE));
49
+ const opad = deserializeLE(new Uint8Array(32).fill(HMAC_OPAD_BYTE));
50
+ // the key is first extended to length B
51
+ // Create a copy to avoid mutating the input parameter
52
+ const paddedKey = [...key];
53
+ const offset = this.hasher.rate - paddedKey.length;
54
+ for (let i = 0; i < offset; ++i) {
55
+ paddedKey.push(0n);
56
+ }
57
+ // inner padding
58
+ const keyPlusIpad = paddedKey.map((k) => k + ipad);
59
+ keyPlusIpad.push(...message);
60
+ const innerDigest = this.hasher.digest(keyPlusIpad);
61
+ // outer padding
62
+ const keyPlusOpad = paddedKey.map((k) => k + opad);
63
+ keyPlusOpad.push(...innerDigest);
64
+ return this.hasher.digest(keyPlusOpad);
65
+ }
66
+ }
@@ -0,0 +1,41 @@
1
+ import {
2
+ CURVE25519_BASE_FIELD,
3
+ } from './rescueDesc.js';
4
+ import { RescueCipherCommon } from './rescueCipherCommon.js';
5
+
6
+ /**
7
+ * The Rescue cipher over Curve25519's base field in Counter (CTR) mode, with a fixed block size m = 5.
8
+ * See: https://tosc.iacr.org/index.php/ToSC/article/view/8695/8287
9
+ */
10
+ export class RescueCipher {
11
+ cipher: RescueCipherCommon;
12
+
13
+ /**
14
+ * Construct a RescueCipher instance using a shared secret.
15
+ * The key is derived using RescuePrimeHash and used to initialize the RescueDesc.
16
+ * @param sharedSecret - Shared secret to derive the cipher key from.
17
+ */
18
+ constructor(sharedSecret: Uint8Array) {
19
+ this.cipher = new RescueCipherCommon(sharedSecret, CURVE25519_BASE_FIELD);
20
+ }
21
+
22
+ /**
23
+ * Encrypt the plaintext vector in Counter (CTR) mode and serialize each block.
24
+ * @param plaintext - Array of plaintext bigints to encrypt.
25
+ * @param nonce - 16-byte nonce for CTR mode.
26
+ * @returns Ciphertext as an array of arrays of numbers (each 32 bytes).
27
+ */
28
+ encrypt(plaintext: bigint[], nonce: Uint8Array): number[][] {
29
+ return this.cipher.encrypt(plaintext, nonce);
30
+ }
31
+
32
+ /**
33
+ * Deserialize and decrypt the ciphertext vector in Counter (CTR) mode.
34
+ * @param ciphertext - Array of arrays of numbers (each 32 bytes) to decrypt.
35
+ * @param nonce - 16-byte nonce for CTR mode.
36
+ * @returns Decrypted plaintext as an array of bigints.
37
+ */
38
+ decrypt(ciphertext: number[][], nonce: Uint8Array): bigint[] {
39
+ return this.cipher.decrypt(ciphertext, nonce);
40
+ }
41
+ }
@@ -0,0 +1,211 @@
1
+ import {
2
+ RescueDesc,
3
+ toVec,
4
+ FpField,
5
+ CURVE25519_BASE_FIELD,
6
+ } from './rescueDesc.js';
7
+ import { deserializeLE, serializeLE } from './cryptography.js';
8
+ import { Matrix } from '../matrix.js';
9
+ import { getBinSize } from '../utils.js';
10
+ import {
11
+ ctLt,
12
+ ctAdd,
13
+ ctSelect,
14
+ ctSub,
15
+ ctSignBit,
16
+ verifyBinSize,
17
+ } from '../ctUtils.js';
18
+ import { RescuePrimeHash } from './rescuePrimeHash.js';
19
+
20
+ /**
21
+ * Block size m for Rescue cipher operations.
22
+ * Rescue operates on 5-element blocks of field elements.
23
+ */
24
+ const RESCUE_CIPHER_BLOCK_SIZE = 5;
25
+
26
+ /**
27
+ * The Rescue cipher in Counter (CTR) mode, with a fixed block size m = 5.
28
+ * See: https://tosc.iacr.org/index.php/ToSC/article/view/8695/8287
29
+ */
30
+ export class RescueCipherCommon {
31
+ desc: RescueDesc;
32
+
33
+ /**
34
+ * Construct a RescueCipherCommon instance using a shared secret.
35
+ * The key is derived using RescuePrimeHash and used to initialize the RescueDesc.
36
+ * @param sharedSecret - Shared secret to derive the cipher key from.
37
+ */
38
+ constructor(sharedSecret: Uint8Array, field: FpField) {
39
+ if (sharedSecret.length != 32) {
40
+ throw Error(`sharedSecret must be of length 32 (found ${sharedSecret.length})`);
41
+ }
42
+
43
+ const hasher = new RescuePrimeHash(field);
44
+
45
+ // In case `field` is different from CURVE25519_BASE_FIELD we need to injectively map sharedSecret
46
+ // to a vector of elements over `field`.
47
+ const converted = [];
48
+ if (field === CURVE25519_BASE_FIELD) {
49
+ converted.push(deserializeLE(sharedSecret));
50
+ }
51
+ else {
52
+ // We chunk sharedSecret by field.BYTES - 1 and convert.
53
+ const chunkSize = field.BYTES - 1;
54
+ const nChunks = Math.ceil(sharedSecret.length / chunkSize);
55
+ for (let i = 0; i < nChunks; ++i) {
56
+ converted.push(deserializeLE(sharedSecret.slice(i * chunkSize, (i + 1) * chunkSize)));
57
+ }
58
+ }
59
+
60
+ // We follow [Section 4, Option 1.](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Cr2.pdf).
61
+ // For our choice of hash function, we have:
62
+ // - H_outputBits = hasher.digestLength = RESCUE_CIPHER_BLOCK_SIZE
63
+ // - max_H_inputBits = arbitrarily long, as the Rescue-Prime hash function is built upon the
64
+ // sponge construction
65
+ // - L = RESCUE_CIPHER_BLOCK_SIZE.
66
+
67
+ // Build the vector `counter || Z || FixedInfo` (we only have i = 1, since reps = 1).
68
+ // For the FixedInfo we simply take L.
69
+ const counter = [1n, ...converted, BigInt(RESCUE_CIPHER_BLOCK_SIZE)];
70
+ const rescueKey = hasher.digest(counter);
71
+ this.desc = new RescueDesc(
72
+ field,
73
+ { kind: 'cipher', key: rescueKey },
74
+ );
75
+ }
76
+
77
+ /**
78
+ * Encrypt the plaintext vector in Counter (CTR) mode (raw, returns bigints).
79
+ * @param plaintext - Array of plaintext bigints to encrypt.
80
+ * @param nonce - 16-byte nonce for CTR mode.
81
+ * @returns Ciphertext as an array of bigints.
82
+ * @throws Error if the nonce is not 16 bytes long.
83
+ */
84
+ encrypt_raw(plaintext: bigint[], nonce: Uint8Array): bigint[] {
85
+ if (nonce.length !== 16) {
86
+ throw Error(`nonce must be of length 16 (found ${nonce.length})`);
87
+ }
88
+ const binSize = getBinSize(this.desc.field.ORDER - 1n);
89
+
90
+ function encryptBatch(desc: RescueDesc, ptxt: bigint[], cntr: bigint[]): bigint[] {
91
+ if (cntr.length !== RESCUE_CIPHER_BLOCK_SIZE) {
92
+ throw Error(`counter must be of length ${RESCUE_CIPHER_BLOCK_SIZE} (found ${cntr.length})`);
93
+ }
94
+ const encryptedCounter = desc.permute(new Matrix(desc.field, toVec(cntr)));
95
+ const ciphertext = [];
96
+ for (let i = 0; i < ptxt.length; ++i) {
97
+ if (!verifyBinSize(ptxt[i], binSize - 1n) || ctSignBit(ptxt[i], binSize) || !ctLt(ptxt[i], desc.field.ORDER, binSize)) {
98
+ throw Error(`plaintext must be non-negative and less than ${desc.field.ORDER}`);
99
+ }
100
+ const sum = ctAdd(ptxt[i], encryptedCounter.data[i][0], binSize);
101
+ ciphertext.push(ctSelect(ctLt(sum, desc.field.ORDER, binSize), sum, ctSub(sum, desc.field.ORDER, binSize), binSize));
102
+ }
103
+ return ciphertext;
104
+ }
105
+
106
+ const nBlocks = Math.ceil(plaintext.length / RESCUE_CIPHER_BLOCK_SIZE);
107
+ const counter = getCounter(deserializeLE(nonce), nBlocks);
108
+
109
+ const ciphertext = [];
110
+ for (let i = 0; i < nBlocks; ++i) {
111
+ const cnt = RESCUE_CIPHER_BLOCK_SIZE * i;
112
+ const newCiphertext = encryptBatch(
113
+ this.desc,
114
+ plaintext.slice(cnt, Math.min(cnt + RESCUE_CIPHER_BLOCK_SIZE, plaintext.length)),
115
+ counter.slice(cnt, cnt + RESCUE_CIPHER_BLOCK_SIZE),
116
+ );
117
+ for (let j = 0; j < newCiphertext.length; ++j) {
118
+ ciphertext.push(newCiphertext[j]);
119
+ }
120
+ }
121
+ return ciphertext;
122
+ }
123
+
124
+ /**
125
+ * Encrypt the plaintext vector in Counter (CTR) mode and serialize each block.
126
+ * @param plaintext - Array of plaintext bigints to encrypt.
127
+ * @param nonce - 16-byte nonce for CTR mode.
128
+ * @returns Ciphertext as an array of arrays of numbers (each 32 bytes).
129
+ */
130
+ encrypt(plaintext: bigint[], nonce: Uint8Array): number[][] {
131
+ return this.encrypt_raw(plaintext, nonce).map((c) => Array.from(serializeLE(c, 32)));
132
+ }
133
+
134
+ /**
135
+ * Decrypt the ciphertext vector in Counter (CTR) mode (raw, expects bigints).
136
+ * @param ciphertext - Array of ciphertext bigints to decrypt.
137
+ * @param nonce - 16-byte nonce for CTR mode.
138
+ * @returns Decrypted plaintext as an array of bigints.
139
+ * @throws Error if the nonce is not 16 bytes long.
140
+ */
141
+ decrypt_raw(ciphertext: bigint[], nonce: Uint8Array): bigint[] {
142
+ if (nonce.length !== 16) {
143
+ throw Error(`nonce must be of length 16 (found ${nonce.length})`);
144
+ }
145
+ const binSize = getBinSize(this.desc.field.ORDER - 1n);
146
+
147
+ function decryptBatch(desc: RescueDesc, ctxt: bigint[], cntr: bigint[]): bigint[] {
148
+ if (cntr.length !== RESCUE_CIPHER_BLOCK_SIZE) {
149
+ throw Error(`counter must be of length ${RESCUE_CIPHER_BLOCK_SIZE} (found ${cntr.length})`);
150
+ }
151
+ const encryptedCounter = desc.permute(new Matrix(desc.field, toVec(cntr)));
152
+ const decrypted = [];
153
+ for (let i = 0; i < ctxt.length; ++i) {
154
+ const diff = ctSub(ctxt[i], encryptedCounter.data[i][0], binSize);
155
+ decrypted.push(ctSelect(ctSignBit(diff, binSize), ctAdd(diff, desc.field.ORDER, binSize), diff, binSize));
156
+ }
157
+ return decrypted;
158
+ }
159
+
160
+ const nBlocks = Math.ceil(ciphertext.length / RESCUE_CIPHER_BLOCK_SIZE);
161
+ const counter = getCounter(deserializeLE(nonce), nBlocks);
162
+
163
+ const decrypted = [];
164
+ for (let i = 0; i < nBlocks; ++i) {
165
+ const cnt = RESCUE_CIPHER_BLOCK_SIZE * i;
166
+ const newDecrypted = decryptBatch(
167
+ this.desc,
168
+ ciphertext.slice(cnt, Math.min(cnt + RESCUE_CIPHER_BLOCK_SIZE, ciphertext.length)),
169
+ counter.slice(cnt, cnt + RESCUE_CIPHER_BLOCK_SIZE),
170
+ );
171
+ for (let j = 0; j < newDecrypted.length; ++j) {
172
+ decrypted.push(newDecrypted[j]);
173
+ }
174
+ }
175
+ return decrypted;
176
+ }
177
+
178
+ /**
179
+ * Deserialize and decrypt the ciphertext vector in Counter (CTR) mode.
180
+ * @param ciphertext - Array of arrays of numbers (each 32 bytes) to decrypt.
181
+ * @param nonce - 16-byte nonce for CTR mode.
182
+ * @returns Decrypted plaintext as an array of bigints.
183
+ */
184
+ decrypt(ciphertext: number[][], nonce: Uint8Array): bigint[] {
185
+ return this.decrypt_raw(ciphertext.map((c) => {
186
+ if (c.length !== 32) {
187
+ throw Error(`ciphertext must be of length 32 (found ${c.length})`);
188
+ }
189
+ return deserializeLE(Uint8Array.from(c));
190
+ }), nonce);
191
+ }
192
+ }
193
+
194
+ /**
195
+ * Generate the counter values for Rescue cipher CTR mode.
196
+ * @param nonce - Initial nonce as a bigint.
197
+ * @param nBlocks - Number of blocks to generate counters for.
198
+ * @returns Array of counter values as bigints.
199
+ */
200
+ function getCounter(nonce: bigint, nBlocks: number): bigint[] {
201
+ const counter = [];
202
+ for (let i = 0n; i < nBlocks; ++i) {
203
+ counter.push(nonce);
204
+ counter.push(i);
205
+ // Pad to RESCUE_CIPHER_BLOCK_SIZE elements per counter block
206
+ for (let j = 2; j < RESCUE_CIPHER_BLOCK_SIZE; ++j) {
207
+ counter.push(0n);
208
+ }
209
+ }
210
+ return counter;
211
+ }