@theqrl/dilithium5 0.1.0 → 0.2.0

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.
@@ -1,7 +1,5 @@
1
- import pkg__default from 'randombytes';
2
- export * from 'randombytes';
3
- import { SHAKE } from 'sha3';
4
- export { SHAKE } from 'sha3';
1
+ import { shake128, shake256 } from '@noble/hashes/sha3';
2
+ import pkg from 'randombytes';
5
3
 
6
4
  const Shake128Rate = 168;
7
5
  const Shake256Rate = 136;
@@ -10,6 +8,7 @@ const Stream256BlockBytes = Shake256Rate;
10
8
 
11
9
  const SeedBytes = 32;
12
10
  const CRHBytes = 64;
11
+ const TRBytes = 64;
13
12
  const N = 256;
14
13
  const Q = 8380417;
15
14
  const QInv = 58728449;
@@ -33,7 +32,7 @@ const PolyW1PackedBytes = 128;
33
32
 
34
33
  const CryptoPublicKeyBytes = SeedBytes + K * PolyT1PackedBytes;
35
34
  const CryptoSecretKeyBytes =
36
- 3 * SeedBytes + L * PolyETAPackedBytes + K * PolyETAPackedBytes + K * PolyT0PackedBytes;
35
+ 2 * SeedBytes + TRBytes + L * PolyETAPackedBytes + K * PolyETAPackedBytes + K * PolyT0PackedBytes;
37
36
  const CryptoBytes = SeedBytes + L * PolyZPackedBytes + PolyVecHPackedBytes;
38
37
 
39
38
  const PolyUniformNBlocks = Math.floor((768 + Stream128BlockBytes - 1) / Stream128BlockBytes);
@@ -64,452 +63,65 @@ const zetas = [
64
63
  -1362209, 3937738, 1400424, -846154, 1976782,
65
64
  ];
66
65
 
67
- const NRounds = 24;
68
-
69
- const KeccakFRoundConstants = BigUint64Array.from([
70
- 0x0000000000000001n,
71
- 0x0000000000008082n,
72
- 0x800000000000808an,
73
- 0x8000000080008000n,
74
- 0x000000000000808bn,
75
- 0x0000000080000001n,
76
- 0x8000000080008081n,
77
- 0x8000000000008009n,
78
- 0x000000000000008an,
79
- 0x0000000000000088n,
80
- 0x0000000080008009n,
81
- 0x000000008000000an,
82
- 0x000000008000808bn,
83
- 0x800000000000008bn,
84
- 0x8000000000008089n,
85
- 0x8000000000008003n,
86
- 0x8000000000008002n,
87
- 0x8000000000000080n,
88
- 0x000000000000800an,
89
- 0x800000008000000an,
90
- 0x8000000080008081n,
91
- 0x8000000000008080n,
92
- 0x0000000080000001n,
93
- 0x8000000080008008n,
94
- ]);
66
+ /**
67
+ * FIPS 202 SHAKE functions using @noble/hashes
68
+ * Provides streaming XOF (extendable output function) interface
69
+ */
95
70
 
