@theqrl/dilithium5 1.0.8 → 1.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/README.md +2 -1
- package/dist/cjs/dilithium5.js +169 -183
- package/dist/mjs/dilithium5.js +169 -182
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -141,7 +141,8 @@ See [SECURITY.md](../../SECURITY.md) for important information about:
|
|
|
141
141
|
|
|
142
142
|
## Requirements
|
|
143
143
|
|
|
144
|
-
- Node.js
|
|
144
|
+
- **Node.js**: 20.19+, 22.x, or 24.x (requires `globalThis.crypto.getRandomValues`)
|
|
145
|
+
- **Browsers**: [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API) and ES2020 (BigInt) -- Chrome 67+, Firefox 68+, Safari 14+, Edge 79+
|
|
145
146
|
- Full TypeScript definitions included
|
|
146
147
|
|
|
147
148
|
## License
|
package/dist/cjs/dilithium5.js
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
var sha3_js = require('@noble/hashes/sha3.js');
|
|
4
4
|
var utils_js = require('@noble/hashes/utils.js');
|
|
5
5
|
|
|
6
|
-
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
7
6
|
const Shake128Rate = 168;
|
|
8
7
|
const Shake256Rate = 136;
|
|
9
8
|
const Stream128BlockBytes = Shake128Rate;
|
|
@@ -433,7 +432,7 @@ function polyZUnpack(rP, a, aOffset) {
|
|
|
433
432
|
r.coeffs[2 * i + 1] = a[aOffset + 5 * i + 2] >> 4;
|
|
434
433
|
r.coeffs[2 * i + 1] |= a[aOffset + 5 * i + 3] << 4;
|
|
435
434
|
r.coeffs[2 * i + 1] |= a[aOffset + 5 * i + 4] << 12;
|
|
436
|
-
r.coeffs[2 * i] &= 0xfffff;
|
|
435
|
+
r.coeffs[2 * i + 1] &= 0xfffff;
|
|
437
436
|
|
|
438
437
|
r.coeffs[2 * i] = GAMMA1 - r.coeffs[2 * i];
|
|
439
438
|
r.coeffs[2 * i + 1] = GAMMA1 - r.coeffs[2 * i + 1];
|
|
@@ -1026,43 +1025,8 @@ function unpackSig(cP, z, hP, sig) {
|
|
|
1026
1025
|
const MAX_BYTES = 65536;
|
|
1027
1026
|
const MAX_UINT32 = 0xffffffff;
|
|
1028
1027
|
|
|
1029
|
-
function getGlobalScope() {
|
|
1030
|
-
if (typeof globalThis === 'object') return globalThis;
|
|
1031
|
-
if (typeof self === 'object') return self;
|
|
1032
|
-
if (typeof window === 'object') return window;
|
|
1033
|
-
if (typeof global === 'object') return global;
|
|
1034
|
-
return {};
|
|
1035
|
-
}
|
|
1036
|
-
|
|
1037
1028
|
function getWebCrypto() {
|
|
1038
|
-
|
|
1039
|
-
return scope.crypto || scope.msCrypto || null;
|
|
1040
|
-
}
|
|
1041
|
-
|
|
1042
|
-
function getNodeRandomBytes() {
|
|
1043
|
-
/* c8 ignore next */
|
|
1044
|
-
const isNode = typeof process === 'object' && process !== null && process.versions && process.versions.node;
|
|
1045
|
-
if (!isNode) return null;
|
|
1046
|
-
|
|
1047
|
-
const req =
|
|
1048
|
-
typeof module !== 'undefined' && module && typeof module.require === 'function'
|
|
1049
|
-
? module.require.bind(module)
|
|
1050
|
-
: typeof module !== 'undefined' && module && typeof module.createRequire === 'function'
|
|
1051
|
-
? module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('dilithium5.js', document.baseURI).href)))
|
|
1052
|
-
: typeof require === 'function'
|
|
1053
|
-
? require
|
|
1054
|
-
: null;
|
|
1055
|
-
if (!req) return null;
|
|
1056
|
-
|
|
1057
|
-
try {
|
|
1058
|
-
const nodeCrypto = req('crypto');
|
|
1059
|
-
if (nodeCrypto && typeof nodeCrypto.randomBytes === 'function') {
|
|
1060
|
-
return nodeCrypto.randomBytes;
|
|
1061
|
-
}
|
|
1062
|
-
} catch {
|
|
1063
|
-
return null;
|
|
1064
|
-
}
|
|
1065
|
-
|
|
1029
|
+
if (typeof globalThis === 'object' && globalThis.crypto) return globalThis.crypto;
|
|
1066
1030
|
return null;
|
|
1067
1031
|
}
|
|
1068
1032
|
|
|
@@ -1081,15 +1045,69 @@ function randomBytes(size) {
|
|
|
1081
1045
|
for (let i = 0; i < size; i += MAX_BYTES) {
|
|
1082
1046
|
cryptoObj.getRandomValues(out.subarray(i, Math.min(size, i + MAX_BYTES)));
|
|
1083
1047
|
}
|
|
1048
|
+
if (size >= 16) {
|
|
1049
|
+
let acc = 0;
|
|
1050
|
+
for (let i = 0; i < 16; i++) acc |= out[i];
|
|
1051
|
+
if (acc === 0) throw new Error('getRandomValues returned all zeros');
|
|
1052
|
+
}
|
|
1084
1053
|
return out;
|
|
1085
1054
|
}
|
|
1086
1055
|
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1056
|
+
throw new Error('Secure random number generation is not supported by this environment');
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
/**
|
|
1060
|
+
* Security utilities for post-quantum signature schemes
|
|
1061
|
+
*
|
|
1062
|
+
* IMPORTANT: JavaScript cannot guarantee secure memory zeroization.
|
|
1063
|
+
* See SECURITY.md for details on limitations.
|
|
1064
|
+
*/
|
|
1065
|
+
|
|
1066
|
+
/**
|
|
1067
|
+
* Attempts to zero out a Uint8Array buffer.
|
|
1068
|
+
*
|
|
1069
|
+
* WARNING: This is a BEST-EFFORT operation. Due to JavaScript/JIT limitations:
|
|
1070
|
+
* - The write may be optimized away if the buffer is unused afterward
|
|
1071
|
+
* - Copies may exist in garbage collector memory
|
|
1072
|
+
* - Data may have been swapped to disk
|
|
1073
|
+
*
|
|
1074
|
+
* For high-security applications, consider native implementations (go-qrllib)
|
|
1075
|
+
* or hardware security modules.
|
|
1076
|
+
*
|
|
1077
|
+
* @param {Uint8Array} buffer - The buffer to zero
|
|
1078
|
+
* @returns {void}
|
|
1079
|
+
*/
|
|
1080
|
+
function zeroize(buffer) {
|
|
1081
|
+
if (!(buffer instanceof Uint8Array)) {
|
|
1082
|
+
throw new TypeError('zeroize requires a Uint8Array');
|
|
1083
|
+
}
|
|
1084
|
+
// Use fill(0) for zeroing - best effort
|
|
1085
|
+
buffer.fill(0);
|
|
1086
|
+
// Accumulator-OR over all bytes to discourage dead-store elimination
|
|
1087
|
+
// (Reading every byte makes it harder for JIT to prove fill is dead)
|
|
1088
|
+
let check = 0;
|
|
1089
|
+
for (let i = 0; i < buffer.length; i++) check |= buffer[i];
|
|
1090
|
+
if (check !== 0) {
|
|
1091
|
+
throw new Error('zeroize failed');
|
|
1090
1092
|
}
|
|
1093
|
+
}
|
|
1091
1094
|
|
|
1092
|
-
|
|
1095
|
+
/**
|
|
1096
|
+
* Checks if a buffer is all zeros.
|
|
1097
|
+
* Uses constant-time comparison to avoid timing leaks.
|
|
1098
|
+
*
|
|
1099
|
+
* @param {Uint8Array} buffer - The buffer to check
|
|
1100
|
+
* @returns {boolean} True if all bytes are zero
|
|
1101
|
+
*/
|
|
1102
|
+
function isZero(buffer) {
|
|
1103
|
+
if (!(buffer instanceof Uint8Array)) {
|
|
1104
|
+
throw new TypeError('isZero requires a Uint8Array');
|
|
1105
|
+
}
|
|
1106
|
+
let acc = 0;
|
|
1107
|
+
for (let i = 0; i < buffer.length; i++) {
|
|
1108
|
+
acc |= buffer[i];
|
|
1109
|
+
}
|
|
1110
|
+
return acc === 0;
|
|
1093
1111
|
}
|
|
1094
1112
|
|
|
1095
1113
|
/**
|
|
@@ -1190,34 +1208,45 @@ function cryptoSignKeypair(passedSeed, pk, sk) {
|
|
|
1190
1208
|
const rhoPrime = seedBuf.slice(SeedBytes, SeedBytes + CRHBytes);
|
|
1191
1209
|
const key = seedBuf.slice(SeedBytes + CRHBytes);
|
|
1192
1210
|
|
|
1193
|
-
|
|
1194
|
-
|
|
1211
|
+
let s1hat;
|
|
1212
|
+
try {
|
|
1213
|
+
// Expand matrix
|
|
1214
|
+
polyVecMatrixExpand(mat, rho);
|
|
1195
1215
|
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1216
|
+
// Sample short vectors s1 and s2
|
|
1217
|
+
polyVecLUniformEta(s1, rhoPrime, 0);
|
|
1218
|
+
polyVecKUniformEta(s2, rhoPrime, L);
|
|
1199
1219
|
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1220
|
+
// Matrix-vector multiplication
|
|
1221
|
+
s1hat = new PolyVecL();
|
|
1222
|
+
s1hat.copy(s1);
|
|
1223
|
+
polyVecLNTT(s1hat);
|
|
1224
|
+
polyVecMatrixPointWiseMontgomery(t1, mat, s1hat);
|
|
1225
|
+
polyVecKReduce(t1);
|
|
1226
|
+
polyVecKInvNTTToMont(t1);
|
|
1207
1227
|
|
|
1208
|
-
|
|
1209
|
-
|
|
1228
|
+
// Add error vector s2
|
|
1229
|
+
polyVecKAdd(t1, t1, s2);
|
|
1210
1230
|
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1231
|
+
// Extract t1 and write public key
|
|
1232
|
+
polyVecKCAddQ(t1);
|
|
1233
|
+
polyVecKPower2round(t1, t0, t1);
|
|
1234
|
+
packPk(pk, rho, t1);
|
|
1215
1235
|
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1236
|
+
// Compute H(rho, t1) and write secret key
|
|
1237
|
+
const tr = sha3_js.shake256.create({}).update(pk).xof(TRBytes);
|
|
1238
|
+
packSk(sk, rho, tr, key, t0, s1, s2);
|
|
1219
1239
|
|
|
1220
|
-
|
|
1240
|
+
return seed;
|
|
1241
|
+
} finally {
|
|
1242
|
+
zeroize(seedBuf);
|
|
1243
|
+
zeroize(rhoPrime);
|
|
1244
|
+
zeroize(key);
|
|
1245
|
+
for (let i = 0; i < L; i++) s1.vec[i].coeffs.fill(0);
|
|
1246
|
+
for (let i = 0; i < K; i++) s2.vec[i].coeffs.fill(0);
|
|
1247
|
+
if (s1hat) for (let i = 0; i < L; i++) s1hat.vec[i].coeffs.fill(0);
|
|
1248
|
+
for (let i = 0; i < K; i++) t0.vec[i].coeffs.fill(0);
|
|
1249
|
+
}
|
|
1221
1250
|
}
|
|
1222
1251
|
|
|
1223
1252
|
/**
|
|
@@ -1265,81 +1294,90 @@ function cryptoSignSignature(sig, m, sk, randomizedSigning) {
|
|
|
1265
1294
|
const h = new PolyVecK();
|
|
1266
1295
|
const cp = new Poly();
|
|
1267
1296
|
|
|
1268
|
-
|
|
1297
|
+
try {
|
|
1298
|
+
unpackSk(rho, tr, key, t0, s1, s2, sk);
|
|
1269
1299
|
|
|
1270
|
-
|
|
1300
|
+
const mu = sha3_js.shake256.create({}).update(tr).update(mBytes).xof(CRHBytes);
|
|
1271
1301
|
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1302
|
+
if (randomizedSigning) {
|
|
1303
|
+
rhoPrime = new Uint8Array(randomBytes(CRHBytes));
|
|
1304
|
+
} else {
|
|
1305
|
+
rhoPrime = sha3_js.shake256.create({}).update(key).update(mu).xof(CRHBytes);
|
|
1306
|
+
}
|
|
1277
1307
|
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1308
|
+
polyVecMatrixExpand(mat, rho);
|
|
1309
|
+
polyVecLNTT(s1);
|
|
1310
|
+
polyVecKNTT(s2);
|
|
1311
|
+
polyVecKNTT(t0);
|
|
1312
|
+
|
|
1313
|
+
while (true) {
|
|
1314
|
+
polyVecLUniformGamma1(y, rhoPrime, nonce++);
|
|
1315
|
+
// Matrix-vector multiplication
|
|
1316
|
+
z.copy(y);
|
|
1317
|
+
polyVecLNTT(z);
|
|
1318
|
+
polyVecMatrixPointWiseMontgomery(w1, mat, z);
|
|
1319
|
+
polyVecKReduce(w1);
|
|
1320
|
+
polyVecKInvNTTToMont(w1);
|
|
1321
|
+
|
|
1322
|
+
// Decompose w and call the random oracle
|
|
1323
|
+
polyVecKCAddQ(w1);
|
|
1324
|
+
polyVecKDecompose(w1, w0, w1);
|
|
1325
|
+
polyVecKPackW1(sig, w1);
|
|
1326
|
+
|
|
1327
|
+
const cHash = sha3_js.shake256
|
|
1328
|
+
.create({})
|
|
1329
|
+
.update(mu)
|
|
1330
|
+
.update(sig.slice(0, K * PolyW1PackedBytes))
|
|
1331
|
+
.xof(SeedBytes);
|
|
1332
|
+
sig.set(cHash);
|
|
1333
|
+
|
|
1334
|
+
polyChallenge(cp, sig);
|
|
1335
|
+
polyNTT(cp);
|
|
1336
|
+
|
|
1337
|
+
// Compute z, reject if it reveals secret
|
|
1338
|
+
polyVecLPointWisePolyMontgomery(z, cp, s1);
|
|
1339
|
+
polyVecLInvNTTToMont(z);
|
|
1340
|
+
polyVecLAdd(z, z, y);
|
|
1341
|
+
polyVecLReduce(z);
|
|
1342
|
+
if (polyVecLChkNorm(z, GAMMA1 - BETA) !== 0) {
|
|
1343
|
+
continue;
|
|
1344
|
+
}
|
|
1282
1345
|
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
polyVecKInvNTTToMont(w1);
|
|
1291
|
-
|
|
1292
|
-
// Decompose w and call the random oracle
|
|
1293
|
-
polyVecKCAddQ(w1);
|
|
1294
|
-
polyVecKDecompose(w1, w0, w1);
|
|
1295
|
-
polyVecKPackW1(sig, w1);
|
|
1296
|
-
|
|
1297
|
-
const cHash = sha3_js.shake256
|
|
1298
|
-
.create({})
|
|
1299
|
-
.update(mu)
|
|
1300
|
-
.update(sig.slice(0, K * PolyW1PackedBytes))
|
|
1301
|
-
.xof(SeedBytes);
|
|
1302
|
-
sig.set(cHash);
|
|
1303
|
-
|
|
1304
|
-
polyChallenge(cp, sig);
|
|
1305
|
-
polyNTT(cp);
|
|
1306
|
-
|
|
1307
|
-
// Compute z, reject if it reveals secret
|
|
1308
|
-
polyVecLPointWisePolyMontgomery(z, cp, s1);
|
|
1309
|
-
polyVecLInvNTTToMont(z);
|
|
1310
|
-
polyVecLAdd(z, z, y);
|
|
1311
|
-
polyVecLReduce(z);
|
|
1312
|
-
if (polyVecLChkNorm(z, GAMMA1 - BETA) !== 0) {
|
|
1313
|
-
continue;
|
|
1314
|
-
}
|
|
1346
|
+
polyVecKPointWisePolyMontgomery(h, cp, s2);
|
|
1347
|
+
polyVecKInvNTTToMont(h);
|
|
1348
|
+
polyVecKSub(w0, w0, h);
|
|
1349
|
+
polyVecKReduce(w0);
|
|
1350
|
+
if (polyVecKChkNorm(w0, GAMMA2 - BETA) !== 0) {
|
|
1351
|
+
continue;
|
|
1352
|
+
}
|
|
1315
1353
|
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1354
|
+
polyVecKPointWisePolyMontgomery(h, cp, t0);
|
|
1355
|
+
polyVecKInvNTTToMont(h);
|
|
1356
|
+
polyVecKReduce(h);
|
|
1357
|
+
/* c8 ignore start */
|
|
1358
|
+
if (polyVecKChkNorm(h, GAMMA2) !== 0) {
|
|
1359
|
+
continue;
|
|
1360
|
+
}
|
|
1361
|
+
/* c8 ignore stop */
|
|
1323
1362
|
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
/* c8 ignore stop */
|
|
1363
|
+
polyVecKAdd(w0, w0, h);
|
|
1364
|
+
const n = polyVecKMakeHint(h, w0, w1);
|
|
1365
|
+
/* c8 ignore start */
|
|
1366
|
+
if (n > OMEGA) {
|
|
1367
|
+
continue;
|
|
1368
|
+
}
|
|
1369
|
+
/* c8 ignore stop */
|
|
1332
1370
|
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
/* c8 ignore start */
|
|
1336
|
-
if (n > OMEGA) {
|
|
1337
|
-
continue;
|
|
1371
|
+
packSig(sig, sig, z, h);
|
|
1372
|
+
return 0;
|
|
1338
1373
|
}
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1374
|
+
} finally {
|
|
1375
|
+
zeroize(key);
|
|
1376
|
+
zeroize(rhoPrime);
|
|
1377
|
+
for (let i = 0; i < L; i++) s1.vec[i].coeffs.fill(0);
|
|
1378
|
+
for (let i = 0; i < K; i++) s2.vec[i].coeffs.fill(0);
|
|
1379
|
+
for (let i = 0; i < K; i++) t0.vec[i].coeffs.fill(0);
|
|
1380
|
+
for (let i = 0; i < L; i++) y.vec[i].coeffs.fill(0);
|
|
1343
1381
|
}
|
|
1344
1382
|
}
|
|
1345
1383
|
|
|
@@ -1498,58 +1536,6 @@ function cryptoSignOpen(sm, pk) {
|
|
|
1498
1536
|
return msg;
|
|
1499
1537
|
}
|
|
1500
1538
|
|
|
1501
|
-
/**
|
|
1502
|
-
* Security utilities for Dilithium5
|
|
1503
|
-
*
|
|
1504
|
-
* IMPORTANT: JavaScript cannot guarantee secure memory zeroization.
|
|
1505
|
-
* See SECURITY.md for details on limitations.
|
|
1506
|
-
*/
|
|
1507
|
-
|
|
1508
|
-
/**
|
|
1509
|
-
* Attempts to zero out a Uint8Array buffer.
|
|
1510
|
-
*
|
|
1511
|
-
* WARNING: This is a BEST-EFFORT operation. Due to JavaScript/JIT limitations:
|
|
1512
|
-
* - The write may be optimized away if the buffer is unused afterward
|
|
1513
|
-
* - Copies may exist in garbage collector memory
|
|
1514
|
-
* - Data may have been swapped to disk
|
|
1515
|
-
*
|
|
1516
|
-
* For high-security applications, consider native implementations (go-qrllib)
|
|
1517
|
-
* or hardware security modules.
|
|
1518
|
-
*
|
|
1519
|
-
* @param {Uint8Array} buffer - The buffer to zero
|
|
1520
|
-
* @returns {void}
|
|
1521
|
-
*/
|
|
1522
|
-
function zeroize(buffer) {
|
|
1523
|
-
if (!(buffer instanceof Uint8Array)) {
|
|
1524
|
-
throw new TypeError('zeroize requires a Uint8Array');
|
|
1525
|
-
}
|
|
1526
|
-
// Use fill(0) for zeroing - best effort
|
|
1527
|
-
buffer.fill(0);
|
|
1528
|
-
// Additional volatile-like access to discourage optimization
|
|
1529
|
-
// (This is a hint to the JIT, not a guarantee)
|
|
1530
|
-
if (buffer.length > 0 && buffer[0] !== 0) {
|
|
1531
|
-
throw new Error('zeroize failed'); // Should never happen
|
|
1532
|
-
}
|
|
1533
|
-
}
|
|
1534
|
-
|
|
1535
|
-
/**
|
|
1536
|
-
* Checks if a buffer is all zeros.
|
|
1537
|
-
* Uses constant-time comparison to avoid timing leaks.
|
|
1538
|
-
*
|
|
1539
|
-
* @param {Uint8Array} buffer - The buffer to check
|
|
1540
|
-
* @returns {boolean} True if all bytes are zero
|
|
1541
|
-
*/
|
|
1542
|
-
function isZero(buffer) {
|
|
1543
|
-
if (!(buffer instanceof Uint8Array)) {
|
|
1544
|
-
throw new TypeError('isZero requires a Uint8Array');
|
|
1545
|
-
}
|
|
1546
|
-
let acc = 0;
|
|
1547
|
-
for (let i = 0; i < buffer.length; i++) {
|
|
1548
|
-
acc |= buffer[i];
|
|
1549
|
-
}
|
|
1550
|
-
return acc === 0;
|
|
1551
|
-
}
|
|
1552
|
-
|
|
1553
1539
|
exports.BETA = BETA;
|
|
1554
1540
|
exports.CRHBytes = CRHBytes;
|
|
1555
1541
|
exports.CryptoBytes = CryptoBytes;
|
package/dist/mjs/dilithium5.js
CHANGED
|
@@ -430,7 +430,7 @@ function polyZUnpack(rP, a, aOffset) {
|
|
|
430
430
|
r.coeffs[2 * i + 1] = a[aOffset + 5 * i + 2] >> 4;
|
|
431
431
|
r.coeffs[2 * i + 1] |= a[aOffset + 5 * i + 3] << 4;
|
|
432
432
|
r.coeffs[2 * i + 1] |= a[aOffset + 5 * i + 4] << 12;
|
|
433
|
-
r.coeffs[2 * i] &= 0xfffff;
|
|
433
|
+
r.coeffs[2 * i + 1] &= 0xfffff;
|
|
434
434
|
|
|
435
435
|
r.coeffs[2 * i] = GAMMA1 - r.coeffs[2 * i];
|
|
436
436
|
r.coeffs[2 * i + 1] = GAMMA1 - r.coeffs[2 * i + 1];
|
|
@@ -1023,43 +1023,8 @@ function unpackSig(cP, z, hP, sig) {
|
|
|
1023
1023
|
const MAX_BYTES = 65536;
|
|
1024
1024
|
const MAX_UINT32 = 0xffffffff;
|
|
1025
1025
|
|
|
1026
|
-
function getGlobalScope() {
|
|
1027
|
-
if (typeof globalThis === 'object') return globalThis;
|
|
1028
|
-
if (typeof self === 'object') return self;
|
|
1029
|
-
if (typeof window === 'object') return window;
|
|
1030
|
-
if (typeof global === 'object') return global;
|
|
1031
|
-
return {};
|
|
1032
|
-
}
|
|
1033
|
-
|
|
1034
1026
|
function getWebCrypto() {
|
|
1035
|
-
|
|
1036
|
-
return scope.crypto || scope.msCrypto || null;
|
|
1037
|
-
}
|
|
1038
|
-
|
|
1039
|
-
function getNodeRandomBytes() {
|
|
1040
|
-
/* c8 ignore next */
|
|
1041
|
-
const isNode = typeof process === 'object' && process !== null && process.versions && process.versions.node;
|
|
1042
|
-
if (!isNode) return null;
|
|
1043
|
-
|
|
1044
|
-
const req =
|
|
1045
|
-
typeof module !== 'undefined' && module && typeof module.require === 'function'
|
|
1046
|
-
? module.require.bind(module)
|
|
1047
|
-
: typeof module !== 'undefined' && module && typeof module.createRequire === 'function'
|
|
1048
|
-
? module.createRequire(import.meta.url)
|
|
1049
|
-
: typeof require === 'function'
|
|
1050
|
-
? require
|
|
1051
|
-
: null;
|
|
1052
|
-
if (!req) return null;
|
|
1053
|
-
|
|
1054
|
-
try {
|
|
1055
|
-
const nodeCrypto = req('crypto');
|
|
1056
|
-
if (nodeCrypto && typeof nodeCrypto.randomBytes === 'function') {
|
|
1057
|
-
return nodeCrypto.randomBytes;
|
|
1058
|
-
}
|
|
1059
|
-
} catch {
|
|
1060
|
-
return null;
|
|
1061
|
-
}
|
|
1062
|
-
|
|
1027
|
+
if (typeof globalThis === 'object' && globalThis.crypto) return globalThis.crypto;
|
|
1063
1028
|
return null;
|
|
1064
1029
|
}
|
|
1065
1030
|
|
|
@@ -1078,15 +1043,69 @@ function randomBytes(size) {
|
|
|
1078
1043
|
for (let i = 0; i < size; i += MAX_BYTES) {
|
|
1079
1044
|
cryptoObj.getRandomValues(out.subarray(i, Math.min(size, i + MAX_BYTES)));
|
|
1080
1045
|
}
|
|
1046
|
+
if (size >= 16) {
|
|
1047
|
+
let acc = 0;
|
|
1048
|
+
for (let i = 0; i < 16; i++) acc |= out[i];
|
|
1049
|
+
if (acc === 0) throw new Error('getRandomValues returned all zeros');
|
|
1050
|
+
}
|
|
1081
1051
|
return out;
|
|
1082
1052
|
}
|
|
1083
1053
|
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1054
|
+
throw new Error('Secure random number generation is not supported by this environment');
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
/**
|
|
1058
|
+
* Security utilities for post-quantum signature schemes
|
|
1059
|
+
*
|
|
1060
|
+
* IMPORTANT: JavaScript cannot guarantee secure memory zeroization.
|
|
1061
|
+
* See SECURITY.md for details on limitations.
|
|
1062
|
+
*/
|
|
1063
|
+
|
|
1064
|
+
/**
|
|
1065
|
+
* Attempts to zero out a Uint8Array buffer.
|
|
1066
|
+
*
|
|
1067
|
+
* WARNING: This is a BEST-EFFORT operation. Due to JavaScript/JIT limitations:
|
|
1068
|
+
* - The write may be optimized away if the buffer is unused afterward
|
|
1069
|
+
* - Copies may exist in garbage collector memory
|
|
1070
|
+
* - Data may have been swapped to disk
|
|
1071
|
+
*
|
|
1072
|
+
* For high-security applications, consider native implementations (go-qrllib)
|
|
1073
|
+
* or hardware security modules.
|
|
1074
|
+
*
|
|
1075
|
+
* @param {Uint8Array} buffer - The buffer to zero
|
|
1076
|
+
* @returns {void}
|
|
1077
|
+
*/
|
|
1078
|
+
function zeroize(buffer) {
|
|
1079
|
+
if (!(buffer instanceof Uint8Array)) {
|
|
1080
|
+
throw new TypeError('zeroize requires a Uint8Array');
|
|
1081
|
+
}
|
|
1082
|
+
// Use fill(0) for zeroing - best effort
|
|
1083
|
+
buffer.fill(0);
|
|
1084
|
+
// Accumulator-OR over all bytes to discourage dead-store elimination
|
|
1085
|
+
// (Reading every byte makes it harder for JIT to prove fill is dead)
|
|
1086
|
+
let check = 0;
|
|
1087
|
+
for (let i = 0; i < buffer.length; i++) check |= buffer[i];
|
|
1088
|
+
if (check !== 0) {
|
|
1089
|
+
throw new Error('zeroize failed');
|
|
1087
1090
|
}
|
|
1091
|
+
}
|
|
1088
1092
|
|
|
1089
|
-
|
|
1093
|
+
/**
|
|
1094
|
+
* Checks if a buffer is all zeros.
|
|
1095
|
+
* Uses constant-time comparison to avoid timing leaks.
|
|
1096
|
+
*
|
|
1097
|
+
* @param {Uint8Array} buffer - The buffer to check
|
|
1098
|
+
* @returns {boolean} True if all bytes are zero
|
|
1099
|
+
*/
|
|
1100
|
+
function isZero(buffer) {
|
|
1101
|
+
if (!(buffer instanceof Uint8Array)) {
|
|
1102
|
+
throw new TypeError('isZero requires a Uint8Array');
|
|
1103
|
+
}
|
|
1104
|
+
let acc = 0;
|
|
1105
|
+
for (let i = 0; i < buffer.length; i++) {
|
|
1106
|
+
acc |= buffer[i];
|
|
1107
|
+
}
|
|
1108
|
+
return acc === 0;
|
|
1090
1109
|
}
|
|
1091
1110
|
|
|
1092
1111
|
/**
|
|
@@ -1187,34 +1206,45 @@ function cryptoSignKeypair(passedSeed, pk, sk) {
|
|
|
1187
1206
|
const rhoPrime = seedBuf.slice(SeedBytes, SeedBytes + CRHBytes);
|
|
1188
1207
|
const key = seedBuf.slice(SeedBytes + CRHBytes);
|
|
1189
1208
|
|
|
1190
|
-
|
|
1191
|
-
|
|
1209
|
+
let s1hat;
|
|
1210
|
+
try {
|
|
1211
|
+
// Expand matrix
|
|
1212
|
+
polyVecMatrixExpand(mat, rho);
|
|
1192
1213
|
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1214
|
+
// Sample short vectors s1 and s2
|
|
1215
|
+
polyVecLUniformEta(s1, rhoPrime, 0);
|
|
1216
|
+
polyVecKUniformEta(s2, rhoPrime, L);
|
|
1196
1217
|
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1218
|
+
// Matrix-vector multiplication
|
|
1219
|
+
s1hat = new PolyVecL();
|
|
1220
|
+
s1hat.copy(s1);
|
|
1221
|
+
polyVecLNTT(s1hat);
|
|
1222
|
+
polyVecMatrixPointWiseMontgomery(t1, mat, s1hat);
|
|
1223
|
+
polyVecKReduce(t1);
|
|
1224
|
+
polyVecKInvNTTToMont(t1);
|
|
1204
1225
|
|
|
1205
|
-
|
|
1206
|
-
|
|
1226
|
+
// Add error vector s2
|
|
1227
|
+
polyVecKAdd(t1, t1, s2);
|
|
1207
1228
|
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1229
|
+
// Extract t1 and write public key
|
|
1230
|
+
polyVecKCAddQ(t1);
|
|
1231
|
+
polyVecKPower2round(t1, t0, t1);
|
|
1232
|
+
packPk(pk, rho, t1);
|
|
1212
1233
|
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1234
|
+
// Compute H(rho, t1) and write secret key
|
|
1235
|
+
const tr = shake256.create({}).update(pk).xof(TRBytes);
|
|
1236
|
+
packSk(sk, rho, tr, key, t0, s1, s2);
|
|
1216
1237
|
|
|
1217
|
-
|
|
1238
|
+
return seed;
|
|
1239
|
+
} finally {
|
|
1240
|
+
zeroize(seedBuf);
|
|
1241
|
+
zeroize(rhoPrime);
|
|
1242
|
+
zeroize(key);
|
|
1243
|
+
for (let i = 0; i < L; i++) s1.vec[i].coeffs.fill(0);
|
|
1244
|
+
for (let i = 0; i < K; i++) s2.vec[i].coeffs.fill(0);
|
|
1245
|
+
if (s1hat) for (let i = 0; i < L; i++) s1hat.vec[i].coeffs.fill(0);
|
|
1246
|
+
for (let i = 0; i < K; i++) t0.vec[i].coeffs.fill(0);
|
|
1247
|
+
}
|
|
1218
1248
|
}
|
|
1219
1249
|
|
|
1220
1250
|
/**
|
|
@@ -1262,81 +1292,90 @@ function cryptoSignSignature(sig, m, sk, randomizedSigning) {
|
|
|
1262
1292
|
const h = new PolyVecK();
|
|
1263
1293
|
const cp = new Poly();
|
|
1264
1294
|
|
|
1265
|
-
|
|
1295
|
+
try {
|
|
1296
|
+
unpackSk(rho, tr, key, t0, s1, s2, sk);
|
|
1266
1297
|
|
|
1267
|
-
|
|
1298
|
+
const mu = shake256.create({}).update(tr).update(mBytes).xof(CRHBytes);
|
|
1268
1299
|
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1300
|
+
if (randomizedSigning) {
|
|
1301
|
+
rhoPrime = new Uint8Array(randomBytes(CRHBytes));
|
|
1302
|
+
} else {
|
|
1303
|
+
rhoPrime = shake256.create({}).update(key).update(mu).xof(CRHBytes);
|
|
1304
|
+
}
|
|
1274
1305
|
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1306
|
+
polyVecMatrixExpand(mat, rho);
|
|
1307
|
+
polyVecLNTT(s1);
|
|
1308
|
+
polyVecKNTT(s2);
|
|
1309
|
+
polyVecKNTT(t0);
|
|
1310
|
+
|
|
1311
|
+
while (true) {
|
|
1312
|
+
polyVecLUniformGamma1(y, rhoPrime, nonce++);
|
|
1313
|
+
// Matrix-vector multiplication
|
|
1314
|
+
z.copy(y);
|
|
1315
|
+
polyVecLNTT(z);
|
|
1316
|
+
polyVecMatrixPointWiseMontgomery(w1, mat, z);
|
|
1317
|
+
polyVecKReduce(w1);
|
|
1318
|
+
polyVecKInvNTTToMont(w1);
|
|
1319
|
+
|
|
1320
|
+
// Decompose w and call the random oracle
|
|
1321
|
+
polyVecKCAddQ(w1);
|
|
1322
|
+
polyVecKDecompose(w1, w0, w1);
|
|
1323
|
+
polyVecKPackW1(sig, w1);
|
|
1324
|
+
|
|
1325
|
+
const cHash = shake256
|
|
1326
|
+
.create({})
|
|
1327
|
+
.update(mu)
|
|
1328
|
+
.update(sig.slice(0, K * PolyW1PackedBytes))
|
|
1329
|
+
.xof(SeedBytes);
|
|
1330
|
+
sig.set(cHash);
|
|
1331
|
+
|
|
1332
|
+
polyChallenge(cp, sig);
|
|
1333
|
+
polyNTT(cp);
|
|
1334
|
+
|
|
1335
|
+
// Compute z, reject if it reveals secret
|
|
1336
|
+
polyVecLPointWisePolyMontgomery(z, cp, s1);
|
|
1337
|
+
polyVecLInvNTTToMont(z);
|
|
1338
|
+
polyVecLAdd(z, z, y);
|
|
1339
|
+
polyVecLReduce(z);
|
|
1340
|
+
if (polyVecLChkNorm(z, GAMMA1 - BETA) !== 0) {
|
|
1341
|
+
continue;
|
|
1342
|
+
}
|
|
1279
1343
|
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
polyVecKInvNTTToMont(w1);
|
|
1288
|
-
|
|
1289
|
-
// Decompose w and call the random oracle
|
|
1290
|
-
polyVecKCAddQ(w1);
|
|
1291
|
-
polyVecKDecompose(w1, w0, w1);
|
|
1292
|
-
polyVecKPackW1(sig, w1);
|
|
1293
|
-
|
|
1294
|
-
const cHash = shake256
|
|
1295
|
-
.create({})
|
|
1296
|
-
.update(mu)
|
|
1297
|
-
.update(sig.slice(0, K * PolyW1PackedBytes))
|
|
1298
|
-
.xof(SeedBytes);
|
|
1299
|
-
sig.set(cHash);
|
|
1300
|
-
|
|
1301
|
-
polyChallenge(cp, sig);
|
|
1302
|
-
polyNTT(cp);
|
|
1303
|
-
|
|
1304
|
-
// Compute z, reject if it reveals secret
|
|
1305
|
-
polyVecLPointWisePolyMontgomery(z, cp, s1);
|
|
1306
|
-
polyVecLInvNTTToMont(z);
|
|
1307
|
-
polyVecLAdd(z, z, y);
|
|
1308
|
-
polyVecLReduce(z);
|
|
1309
|
-
if (polyVecLChkNorm(z, GAMMA1 - BETA) !== 0) {
|
|
1310
|
-
continue;
|
|
1311
|
-
}
|
|
1344
|
+
polyVecKPointWisePolyMontgomery(h, cp, s2);
|
|
1345
|
+
polyVecKInvNTTToMont(h);
|
|
1346
|
+
polyVecKSub(w0, w0, h);
|
|
1347
|
+
polyVecKReduce(w0);
|
|
1348
|
+
if (polyVecKChkNorm(w0, GAMMA2 - BETA) !== 0) {
|
|
1349
|
+
continue;
|
|
1350
|
+
}
|
|
1312
1351
|
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1352
|
+
polyVecKPointWisePolyMontgomery(h, cp, t0);
|
|
1353
|
+
polyVecKInvNTTToMont(h);
|
|
1354
|
+
polyVecKReduce(h);
|
|
1355
|
+
/* c8 ignore start */
|
|
1356
|
+
if (polyVecKChkNorm(h, GAMMA2) !== 0) {
|
|
1357
|
+
continue;
|
|
1358
|
+
}
|
|
1359
|
+
/* c8 ignore stop */
|
|
1320
1360
|
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
/* c8 ignore stop */
|
|
1361
|
+
polyVecKAdd(w0, w0, h);
|
|
1362
|
+
const n = polyVecKMakeHint(h, w0, w1);
|
|
1363
|
+
/* c8 ignore start */
|
|
1364
|
+
if (n > OMEGA) {
|
|
1365
|
+
continue;
|
|
1366
|
+
}
|
|
1367
|
+
/* c8 ignore stop */
|
|
1329
1368
|
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
/* c8 ignore start */
|
|
1333
|
-
if (n > OMEGA) {
|
|
1334
|
-
continue;
|
|
1369
|
+
packSig(sig, sig, z, h);
|
|
1370
|
+
return 0;
|
|
1335
1371
|
}
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1372
|
+
} finally {
|
|
1373
|
+
zeroize(key);
|
|
1374
|
+
zeroize(rhoPrime);
|
|
1375
|
+
for (let i = 0; i < L; i++) s1.vec[i].coeffs.fill(0);
|
|
1376
|
+
for (let i = 0; i < K; i++) s2.vec[i].coeffs.fill(0);
|
|
1377
|
+
for (let i = 0; i < K; i++) t0.vec[i].coeffs.fill(0);
|
|
1378
|
+
for (let i = 0; i < L; i++) y.vec[i].coeffs.fill(0);
|
|
1340
1379
|
}
|
|
1341
1380
|
}
|
|
1342
1381
|
|
|
@@ -1495,56 +1534,4 @@ function cryptoSignOpen(sm, pk) {
|
|
|
1495
1534
|
return msg;
|
|
1496
1535
|
}
|
|
1497
1536
|
|
|
1498
|
-
/**
|
|
1499
|
-
* Security utilities for Dilithium5
|
|
1500
|
-
*
|
|
1501
|
-
* IMPORTANT: JavaScript cannot guarantee secure memory zeroization.
|
|
1502
|
-
* See SECURITY.md for details on limitations.
|
|
1503
|
-
*/
|
|
1504
|
-
|
|
1505
|
-
/**
|
|
1506
|
-
* Attempts to zero out a Uint8Array buffer.
|
|
1507
|
-
*
|
|
1508
|
-
* WARNING: This is a BEST-EFFORT operation. Due to JavaScript/JIT limitations:
|
|
1509
|
-
* - The write may be optimized away if the buffer is unused afterward
|
|
1510
|
-
* - Copies may exist in garbage collector memory
|
|
1511
|
-
* - Data may have been swapped to disk
|
|
1512
|
-
*
|
|
1513
|
-
* For high-security applications, consider native implementations (go-qrllib)
|
|
1514
|
-
* or hardware security modules.
|
|
1515
|
-
*
|
|
1516
|
-
* @param {Uint8Array} buffer - The buffer to zero
|
|
1517
|
-
* @returns {void}
|
|
1518
|
-
*/
|
|
1519
|
-
function zeroize(buffer) {
|
|
1520
|
-
if (!(buffer instanceof Uint8Array)) {
|
|
1521
|
-
throw new TypeError('zeroize requires a Uint8Array');
|
|
1522
|
-
}
|
|
1523
|
-
// Use fill(0) for zeroing - best effort
|
|
1524
|
-
buffer.fill(0);
|
|
1525
|
-
// Additional volatile-like access to discourage optimization
|
|
1526
|
-
// (This is a hint to the JIT, not a guarantee)
|
|
1527
|
-
if (buffer.length > 0 && buffer[0] !== 0) {
|
|
1528
|
-
throw new Error('zeroize failed'); // Should never happen
|
|
1529
|
-
}
|
|
1530
|
-
}
|
|
1531
|
-
|
|
1532
|
-
/**
|
|
1533
|
-
* Checks if a buffer is all zeros.
|
|
1534
|
-
* Uses constant-time comparison to avoid timing leaks.
|
|
1535
|
-
*
|
|
1536
|
-
* @param {Uint8Array} buffer - The buffer to check
|
|
1537
|
-
* @returns {boolean} True if all bytes are zero
|
|
1538
|
-
*/
|
|
1539
|
-
function isZero(buffer) {
|
|
1540
|
-
if (!(buffer instanceof Uint8Array)) {
|
|
1541
|
-
throw new TypeError('isZero requires a Uint8Array');
|
|
1542
|
-
}
|
|
1543
|
-
let acc = 0;
|
|
1544
|
-
for (let i = 0; i < buffer.length; i++) {
|
|
1545
|
-
acc |= buffer[i];
|
|
1546
|
-
}
|
|
1547
|
-
return acc === 0;
|
|
1548
|
-
}
|
|
1549
|
-
|
|
1550
1537
|
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 };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theqrl/dilithium5",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Dilithium-5 cryptography",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dilithium",
|
|
@@ -50,20 +50,20 @@
|
|
|
50
50
|
},
|
|
51
51
|
"type": "module",
|
|
52
52
|
"engines": {
|
|
53
|
-
"node": ">=
|
|
53
|
+
"node": ">=20.19.0"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@eslint/js": "^
|
|
56
|
+
"@eslint/js": "^10.0.1",
|
|
57
57
|
"c8": "^10.1.3",
|
|
58
58
|
"chai": "^6.2.2",
|
|
59
|
-
"eslint": "^
|
|
59
|
+
"eslint": "^10.0.0",
|
|
60
60
|
"eslint-config-prettier": "^10.1.8",
|
|
61
61
|
"eslint-plugin-import-x": "^4.15.0",
|
|
62
62
|
"eslint-plugin-prettier": "^5.5.4",
|
|
63
|
-
"globals": "^17.
|
|
63
|
+
"globals": "^17.3.0",
|
|
64
64
|
"mocha": "^11.7.5",
|
|
65
|
-
"prettier": "^3.
|
|
66
|
-
"rollup": "^4.
|
|
65
|
+
"prettier": "^3.8.1",
|
|
66
|
+
"rollup": "^4.57.1"
|
|
67
67
|
},
|
|
68
68
|
"dependencies": {
|
|
69
69
|
"@noble/hashes": "^2.0.1"
|