@theqrl/dilithium5 0.0.9 → 0.1.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.
- package/dist/dilithium5.cjs.js +1825 -0
- package/dist/dilithium5.esm.js +1683 -0
- package/package.json +18 -9
- package/src/index.js +10 -13
- package/src/const.js +0 -93
- package/src/fips202.js +0 -446
- package/src/ntt.js +0 -45
- package/src/packing.js +0 -194
- package/src/poly.js +0 -472
- package/src/polyvec.js +0 -248
- package/src/reduce.js +0 -25
- package/src/rounding.js +0 -42
- package/src/sign.js +0 -330
- package/src/symmetric-shake.js +0 -42
|
@@ -0,0 +1,1825 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var pkg = require('randombytes');
|
|
4
|
+
var sha3 = require('sha3');
|
|
5
|
+
|
|
6
|
+
const Shake128Rate = 168;
|
|
7
|
+
const Shake256Rate = 136;
|
|
8
|
+
const Stream128BlockBytes = Shake128Rate;
|
|
9
|
+
const Stream256BlockBytes = Shake256Rate;
|
|
10
|
+
|
|
11
|
+
const SeedBytes = 32;
|
|
12
|
+
const CRHBytes = 64;
|
|
13
|
+
const N = 256;
|
|
14
|
+
const Q = 8380417;
|
|
15
|
+
const QInv = 58728449;
|
|
16
|
+
const D = 13;
|
|
17
|
+
|
|
18
|
+
const K = 8;
|
|
19
|
+
const L = 7;
|
|
20
|
+
const ETA = 2;
|
|
21
|
+
const TAU = 60;
|
|
22
|
+
const BETA = 120;
|
|
23
|
+
const GAMMA1 = 1 << 19;
|
|
24
|
+
const GAMMA2 = Math.floor((Q - 1) / 32);
|
|
25
|
+
const OMEGA = 75;
|
|
26
|
+
|
|
27
|
+
const PolyT1PackedBytes = 320;
|
|
28
|
+
const PolyT0PackedBytes = 416;
|
|
29
|
+
const PolyETAPackedBytes = 96;
|
|
30
|
+
const PolyZPackedBytes = 640;
|
|
31
|
+
const PolyVecHPackedBytes = OMEGA + K;
|
|
32
|
+
const PolyW1PackedBytes = 128;
|
|
33
|
+
|
|
34
|
+
const CryptoPublicKeyBytes = SeedBytes + K * PolyT1PackedBytes;
|
|
35
|
+
const CryptoSecretKeyBytes =
|
|
36
|
+
3 * SeedBytes + L * PolyETAPackedBytes + K * PolyETAPackedBytes + K * PolyT0PackedBytes;
|
|
37
|
+
const CryptoBytes = SeedBytes + L * PolyZPackedBytes + PolyVecHPackedBytes;
|
|
38
|
+
|
|
39
|
+
const PolyUniformNBlocks = Math.floor((768 + Stream128BlockBytes - 1) / Stream128BlockBytes);
|
|
40
|
+
const PolyUniformETANBlocks = Math.floor((136 + Stream256BlockBytes - 1) / Stream256BlockBytes);
|
|
41
|
+
const PolyUniformGamma1NBlocks = Math.floor((PolyZPackedBytes + Stream256BlockBytes - 1) / Stream256BlockBytes);
|
|
42
|
+
|
|
43
|
+
const zetas = [
|
|
44
|
+
0, 25847, -2608894, -518909, 237124, -777960, -876248, 466468, 1826347, 2353451, -359251, -2091905, 3119733, -2884855,
|
|
45
|
+
3111497, 2680103, 2725464, 1024112, -1079900, 3585928, -549488, -1119584, 2619752, -2108549, -2118186, -3859737,
|
|
46
|
+
-1399561, -3277672, 1757237, -19422, 4010497, 280005, 2706023, 95776, 3077325, 3530437, -1661693, -3592148, -2537516,
|
|
47
|
+
3915439, -3861115, -3043716, 3574422, -2867647, 3539968, -300467, 2348700, -539299, -1699267, -1643818, 3505694,
|
|
48
|
+
-3821735, 3507263, -2140649, -1600420, 3699596, 811944, 531354, 954230, 3881043, 3900724, -2556880, 2071892, -2797779,
|
|
49
|
+
-3930395, -1528703, -3677745, -3041255, -1452451, 3475950, 2176455, -1585221, -1257611, 1939314, -4083598, -1000202,
|
|
50
|
+
-3190144, -3157330, -3632928, 126922, 3412210, -983419, 2147896, 2715295, -2967645, -3693493, -411027, -2477047,
|
|
51
|
+
-671102, -1228525, -22981, -1308169, -381987, 1349076, 1852771, -1430430, -3343383, 264944, 508951, 3097992, 44288,
|
|
52
|
+
-1100098, 904516, 3958618, -3724342, -8578, 1653064, -3249728, 2389356, -210977, 759969, -1316856, 189548, -3553272,
|
|
53
|
+
3159746, -1851402, -2409325, -177440, 1315589, 1341330, 1285669, -1584928, -812732, -1439742, -3019102, -3881060,
|
|
54
|
+
-3628969, 3839961, 2091667, 3407706, 2316500, 3817976, -3342478, 2244091, -2446433, -3562462, 266997, 2434439,
|
|
55
|
+
-1235728, 3513181, -3520352, -3759364, -1197226, -3193378, 900702, 1859098, 909542, 819034, 495491, -1613174, -43260,
|
|
56
|
+
-522500, -655327, -3122442, 2031748, 3207046, -3556995, -525098, -768622, -3595838, 342297, 286988, -2437823, 4108315,
|
|
57
|
+
3437287, -3342277, 1735879, 203044, 2842341, 2691481, -2590150, 1265009, 4055324, 1247620, 2486353, 1595974, -3767016,
|
|
58
|
+
1250494, 2635921, -3548272, -2994039, 1869119, 1903435, -1050970, -1333058, 1237275, -3318210, -1430225, -451100,
|
|
59
|
+
1312455, 3306115, -1962642, -1279661, 1917081, -2546312, -1374803, 1500165, 777191, 2235880, 3406031, -542412,
|
|
60
|
+
-2831860, -1671176, -1846953, -2584293, -3724270, 594136, -3776993, -2013608, 2432395, 2454455, -164721, 1957272,
|
|
61
|
+
3369112, 185531, -1207385, -3183426, 162844, 1616392, 3014001, 810149, 1652634, -3694233, -1799107, -3038916, 3523897,
|
|
62
|
+
3866901, 269760, 2213111, -975884, 1717735, 472078, -426683, 1723600, -1803090, 1910376, -1667432, -1104333, -260646,
|
|
63
|
+
-3833893, -2939036, -2235985, -420899, -2286327, 183443, -976891, 1612842, -3545687, -554416, 3919660, -48306,
|
|
64
|
+
-1362209, 3937738, 1400424, -846154, 1976782,
|
|
65
|
+
];
|
|
66
|
+
|
|
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
|
+
]);
|
|
95
|
+
|
|
96
|
+
class KeccakState {
|
|
97
|
+
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;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
|
|
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
|
+
}
|
|
472
|
+
|
|
473
|
+
function shake128Finalize(stateP) {
|
|
474
|
+
const state = stateP;
|
|
475
|
+
keccakFinalize(state.s, state.pos, Shake128Rate, 0x1f);
|
|
476
|
+
state.pos = Shake128Rate;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
function shake128Squeeze(out, stateP) {
|
|
480
|
+
const state = stateP;
|
|
481
|
+
state.pos = keccakSqueeze(out, state.s, state.pos, Shake128Rate);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
function shake128AbsorbOnce(stateP, input) {
|
|
485
|
+
const state = stateP;
|
|
486
|
+
keccakAbsorbOnce(state.s, Shake128Rate, input, 0x1f);
|
|
487
|
+
state.pos = Shake128Rate;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
function shake128SqueezeBlocks(out, outputOffset, nBlocks, state) {
|
|
491
|
+
keccakSqueezeBlocks(out, outputOffset, nBlocks, state.s, Shake128Rate);
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
function shake256Init(stateP) {
|
|
495
|
+
const state = stateP;
|
|
496
|
+
keccakInit(state.s);
|
|
497
|
+
state.pos = 0;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
function shake256Absorb(stateP, input) {
|
|
501
|
+
const state = stateP;
|
|
502
|
+
state.pos = keccakAbsorb(state.s, state.pos, Shake256Rate, input);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
function shake256Finalize(stateP) {
|
|
506
|
+
const state = stateP;
|
|
507
|
+
keccakFinalize(state.s, state.pos, Shake256Rate, 0x1f);
|
|
508
|
+
state.pos = Shake256Rate;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
function shake256SqueezeBlocks(out, outputOffset, nBlocks, state) {
|
|
512
|
+
keccakSqueezeBlocks(out, outputOffset, nBlocks, state.s, Shake256Rate);
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
function dilithiumShake128StreamInit(state, seed, nonce) {
|
|
516
|
+
if (seed.length !== SeedBytes) {
|
|
517
|
+
throw new Error(`invalid seed length ${seed.length} | expected ${SeedBytes}`);
|
|
518
|
+
}
|
|
519
|
+
const t = new Uint8Array(2);
|
|
520
|
+
t[0] = nonce & 0xff;
|
|
521
|
+
t[1] = nonce >> 8;
|
|
522
|
+
|
|
523
|
+
shake128Init(state);
|
|
524
|
+
shake128Absorb(state, seed);
|
|
525
|
+
shake128Absorb(state, t);
|
|
526
|
+
shake128Finalize(state);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
function dilithiumShake256StreamInit(state, seed, nonce) {
|
|
530
|
+
if (seed.length !== CRHBytes) {
|
|
531
|
+
throw new Error(`invalid seed length ${seed.length} | expected ${CRHBytes}`);
|
|
532
|
+
}
|
|
533
|
+
const t = new Uint8Array(2);
|
|
534
|
+
t[0] = nonce & 0xff;
|
|
535
|
+
t[1] = nonce >> 8;
|
|
536
|
+
|
|
537
|
+
shake256Init(state);
|
|
538
|
+
shake256Absorb(state, seed);
|
|
539
|
+
shake256Absorb(state, t);
|
|
540
|
+
shake256Finalize(state);
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
function montgomeryReduce(a) {
|
|
544
|
+
let t = BigInt.asIntN(32, BigInt.asIntN(64, BigInt.asIntN(32, a)) * BigInt(QInv));
|
|
545
|
+
t = BigInt.asIntN(32, (a - t * BigInt(Q)) >> 32n);
|
|
546
|
+
return t;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
function reduce32(a) {
|
|
550
|
+
let t = (a + (1 << 22)) >> 23;
|
|
551
|
+
t = a - t * Q;
|
|
552
|
+
return t;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
function cAddQ(a) {
|
|
556
|
+
let ar = a;
|
|
557
|
+
ar += (ar >> 31) & Q;
|
|
558
|
+
return ar;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
function ntt(a) {
|
|
562
|
+
let k = 0;
|
|
563
|
+
let j = 0;
|
|
564
|
+
|
|
565
|
+
for (let len = 128; len > 0; len >>= 1) {
|
|
566
|
+
for (let start = 0; start < N; start = j + len) {
|
|
567
|
+
const zeta = zetas[++k];
|
|
568
|
+
for (j = start; j < start + len; ++j) {
|
|
569
|
+
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;
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
function invNTTToMont(a) {
|
|
579
|
+
const f = 41978n; // mont^2/256
|
|
580
|
+
let j = 0;
|
|
581
|
+
let k = 256;
|
|
582
|
+
|
|
583
|
+
for (let len = 1; len < N; len <<= 1) {
|
|
584
|
+
for (let start = 0; start < N; start = j + len) {
|
|
585
|
+
const zeta = BigInt.asIntN(32, BigInt(-zetas[--k]));
|
|
586
|
+
for (j = start; j < start + len; ++j) {
|
|
587
|
+
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
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
// eslint-disable-next-line no-shadow
|
|
595
|
+
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
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
function power2round(a0p, i, a) {
|
|
601
|
+
const a0 = a0p;
|
|
602
|
+
const a1 = (a + (1 << (D - 1)) - 1) >> D;
|
|
603
|
+
a0[i] = a - (a1 << D);
|
|
604
|
+
return a1;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
function decompose(a0p, i, a) {
|
|
608
|
+
const a0 = a0p;
|
|
609
|
+
let a1 = (a + 127) >> 7;
|
|
610
|
+
a1 = (a1 * 1025 + (1 << 21)) >> 22;
|
|
611
|
+
a1 &= 15;
|
|
612
|
+
|
|
613
|
+
a0[i] = a - a1 * 2 * GAMMA2;
|
|
614
|
+
a0[i] -= (((Q - 1) / 2 - a0[i]) >> 31) & Q;
|
|
615
|
+
return a1;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
function makeHint(a0, a1) {
|
|
619
|
+
if (a0 > GAMMA2 || a0 < -GAMMA2 || (a0 === -GAMMA2 && a1 !== 0)) return 1;
|
|
620
|
+
|
|
621
|
+
return 0;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
function useHint(a, hint) {
|
|
625
|
+
const a0 = new Int32Array(1);
|
|
626
|
+
const a1 = decompose(a0, 0, a);
|
|
627
|
+
|
|
628
|
+
if (hint === 0) return a1;
|
|
629
|
+
|
|
630
|
+
if (a0[0] > 0) return (a1 + 1) & 15;
|
|
631
|
+
return (a1 - 1) & 15;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
class Poly {
|
|
635
|
+
constructor() {
|
|
636
|
+
this.coeffs = new Int32Array(N);
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
copy(poly) {
|
|
640
|
+
for (let i = N - 1; i >= 0; i--) {
|
|
641
|
+
this.coeffs[i] = poly.coeffs[i];
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
function polyReduce(aP) {
|
|
647
|
+
const a = aP;
|
|
648
|
+
for (let i = 0; i < N; ++i) a.coeffs[i] = reduce32(a.coeffs[i]);
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
function polyCAddQ(aP) {
|
|
652
|
+
const a = aP;
|
|
653
|
+
for (let i = 0; i < N; ++i) a.coeffs[i] = cAddQ(a.coeffs[i]);
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
function polyAdd(cP, a, b) {
|
|
657
|
+
const c = cP;
|
|
658
|
+
for (let i = 0; i < N; ++i) c.coeffs[i] = a.coeffs[i] + b.coeffs[i];
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
function polySub(cP, a, b) {
|
|
662
|
+
const c = cP;
|
|
663
|
+
for (let i = 0; i < N; ++i) c.coeffs[i] = a.coeffs[i] - b.coeffs[i];
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
function polyShiftL(aP) {
|
|
667
|
+
const a = aP;
|
|
668
|
+
for (let i = 0; i < N; ++i) a.coeffs[i] <<= D;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
function polyNTT(a) {
|
|
672
|
+
ntt(a.coeffs);
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
function polyInvNTTToMont(a) {
|
|
676
|
+
invNTTToMont(a.coeffs);
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
function polyPointWiseMontgomery(cP, a, b) {
|
|
680
|
+
const c = cP;
|
|
681
|
+
for (let i = 0; i < N; ++i) c.coeffs[i] = Number(montgomeryReduce(BigInt(a.coeffs[i]) * BigInt(b.coeffs[i])));
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
function polyPower2round(a1p, a0, a) {
|
|
685
|
+
const a1 = a1p;
|
|
686
|
+
for (let i = 0; i < N; ++i) a1.coeffs[i] = power2round(a0.coeffs, i, a.coeffs[i]);
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
function polyDecompose(a1p, a0, a) {
|
|
690
|
+
const a1 = a1p;
|
|
691
|
+
for (let i = 0; i < N; ++i) a1.coeffs[i] = decompose(a0.coeffs, i, a.coeffs[i]);
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
function polyMakeHint(hp, a0, a1) {
|
|
695
|
+
let s = 0;
|
|
696
|
+
const h = hp;
|
|
697
|
+
for (let i = 0; i < N; ++i) {
|
|
698
|
+
h.coeffs[i] = makeHint(a0.coeffs[i], a1.coeffs[i]);
|
|
699
|
+
s += h.coeffs[i];
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
return s;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
function polyUseHint(bp, a, h) {
|
|
706
|
+
const b = bp;
|
|
707
|
+
for (let i = 0; i < N; ++i) {
|
|
708
|
+
b.coeffs[i] = useHint(a.coeffs[i], h.coeffs[i]);
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
function polyChkNorm(a, b) {
|
|
713
|
+
if (b > Math.floor((Q - 1) / 8)) {
|
|
714
|
+
return 1;
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
for (let i = 0; i < N; i++) {
|
|
718
|
+
let t = a.coeffs[i] >> 31;
|
|
719
|
+
t = a.coeffs[i] - (t & (2 * a.coeffs[i]));
|
|
720
|
+
|
|
721
|
+
if (t >= b) {
|
|
722
|
+
return 1;
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
return 0;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
function rejUniform(ap, aOffset, len, buf, bufLen) {
|
|
730
|
+
let ctr = 0;
|
|
731
|
+
let pos = 0;
|
|
732
|
+
const a = ap;
|
|
733
|
+
while (ctr < len && pos + 3 <= bufLen) {
|
|
734
|
+
let t = buf[pos++];
|
|
735
|
+
t |= buf[pos++] << 8;
|
|
736
|
+
t |= buf[pos++] << 16;
|
|
737
|
+
t &= 0x7fffff;
|
|
738
|
+
|
|
739
|
+
if (t < Q) {
|
|
740
|
+
a[aOffset + ctr++] = t;
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
return ctr;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
function polyUniform(a, seed, nonce) {
|
|
748
|
+
let off = 0;
|
|
749
|
+
let bufLen = PolyUniformNBlocks * Stream128BlockBytes;
|
|
750
|
+
const buf = new Uint8Array(PolyUniformNBlocks * Stream128BlockBytes + 2);
|
|
751
|
+
|
|
752
|
+
const state = new KeccakState();
|
|
753
|
+
dilithiumShake128StreamInit(state, seed, nonce);
|
|
754
|
+
shake128SqueezeBlocks(buf, off, PolyUniformNBlocks, state);
|
|
755
|
+
|
|
756
|
+
let ctr = rejUniform(a.coeffs, 0, N, buf, bufLen);
|
|
757
|
+
|
|
758
|
+
while (ctr < N) {
|
|
759
|
+
off = bufLen % 3;
|
|
760
|
+
for (let i = 0; i < off; ++i) buf[i] = buf[bufLen - off + i];
|
|
761
|
+
|
|
762
|
+
shake128SqueezeBlocks(buf, off, 1, state);
|
|
763
|
+
bufLen = Stream128BlockBytes + off;
|
|
764
|
+
ctr += rejUniform(a.coeffs, ctr, N - ctr, buf, bufLen);
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
function rejEta(aP, aOffset, len, buf, bufLen) {
|
|
769
|
+
let ctr;
|
|
770
|
+
let pos;
|
|
771
|
+
let t0;
|
|
772
|
+
let t1;
|
|
773
|
+
const a = aP;
|
|
774
|
+
ctr = 0;
|
|
775
|
+
pos = 0;
|
|
776
|
+
while (ctr < len && pos < bufLen) {
|
|
777
|
+
t0 = buf[pos] & 0x0f;
|
|
778
|
+
t1 = buf[pos++] >> 4;
|
|
779
|
+
|
|
780
|
+
if (t0 < 15) {
|
|
781
|
+
t0 -= ((205 * t0) >> 10) * 5;
|
|
782
|
+
a[aOffset + ctr++] = 2 - t0;
|
|
783
|
+
}
|
|
784
|
+
if (t1 < 15 && ctr < len) {
|
|
785
|
+
t1 -= ((205 * t1) >> 10) * 5;
|
|
786
|
+
a[aOffset + ctr++] = 2 - t1;
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
return ctr;
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
function polyUniformEta(a, seed, nonce) {
|
|
794
|
+
let ctr;
|
|
795
|
+
const bufLen = PolyUniformETANBlocks * Stream256BlockBytes;
|
|
796
|
+
const buf = new Uint8Array(bufLen);
|
|
797
|
+
|
|
798
|
+
const state = new KeccakState();
|
|
799
|
+
dilithiumShake256StreamInit(state, seed, nonce);
|
|
800
|
+
shake256SqueezeBlocks(buf, 0, PolyUniformETANBlocks, state);
|
|
801
|
+
|
|
802
|
+
ctr = rejEta(a.coeffs, 0, N, buf, bufLen);
|
|
803
|
+
while (ctr < N) {
|
|
804
|
+
shake256SqueezeBlocks(buf, 0, 1, state);
|
|
805
|
+
ctr += rejEta(a.coeffs, ctr, N - ctr, buf, Stream256BlockBytes);
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
function polyZUnpack(rP, a, aOffset) {
|
|
810
|
+
const r = rP;
|
|
811
|
+
for (let i = 0; i < N / 2; ++i) {
|
|
812
|
+
r.coeffs[2 * i] = a[aOffset + 5 * i];
|
|
813
|
+
r.coeffs[2 * i] |= a[aOffset + 5 * i + 1] << 8;
|
|
814
|
+
r.coeffs[2 * i] |= a[aOffset + 5 * i + 2] << 16;
|
|
815
|
+
r.coeffs[2 * i] &= 0xfffff;
|
|
816
|
+
|
|
817
|
+
r.coeffs[2 * i + 1] = a[aOffset + 5 * i + 2] >> 4;
|
|
818
|
+
r.coeffs[2 * i + 1] |= a[aOffset + 5 * i + 3] << 4;
|
|
819
|
+
r.coeffs[2 * i + 1] |= a[aOffset + 5 * i + 4] << 12;
|
|
820
|
+
r.coeffs[2 * i] &= 0xfffff;
|
|
821
|
+
|
|
822
|
+
r.coeffs[2 * i] = GAMMA1 - r.coeffs[2 * i];
|
|
823
|
+
r.coeffs[2 * i + 1] = GAMMA1 - r.coeffs[2 * i + 1];
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
function polyUniformGamma1(a, seed, nonce) {
|
|
828
|
+
const buf = new Uint8Array(PolyUniformGamma1NBlocks * Stream256BlockBytes);
|
|
829
|
+
|
|
830
|
+
const state = new KeccakState();
|
|
831
|
+
dilithiumShake256StreamInit(state, seed, nonce);
|
|
832
|
+
shake256SqueezeBlocks(buf, 0, PolyUniformGamma1NBlocks, state);
|
|
833
|
+
polyZUnpack(a, buf, 0);
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
function polyChallenge(cP, seed) {
|
|
837
|
+
let b;
|
|
838
|
+
let pos;
|
|
839
|
+
const c = cP;
|
|
840
|
+
const buf = new Uint8Array(Shake256Rate);
|
|
841
|
+
|
|
842
|
+
const state = new KeccakState();
|
|
843
|
+
shake256Init(state);
|
|
844
|
+
shake256Absorb(state, seed.slice(0, SeedBytes));
|
|
845
|
+
shake256Finalize(state);
|
|
846
|
+
shake256SqueezeBlocks(buf, 0, 1, state);
|
|
847
|
+
|
|
848
|
+
let signs = 0n;
|
|
849
|
+
for (let i = 0; i < 8; ++i) {
|
|
850
|
+
signs = BigInt.asUintN(64, signs | (BigInt(buf[i]) << BigInt(8 * i)));
|
|
851
|
+
}
|
|
852
|
+
pos = 8;
|
|
853
|
+
|
|
854
|
+
for (let i = 0; i < N; ++i) {
|
|
855
|
+
c.coeffs[i] = 0;
|
|
856
|
+
}
|
|
857
|
+
for (let i = N - TAU; i < N; ++i) {
|
|
858
|
+
do {
|
|
859
|
+
if (pos >= Shake256Rate) {
|
|
860
|
+
shake256SqueezeBlocks(buf, 0, 1, state);
|
|
861
|
+
pos = 0;
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
b = buf[pos++];
|
|
865
|
+
} while (b > i);
|
|
866
|
+
|
|
867
|
+
c.coeffs[i] = c.coeffs[b];
|
|
868
|
+
c.coeffs[b] = Number(1n - 2n * (signs & 1n));
|
|
869
|
+
signs >>= 1n;
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
function polyEtaPack(rP, rOffset, a) {
|
|
874
|
+
const t = new Uint8Array(8);
|
|
875
|
+
const r = rP;
|
|
876
|
+
for (let i = 0; i < N / 8; ++i) {
|
|
877
|
+
t[0] = ETA - a.coeffs[8 * i];
|
|
878
|
+
t[1] = ETA - a.coeffs[8 * i + 1];
|
|
879
|
+
t[2] = ETA - a.coeffs[8 * i + 2];
|
|
880
|
+
t[3] = ETA - a.coeffs[8 * i + 3];
|
|
881
|
+
t[4] = ETA - a.coeffs[8 * i + 4];
|
|
882
|
+
t[5] = ETA - a.coeffs[8 * i + 5];
|
|
883
|
+
t[6] = ETA - a.coeffs[8 * i + 6];
|
|
884
|
+
t[7] = ETA - a.coeffs[8 * i + 7];
|
|
885
|
+
|
|
886
|
+
r[rOffset + 3 * i] = (t[0] >> 0) | (t[1] << 3) | (t[2] << 6);
|
|
887
|
+
r[rOffset + 3 * i + 1] = (t[2] >> 2) | (t[3] << 1) | (t[4] << 4) | (t[5] << 7);
|
|
888
|
+
r[rOffset + 3 * i + 2] = (t[5] >> 1) | (t[6] << 2) | (t[7] << 5);
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
function polyEtaUnpack(rP, a, aOffset) {
|
|
893
|
+
const r = rP;
|
|
894
|
+
for (let i = 0; i < N / 8; ++i) {
|
|
895
|
+
r.coeffs[8 * i] = (a[aOffset + 3 * i] >> 0) & 7;
|
|
896
|
+
r.coeffs[8 * i + 1] = (a[aOffset + 3 * i] >> 3) & 7;
|
|
897
|
+
r.coeffs[8 * i + 2] = ((a[aOffset + 3 * i] >> 6) | (a[aOffset + 3 * i + 1] << 2)) & 7;
|
|
898
|
+
r.coeffs[8 * i + 3] = (a[aOffset + 3 * i + 1] >> 1) & 7;
|
|
899
|
+
r.coeffs[8 * i + 4] = (a[aOffset + 3 * i + 1] >> 4) & 7;
|
|
900
|
+
r.coeffs[8 * i + 5] = ((a[aOffset + 3 * i + 1] >> 7) | (a[aOffset + 3 * i + 2] << 1)) & 7;
|
|
901
|
+
r.coeffs[8 * i + 6] = (a[aOffset + 3 * i + 2] >> 2) & 7;
|
|
902
|
+
r.coeffs[8 * i + 7] = (a[aOffset + 3 * i + 2] >> 5) & 7;
|
|
903
|
+
|
|
904
|
+
r.coeffs[8 * i] = ETA - r.coeffs[8 * i];
|
|
905
|
+
r.coeffs[8 * i + 1] = ETA - r.coeffs[8 * i + 1];
|
|
906
|
+
r.coeffs[8 * i + 2] = ETA - r.coeffs[8 * i + 2];
|
|
907
|
+
r.coeffs[8 * i + 3] = ETA - r.coeffs[8 * i + 3];
|
|
908
|
+
r.coeffs[8 * i + 4] = ETA - r.coeffs[8 * i + 4];
|
|
909
|
+
r.coeffs[8 * i + 5] = ETA - r.coeffs[8 * i + 5];
|
|
910
|
+
r.coeffs[8 * i + 6] = ETA - r.coeffs[8 * i + 6];
|
|
911
|
+
r.coeffs[8 * i + 7] = ETA - r.coeffs[8 * i + 7];
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
function polyT1Pack(rP, rOffset, a) {
|
|
916
|
+
const r = rP;
|
|
917
|
+
for (let i = 0; i < N / 4; ++i) {
|
|
918
|
+
r[rOffset + 5 * i] = a.coeffs[4 * i] >> 0;
|
|
919
|
+
r[rOffset + 5 * i + 1] = (a.coeffs[4 * i] >> 8) | (a.coeffs[4 * i + 1] << 2);
|
|
920
|
+
r[rOffset + 5 * i + 2] = (a.coeffs[4 * i + 1] >> 6) | (a.coeffs[4 * i + 2] << 4);
|
|
921
|
+
r[rOffset + 5 * i + 3] = (a.coeffs[4 * i + 2] >> 4) | (a.coeffs[4 * i + 3] << 6);
|
|
922
|
+
r[rOffset + 5 * i + 4] = a.coeffs[4 * i + 3] >> 2;
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
function polyT1Unpack(rP, a, aOffset) {
|
|
927
|
+
const r = rP;
|
|
928
|
+
for (let i = 0; i < N / 4; ++i) {
|
|
929
|
+
r.coeffs[4 * i] = ((a[aOffset + 5 * i] >> 0) | (a[aOffset + 5 * i + 1] << 8)) & 0x3ff;
|
|
930
|
+
r.coeffs[4 * i + 1] = ((a[aOffset + 5 * i + 1] >> 2) | (a[aOffset + 5 * i + 2] << 6)) & 0x3ff;
|
|
931
|
+
r.coeffs[4 * i + 2] = ((a[aOffset + 5 * i + 2] >> 4) | (a[aOffset + 5 * i + 3] << 4)) & 0x3ff;
|
|
932
|
+
r.coeffs[4 * i + 3] = ((a[aOffset + 5 * i + 3] >> 6) | (a[aOffset + 5 * i + 4] << 2)) & 0x3ff;
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
function polyT0Pack(rP, rOffset, a) {
|
|
937
|
+
const t = new Uint32Array(8);
|
|
938
|
+
const r = rP;
|
|
939
|
+
for (let i = 0; i < N / 8; ++i) {
|
|
940
|
+
t[0] = (1 << (D - 1)) - a.coeffs[8 * i];
|
|
941
|
+
t[1] = (1 << (D - 1)) - a.coeffs[8 * i + 1];
|
|
942
|
+
t[2] = (1 << (D - 1)) - a.coeffs[8 * i + 2];
|
|
943
|
+
t[3] = (1 << (D - 1)) - a.coeffs[8 * i + 3];
|
|
944
|
+
t[4] = (1 << (D - 1)) - a.coeffs[8 * i + 4];
|
|
945
|
+
t[5] = (1 << (D - 1)) - a.coeffs[8 * i + 5];
|
|
946
|
+
t[6] = (1 << (D - 1)) - a.coeffs[8 * i + 6];
|
|
947
|
+
t[7] = (1 << (D - 1)) - a.coeffs[8 * i + 7];
|
|
948
|
+
|
|
949
|
+
r[rOffset + 13 * i] = t[0]; // eslint-disable-line prefer-destructuring
|
|
950
|
+
r[rOffset + 13 * i + 1] = t[0] >> 8;
|
|
951
|
+
r[rOffset + 13 * i + 1] |= t[1] << 5;
|
|
952
|
+
r[rOffset + 13 * i + 2] = t[1] >> 3;
|
|
953
|
+
r[rOffset + 13 * i + 3] = t[1] >> 11;
|
|
954
|
+
r[rOffset + 13 * i + 3] |= t[2] << 2;
|
|
955
|
+
r[rOffset + 13 * i + 4] = t[2] >> 6;
|
|
956
|
+
r[rOffset + 13 * i + 4] |= t[3] << 7;
|
|
957
|
+
r[rOffset + 13 * i + 5] = t[3] >> 1;
|
|
958
|
+
r[rOffset + 13 * i + 6] = t[3] >> 9;
|
|
959
|
+
r[rOffset + 13 * i + 6] |= t[4] << 4;
|
|
960
|
+
r[rOffset + 13 * i + 7] = t[4] >> 4;
|
|
961
|
+
r[rOffset + 13 * i + 8] = t[4] >> 12;
|
|
962
|
+
r[rOffset + 13 * i + 8] |= t[5] << 1;
|
|
963
|
+
r[rOffset + 13 * i + 9] = t[5] >> 7;
|
|
964
|
+
r[rOffset + 13 * i + 9] |= t[6] << 6;
|
|
965
|
+
r[rOffset + 13 * i + 10] = t[6] >> 2;
|
|
966
|
+
r[rOffset + 13 * i + 11] = t[6] >> 10;
|
|
967
|
+
r[rOffset + 13 * i + 11] |= t[7] << 3;
|
|
968
|
+
r[rOffset + 13 * i + 12] = t[7] >> 5;
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
function polyT0Unpack(rP, a, aOffset) {
|
|
973
|
+
const r = rP;
|
|
974
|
+
for (let i = 0; i < N / 8; ++i) {
|
|
975
|
+
r.coeffs[8 * i] = a[aOffset + 13 * i];
|
|
976
|
+
r.coeffs[8 * i] |= a[aOffset + 13 * i + 1] << 8;
|
|
977
|
+
r.coeffs[8 * i] &= 0x1fff;
|
|
978
|
+
|
|
979
|
+
r.coeffs[8 * i + 1] = a[aOffset + 13 * i + 1] >> 5;
|
|
980
|
+
r.coeffs[8 * i + 1] |= a[aOffset + 13 * i + 2] << 3;
|
|
981
|
+
r.coeffs[8 * i + 1] |= a[aOffset + 13 * i + 3] << 11;
|
|
982
|
+
r.coeffs[8 * i + 1] &= 0x1fff;
|
|
983
|
+
|
|
984
|
+
r.coeffs[8 * i + 2] = a[aOffset + 13 * i + 3] >> 2;
|
|
985
|
+
r.coeffs[8 * i + 2] |= a[aOffset + 13 * i + 4] << 6;
|
|
986
|
+
r.coeffs[8 * i + 2] &= 0x1fff;
|
|
987
|
+
|
|
988
|
+
r.coeffs[8 * i + 3] = a[aOffset + 13 * i + 4] >> 7;
|
|
989
|
+
r.coeffs[8 * i + 3] |= a[aOffset + 13 * i + 5] << 1;
|
|
990
|
+
r.coeffs[8 * i + 3] |= a[aOffset + 13 * i + 6] << 9;
|
|
991
|
+
r.coeffs[8 * i + 3] &= 0x1fff;
|
|
992
|
+
|
|
993
|
+
r.coeffs[8 * i + 4] = a[aOffset + 13 * i + 6] >> 4;
|
|
994
|
+
r.coeffs[8 * i + 4] |= a[aOffset + 13 * i + 7] << 4;
|
|
995
|
+
r.coeffs[8 * i + 4] |= a[aOffset + 13 * i + 8] << 12;
|
|
996
|
+
r.coeffs[8 * i + 4] &= 0x1fff;
|
|
997
|
+
|
|
998
|
+
r.coeffs[8 * i + 5] = a[aOffset + 13 * i + 8] >> 1;
|
|
999
|
+
r.coeffs[8 * i + 5] |= a[aOffset + 13 * i + 9] << 7;
|
|
1000
|
+
r.coeffs[8 * i + 5] &= 0x1fff;
|
|
1001
|
+
|
|
1002
|
+
r.coeffs[8 * i + 6] = a[aOffset + 13 * i + 9] >> 6;
|
|
1003
|
+
r.coeffs[8 * i + 6] |= a[aOffset + 13 * i + 10] << 2;
|
|
1004
|
+
r.coeffs[8 * i + 6] |= a[aOffset + 13 * i + 11] << 10;
|
|
1005
|
+
r.coeffs[8 * i + 6] &= 0x1fff;
|
|
1006
|
+
|
|
1007
|
+
r.coeffs[8 * i + 7] = a[aOffset + 13 * i + 11] >> 3;
|
|
1008
|
+
r.coeffs[8 * i + 7] |= a[aOffset + 13 * i + 12] << 5;
|
|
1009
|
+
r.coeffs[8 * i + 7] &= 0x1fff;
|
|
1010
|
+
|
|
1011
|
+
r.coeffs[8 * i] = (1 << (D - 1)) - r.coeffs[8 * i];
|
|
1012
|
+
r.coeffs[8 * i + 1] = (1 << (D - 1)) - r.coeffs[8 * i + 1];
|
|
1013
|
+
r.coeffs[8 * i + 2] = (1 << (D - 1)) - r.coeffs[8 * i + 2];
|
|
1014
|
+
r.coeffs[8 * i + 3] = (1 << (D - 1)) - r.coeffs[8 * i + 3];
|
|
1015
|
+
r.coeffs[8 * i + 4] = (1 << (D - 1)) - r.coeffs[8 * i + 4];
|
|
1016
|
+
r.coeffs[8 * i + 5] = (1 << (D - 1)) - r.coeffs[8 * i + 5];
|
|
1017
|
+
r.coeffs[8 * i + 6] = (1 << (D - 1)) - r.coeffs[8 * i + 6];
|
|
1018
|
+
r.coeffs[8 * i + 7] = (1 << (D - 1)) - r.coeffs[8 * i + 7];
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
function polyZPack(rP, rOffset, a) {
|
|
1023
|
+
const t = new Uint32Array(4);
|
|
1024
|
+
const r = rP;
|
|
1025
|
+
for (let i = 0; i < N / 2; ++i) {
|
|
1026
|
+
t[0] = GAMMA1 - a.coeffs[2 * i];
|
|
1027
|
+
t[1] = GAMMA1 - a.coeffs[2 * i + 1];
|
|
1028
|
+
|
|
1029
|
+
r[rOffset + 5 * i] = t[0]; // eslint-disable-line prefer-destructuring
|
|
1030
|
+
r[rOffset + 5 * i + 1] = t[0] >> 8;
|
|
1031
|
+
r[rOffset + 5 * i + 2] = t[0] >> 16;
|
|
1032
|
+
r[rOffset + 5 * i + 2] |= t[1] << 4;
|
|
1033
|
+
r[rOffset + 5 * i + 3] = t[1] >> 4;
|
|
1034
|
+
r[rOffset + 5 * i + 4] = t[1] >> 12;
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
function polyW1Pack(rP, rOffset, a) {
|
|
1039
|
+
const r = rP;
|
|
1040
|
+
for (let i = 0; i < N / 2; ++i) {
|
|
1041
|
+
r[rOffset + i] = a.coeffs[2 * i] | (a.coeffs[2 * i + 1] << 4);
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
class PolyVecK {
|
|
1046
|
+
constructor() {
|
|
1047
|
+
this.vec = new Array(K).fill().map(() => new Poly());
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
class PolyVecL {
|
|
1052
|
+
constructor() {
|
|
1053
|
+
this.vec = new Array(L).fill().map(() => new Poly());
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
copy(polyVecL) {
|
|
1057
|
+
for (let i = L - 1; i >= 0; i--) {
|
|
1058
|
+
this.vec[i].copy(polyVecL.vec[i]);
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
function polyVecMatrixExpand(mat, rho) {
|
|
1064
|
+
if (rho.length !== SeedBytes) {
|
|
1065
|
+
throw new Error(`invalid rho length ${rho.length} | Expected length ${SeedBytes}`);
|
|
1066
|
+
}
|
|
1067
|
+
for (let i = 0; i < K; ++i) {
|
|
1068
|
+
for (let j = 0; j < L; ++j) {
|
|
1069
|
+
polyUniform(mat[i].vec[j], rho, (i << 8) + j);
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
function polyVecMatrixPointWiseMontgomery(t, mat, v) {
|
|
1075
|
+
for (let i = 0; i < K; ++i) {
|
|
1076
|
+
polyVecLPointWiseAccMontgomery(t.vec[i], mat[i], v); // eslint-disable-line no-use-before-define
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
function polyVecLUniformEta(v, seed, nonceP) {
|
|
1081
|
+
let nonce = nonceP;
|
|
1082
|
+
if (seed.length !== CRHBytes) {
|
|
1083
|
+
throw new Error(`invalid seed length ${seed.length} | Expected length ${CRHBytes}`);
|
|
1084
|
+
}
|
|
1085
|
+
for (let i = 0; i < L; i++) {
|
|
1086
|
+
polyUniformEta(v.vec[i], seed, nonce++);
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
function polyVecLUniformGamma1(v, seed, nonce) {
|
|
1091
|
+
if (seed.length !== CRHBytes) {
|
|
1092
|
+
throw new Error(`invalid seed length ${seed.length} | Expected length ${CRHBytes}`);
|
|
1093
|
+
}
|
|
1094
|
+
for (let i = 0; i < L; i++) {
|
|
1095
|
+
polyUniformGamma1(v.vec[i], seed, L * nonce + i);
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
function polyVecLReduce(v) {
|
|
1100
|
+
for (let i = 0; i < L; i++) {
|
|
1101
|
+
polyReduce(v.vec[i]);
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
function polyVecLAdd(w, u, v) {
|
|
1106
|
+
for (let i = 0; i < L; ++i) {
|
|
1107
|
+
polyAdd(w.vec[i], u.vec[i], v.vec[i]);
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
function polyVecLNTT(v) {
|
|
1112
|
+
for (let i = 0; i < L; ++i) {
|
|
1113
|
+
polyNTT(v.vec[i]);
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
function polyVecLInvNTTToMont(v) {
|
|
1118
|
+
for (let i = 0; i < L; ++i) {
|
|
1119
|
+
polyInvNTTToMont(v.vec[i]);
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
function polyVecLPointWisePolyMontgomery(r, a, v) {
|
|
1124
|
+
for (let i = 0; i < L; ++i) {
|
|
1125
|
+
polyPointWiseMontgomery(r.vec[i], a, v.vec[i]);
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
function polyVecLPointWiseAccMontgomery(w, u, v) {
|
|
1130
|
+
const t = new Poly();
|
|
1131
|
+
polyPointWiseMontgomery(w, u.vec[0], v.vec[0]);
|
|
1132
|
+
for (let i = 1; i < L; i++) {
|
|
1133
|
+
polyPointWiseMontgomery(t, u.vec[i], v.vec[i]);
|
|
1134
|
+
polyAdd(w, w, t);
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
function polyVecLChkNorm(v, bound) {
|
|
1139
|
+
for (let i = 0; i < L; i++) {
|
|
1140
|
+
if (polyChkNorm(v.vec[i], bound) !== 0) {
|
|
1141
|
+
return 1;
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
return 0;
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
function polyVecKUniformEta(v, seed, nonceP) {
|
|
1148
|
+
let nonce = nonceP;
|
|
1149
|
+
for (let i = 0; i < K; ++i) {
|
|
1150
|
+
polyUniformEta(v.vec[i], seed, nonce++);
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
function polyVecKReduce(v) {
|
|
1155
|
+
for (let i = 0; i < K; ++i) {
|
|
1156
|
+
polyReduce(v.vec[i]);
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
function polyVecKCAddQ(v) {
|
|
1161
|
+
for (let i = 0; i < K; ++i) {
|
|
1162
|
+
polyCAddQ(v.vec[i]);
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
function polyVecKAdd(w, u, v) {
|
|
1167
|
+
for (let i = 0; i < K; ++i) {
|
|
1168
|
+
polyAdd(w.vec[i], u.vec[i], v.vec[i]);
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
function polyVecKSub(w, u, v) {
|
|
1173
|
+
for (let i = 0; i < K; ++i) {
|
|
1174
|
+
polySub(w.vec[i], u.vec[i], v.vec[i]);
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
function polyVecKShiftL(v) {
|
|
1179
|
+
for (let i = 0; i < K; ++i) {
|
|
1180
|
+
polyShiftL(v.vec[i]);
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
function polyVecKNTT(v) {
|
|
1185
|
+
for (let i = 0; i < K; i++) {
|
|
1186
|
+
polyNTT(v.vec[i]);
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1190
|
+
function polyVecKInvNTTToMont(v) {
|
|
1191
|
+
for (let i = 0; i < K; i++) {
|
|
1192
|
+
polyInvNTTToMont(v.vec[i]);
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
function polyVecKPointWisePolyMontgomery(r, a, v) {
|
|
1197
|
+
for (let i = 0; i < K; i++) {
|
|
1198
|
+
polyPointWiseMontgomery(r.vec[i], a, v.vec[i]);
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
function polyVecKChkNorm(v, bound) {
|
|
1203
|
+
for (let i = 0; i < K; i++) {
|
|
1204
|
+
if (polyChkNorm(v.vec[i], bound) !== 0) {
|
|
1205
|
+
return 1;
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
return 0;
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1211
|
+
function polyVecKPower2round(v1, v0, v) {
|
|
1212
|
+
for (let i = 0; i < K; i++) {
|
|
1213
|
+
polyPower2round(v1.vec[i], v0.vec[i], v.vec[i]);
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
function polyVecKDecompose(v1, v0, v) {
|
|
1218
|
+
for (let i = 0; i < K; i++) {
|
|
1219
|
+
polyDecompose(v1.vec[i], v0.vec[i], v.vec[i]);
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
function polyVecKMakeHint(h, v0, v1) {
|
|
1224
|
+
let s = 0;
|
|
1225
|
+
for (let i = 0; i < K; i++) {
|
|
1226
|
+
s += polyMakeHint(h.vec[i], v0.vec[i], v1.vec[i]);
|
|
1227
|
+
}
|
|
1228
|
+
return s;
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1231
|
+
function polyVecKUseHint(w, u, h) {
|
|
1232
|
+
for (let i = 0; i < K; ++i) {
|
|
1233
|
+
polyUseHint(w.vec[i], u.vec[i], h.vec[i]);
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
function polyVecKPackW1(r, w1) {
|
|
1238
|
+
for (let i = 0; i < K; ++i) {
|
|
1239
|
+
polyW1Pack(r, i * PolyW1PackedBytes, w1.vec[i]);
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
function packPk(pkp, rho, t1) {
|
|
1244
|
+
const pk = pkp;
|
|
1245
|
+
for (let i = 0; i < SeedBytes; ++i) {
|
|
1246
|
+
pk[i] = rho[i];
|
|
1247
|
+
}
|
|
1248
|
+
for (let i = 0; i < K; ++i) {
|
|
1249
|
+
polyT1Pack(pk, SeedBytes + i * PolyT1PackedBytes, t1.vec[i]);
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
function unpackPk(rhop, t1, pk) {
|
|
1254
|
+
const rho = rhop;
|
|
1255
|
+
for (let i = 0; i < SeedBytes; ++i) {
|
|
1256
|
+
rho[i] = pk[i];
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
for (let i = 0; i < K; ++i) {
|
|
1260
|
+
polyT1Unpack(t1.vec[i], pk, SeedBytes + i * PolyT1PackedBytes);
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
function packSk(skp, rho, tr, key, t0, s1, s2) {
|
|
1265
|
+
let skOffset = 0;
|
|
1266
|
+
const sk = skp;
|
|
1267
|
+
for (let i = 0; i < SeedBytes; ++i) {
|
|
1268
|
+
sk[i] = rho[i];
|
|
1269
|
+
}
|
|
1270
|
+
skOffset += SeedBytes;
|
|
1271
|
+
|
|
1272
|
+
for (let i = 0; i < SeedBytes; ++i) {
|
|
1273
|
+
sk[skOffset + i] = key[i];
|
|
1274
|
+
}
|
|
1275
|
+
skOffset += SeedBytes;
|
|
1276
|
+
|
|
1277
|
+
for (let i = 0; i < SeedBytes; ++i) {
|
|
1278
|
+
sk[skOffset + i] = tr[i];
|
|
1279
|
+
}
|
|
1280
|
+
skOffset += SeedBytes;
|
|
1281
|
+
|
|
1282
|
+
for (let i = 0; i < L; ++i) {
|
|
1283
|
+
polyEtaPack(sk, skOffset + i * PolyETAPackedBytes, s1.vec[i]);
|
|
1284
|
+
}
|
|
1285
|
+
skOffset += L * PolyETAPackedBytes;
|
|
1286
|
+
|
|
1287
|
+
for (let i = 0; i < K; ++i) {
|
|
1288
|
+
polyEtaPack(sk, skOffset + i * PolyETAPackedBytes, s2.vec[i]);
|
|
1289
|
+
}
|
|
1290
|
+
skOffset += K * PolyETAPackedBytes;
|
|
1291
|
+
|
|
1292
|
+
for (let i = 0; i < K; ++i) {
|
|
1293
|
+
polyT0Pack(sk, skOffset + i * PolyT0PackedBytes, t0.vec[i]);
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
|
|
1297
|
+
function unpackSk(rhoP, trP, keyP, t0, s1, s2, sk) {
|
|
1298
|
+
let skOffset = 0;
|
|
1299
|
+
const rho = rhoP;
|
|
1300
|
+
const tr = trP;
|
|
1301
|
+
const key = keyP;
|
|
1302
|
+
for (let i = 0; i < SeedBytes; ++i) {
|
|
1303
|
+
rho[i] = sk[skOffset + i];
|
|
1304
|
+
}
|
|
1305
|
+
skOffset += SeedBytes;
|
|
1306
|
+
|
|
1307
|
+
for (let i = 0; i < SeedBytes; ++i) {
|
|
1308
|
+
key[i] = sk[skOffset + i];
|
|
1309
|
+
}
|
|
1310
|
+
skOffset += SeedBytes;
|
|
1311
|
+
|
|
1312
|
+
for (let i = 0; i < SeedBytes; ++i) {
|
|
1313
|
+
tr[i] = sk[skOffset + i];
|
|
1314
|
+
}
|
|
1315
|
+
skOffset += SeedBytes;
|
|
1316
|
+
|
|
1317
|
+
for (let i = 0; i < L; ++i) {
|
|
1318
|
+
polyEtaUnpack(s1.vec[i], sk, skOffset + i * PolyETAPackedBytes);
|
|
1319
|
+
}
|
|
1320
|
+
skOffset += L * PolyETAPackedBytes;
|
|
1321
|
+
|
|
1322
|
+
for (let i = 0; i < K; ++i) {
|
|
1323
|
+
polyEtaUnpack(s2.vec[i], sk, skOffset + i * PolyETAPackedBytes);
|
|
1324
|
+
}
|
|
1325
|
+
skOffset += K * PolyETAPackedBytes;
|
|
1326
|
+
|
|
1327
|
+
for (let i = 0; i < K; ++i) {
|
|
1328
|
+
polyT0Unpack(t0.vec[i], sk, skOffset + i * PolyT0PackedBytes);
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
function packSig(sigP, c, z, h) {
|
|
1333
|
+
let sigOffset = 0;
|
|
1334
|
+
const sig = sigP;
|
|
1335
|
+
for (let i = 0; i < SeedBytes; ++i) {
|
|
1336
|
+
sig[i] = c[i];
|
|
1337
|
+
}
|
|
1338
|
+
sigOffset += SeedBytes;
|
|
1339
|
+
|
|
1340
|
+
for (let i = 0; i < L; ++i) {
|
|
1341
|
+
polyZPack(sig, sigOffset + i * PolyZPackedBytes, z.vec[i]);
|
|
1342
|
+
}
|
|
1343
|
+
sigOffset += L * PolyZPackedBytes;
|
|
1344
|
+
|
|
1345
|
+
for (let i = 0; i < OMEGA + K; ++i) {
|
|
1346
|
+
sig[sigOffset + i] = 0;
|
|
1347
|
+
}
|
|
1348
|
+
|
|
1349
|
+
let k = 0;
|
|
1350
|
+
for (let i = 0; i < K; ++i) {
|
|
1351
|
+
for (let j = 0; j < N; ++j) {
|
|
1352
|
+
if (h.vec[i].coeffs[j] !== 0) {
|
|
1353
|
+
sig[sigOffset + k++] = j;
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
|
|
1357
|
+
sig[sigOffset + OMEGA + i] = k;
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1361
|
+
function unpackSig(cP, z, hP, sig) {
|
|
1362
|
+
let sigOffset = 0;
|
|
1363
|
+
const c = cP;
|
|
1364
|
+
const h = hP;
|
|
1365
|
+
for (let i = 0; i < SeedBytes; ++i) {
|
|
1366
|
+
c[i] = sig[i];
|
|
1367
|
+
}
|
|
1368
|
+
sigOffset += SeedBytes;
|
|
1369
|
+
|
|
1370
|
+
for (let i = 0; i < L; ++i) {
|
|
1371
|
+
polyZUnpack(z.vec[i], sig, sigOffset + i * PolyZPackedBytes);
|
|
1372
|
+
}
|
|
1373
|
+
sigOffset += L * PolyZPackedBytes;
|
|
1374
|
+
|
|
1375
|
+
/* Decode h */
|
|
1376
|
+
let k = 0;
|
|
1377
|
+
for (let i = 0; i < K; ++i) {
|
|
1378
|
+
for (let j = 0; j < N; ++j) {
|
|
1379
|
+
h.vec[i].coeffs[j] = 0;
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
if (sig[sigOffset + OMEGA + i] < k || sig[sigOffset + OMEGA + i] > OMEGA) {
|
|
1383
|
+
return 1;
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1386
|
+
for (let j = k; j < sig[sigOffset + OMEGA + i]; ++j) {
|
|
1387
|
+
/* Coefficients are ordered for strong unforgeability */
|
|
1388
|
+
if (j > k && sig[sigOffset + j] <= sig[sigOffset + j - 1]) {
|
|
1389
|
+
return 1;
|
|
1390
|
+
}
|
|
1391
|
+
h.vec[i].coeffs[sig[sigOffset + j]] = 1;
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1394
|
+
k = sig[sigOffset + OMEGA + i];
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1397
|
+
/* Extra indices are zero for strong unforgeability */
|
|
1398
|
+
for (let j = k; j < OMEGA; ++j) {
|
|
1399
|
+
if (sig[sigOffset + j]) {
|
|
1400
|
+
return 1;
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
|
|
1404
|
+
return 0;
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1407
|
+
const randomBytes = pkg;
|
|
1408
|
+
|
|
1409
|
+
function cryptoSignKeypair(passedSeed, pk, sk) {
|
|
1410
|
+
try {
|
|
1411
|
+
if (pk.length !== CryptoPublicKeyBytes) {
|
|
1412
|
+
throw new Error(`invalid pk length ${pk.length} | Expected length ${CryptoPublicKeyBytes}`);
|
|
1413
|
+
}
|
|
1414
|
+
if (sk.length !== CryptoSecretKeyBytes) {
|
|
1415
|
+
throw new Error(`invalid sk length ${sk.length} | Expected length ${CryptoSecretKeyBytes}`);
|
|
1416
|
+
}
|
|
1417
|
+
} catch (e) {
|
|
1418
|
+
if (e instanceof TypeError) {
|
|
1419
|
+
throw new Error(`pk/sk cannot be null`);
|
|
1420
|
+
} else {
|
|
1421
|
+
throw new Error(`${e.message}`);
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
// eslint-disable-next-line no-unused-vars
|
|
1425
|
+
const mat = new Array(K).fill().map((_) => new PolyVecL());
|
|
1426
|
+
const s1 = new PolyVecL();
|
|
1427
|
+
const s2 = new PolyVecK();
|
|
1428
|
+
const t1 = new PolyVecK();
|
|
1429
|
+
const t0 = new PolyVecK();
|
|
1430
|
+
|
|
1431
|
+
// Get randomness for rho, rhoPrime and key
|
|
1432
|
+
const seed = passedSeed || randomBytes(SeedBytes);
|
|
1433
|
+
|
|
1434
|
+
const state = new sha3.SHAKE(256);
|
|
1435
|
+
let outputLength = 2 * SeedBytes + CRHBytes;
|
|
1436
|
+
state.update(seed);
|
|
1437
|
+
const seedBuf = state.digest({ buffer: Buffer.alloc(outputLength) });
|
|
1438
|
+
const rho = seedBuf.slice(0, SeedBytes);
|
|
1439
|
+
const rhoPrime = seedBuf.slice(SeedBytes, SeedBytes + CRHBytes);
|
|
1440
|
+
const key = seedBuf.slice(SeedBytes + CRHBytes);
|
|
1441
|
+
|
|
1442
|
+
// Expand matrix
|
|
1443
|
+
polyVecMatrixExpand(mat, rho);
|
|
1444
|
+
|
|
1445
|
+
// Sample short vectors s1 and s2
|
|
1446
|
+
polyVecLUniformEta(s1, rhoPrime, 0);
|
|
1447
|
+
polyVecKUniformEta(s2, rhoPrime, L);
|
|
1448
|
+
|
|
1449
|
+
// Matrix-vector multiplication
|
|
1450
|
+
const s1hat = new PolyVecL();
|
|
1451
|
+
s1hat.copy(s1);
|
|
1452
|
+
polyVecLNTT(s1hat);
|
|
1453
|
+
polyVecMatrixPointWiseMontgomery(t1, mat, s1hat);
|
|
1454
|
+
polyVecKReduce(t1);
|
|
1455
|
+
polyVecKInvNTTToMont(t1);
|
|
1456
|
+
|
|
1457
|
+
// Add error vector s2
|
|
1458
|
+
polyVecKAdd(t1, t1, s2);
|
|
1459
|
+
|
|
1460
|
+
// Extract t1 and write public key
|
|
1461
|
+
polyVecKCAddQ(t1);
|
|
1462
|
+
polyVecKPower2round(t1, t0, t1);
|
|
1463
|
+
packPk(pk, rho, t1);
|
|
1464
|
+
|
|
1465
|
+
// Compute H(rho, t1) and write secret key
|
|
1466
|
+
const hasher = new sha3.SHAKE(256);
|
|
1467
|
+
outputLength = SeedBytes;
|
|
1468
|
+
hasher.update(Buffer.from(pk, 'hex'));
|
|
1469
|
+
const tr = new Uint8Array(hasher.digest());
|
|
1470
|
+
packSk(sk, rho, tr, key, t0, s1, s2);
|
|
1471
|
+
|
|
1472
|
+
return seed;
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1475
|
+
function cryptoSignSignature(sig, m, sk, randomizedSigning) {
|
|
1476
|
+
if (sk.length !== CryptoSecretKeyBytes) {
|
|
1477
|
+
throw new Error(`invalid sk length ${sk.length} | Expected length ${CryptoSecretKeyBytes}`);
|
|
1478
|
+
}
|
|
1479
|
+
|
|
1480
|
+
const rho = new Uint8Array(SeedBytes);
|
|
1481
|
+
const tr = new Uint8Array(SeedBytes);
|
|
1482
|
+
const key = new Uint8Array(SeedBytes);
|
|
1483
|
+
let rhoPrime = new Uint8Array(CRHBytes);
|
|
1484
|
+
let nonce = 0;
|
|
1485
|
+
let state = null;
|
|
1486
|
+
const mat = Array(K)
|
|
1487
|
+
.fill()
|
|
1488
|
+
// eslint-disable-next-line no-unused-vars
|
|
1489
|
+
.map((_) => new PolyVecL());
|
|
1490
|
+
const s1 = new PolyVecL();
|
|
1491
|
+
const y = new PolyVecL();
|
|
1492
|
+
const z = new PolyVecL();
|
|
1493
|
+
const t0 = new PolyVecK();
|
|
1494
|
+
const s2 = new PolyVecK();
|
|
1495
|
+
const w1 = new PolyVecK();
|
|
1496
|
+
const w0 = new PolyVecK();
|
|
1497
|
+
const h = new PolyVecK();
|
|
1498
|
+
const cp = new Poly();
|
|
1499
|
+
|
|
1500
|
+
unpackSk(rho, tr, key, t0, s1, s2, sk);
|
|
1501
|
+
|
|
1502
|
+
state = new sha3.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) }));
|
|
1507
|
+
|
|
1508
|
+
if (randomizedSigning) rhoPrime = new Uint8Array(randomBytes(CRHBytes));
|
|
1509
|
+
else {
|
|
1510
|
+
state = new sha3.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) }));
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1517
|
+
polyVecMatrixExpand(mat, rho);
|
|
1518
|
+
polyVecLNTT(s1);
|
|
1519
|
+
polyVecKNTT(s2);
|
|
1520
|
+
polyVecKNTT(t0);
|
|
1521
|
+
|
|
1522
|
+
// eslint-disable-next-line no-constant-condition
|
|
1523
|
+
while (true) {
|
|
1524
|
+
polyVecLUniformGamma1(y, rhoPrime, nonce++);
|
|
1525
|
+
// Matrix-vector multiplication
|
|
1526
|
+
z.copy(y);
|
|
1527
|
+
polyVecLNTT(z);
|
|
1528
|
+
polyVecMatrixPointWiseMontgomery(w1, mat, z);
|
|
1529
|
+
polyVecKReduce(w1);
|
|
1530
|
+
polyVecKInvNTTToMont(w1);
|
|
1531
|
+
|
|
1532
|
+
// Decompose w and call the random oracle
|
|
1533
|
+
polyVecKCAddQ(w1);
|
|
1534
|
+
polyVecKDecompose(w1, w0, w1);
|
|
1535
|
+
polyVecKPackW1(sig, w1);
|
|
1536
|
+
|
|
1537
|
+
state = new sha3.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) }));
|
|
1542
|
+
|
|
1543
|
+
polyChallenge(cp, sig);
|
|
1544
|
+
polyNTT(cp);
|
|
1545
|
+
|
|
1546
|
+
// Compute z, reject if it reveals secret
|
|
1547
|
+
polyVecLPointWisePolyMontgomery(z, cp, s1);
|
|
1548
|
+
polyVecLInvNTTToMont(z);
|
|
1549
|
+
polyVecLAdd(z, z, y);
|
|
1550
|
+
polyVecLReduce(z);
|
|
1551
|
+
if (polyVecLChkNorm(z, GAMMA1 - BETA) !== 0) {
|
|
1552
|
+
continue; // eslint-disable-line no-continue
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1555
|
+
polyVecKPointWisePolyMontgomery(h, cp, s2);
|
|
1556
|
+
polyVecKInvNTTToMont(h);
|
|
1557
|
+
polyVecKSub(w0, w0, h);
|
|
1558
|
+
polyVecKReduce(w0);
|
|
1559
|
+
if (polyVecKChkNorm(w0, GAMMA2 - BETA) !== 0) {
|
|
1560
|
+
continue; // eslint-disable-line no-continue
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
polyVecKPointWisePolyMontgomery(h, cp, t0);
|
|
1564
|
+
polyVecKInvNTTToMont(h);
|
|
1565
|
+
polyVecKReduce(h);
|
|
1566
|
+
if (polyVecKChkNorm(h, GAMMA2) !== 0) {
|
|
1567
|
+
continue; // eslint-disable-line no-continue
|
|
1568
|
+
}
|
|
1569
|
+
|
|
1570
|
+
polyVecKAdd(w0, w0, h);
|
|
1571
|
+
const n = polyVecKMakeHint(h, w0, w1);
|
|
1572
|
+
if (n > OMEGA) {
|
|
1573
|
+
continue; // eslint-disable-line no-continue
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
packSig(sig, sig, z, h);
|
|
1577
|
+
return 0;
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
|
|
1581
|
+
function cryptoSign(msg, sk, randomizedSigning) {
|
|
1582
|
+
const sm = new Uint8Array(CryptoBytes + msg.length);
|
|
1583
|
+
const mLen = msg.length;
|
|
1584
|
+
for (let i = 0; i < mLen; ++i) {
|
|
1585
|
+
sm[CryptoBytes + mLen - 1 - i] = msg[mLen - 1 - i];
|
|
1586
|
+
}
|
|
1587
|
+
const result = cryptoSignSignature(sm, msg, sk, randomizedSigning);
|
|
1588
|
+
|
|
1589
|
+
if (result !== 0) {
|
|
1590
|
+
throw new Error('failed to sign');
|
|
1591
|
+
}
|
|
1592
|
+
return sm;
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
function cryptoSignVerify(sig, m, pk) {
|
|
1596
|
+
let i;
|
|
1597
|
+
const buf = new Uint8Array(K * PolyW1PackedBytes);
|
|
1598
|
+
const rho = new Uint8Array(SeedBytes);
|
|
1599
|
+
const mu = new Uint8Array(CRHBytes);
|
|
1600
|
+
const c = new Uint8Array(SeedBytes);
|
|
1601
|
+
const c2 = new Uint8Array(SeedBytes);
|
|
1602
|
+
const cp = new Poly();
|
|
1603
|
+
// eslint-disable-next-line no-unused-vars
|
|
1604
|
+
const mat = new Array(K).fill().map((_) => new PolyVecL());
|
|
1605
|
+
const z = new PolyVecL();
|
|
1606
|
+
const t1 = new PolyVecK();
|
|
1607
|
+
const w1 = new PolyVecK();
|
|
1608
|
+
const h = new PolyVecK();
|
|
1609
|
+
|
|
1610
|
+
if (sig.length !== CryptoBytes) {
|
|
1611
|
+
return false;
|
|
1612
|
+
}
|
|
1613
|
+
if (pk.length !== CryptoPublicKeyBytes) {
|
|
1614
|
+
return false;
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1617
|
+
unpackPk(rho, t1, pk);
|
|
1618
|
+
if (unpackSig(c, z, h, sig)) {
|
|
1619
|
+
return false;
|
|
1620
|
+
}
|
|
1621
|
+
if (polyVecLChkNorm(z, GAMMA1 - BETA)) {
|
|
1622
|
+
return false;
|
|
1623
|
+
}
|
|
1624
|
+
|
|
1625
|
+
/* Compute CRH(H(rho, t1), msg) */
|
|
1626
|
+
let state = new sha3.SHAKE(256);
|
|
1627
|
+
let outputLength = SeedBytes;
|
|
1628
|
+
state.update(pk.slice(0, CryptoPublicKeyBytes));
|
|
1629
|
+
mu.set(state.digest({ buffer: Buffer.alloc(outputLength) }));
|
|
1630
|
+
|
|
1631
|
+
state = new sha3.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) }));
|
|
1636
|
+
|
|
1637
|
+
/* Matrix-vector multiplication; compute Az - c2^dt1 */
|
|
1638
|
+
polyChallenge(cp, c);
|
|
1639
|
+
polyVecMatrixExpand(mat, rho);
|
|
1640
|
+
|
|
1641
|
+
polyVecLNTT(z);
|
|
1642
|
+
polyVecMatrixPointWiseMontgomery(w1, mat, z);
|
|
1643
|
+
|
|
1644
|
+
polyNTT(cp);
|
|
1645
|
+
polyVecKShiftL(t1);
|
|
1646
|
+
polyVecKNTT(t1);
|
|
1647
|
+
polyVecKPointWisePolyMontgomery(t1, cp, t1);
|
|
1648
|
+
|
|
1649
|
+
polyVecKSub(w1, w1, t1);
|
|
1650
|
+
polyVecKReduce(w1);
|
|
1651
|
+
polyVecKInvNTTToMont(w1);
|
|
1652
|
+
|
|
1653
|
+
/* Reconstruct w1 */
|
|
1654
|
+
polyVecKCAddQ(w1);
|
|
1655
|
+
polyVecKUseHint(w1, w1, h);
|
|
1656
|
+
polyVecKPackW1(buf, w1);
|
|
1657
|
+
|
|
1658
|
+
/* Call random oracle and verify challenge */
|
|
1659
|
+
state = new sha3.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
|
+
|
|
1669
|
+
function cryptoSignOpen(sm, pk) {
|
|
1670
|
+
if (sm.length < CryptoBytes) {
|
|
1671
|
+
return undefined;
|
|
1672
|
+
}
|
|
1673
|
+
|
|
1674
|
+
const sig = sm.slice(0, CryptoBytes);
|
|
1675
|
+
const msg = sm.slice(CryptoBytes);
|
|
1676
|
+
if (!cryptoSignVerify(sig, msg, pk)) {
|
|
1677
|
+
return undefined;
|
|
1678
|
+
}
|
|
1679
|
+
|
|
1680
|
+
return msg;
|
|
1681
|
+
}
|
|
1682
|
+
|
|
1683
|
+
Object.defineProperty(exports, "SHAKE", {
|
|
1684
|
+
enumerable: true,
|
|
1685
|
+
get: function () { return sha3.SHAKE; }
|
|
1686
|
+
});
|
|
1687
|
+
exports.BETA = BETA;
|
|
1688
|
+
exports.CRHBytes = CRHBytes;
|
|
1689
|
+
exports.CryptoBytes = CryptoBytes;
|
|
1690
|
+
exports.CryptoPublicKeyBytes = CryptoPublicKeyBytes;
|
|
1691
|
+
exports.CryptoSecretKeyBytes = CryptoSecretKeyBytes;
|
|
1692
|
+
exports.D = D;
|
|
1693
|
+
exports.ETA = ETA;
|
|
1694
|
+
exports.GAMMA1 = GAMMA1;
|
|
1695
|
+
exports.GAMMA2 = GAMMA2;
|
|
1696
|
+
exports.K = K;
|
|
1697
|
+
exports.KeccakF1600StatePermute = KeccakF1600StatePermute;
|
|
1698
|
+
exports.KeccakFRoundConstants = KeccakFRoundConstants;
|
|
1699
|
+
exports.KeccakState = KeccakState;
|
|
1700
|
+
exports.L = L;
|
|
1701
|
+
exports.N = N;
|
|
1702
|
+
exports.NRounds = NRounds;
|
|
1703
|
+
exports.OMEGA = OMEGA;
|
|
1704
|
+
exports.Poly = Poly;
|
|
1705
|
+
exports.PolyETAPackedBytes = PolyETAPackedBytes;
|
|
1706
|
+
exports.PolyT0PackedBytes = PolyT0PackedBytes;
|
|
1707
|
+
exports.PolyT1PackedBytes = PolyT1PackedBytes;
|
|
1708
|
+
exports.PolyUniformETANBlocks = PolyUniformETANBlocks;
|
|
1709
|
+
exports.PolyUniformGamma1NBlocks = PolyUniformGamma1NBlocks;
|
|
1710
|
+
exports.PolyUniformNBlocks = PolyUniformNBlocks;
|
|
1711
|
+
exports.PolyVecHPackedBytes = PolyVecHPackedBytes;
|
|
1712
|
+
exports.PolyVecK = PolyVecK;
|
|
1713
|
+
exports.PolyVecL = PolyVecL;
|
|
1714
|
+
exports.PolyW1PackedBytes = PolyW1PackedBytes;
|
|
1715
|
+
exports.PolyZPackedBytes = PolyZPackedBytes;
|
|
1716
|
+
exports.Q = Q;
|
|
1717
|
+
exports.QInv = QInv;
|
|
1718
|
+
exports.ROL = ROL;
|
|
1719
|
+
exports.SeedBytes = SeedBytes;
|
|
1720
|
+
exports.Shake128Rate = Shake128Rate;
|
|
1721
|
+
exports.Shake256Rate = Shake256Rate;
|
|
1722
|
+
exports.Stream128BlockBytes = Stream128BlockBytes;
|
|
1723
|
+
exports.Stream256BlockBytes = Stream256BlockBytes;
|
|
1724
|
+
exports.TAU = TAU;
|
|
1725
|
+
exports.cAddQ = cAddQ;
|
|
1726
|
+
exports.cryptoSign = cryptoSign;
|
|
1727
|
+
exports.cryptoSignKeypair = cryptoSignKeypair;
|
|
1728
|
+
exports.cryptoSignOpen = cryptoSignOpen;
|
|
1729
|
+
exports.cryptoSignSignature = cryptoSignSignature;
|
|
1730
|
+
exports.cryptoSignVerify = cryptoSignVerify;
|
|
1731
|
+
exports.decompose = decompose;
|
|
1732
|
+
exports.dilithiumShake128StreamInit = dilithiumShake128StreamInit;
|
|
1733
|
+
exports.dilithiumShake256StreamInit = dilithiumShake256StreamInit;
|
|
1734
|
+
exports.invNTTToMont = invNTTToMont;
|
|
1735
|
+
exports.keccakAbsorb = keccakAbsorb;
|
|
1736
|
+
exports.keccakAbsorbOnce = keccakAbsorbOnce;
|
|
1737
|
+
exports.keccakFinalize = keccakFinalize;
|
|
1738
|
+
exports.keccakInit = keccakInit;
|
|
1739
|
+
exports.keccakSqueeze = keccakSqueeze;
|
|
1740
|
+
exports.keccakSqueezeBlocks = keccakSqueezeBlocks;
|
|
1741
|
+
exports.load64 = load64;
|
|
1742
|
+
exports.makeHint = makeHint;
|
|
1743
|
+
exports.montgomeryReduce = montgomeryReduce;
|
|
1744
|
+
exports.ntt = ntt;
|
|
1745
|
+
exports.packPk = packPk;
|
|
1746
|
+
exports.packSig = packSig;
|
|
1747
|
+
exports.packSk = packSk;
|
|
1748
|
+
exports.polyAdd = polyAdd;
|
|
1749
|
+
exports.polyCAddQ = polyCAddQ;
|
|
1750
|
+
exports.polyChallenge = polyChallenge;
|
|
1751
|
+
exports.polyChkNorm = polyChkNorm;
|
|
1752
|
+
exports.polyDecompose = polyDecompose;
|
|
1753
|
+
exports.polyEtaPack = polyEtaPack;
|
|
1754
|
+
exports.polyEtaUnpack = polyEtaUnpack;
|
|
1755
|
+
exports.polyInvNTTToMont = polyInvNTTToMont;
|
|
1756
|
+
exports.polyMakeHint = polyMakeHint;
|
|
1757
|
+
exports.polyNTT = polyNTT;
|
|
1758
|
+
exports.polyPointWiseMontgomery = polyPointWiseMontgomery;
|
|
1759
|
+
exports.polyPower2round = polyPower2round;
|
|
1760
|
+
exports.polyReduce = polyReduce;
|
|
1761
|
+
exports.polyShiftL = polyShiftL;
|
|
1762
|
+
exports.polySub = polySub;
|
|
1763
|
+
exports.polyT0Pack = polyT0Pack;
|
|
1764
|
+
exports.polyT0Unpack = polyT0Unpack;
|
|
1765
|
+
exports.polyT1Pack = polyT1Pack;
|
|
1766
|
+
exports.polyT1Unpack = polyT1Unpack;
|
|
1767
|
+
exports.polyUniform = polyUniform;
|
|
1768
|
+
exports.polyUniformEta = polyUniformEta;
|
|
1769
|
+
exports.polyUniformGamma1 = polyUniformGamma1;
|
|
1770
|
+
exports.polyUseHint = polyUseHint;
|
|
1771
|
+
exports.polyVecKAdd = polyVecKAdd;
|
|
1772
|
+
exports.polyVecKCAddQ = polyVecKCAddQ;
|
|
1773
|
+
exports.polyVecKChkNorm = polyVecKChkNorm;
|
|
1774
|
+
exports.polyVecKDecompose = polyVecKDecompose;
|
|
1775
|
+
exports.polyVecKInvNTTToMont = polyVecKInvNTTToMont;
|
|
1776
|
+
exports.polyVecKMakeHint = polyVecKMakeHint;
|
|
1777
|
+
exports.polyVecKNTT = polyVecKNTT;
|
|
1778
|
+
exports.polyVecKPackW1 = polyVecKPackW1;
|
|
1779
|
+
exports.polyVecKPointWisePolyMontgomery = polyVecKPointWisePolyMontgomery;
|
|
1780
|
+
exports.polyVecKPower2round = polyVecKPower2round;
|
|
1781
|
+
exports.polyVecKReduce = polyVecKReduce;
|
|
1782
|
+
exports.polyVecKShiftL = polyVecKShiftL;
|
|
1783
|
+
exports.polyVecKSub = polyVecKSub;
|
|
1784
|
+
exports.polyVecKUniformEta = polyVecKUniformEta;
|
|
1785
|
+
exports.polyVecKUseHint = polyVecKUseHint;
|
|
1786
|
+
exports.polyVecLAdd = polyVecLAdd;
|
|
1787
|
+
exports.polyVecLChkNorm = polyVecLChkNorm;
|
|
1788
|
+
exports.polyVecLInvNTTToMont = polyVecLInvNTTToMont;
|
|
1789
|
+
exports.polyVecLNTT = polyVecLNTT;
|
|
1790
|
+
exports.polyVecLPointWiseAccMontgomery = polyVecLPointWiseAccMontgomery;
|
|
1791
|
+
exports.polyVecLPointWisePolyMontgomery = polyVecLPointWisePolyMontgomery;
|
|
1792
|
+
exports.polyVecLReduce = polyVecLReduce;
|
|
1793
|
+
exports.polyVecLUniformEta = polyVecLUniformEta;
|
|
1794
|
+
exports.polyVecLUniformGamma1 = polyVecLUniformGamma1;
|
|
1795
|
+
exports.polyVecMatrixExpand = polyVecMatrixExpand;
|
|
1796
|
+
exports.polyVecMatrixPointWiseMontgomery = polyVecMatrixPointWiseMontgomery;
|
|
1797
|
+
exports.polyW1Pack = polyW1Pack;
|
|
1798
|
+
exports.polyZPack = polyZPack;
|
|
1799
|
+
exports.polyZUnpack = polyZUnpack;
|
|
1800
|
+
exports.power2round = power2round;
|
|
1801
|
+
exports.reduce32 = reduce32;
|
|
1802
|
+
exports.rejEta = rejEta;
|
|
1803
|
+
exports.rejUniform = rejUniform;
|
|
1804
|
+
exports.shake128Absorb = shake128Absorb;
|
|
1805
|
+
exports.shake128AbsorbOnce = shake128AbsorbOnce;
|
|
1806
|
+
exports.shake128Finalize = shake128Finalize;
|
|
1807
|
+
exports.shake128Init = shake128Init;
|
|
1808
|
+
exports.shake128Squeeze = shake128Squeeze;
|
|
1809
|
+
exports.shake128SqueezeBlocks = shake128SqueezeBlocks;
|
|
1810
|
+
exports.shake256Absorb = shake256Absorb;
|
|
1811
|
+
exports.shake256Finalize = shake256Finalize;
|
|
1812
|
+
exports.shake256Init = shake256Init;
|
|
1813
|
+
exports.shake256SqueezeBlocks = shake256SqueezeBlocks;
|
|
1814
|
+
exports.store64 = store64;
|
|
1815
|
+
exports.unpackPk = unpackPk;
|
|
1816
|
+
exports.unpackSig = unpackSig;
|
|
1817
|
+
exports.unpackSk = unpackSk;
|
|
1818
|
+
exports.useHint = useHint;
|
|
1819
|
+
exports.zetas = zetas;
|
|
1820
|
+
Object.keys(pkg).forEach(function (k) {
|
|
1821
|
+
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
1822
|
+
enumerable: true,
|
|
1823
|
+
get: function () { return pkg[k]; }
|
|
1824
|
+
});
|
|
1825
|
+
});
|