71
+
72
+ /**
73
+ * Keccak state wrapper for @noble/hashes
74
+ * Maintains hasher instance for streaming operations
75
+ */
96
76
  class KeccakState {
97
77
  constructor() {
98
- this.s = new BigUint64Array(25);
99
- this.pos = 0;
100
- }
101
- }
102
-
103
- function ROL(a, offset) {
104
- return BigInt.asUintN(64, BigInt.asUintN(64, a << offset) ^ (a >> (64n - offset)));
105
- }
106
-
107
- function load64(x, xOffset) {
108
- let r = BigInt(0);
109
-
110
- for (let i = 0; i < 8; i++) r = BigInt.asUintN(64, r | BigInt.asUintN(64, BigInt(x[xOffset + i]) << BigInt(8 * i)));
111
-
112
- return r;
113
- }
114
-
115
- function store64(xP, xOffset, u) {
116
- const x = xP;
117
- for (let i = 0; i < 8; i++) x[xOffset + i] = Number((u >> BigInt(8 * i)) & 0xffn);
118
- }
119
-
120
- function KeccakF1600StatePermute(stateP) {
121
- const state = stateP;
122
- // copyFromState(A, state)
123
- let Aba = state[0];
124
- let Abe = state[1];
125
- let Abi = state[2];
126
- let Abo = state[3];
127
- let Abu = state[4];
128
- let Aga = state[5];
129
- let Age = state[6];
130
- let Agi = state[7];
131
- let Ago = state[8];
132
- let Agu = state[9];
133
- let Aka = state[10];
134
- let Ake = state[11];
135
- let Aki = state[12];
136
- let Ako = state[13];
137
- let Aku = state[14];
138
- let Ama = state[15];
139
- let Ame = state[16];
140
- let Ami = state[17];
141
- let Amo = state[18];
142
- let Amu = state[19];
143
- let Asa = state[20];
144
- let Ase = state[21];
145
- let Asi = state[22];
146
- let Aso = state[23];
147
- let Asu = state[24];
148
-
149
- for (let round = 0; round < NRounds; round += 2) {
150
- // prepareTheta
151
- let BCa = BigInt.asUintN(64, Aba ^ Aga ^ Aka ^ Ama ^ Asa);
152
- let BCe = BigInt.asUintN(64, Abe ^ Age ^ Ake ^ Ame ^ Ase);
153
- let BCi = BigInt.asUintN(64, Abi ^ Agi ^ Aki ^ Ami ^ Asi);
154
- let BCo = BigInt.asUintN(64, Abo ^ Ago ^ Ako ^ Amo ^ Aso);
155
- let BCu = BigInt.asUintN(64, Abu ^ Agu ^ Aku ^ Amu ^ Asu);
156
-
157
- // thetaRhoPiChiIotaPrepareTheta(round, A, E)
158
- let Da = BigInt.asUintN(64, BCu ^ ROL(BCe, 1n));
159
- let De = BigInt.asUintN(64, BCa ^ ROL(BCi, 1n));
160
- let Di = BigInt.asUintN(64, BCe ^ ROL(BCo, 1n));
161
- let Do = BigInt.asUintN(64, BCi ^ ROL(BCu, 1n));
162
- let Du = BigInt.asUintN(64, BCo ^ ROL(BCa, 1n));
163
-
164
- Aba = BigInt.asUintN(64, Aba ^ Da);
165
- BCa = Aba;
166
- Age = BigInt.asUintN(64, Age ^ De);
167
- BCe = ROL(Age, 44n);
168
- Aki = BigInt.asUintN(64, Aki ^ Di);
169
- BCi = ROL(Aki, 43n);
170
- Amo = BigInt.asUintN(64, Amo ^ Do);
171
- BCo = ROL(Amo, 21n);
172
- Asu = BigInt.asUintN(64, Asu ^ Du);
173
- BCu = ROL(Asu, 14n);
174
- let Eba = BigInt.asUintN(64, BCa ^ (~BCe & BCi));
175
- Eba = BigInt.asUintN(64, Eba ^ KeccakFRoundConstants[round]);
176
- let Ebe = BigInt.asUintN(64, BCe ^ (~BCi & BCo));
177
- let Ebi = BigInt.asUintN(64, BCi ^ (~BCo & BCu));
178
- let Ebo = BigInt.asUintN(64, BCo ^ (~BCu & BCa));
179
- let Ebu = BigInt.asUintN(64, BCu ^ (~BCa & BCe));
180
-
181
- Abo = BigInt.asUintN(64, Abo ^ Do);
182
- BCa = ROL(Abo, 28n);
183
- Agu = BigInt.asUintN(64, Agu ^ Du);
184
- BCe = ROL(Agu, 20n);
185
- Aka = BigInt.asUintN(64, Aka ^ Da);
186
- BCi = ROL(Aka, 3n);
187
- Ame = BigInt.asUintN(64, Ame ^ De);
188
- BCo = ROL(Ame, 45n);
189
- Asi = BigInt.asUintN(64, Asi ^ Di);
190
- BCu = ROL(Asi, 61n);
191
- let Ega = BigInt.asUintN(64, BCa ^ (~BCe & BCi));
192
- let Ege = BigInt.asUintN(64, BCe ^ (~BCi & BCo));
193
- let Egi = BigInt.asUintN(64, BCi ^ (~BCo & BCu));
194
- let Ego = BigInt.asUintN(64, BCo ^ (~BCu & BCa));
195
- let Egu = BigInt.asUintN(64, BCu ^ (~BCa & BCe));
196
-
197
- Abe = BigInt.asUintN(64, Abe ^ De);
198
- BCa = ROL(Abe, 1n);
199
- Agi = BigInt.asUintN(64, Agi ^ Di);
200
- BCe = ROL(Agi, 6n);
201
- Ako = BigInt.asUintN(64, Ako ^ Do);
202
- BCi = ROL(Ako, 25n);
203
- Amu = BigInt.asUintN(64, Amu ^ Du);
204
- BCo = ROL(Amu, 8n);
205
- Asa = BigInt.asUintN(64, Asa ^ Da);
206
- BCu = ROL(Asa, 18n);
207
- let Eka = BigInt.asUintN(64, BCa ^ (~BCe & BCi));
208
- let Eke = BigInt.asUintN(64, BCe ^ (~BCi & BCo));
209
- let Eki = BigInt.asUintN(64, BCi ^ (~BCo & BCu));
210
- let Eko = BigInt.asUintN(64, BCo ^ (~BCu & BCa));
211
- let Eku = BigInt.asUintN(64, BCu ^ (~BCa & BCe));
212
-
213
- Abu = BigInt.asUintN(64, Abu ^ Du);
214
- BCa = ROL(Abu, 27n);
215
- Aga = BigInt.asUintN(64, Aga ^ Da);
216
- BCe = ROL(Aga, 36n);
217
- Ake = BigInt.asUintN(64, Ake ^ De);
218
- BCi = ROL(Ake, 10n);
219
- Ami = BigInt.asUintN(64, Ami ^ Di);
220
- BCo = ROL(Ami, 15n);
221
- Aso = BigInt.asUintN(64, Aso ^ Do);
222
- BCu = ROL(Aso, 56n);
223
- let Ema = BigInt.asUintN(64, BCa ^ (~BCe & BCi));
224
- let Eme = BigInt.asUintN(64, BCe ^ (~BCi & BCo));
225
- let Emi = BigInt.asUintN(64, BCi ^ (~BCo & BCu));
226
- let Emo = BigInt.asUintN(64, BCo ^ (~BCu & BCa));
227
- let Emu = BigInt.asUintN(64, BCu ^ (~BCa & BCe));
228
-
229
- Abi = BigInt.asUintN(64, Abi ^ Di);
230
- BCa = ROL(Abi, 62n);
231
- Ago = BigInt.asUintN(64, Ago ^ Do);
232
- BCe = ROL(Ago, 55n);
233
- Aku = BigInt.asUintN(64, Aku ^ Du);
234
- BCi = ROL(Aku, 39n);
235
- Ama = BigInt.asUintN(64, Ama ^ Da);
236
- BCo = ROL(Ama, 41n);
237
- Ase = BigInt.asUintN(64, Ase ^ De);
238
- BCu = ROL(Ase, 2n);
239
- let Esa = BigInt.asUintN(64, BCa ^ (~BCe & BCi));
240
- let Ese = BigInt.asUintN(64, BCe ^ (~BCi & BCo));
241
- let Esi = BigInt.asUintN(64, BCi ^ (~BCo & BCu));
242
- let Eso = BigInt.asUintN(64, BCo ^ (~BCu & BCa));
243
- let Esu = BigInt.asUintN(64, BCu ^ (~BCa & BCe));
244
-
245
- // prepareTheta
246
- BCa = BigInt.asUintN(64, Eba ^ Ega ^ Eka ^ Ema ^ Esa);
247
- BCe = BigInt.asUintN(64, Ebe ^ Ege ^ Eke ^ Eme ^ Ese);
248
- BCi = BigInt.asUintN(64, Ebi ^ Egi ^ Eki ^ Emi ^ Esi);
249
- BCo = BigInt.asUintN(64, Ebo ^ Ego ^ Eko ^ Emo ^ Eso);
250
- BCu = BigInt.asUintN(64, Ebu ^ Egu ^ Eku ^ Emu ^ Esu);
251
-
252
- // thetaRhoPiChiIotaPrepareTheta(round+1, E, A)
253
- Da = BigInt.asUintN(64, BCu ^ ROL(BCe, 1n));
254
- De = BigInt.asUintN(64, BCa ^ ROL(BCi, 1n));
255
- Di = BigInt.asUintN(64, BCe ^ ROL(BCo, 1n));
256
- Do = BigInt.asUintN(64, BCi ^ ROL(BCu, 1n));
257
- Du = BigInt.asUintN(64, BCo ^ ROL(BCa, 1n));
258
-
259
- Eba = BigInt.asUintN(64, Eba ^ Da);
260
- BCa = Eba;
261
- Ege = BigInt.asUintN(64, Ege ^ De);
262
- BCe = ROL(Ege, 44n);
263
- Eki = BigInt.asUintN(64, Eki ^ Di);
264
- BCi = ROL(Eki, 43n);
265
- Emo = BigInt.asUintN(64, Emo ^ Do);
266
- BCo = ROL(Emo, 21n);
267
- Esu = BigInt.asUintN(64, Esu ^ Du);
268
- BCu = ROL(Esu, 14n);
269
- Aba = BigInt.asUintN(64, BCa ^ (~BCe & BCi));
270
- Aba = BigInt.asUintN(64, Aba ^ KeccakFRoundConstants[round + 1]);
271
- Abe = BigInt.asUintN(64, BCe ^ (~BCi & BCo));
272
- Abi = BigInt.asUintN(64, BCi ^ (~BCo & BCu));
273
- Abo = BigInt.asUintN(64, BCo ^ (~BCu & BCa));
274
- Abu = BigInt.asUintN(64, BCu ^ (~BCa & BCe));
275
-
276
- Ebo = BigInt.asUintN(64, Ebo ^ Do);
277
- BCa = ROL(Ebo, 28n);
278
- Egu = BigInt.asUintN(64, Egu ^ Du);
279
- BCe = ROL(Egu, 20n);
280
- Eka = BigInt.asUintN(64, Eka ^ Da);
281
- BCi = ROL(Eka, 3n);
282
- Eme = BigInt.asUintN(64, Eme ^ De);
283
- BCo = ROL(Eme, 45n);
284
- Esi = BigInt.asUintN(64, Esi ^ Di);
285
- BCu = ROL(Esi, 61n);
286
- Aga = BigInt.asUintN(64, BCa ^ (~BCe & BCi));
287
- Age = BigInt.asUintN(64, BCe ^ (~BCi & BCo));
288
- Agi = BigInt.asUintN(64, BCi ^ (~BCo & BCu));
289
- Ago = BigInt.asUintN(64, BCo ^ (~BCu & BCa));
290
- Agu = BigInt.asUintN(64, BCu ^ (~BCa & BCe));
291
-
292
- Ebe = BigInt.asUintN(64, Ebe ^ De);
293
- BCa = ROL(Ebe, 1n);
294
- Egi = BigInt.asUintN(64, Egi ^ Di);
295
- BCe = ROL(Egi, 6n);
296
- Eko = BigInt.asUintN(64, Eko ^ Do);
297
- BCi = ROL(Eko, 25n);
298
- Emu = BigInt.asUintN(64, Emu ^ Du);
299
- BCo = ROL(Emu, 8n);
300
- Esa = BigInt.asUintN(64, Esa ^ Da);
301
- BCu = ROL(Esa, 18n);
302
- Aka = BigInt.asUintN(64, BCa ^ (~BCe & BCi));
303
- Ake = BigInt.asUintN(64, BCe ^ (~BCi & BCo));
304
- Aki = BigInt.asUintN(64, BCi ^ (~BCo & BCu));
305
- Ako = BigInt.asUintN(64, BCo ^ (~BCu & BCa));
306
- Aku = BigInt.asUintN(64, BCu ^ (~BCa & BCe));
307
-
308
- Ebu = BigInt.asUintN(64, Ebu ^ Du);
309
- BCa = ROL(Ebu, 27n);
310
- Ega = BigInt.asUintN(64, Ega ^ Da);
311
- BCe = ROL(Ega, 36n);
312
- Eke = BigInt.asUintN(64, Eke ^ De);
313
- BCi = ROL(Eke, 10n);
314
- Emi = BigInt.asUintN(64, Emi ^ Di);
315
- BCo = ROL(Emi, 15n);
316
- Eso = BigInt.asUintN(64, Eso ^ Do);
317
- BCu = ROL(Eso, 56n);
318
- Ama = BigInt.asUintN(64, BCa ^ (~BCe & BCi));
319
- Ame = BigInt.asUintN(64, BCe ^ (~BCi & BCo));
320
- Ami = BigInt.asUintN(64, BCi ^ (~BCo & BCu));
321
- Amo = BigInt.asUintN(64, BCo ^ (~BCu & BCa));
322
- Amu = BigInt.asUintN(64, BCu ^ (~BCa & BCe));
323
-
324
- Ebi = BigInt.asUintN(64, Ebi ^ Di);
325
- BCa = ROL(Ebi, 62n);
326
- Ego = BigInt.asUintN(64, Ego ^ Do);
327
- BCe = ROL(Ego, 55n);
328
- Eku = BigInt.asUintN(64, Eku ^ Du);
329
- BCi = ROL(Eku, 39n);
330
- Ema = BigInt.asUintN(64, Ema ^ Da);
331
- BCo = ROL(Ema, 41n);
332
- Ese = BigInt.asUintN(64, Ese ^ De);
333
- BCu = ROL(Ese, 2n);
334
- Asa = BigInt.asUintN(64, BCa ^ (~BCe & BCi));
335
- Ase = BigInt.asUintN(64, BCe ^ (~BCi & BCo));
336
- Asi = BigInt.asUintN(64, BCi ^ (~BCo & BCu));
337
- Aso = BigInt.asUintN(64, BCo ^ (~BCu & BCa));
338
- Asu = BigInt.asUintN(64, BCu ^ (~BCa & BCe));
339
- }
340
-
341
- state[0] = Aba;
342
- state[1] = Abe;
343
- state[2] = Abi;
344
- state[3] = Abo;
345
- state[4] = Abu;
346
- state[5] = Aga;
347
- state[6] = Age;
348
- state[7] = Agi;
349
- state[8] = Ago;
350
- state[9] = Agu;
351
- state[10] = Aka;
352
- state[11] = Ake;
353
- state[12] = Aki;
354
- state[13] = Ako;
355
- state[14] = Aku;
356
- state[15] = Ama;
357
- state[16] = Ame;
358
- state[17] = Ami;
359
- state[18] = Amo;
360
- state[19] = Amu;
361
- state[20] = Asa;
362
- state[21] = Ase;
363
- state[22] = Asi;
364
- state[23] = Aso;
365
- state[24] = Asu;
366
- }
367
-
368
- function keccakInit(sP) {
369
- const s = sP;
370
- for (let i = 0; i < 25; i++) s[i] = 0n;
371
- }
372
-
373
- function keccakAbsorb(sP, posP, r, input) {
374
- const s = sP;
375
- let pos = posP;
376
- let inLen = input.length;
377
- let i;
378
- let inputOffset = 0;
379
- while (pos + inLen >= r) {
380
- for (i = pos; i < r; i++)
381
- s[Math.floor(i / 8)] = BigInt.asUintN(
382
- 64,
383
- s[Math.floor(i / 8)] ^ (BigInt(input[inputOffset++]) << BigInt(8 * (i % 8)))
384
- );
385
- inLen -= r - pos;
386
- KeccakF1600StatePermute(s);
387
- pos = 0;
388
- }
389
-
390
- for (i = pos; i < pos + inLen; i++) {
391
- s[Math.floor(i / 8)] = BigInt.asUintN(
392
- 64,
393
- s[Math.floor(i / 8)] ^ (BigInt(input[inputOffset++]) << BigInt(8 * (i % 8)))
394
- );
395
- }
396
-
397
- return i;
398
- }
399
-
400
- function keccakFinalize(sP, pos, r, p) {
401
- const s = sP;
402
- s[Math.floor(pos / 8)] = BigInt.asUintN(64, s[Math.floor(pos / 8)] ^ (BigInt(p) << BigInt(8 * (pos % 8))));
403
- s[Math.floor(r / 8) - 1] = BigInt.asUintN(64, s[Math.floor(r / 8) - 1] ^ (1n << 63n));
404
- }
405
-
406
- function keccakSqueeze(outP, s, posP, r) {
407
- let pos = posP;
408
- const out = outP;
409
- let outLen = out.length;
410
- let outputOffset = 0;
411
- let i = 0;
412
-
413
- while (outLen) {
414
- if (pos === r) {
415
- KeccakF1600StatePermute(s);
416
- pos = 0;
417
- }
418
- for (i = pos; i < r && i < pos + outLen; i++) out[outputOffset++] = s[Math.floor(i / 8)] >> BigInt(8 * (i % 8));
419
- outLen -= i - pos;
420
- pos = i;
421
- }
422
-
423
- return pos;
424
- }
425
-
426
- function keccakAbsorbOnce(sP, r, input, p) {
427
- const s = sP;
428
- let inLen = input.length;
429
- let inputOffset = 0;
430
- let i;
431
-
432
- for (i = 0; i < 25; i++) s[i] = 0;
433
-
434
- while (inLen >= r) {
435
- for (i = 0; i < Math.floor(r / 8); i++) s[i] = BigInt.asUintN(64, s[i] ^ load64(input, inputOffset + 8 * i));
436
- inputOffset += r;
437
- inLen -= r;
438
- KeccakF1600StatePermute(s);
439
- }
440
-
441
- for (i = 0; i < inLen; i++)
442
- s[Math.floor(i / 8)] = BigInt.asUintN(
443
- 64,
444
- s[Math.floor(i / 8)] ^ (BigInt(input[inputOffset + i]) << BigInt(8 * (i % 8)))
445
- );
446
-
447
- s[Math.floor(i / 8)] = BigInt.asUintN(64, s[Math.floor(i / 8)] ^ (BigInt(p) << BigInt(8 * (i % 8))));
448
- s[Math.floor((r - 1) / 8)] = BigInt.asUintN(64, s[Math.floor((r - 1) / 8)] ^ (1n << 63n));
449
- }
450
-
451
- function keccakSqueezeBlocks(output, outputOffsetP, nBlocksP, s, r) {
452
- let nBlocks = nBlocksP;
453
- let outputOffset = outputOffsetP;
454
- while (nBlocks) {
455
- KeccakF1600StatePermute(s);
456
- for (let i = 0; i < Math.floor(r / 8); i++) store64(output, outputOffset + 8 * i, s[i]);
457
- outputOffset += r;
458
- nBlocks -= 1;
78
+ this.hasher = null;
79
+ this.finalized = false;
459
80
  }
460
81
  }
461
82
 
462
- function shake128Init(stateP) {
463
- const state = stateP;
464
- keccakInit(state.s);
465
- state.pos = 0;
466
- }
467
-
468
- function shake128Absorb(stateP, input) {
469
- const state = stateP;
470
- state.pos = keccakAbsorb(state.s, state.pos, Shake128Rate, input);
471
- }
83
+ // SHAKE-128 functions
472
84
 
473
- function shake128Finalize(stateP) {
474
- const state = stateP;
475
- keccakFinalize(state.s, state.pos, Shake128Rate, 0x1f);
476
- state.pos = Shake128Rate;
85
+ function shake128Init(state) {
86
+ state.hasher = shake128.create({});
87
+ state.finalized = false;
477
88
  }
478
89
 
479
- function shake128Squeeze(out, stateP) {
480
- const state = stateP;
481
- state.pos = keccakSqueeze(out, state.s, state.pos, Shake128Rate);
90
+ function shake128Absorb(state, input) {
91
+ state.hasher.update(input);
482
92
  }
483
93
 
484
- function shake128AbsorbOnce(stateP, input) {
485
- const state = stateP;
486
- keccakAbsorbOnce(state.s, Shake128Rate, input, 0x1f);
487
- state.pos = Shake128Rate;
94
+ function shake128Finalize(state) {
95
+ // Mark as finalized - actual finalization happens on first xofInto call
96
+ state.finalized = true;
488
97
  }
489
98
 
490
99
  function shake128SqueezeBlocks(out, outputOffset, nBlocks, state) {
491
- keccakSqueezeBlocks(out, outputOffset, nBlocks, state.s, Shake128Rate);
100
+ const len = nBlocks * Shake128Rate;
101
+ const output = out.subarray(outputOffset, outputOffset + len);
102
+ state.hasher.xofInto(output);
492
103
  }
493
104
 
494
- function shake256Init(stateP) {
495
- const state = stateP;
496
- keccakInit(state.s);
497
- state.pos = 0;
105
+ // SHAKE-256 functions
106
+
107
+ function shake256Init(state) {
108
+ state.hasher = shake256.create({});
109
+ state.finalized = false;
498
110
  }
499
111
 
500
- function shake256Absorb(stateP, input) {
501
- const state = stateP;
502
- state.pos = keccakAbsorb(state.s, state.pos, Shake256Rate, input);
112
+ function shake256Absorb(state, input) {
113
+ state.hasher.update(input);
503
114
  }
504
115
 
505
- function shake256Finalize(stateP) {
506
- const state = stateP;
507
- keccakFinalize(state.s, state.pos, Shake256Rate, 0x1f);
508
- state.pos = Shake256Rate;
116
+ function shake256Finalize(state) {
117
+ // Mark as finalized - actual finalization happens on first xofInto call
118
+ state.finalized = true;
509
119
  }
510
120
 
511
121
  function shake256SqueezeBlocks(out, outputOffset, nBlocks, state) {
512
- keccakSqueezeBlocks(out, outputOffset, nBlocks, state.s, Shake256Rate);
122
+ const len = nBlocks * Shake256Rate;
123
+ const output = out.subarray(outputOffset, outputOffset + len);
124
+ state.hasher.xofInto(output);
513
125
  }
514
126
 
515
127
  function dilithiumShake128StreamInit(state, seed, nonce) {
@@ -567,9 +179,8 @@ function ntt(a) {
567
179
  const zeta = zetas[++k];
568
180
  for (j = start; j < start + len; ++j) {
569
181
  const t = Number(montgomeryReduce(BigInt.asIntN(64, BigInt(zeta) * BigInt(a[j + len]))));
570
- a[j + len] = a[j] - t; // eslint-disable-line no-param-reassign
571
- // eslint-disable-next-line
572
- a[j] = a[j] + t;
182
+ a[j + len] = a[j] - t;
183
+ a[j] += t;
573
184
  }
574
185
  }
575
186
  }
@@ -585,15 +196,14 @@ function invNTTToMont(a) {
585
196
  const zeta = BigInt.asIntN(32, BigInt(-zetas[--k]));
586
197
  for (j = start; j < start + len; ++j) {
587
198
  const t = a[j];
588
- a[j] = t + a[j + len]; // eslint-disable-line no-param-reassign
589
- a[j + len] = t - a[j + len]; // eslint-disable-line no-param-reassign
590
- a[j + len] = Number(montgomeryReduce(BigInt.asIntN(64, zeta * BigInt(a[j + len])))); // eslint-disable-line no-param-reassign
199
+ a[j] = t + a[j + len];
200
+ a[j + len] = t - a[j + len];
201
+ a[j + len] = Number(montgomeryReduce(BigInt.asIntN(64, zeta * BigInt(a[j + len]))));
591
202
  }
592
203
  }
593
204
  }
594
- // eslint-disable-next-line no-shadow
595
205
  for (let j = 0; j < N; ++j) {
596
- a[j] = Number(montgomeryReduce(BigInt.asIntN(64, f * BigInt(a[j])))); // eslint-disable-line no-param-reassign
206
+ a[j] = Number(montgomeryReduce(BigInt.asIntN(64, f * BigInt(a[j]))));
597
207
  }
598
208
  }
599
209
 
@@ -946,7 +556,7 @@ function polyT0Pack(rP, rOffset, a) {
946
556
  t[6] = (1 << (D - 1)) - a.coeffs[8 * i + 6];
947
557
  t[7] = (1 << (D - 1)) - a.coeffs[8 * i + 7];
948
558
 
949
- r[rOffset + 13 * i] = t[0]; // eslint-disable-line prefer-destructuring
559
+ r[rOffset + 13 * i] = t[0];
950
560
  r[rOffset + 13 * i + 1] = t[0] >> 8;
951
561
  r[rOffset + 13 * i + 1] |= t[1] << 5;
952
562
  r[rOffset + 13 * i + 2] = t[1] >> 3;
@@ -1026,7 +636,7 @@ function polyZPack(rP, rOffset, a) {
1026
636
  t[0] = GAMMA1 - a.coeffs[2 * i];
1027
637
  t[1] = GAMMA1 - a.coeffs[2 * i + 1];
1028
638
 
1029
- r[rOffset + 5 * i] = t[0]; // eslint-disable-line prefer-destructuring
639
+ r[rOffset + 5 * i] = t[0];
1030
640
  r[rOffset + 5 * i + 1] = t[0] >> 8;
1031
641
  r[rOffset + 5 * i + 2] = t[0] >> 16;
1032
642
  r[rOffset + 5 * i + 2] |= t[1] << 4;
@@ -1073,7 +683,7 @@ function polyVecMatrixExpand(mat, rho) {
1073
683
 
1074
684
  function polyVecMatrixPointWiseMontgomery(t, mat, v) {
1075
685
  for (let i = 0; i < K; ++i) {
1076
- polyVecLPointWiseAccMontgomery(t.vec[i], mat[i], v); // eslint-disable-line no-use-before-define
686
+ polyVecLPointWiseAccMontgomery(t.vec[i], mat[i], v);
1077
687
  }
1078
688
  }
1079
689
 
@@ -1274,10 +884,10 @@ function packSk(skp, rho, tr, key, t0, s1, s2) {
1274
884
  }
1275
885
  skOffset += SeedBytes;
1276
886
 
1277
- for (let i = 0; i < SeedBytes; ++i) {
887
+ for (let i = 0; i < TRBytes; ++i) {
1278
888
  sk[skOffset + i] = tr[i];
1279
889
  }
1280
- skOffset += SeedBytes;
890
+ skOffset += TRBytes;
1281
891
 
1282
892
  for (let i = 0; i < L; ++i) {
1283
893
  polyEtaPack(sk, skOffset + i * PolyETAPackedBytes, s1.vec[i]);
@@ -1309,10 +919,10 @@ function unpackSk(rhoP, trP, keyP, t0, s1, s2, sk) {
1309
919
  }
1310
920
  skOffset += SeedBytes;
1311
921
 
1312
- for (let i = 0; i < SeedBytes; ++i) {
922
+ for (let i = 0; i < TRBytes; ++i) {
1313
923
  tr[i] = sk[skOffset + i];
1314
924
  }
1315
- skOffset += SeedBytes;
925
+ skOffset += TRBytes;
1316
926
 
1317
927
  for (let i = 0; i < L; ++i) {
1318
928
  polyEtaUnpack(s1.vec[i], sk, skOffset + i * PolyETAPackedBytes);
@@ -1404,8 +1014,38 @@ function unpackSig(cP, z, hP, sig) {
1404
1014
  return 0;
1405
1015
  }
1406
1016
 
1407
- const randomBytes = pkg__default;
1408
-
1017
+ const randomBytes = pkg;
1018
+
1019
+ /**
1020
+ * Convert hex string to Uint8Array
1021
+ * @param {string} hex - Hex-encoded string
1022
+ * @returns {Uint8Array} Decoded bytes
1023
+ * @private
1024
+ */
1025
+ function hexToBytes(hex) {
1026
+ const len = hex.length / 2;
1027
+ const result = new Uint8Array(len);
1028
+ for (let i = 0; i < len; i++) {
1029
+ result[i] = parseInt(hex.substr(i * 2, 2), 16);
1030
+ }
1031
+ return result;
1032
+ }
1033
+
1034
+ /**
1035
+ * Generate a Dilithium-5 key pair.
1036
+ *
1037
+ * @param {Uint8Array|null} passedSeed - Optional 32-byte seed for deterministic key generation.
1038
+ * Pass null for random key generation.
1039
+ * @param {Uint8Array} pk - Output buffer for public key (must be CryptoPublicKeyBytes = 2592 bytes)
1040
+ * @param {Uint8Array} sk - Output buffer for secret key (must be CryptoSecretKeyBytes = 4896 bytes)
1041
+ * @returns {Uint8Array} The seed used for key generation (useful when passedSeed is null)
1042
+ * @throws {Error} If pk/sk buffers are null or wrong size, or if seed is wrong size
1043
+ *
1044
+ * @example
1045
+ * const pk = new Uint8Array(CryptoPublicKeyBytes);
1046
+ * const sk = new Uint8Array(CryptoSecretKeyBytes);
1047
+ * const seed = cryptoSignKeypair(null, pk, sk);
1048
+ */
1409
1049
  function cryptoSignKeypair(passedSeed, pk, sk) {
1410
1050
  try {
1411
1051
  if (pk.length !== CryptoPublicKeyBytes) {
@@ -1421,8 +1061,15 @@ function cryptoSignKeypair(passedSeed, pk, sk) {
1421
1061
  throw new Error(`${e.message}`);
1422
1062
  }
1423
1063
  }
1424
- // eslint-disable-next-line no-unused-vars
1425
- const mat = new Array(K).fill().map((_) => new PolyVecL());
1064
+
1065
+ // Validate seed length if provided
1066
+ if (passedSeed !== null && passedSeed !== undefined) {
1067
+ if (passedSeed.length !== SeedBytes) {
1068
+ throw new Error(`invalid seed length ${passedSeed.length} | Expected length ${SeedBytes}`);
1069
+ }
1070
+ }
1071
+
1072
+ const mat = new Array(K).fill().map(() => new PolyVecL());
1426
1073
  const s1 = new PolyVecL();
1427
1074
  const s2 = new PolyVecK();
1428
1075
  const t1 = new PolyVecK();
@@ -1431,10 +1078,8 @@ function cryptoSignKeypair(passedSeed, pk, sk) {
1431
1078
  // Get randomness for rho, rhoPrime and key
1432
1079
  const seed = passedSeed || randomBytes(SeedBytes);
1433
1080
 
1434
- const state = new SHAKE(256);
1435
- let outputLength = 2 * SeedBytes + CRHBytes;
1436
- state.update(seed);
1437
- const seedBuf = state.digest({ buffer: Buffer.alloc(outputLength) });
1081
+ const outputLength = 2 * SeedBytes + CRHBytes;
1082
+ const seedBuf = shake256.create({}).update(seed).xof(outputLength);
1438
1083
  const rho = seedBuf.slice(0, SeedBytes);
1439
1084
  const rhoPrime = seedBuf.slice(SeedBytes, SeedBytes + CRHBytes);
1440
1085
  const key = seedBuf.slice(SeedBytes + CRHBytes);
@@ -1463,30 +1108,42 @@ function cryptoSignKeypair(passedSeed, pk, sk) {
1463
1108
  packPk(pk, rho, t1);
1464
1109
 
1465
1110
  // Compute H(rho, t1) and write secret key
1466
- const hasher = new SHAKE(256);
1467
- outputLength = SeedBytes;
1468
- hasher.update(Buffer.from(pk, 'hex'));
1469
- const tr = new Uint8Array(hasher.digest());
1111
+ const tr = shake256.create({}).update(pk).xof(TRBytes);
1470
1112
  packSk(sk, rho, tr, key, t0, s1, s2);
1471
1113
 
1472
1114
  return seed;
1473
1115
  }
1474
1116
 
1117
+ /**
1118
+ * Create a detached signature for a message.
1119
+ *
1120
+ * Uses the Dilithium-5 (Round 3) signing algorithm with rejection sampling.
1121
+ *
1122
+ * @param {Uint8Array} sig - Output buffer for signature (must be at least CryptoBytes = 4595 bytes)
1123
+ * @param {string|Uint8Array} m - Message to sign (hex string or Uint8Array)
1124
+ * @param {Uint8Array} sk - Secret key (must be CryptoSecretKeyBytes = 4896 bytes)
1125
+ * @param {boolean} randomizedSigning - If true, use random nonce for hedged signing.
1126
+ * If false, use deterministic nonce derived from message and key.
1127
+ * @returns {number} 0 on success
1128
+ * @throws {Error} If sk is wrong size
1129
+ *
1130
+ * @example
1131
+ * const sig = new Uint8Array(CryptoBytes);
1132
+ * cryptoSignSignature(sig, message, sk, false);
1133
+ */
1475
1134
  function cryptoSignSignature(sig, m, sk, randomizedSigning) {
1476
1135
  if (sk.length !== CryptoSecretKeyBytes) {
1477
1136
  throw new Error(`invalid sk length ${sk.length} | Expected length ${CryptoSecretKeyBytes}`);
1478
1137
  }
1479
1138
 
1480
1139
  const rho = new Uint8Array(SeedBytes);
1481
- const tr = new Uint8Array(SeedBytes);
1140
+ const tr = new Uint8Array(TRBytes);
1482
1141
  const key = new Uint8Array(SeedBytes);
1483
1142
  let rhoPrime = new Uint8Array(CRHBytes);
1484
1143
  let nonce = 0;
1485
- let state = null;
1486
1144
  const mat = Array(K)
1487
1145
  .fill()
1488
- // eslint-disable-next-line no-unused-vars
1489
- .map((_) => new PolyVecL());
1146
+ .map(() => new PolyVecL());
1490
1147
  const s1 = new PolyVecL();
1491
1148
  const y = new PolyVecL();
1492
1149
  const z = new PolyVecL();
@@ -1499,19 +1156,14 @@ function cryptoSignSignature(sig, m, sk, randomizedSigning) {
1499
1156
 
1500
1157
  unpackSk(rho, tr, key, t0, s1, s2, sk);
1501
1158
 
1502
- state = new SHAKE(256);
1503
- let outputLength = CRHBytes;
1504
- state.update(Buffer.from(tr, 'hex'));
1505
- state.update(Buffer.from(m, 'hex'));
1506
- const mu = new Uint8Array(state.digest({ buffer: Buffer.alloc(outputLength) }));
1159
+ // Convert hex message to bytes
1160
+ const mBytes = typeof m === 'string' ? hexToBytes(m) : m;
1161
+ const mu = shake256.create({}).update(tr).update(mBytes).xof(CRHBytes);
1507
1162
 
1508
- if (randomizedSigning) rhoPrime = new Uint8Array(randomBytes(CRHBytes));
1509
- else {
1510
- state = new SHAKE(256);
1511
- outputLength = CRHBytes;
1512
- state.update(Buffer.from(key, 'hex'));
1513
- state.update(Buffer.from(mu, 'hex'));
1514
- rhoPrime.set(state.digest({ buffer: Buffer.alloc(outputLength) }));
1163
+ if (randomizedSigning) {
1164
+ rhoPrime = new Uint8Array(randomBytes(CRHBytes));
1165
+ } else {
1166
+ rhoPrime = shake256.create({}).update(key).update(mu).xof(CRHBytes);
1515
1167
  }
1516
1168
 
1517
1169
  polyVecMatrixExpand(mat, rho);
@@ -1519,7 +1171,6 @@ function cryptoSignSignature(sig, m, sk, randomizedSigning) {
1519
1171
  polyVecKNTT(s2);
1520
1172
  polyVecKNTT(t0);
1521
1173
 
1522
- // eslint-disable-next-line no-constant-condition
1523
1174
  while (true) {
1524
1175
  polyVecLUniformGamma1(y, rhoPrime, nonce++);
1525
1176
  // Matrix-vector multiplication
@@ -1534,11 +1185,12 @@ function cryptoSignSignature(sig, m, sk, randomizedSigning) {
1534
1185
  polyVecKDecompose(w1, w0, w1);
1535
1186
  polyVecKPackW1(sig, w1);
1536
1187
 
1537
- state = new SHAKE(256);
1538
- outputLength = SeedBytes;
1539
- state.update(Buffer.from(mu, 'hex'));
1540
- state.update(Buffer.from(sig.slice(0, K * PolyW1PackedBytes)), 'hex');
1541
- sig.set(state.digest({ buffer: Buffer.alloc(outputLength) }));
1188
+ const cHash = shake256
1189
+ .create({})
1190
+ .update(mu)
1191
+ .update(sig.slice(0, K * PolyW1PackedBytes))
1192
+ .xof(SeedBytes);
1193
+ sig.set(cHash);
1542
1194
 
1543
1195
  polyChallenge(cp, sig);
1544
1196
  polyNTT(cp);
@@ -1549,7 +1201,7 @@ function cryptoSignSignature(sig, m, sk, randomizedSigning) {
1549
1201
  polyVecLAdd(z, z, y);
1550
1202
  polyVecLReduce(z);
1551
1203
  if (polyVecLChkNorm(z, GAMMA1 - BETA) !== 0) {
1552
- continue; // eslint-disable-line no-continue
1204
+ continue;
1553
1205
  }
1554
1206
 
1555
1207
  polyVecKPointWisePolyMontgomery(h, cp, s2);
@@ -1557,20 +1209,20 @@ function cryptoSignSignature(sig, m, sk, randomizedSigning) {
1557
1209
  polyVecKSub(w0, w0, h);
1558
1210
  polyVecKReduce(w0);
1559
1211
  if (polyVecKChkNorm(w0, GAMMA2 - BETA) !== 0) {
1560
- continue; // eslint-disable-line no-continue
1212
+ continue;
1561
1213
  }
1562
1214
 
1563
1215
  polyVecKPointWisePolyMontgomery(h, cp, t0);
1564
1216
  polyVecKInvNTTToMont(h);
1565
1217
  polyVecKReduce(h);
1566
1218
  if (polyVecKChkNorm(h, GAMMA2) !== 0) {
1567
- continue; // eslint-disable-line no-continue
1219
+ continue;
1568
1220
  }
1569
1221
 
1570
1222
  polyVecKAdd(w0, w0, h);
1571
1223
  const n = polyVecKMakeHint(h, w0, w1);
1572
1224
  if (n > OMEGA) {
1573
- continue; // eslint-disable-line no-continue
1225
+ continue;
1574
1226
  }
1575
1227
 
1576
1228
  packSig(sig, sig, z, h);
@@ -1578,6 +1230,22 @@ function cryptoSignSignature(sig, m, sk, randomizedSigning) {
1578
1230
  }
1579
1231
  }
1580
1232
 
1233
+ /**
1234
+ * Sign a message, returning signature concatenated with message.
1235
+ *
1236
+ * This is the combined sign operation that produces a "signed message" containing
1237
+ * both the signature and the original message (signature || message).
1238
+ *
1239
+ * @param {Uint8Array} msg - Message to sign
1240
+ * @param {Uint8Array} sk - Secret key (must be CryptoSecretKeyBytes = 4896 bytes)
1241
+ * @param {boolean} randomizedSigning - If true, use random nonce; if false, deterministic
1242
+ * @returns {Uint8Array} Signed message (CryptoBytes + msg.length bytes)
1243
+ * @throws {Error} If signing fails
1244
+ *
1245
+ * @example
1246
+ * const signedMsg = cryptoSign(message, sk, false);
1247
+ * // signedMsg contains: signature (4595 bytes) || message
1248
+ */
1581
1249
  function cryptoSign(msg, sk, randomizedSigning) {
1582
1250
  const sm = new Uint8Array(CryptoBytes + msg.length);
1583
1251
  const mLen = msg.length;
@@ -1592,6 +1260,22 @@ function cryptoSign(msg, sk, randomizedSigning) {
1592
1260
  return sm;
1593
1261
  }
1594
1262
 
1263
+ /**
1264
+ * Verify a detached signature.
1265
+ *
1266
+ * Performs constant-time verification to prevent timing side-channel attacks.
1267
+ *
1268
+ * @param {Uint8Array} sig - Signature to verify (must be CryptoBytes = 4595 bytes)
1269
+ * @param {string|Uint8Array} m - Message that was signed (hex string or Uint8Array)
1270
+ * @param {Uint8Array} pk - Public key (must be CryptoPublicKeyBytes = 2592 bytes)
1271
+ * @returns {boolean} true if signature is valid, false otherwise
1272
+ *
1273
+ * @example
1274
+ * const isValid = cryptoSignVerify(signature, message, pk);
1275
+ * if (!isValid) {
1276
+ * throw new Error('Invalid signature');
1277
+ * }
1278
+ */
1595
1279
  function cryptoSignVerify(sig, m, pk) {
1596
1280
  let i;
1597
1281
  const buf = new Uint8Array(K * PolyW1PackedBytes);
@@ -1600,8 +1284,7 @@ function cryptoSignVerify(sig, m, pk) {
1600
1284
  const c = new Uint8Array(SeedBytes);
1601
1285
  const c2 = new Uint8Array(SeedBytes);
1602
1286
  const cp = new Poly();
1603
- // eslint-disable-next-line no-unused-vars
1604
- const mat = new Array(K).fill().map((_) => new PolyVecL());
1287
+ const mat = new Array(K).fill().map(() => new PolyVecL());
1605
1288
  const z = new PolyVecL();
1606
1289
  const t1 = new PolyVecK();
1607
1290
  const w1 = new PolyVecK();
@@ -1623,16 +1306,13 @@ function cryptoSignVerify(sig, m, pk) {
1623
1306
  }
1624
1307
 
1625
1308
  /* Compute CRH(H(rho, t1), msg) */
1626
- let state = new SHAKE(256);
1627
- let outputLength = SeedBytes;
1628
- state.update(pk.slice(0, CryptoPublicKeyBytes));
1629
- mu.set(state.digest({ buffer: Buffer.alloc(outputLength) }));
1309
+ const tr = shake256.create({}).update(pk).xof(TRBytes);
1310
+ mu.set(tr);
1630
1311
 
1631
- state = new SHAKE(256);
1632
- outputLength = CRHBytes;
1633
- state.update(Buffer.from(mu.slice(0, SeedBytes), 'hex'));
1634
- state.update(Buffer.from(m, 'hex'));
1635
- mu.set(state.digest({ buffer: Buffer.alloc(outputLength) }));
1312
+ // Convert hex message to bytes
1313
+ const mBytes = typeof m === 'string' ? hexToBytes(m) : m;
1314
+ const muFull = shake256.create({}).update(mu.slice(0, TRBytes)).update(mBytes).xof(CRHBytes);
1315
+ mu.set(muFull);
1636
1316
 
1637
1317
  /* Matrix-vector multiplication; compute Az - c2^dt1 */
1638
1318
  polyChallenge(cp, c);
@@ -1656,16 +1336,33 @@ function cryptoSignVerify(sig, m, pk) {
1656
1336
  polyVecKPackW1(buf, w1);
1657
1337
 
1658
1338
  /* Call random oracle and verify challenge */
1659
- state = new SHAKE(256);
1660
- outputLength = SeedBytes;
1661
- state.update(Buffer.from(mu, 'hex'));
1662
- state.update(Buffer.from(buf, 'hex'));
1663
- c2.set(state.digest({ buffer: Buffer.alloc(outputLength) }));
1664
-
1665
- for (i = 0; i < SeedBytes; ++i) if (c[i] !== c2[i]) return false;
1666
- return true;
1667
- }
1668
-
1339
+ const c2Hash = shake256.create({}).update(mu).update(buf).xof(SeedBytes);
1340
+ c2.set(c2Hash);
1341
+
1342
+ // Constant-time comparison to prevent timing attacks
1343
+ let diff = 0;
1344
+ for (i = 0; i < SeedBytes; ++i) {
1345
+ diff |= c[i] ^ c2[i];
1346
+ }
1347
+ return diff === 0;
1348
+ }
1349
+
1350
+ /**
1351
+ * Open a signed message (verify and extract message).
1352
+ *
1353
+ * This is the counterpart to cryptoSign(). It verifies the signature and
1354
+ * extracts the original message from a signed message.
1355
+ *
1356
+ * @param {Uint8Array} sm - Signed message (signature || message)
1357
+ * @param {Uint8Array} pk - Public key (must be CryptoPublicKeyBytes = 2592 bytes)
1358
+ * @returns {Uint8Array|undefined} The original message if valid, undefined if verification fails
1359
+ *
1360
+ * @example
1361
+ * const message = cryptoSignOpen(signedMsg, pk);
1362
+ * if (message === undefined) {
1363
+ * throw new Error('Invalid signature');
1364
+ * }
1365
+ */
1669
1366
  function cryptoSignOpen(sm, pk) {
1670
1367
  if (sm.length < CryptoBytes) {
1671
1368
  return undefined;
@@ -1680,4 +1377,56 @@ function cryptoSignOpen(sm, pk) {
1680
1377
  return msg;
1681
1378
  }
1682
1379
 
1683
- export { BETA, CRHBytes, CryptoBytes, CryptoPublicKeyBytes, CryptoSecretKeyBytes, D, ETA, GAMMA1, GAMMA2, K, KeccakF1600StatePermute, KeccakFRoundConstants, KeccakState, L, N, NRounds, OMEGA, Poly, PolyETAPackedBytes, PolyT0PackedBytes, PolyT1PackedBytes, PolyUniformETANBlocks, PolyUniformGamma1NBlocks, PolyUniformNBlocks, PolyVecHPackedBytes, PolyVecK, PolyVecL, PolyW1PackedBytes, PolyZPackedBytes, Q, QInv, ROL, SeedBytes, Shake128Rate, Shake256Rate, Stream128BlockBytes, Stream256BlockBytes, TAU, cAddQ, cryptoSign, cryptoSignKeypair, cryptoSignOpen, cryptoSignSignature, cryptoSignVerify, decompose, dilithiumShake128StreamInit, dilithiumShake256StreamInit, invNTTToMont, keccakAbsorb, keccakAbsorbOnce, keccakFinalize, keccakInit, keccakSqueeze, keccakSqueezeBlocks, load64, makeHint, montgomeryReduce, ntt, packPk, packSig, packSk, polyAdd, polyCAddQ, polyChallenge, polyChkNorm, polyDecompose, polyEtaPack, polyEtaUnpack, polyInvNTTToMont, polyMakeHint, polyNTT, polyPointWiseMontgomery, polyPower2round, polyReduce, polyShiftL, polySub, polyT0Pack, polyT0Unpack, polyT1Pack, polyT1Unpack, polyUniform, polyUniformEta, polyUniformGamma1, polyUseHint, polyVecKAdd, polyVecKCAddQ, polyVecKChkNorm, polyVecKDecompose, polyVecKInvNTTToMont, polyVecKMakeHint, polyVecKNTT, polyVecKPackW1, polyVecKPointWisePolyMontgomery, polyVecKPower2round, polyVecKReduce, polyVecKShiftL, polyVecKSub, polyVecKUniformEta, polyVecKUseHint, polyVecLAdd, polyVecLChkNorm, polyVecLInvNTTToMont, polyVecLNTT, polyVecLPointWiseAccMontgomery, polyVecLPointWisePolyMontgomery, polyVecLReduce, polyVecLUniformEta, polyVecLUniformGamma1, polyVecMatrixExpand, polyVecMatrixPointWiseMontgomery, polyW1Pack, polyZPack, polyZUnpack, power2round, reduce32, rejEta, rejUniform, shake128Absorb, shake128AbsorbOnce, shake128Finalize, shake128Init, shake128Squeeze, shake128SqueezeBlocks, shake256Absorb, shake256Finalize, shake256Init, shake256SqueezeBlocks, store64, unpackPk, unpackSig, unpackSk, useHint, zetas };
1380
+ /**
1381
+ * Security utilities for Dilithium5
1382
+ *
1383
+ * IMPORTANT: JavaScript cannot guarantee secure memory zeroization.
1384
+ * See SECURITY.md for details on limitations.
1385
+ */
1386
+
1387
+ /**
1388
+ * Attempts to zero out a Uint8Array buffer.
1389
+ *
1390
+ * WARNING: This is a BEST-EFFORT operation. Due to JavaScript/JIT limitations:
1391
+ * - The write may be optimized away if the buffer is unused afterward
1392
+ * - Copies may exist in garbage collector memory
1393
+ * - Data may have been swapped to disk
1394
+ *
1395
+ * For high-security applications, consider native implementations (go-qrllib)
1396
+ * or hardware security modules.
1397
+ *
1398
+ * @param {Uint8Array} buffer - The buffer to zero
1399
+ * @returns {void}
1400
+ */
1401
+ function zeroize(buffer) {
1402
+ if (!(buffer instanceof Uint8Array)) {
1403
+ throw new TypeError('zeroize requires a Uint8Array');
1404
+ }
1405
+ // Use fill(0) for zeroing - best effort
1406
+ buffer.fill(0);
1407
+ // Additional volatile-like access to discourage optimization
1408
+ // (This is a hint to the JIT, not a guarantee)
1409
+ if (buffer.length > 0 && buffer[0] !== 0) {
1410
+ throw new Error('zeroize failed'); // Should never happen
1411
+ }
1412
+ }
1413
+
1414
+ /**
1415
+ * Checks if a buffer is all zeros.
1416
+ * Uses constant-time comparison to avoid timing leaks.
1417
+ *
1418
+ * @param {Uint8Array} buffer - The buffer to check
1419
+ * @returns {boolean} True if all bytes are zero
1420
+ */
1421
+ function isZero(buffer) {
1422
+ if (!(buffer instanceof Uint8Array)) {
1423
+ throw new TypeError('isZero requires a Uint8Array');
1424
+ }
1425
+ let acc = 0;
1426
+ for (let i = 0; i < buffer.length; i++) {
1427
+ acc |= buffer[i];
1428
+ }
1429
+ return acc === 0;
1430
+ }
1431
+
1432
+ export { BETA, CRHBytes, CryptoBytes, CryptoPublicKeyBytes, CryptoSecretKeyBytes, D, ETA, GAMMA1, GAMMA2, K, KeccakState, L, N, OMEGA, Poly, PolyETAPackedBytes, PolyT0PackedBytes, PolyT1PackedBytes, PolyUniformETANBlocks, PolyUniformGamma1NBlocks, PolyUniformNBlocks, PolyVecHPackedBytes, PolyVecK, PolyVecL, PolyW1PackedBytes, PolyZPackedBytes, Q, QInv, SeedBytes, Shake128Rate, Shake256Rate, Stream128BlockBytes, Stream256BlockBytes, TAU, TRBytes, cAddQ, cryptoSign, cryptoSignKeypair, cryptoSignOpen, cryptoSignSignature, cryptoSignVerify, decompose, dilithiumShake128StreamInit, dilithiumShake256StreamInit, invNTTToMont, isZero, makeHint, montgomeryReduce, ntt, packPk, packSig, packSk, polyAdd, polyCAddQ, polyChallenge, polyChkNorm, polyDecompose, polyEtaPack, polyEtaUnpack, polyInvNTTToMont, polyMakeHint, polyNTT, polyPointWiseMontgomery, polyPower2round, polyReduce, polyShiftL, polySub, polyT0Pack, polyT0Unpack, polyT1Pack, polyT1Unpack, polyUniform, polyUniformEta, polyUniformGamma1, polyUseHint, polyVecKAdd, polyVecKCAddQ, polyVecKChkNorm, polyVecKDecompose, polyVecKInvNTTToMont, polyVecKMakeHint, polyVecKNTT, polyVecKPackW1, polyVecKPointWisePolyMontgomery, polyVecKPower2round, polyVecKReduce, polyVecKShiftL, polyVecKSub, polyVecKUniformEta, polyVecKUseHint, polyVecLAdd, polyVecLChkNorm, polyVecLInvNTTToMont, polyVecLNTT, polyVecLPointWiseAccMontgomery, polyVecLPointWisePolyMontgomery, polyVecLReduce, polyVecLUniformEta, polyVecLUniformGamma1, polyVecMatrixExpand, polyVecMatrixPointWiseMontgomery, polyW1Pack, polyZPack, polyZUnpack, power2round, reduce32, rejEta, rejUniform, shake128Absorb, shake128Finalize, shake128Init, shake128SqueezeBlocks, shake256Absorb, shake256Finalize, shake256Init, shake256SqueezeBlocks, unpackPk, unpackSig, unpackSk, useHint, zeroize, zetas };