@theqrl/dilithium5 1.0.5 → 1.0.7
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/LICENSE +1 -0
- package/README.md +6 -4
- package/dist/cjs/dilithium5.js +94 -12
- package/dist/mjs/dilithium5.js +93 -12
- package/package.json +8 -4
- package/src/index.d.ts +2 -2
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -64,7 +64,7 @@ Generate a keypair from a seed.
|
|
|
64
64
|
|
|
65
65
|
Sign a message (combined mode: returns signature || message).
|
|
66
66
|
|
|
67
|
-
- `message`: `Uint8Array` - message
|
|
67
|
+
- `message`: `Uint8Array` or `string` - message bytes; if `string`, it must be hex only (optional `0x`, even length). Plain-text strings are not accepted.
|
|
68
68
|
- `sk`: `Uint8Array(4896)` - secret key
|
|
69
69
|
- `randomized`: `boolean` - `true` for hedged signing, `false` for deterministic
|
|
70
70
|
- Returns: `Uint8Array` containing signature + message
|
|
@@ -82,7 +82,7 @@ Verify and extract message from signed message.
|
|
|
82
82
|
Create a detached signature.
|
|
83
83
|
|
|
84
84
|
- `sig`: `Uint8Array(4595)` - output buffer for signature
|
|
85
|
-
- `message`: `Uint8Array` - message
|
|
85
|
+
- `message`: `Uint8Array` or `string` - message bytes; if `string`, it must be hex only (optional `0x`, even length). Plain-text strings are not accepted.
|
|
86
86
|
- `sk`: `Uint8Array(4896)` - secret key
|
|
87
87
|
- `randomized`: `boolean` - `true` for hedged, `false` for deterministic
|
|
88
88
|
- Returns: `0` on success
|
|
@@ -92,10 +92,12 @@ Create a detached signature.
|
|
|
92
92
|
Verify a detached signature.
|
|
93
93
|
|
|
94
94
|
- `sig`: `Uint8Array(4595)` - signature to verify
|
|
95
|
-
- `message`: `Uint8Array` - original message
|
|
95
|
+
- `message`: `Uint8Array` or `string` - original message bytes; if `string`, it must be hex only (optional `0x`, even length). Plain-text strings are not accepted.
|
|
96
96
|
- `pk`: `Uint8Array(2592)` - public key
|
|
97
97
|
- Returns: `true` if valid, `false` otherwise
|
|
98
98
|
|
|
99
|
+
**Note:** To sign or verify plain text, convert it to bytes (e.g., `new TextEncoder().encode('Hello')`). String inputs are interpreted as hex only.
|
|
100
|
+
|
|
99
101
|
#### `zeroize(buffer)`
|
|
100
102
|
|
|
101
103
|
Zero out sensitive data (best-effort, see security notes).
|
|
@@ -139,7 +141,7 @@ See [SECURITY.md](../../SECURITY.md) for important information about:
|
|
|
139
141
|
|
|
140
142
|
## Requirements
|
|
141
143
|
|
|
142
|
-
- Node.js 18+ or modern browsers with ES2020 support
|
|
144
|
+
- Node.js 18.20+ or modern browsers with ES2020 support
|
|
143
145
|
- Full TypeScript definitions included
|
|
144
146
|
|
|
145
147
|
## License
|
package/dist/cjs/dilithium5.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var sha3_js = require('@noble/hashes/sha3.js');
|
|
4
|
-
var pkg = require('randombytes');
|
|
5
4
|
var utils_js = require('@noble/hashes/utils.js');
|
|
6
5
|
|
|
6
|
+
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
7
7
|
const Shake128Rate = 168;
|
|
8
8
|
const Shake256Rate = 136;
|
|
9
9
|
const Stream128BlockBytes = Shake128Rate;
|
|
@@ -368,6 +368,8 @@ function polyUniform(a, seed, nonce) {
|
|
|
368
368
|
|
|
369
369
|
let ctr = rejUniform(a.coeffs, 0, N, buf, bufLen);
|
|
370
370
|
|
|
371
|
+
// Note: With current parameters, needing extra blocks is vanishingly unlikely.
|
|
372
|
+
/* c8 ignore start */
|
|
371
373
|
while (ctr < N) {
|
|
372
374
|
off = bufLen % 3;
|
|
373
375
|
for (let i = 0; i < off; ++i) buf[i] = buf[bufLen - off + i];
|
|
@@ -376,6 +378,7 @@ function polyUniform(a, seed, nonce) {
|
|
|
376
378
|
bufLen = Stream128BlockBytes + off;
|
|
377
379
|
ctr += rejUniform(a.coeffs, ctr, N - ctr, buf, bufLen);
|
|
378
380
|
}
|
|
381
|
+
/* c8 ignore stop */
|
|
379
382
|
}
|
|
380
383
|
|
|
381
384
|
function rejEta(aP, aOffset, len, buf, bufLen) {
|
|
@@ -469,10 +472,13 @@ function polyChallenge(cP, seed) {
|
|
|
469
472
|
}
|
|
470
473
|
for (let i = N - TAU; i < N; ++i) {
|
|
471
474
|
do {
|
|
475
|
+
// Note: Re-squeezing here is extremely unlikely with TAU=60.
|
|
476
|
+
/* c8 ignore start */
|
|
472
477
|
if (pos >= Shake256Rate) {
|
|
473
478
|
shake256SqueezeBlocks(buf, 0, 1, state);
|
|
474
479
|
pos = 0;
|
|
475
480
|
}
|
|
481
|
+
/* c8 ignore stop */
|
|
476
482
|
|
|
477
483
|
b = buf[pos++];
|
|
478
484
|
} while (b > i);
|
|
@@ -1017,19 +1023,98 @@ function unpackSig(cP, z, hP, sig) {
|
|
|
1017
1023
|
return 0;
|
|
1018
1024
|
}
|
|
1019
1025
|
|
|
1020
|
-
const
|
|
1026
|
+
const MAX_BYTES = 65536;
|
|
1027
|
+
const MAX_UINT32 = 0xffffffff;
|
|
1028
|
+
|
|
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
|
+
function getWebCrypto() {
|
|
1038
|
+
const scope = getGlobalScope();
|
|
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
|
+
|
|
1066
|
+
return null;
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
function randomBytes(size) {
|
|
1070
|
+
if (!Number.isSafeInteger(size) || size < 0) {
|
|
1071
|
+
throw new RangeError('size must be a non-negative integer');
|
|
1072
|
+
}
|
|
1073
|
+
if (size > MAX_UINT32) {
|
|
1074
|
+
throw new RangeError('requested too many random bytes');
|
|
1075
|
+
}
|
|
1076
|
+
if (size === 0) return new Uint8Array(0);
|
|
1077
|
+
|
|
1078
|
+
const cryptoObj = getWebCrypto();
|
|
1079
|
+
if (cryptoObj && typeof cryptoObj.getRandomValues === 'function') {
|
|
1080
|
+
const out = new Uint8Array(size);
|
|
1081
|
+
for (let i = 0; i < size; i += MAX_BYTES) {
|
|
1082
|
+
cryptoObj.getRandomValues(out.subarray(i, Math.min(size, i + MAX_BYTES)));
|
|
1083
|
+
}
|
|
1084
|
+
return out;
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
const nodeRandomBytes = getNodeRandomBytes();
|
|
1088
|
+
if (nodeRandomBytes) {
|
|
1089
|
+
return nodeRandomBytes(size);
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
throw new Error('Secure random number generation is not supported by this environment');
|
|
1093
|
+
}
|
|
1021
1094
|
|
|
1022
1095
|
/**
|
|
1023
1096
|
* Convert hex string to Uint8Array with strict validation.
|
|
1097
|
+
*
|
|
1098
|
+
* NOTE: This function accepts multiple hex formats (with/without 0x prefix,
|
|
1099
|
+
* leading/trailing whitespace). While user-friendly, this flexibility could
|
|
1100
|
+
* mask input errors. Applications requiring strict format validation should
|
|
1101
|
+
* validate hex format before calling cryptographic functions, e.g.:
|
|
1102
|
+
* - Reject strings with 0x prefix if raw hex is expected
|
|
1103
|
+
* - Reject strings with whitespace
|
|
1104
|
+
* - Enforce consistent casing (lowercase/uppercase)
|
|
1105
|
+
*
|
|
1024
1106
|
* @param {string} hex - Hex string (optional 0x prefix, even length).
|
|
1025
1107
|
* @returns {Uint8Array} Decoded bytes.
|
|
1026
1108
|
* @private
|
|
1027
1109
|
*/
|
|
1028
1110
|
function hexToBytes(hex) {
|
|
1111
|
+
/* c8 ignore start */
|
|
1029
1112
|
if (typeof hex !== 'string') {
|
|
1030
1113
|
throw new Error('message must be a hex string');
|
|
1031
1114
|
}
|
|
1115
|
+
/* c8 ignore stop */
|
|
1032
1116
|
let clean = hex.trim();
|
|
1117
|
+
// Accepts both "0x..." and raw hex formats for convenience
|
|
1033
1118
|
if (clean.startsWith('0x') || clean.startsWith('0X')) {
|
|
1034
1119
|
clean = clean.slice(2);
|
|
1035
1120
|
}
|
|
@@ -1049,7 +1134,7 @@ function messageToBytes(message) {
|
|
|
1049
1134
|
if (message instanceof Uint8Array) {
|
|
1050
1135
|
return message;
|
|
1051
1136
|
}
|
|
1052
|
-
|
|
1137
|
+
throw new Error('message must be Uint8Array or hex string');
|
|
1053
1138
|
}
|
|
1054
1139
|
|
|
1055
1140
|
/**
|
|
@@ -1161,9 +1246,6 @@ function cryptoSignSignature(sig, m, sk, randomizedSigning) {
|
|
|
1161
1246
|
}
|
|
1162
1247
|
|
|
1163
1248
|
const mBytes = messageToBytes(m);
|
|
1164
|
-
if (!mBytes) {
|
|
1165
|
-
throw new Error('message must be Uint8Array or hex string');
|
|
1166
|
-
}
|
|
1167
1249
|
|
|
1168
1250
|
const rho = new Uint8Array(SeedBytes);
|
|
1169
1251
|
const tr = new Uint8Array(TRBytes);
|
|
@@ -1242,15 +1324,19 @@ function cryptoSignSignature(sig, m, sk, randomizedSigning) {
|
|
|
1242
1324
|
polyVecKPointWisePolyMontgomery(h, cp, t0);
|
|
1243
1325
|
polyVecKInvNTTToMont(h);
|
|
1244
1326
|
polyVecKReduce(h);
|
|
1327
|
+
/* c8 ignore start */
|
|
1245
1328
|
if (polyVecKChkNorm(h, GAMMA2) !== 0) {
|
|
1246
1329
|
continue;
|
|
1247
1330
|
}
|
|
1331
|
+
/* c8 ignore stop */
|
|
1248
1332
|
|
|
1249
1333
|
polyVecKAdd(w0, w0, h);
|
|
1250
1334
|
const n = polyVecKMakeHint(h, w0, w1);
|
|
1335
|
+
/* c8 ignore start */
|
|
1251
1336
|
if (n > OMEGA) {
|
|
1252
1337
|
continue;
|
|
1253
1338
|
}
|
|
1339
|
+
/* c8 ignore stop */
|
|
1254
1340
|
|
|
1255
1341
|
packSig(sig, sig, z, h);
|
|
1256
1342
|
return 0;
|
|
@@ -1275,9 +1361,6 @@ function cryptoSignSignature(sig, m, sk, randomizedSigning) {
|
|
|
1275
1361
|
*/
|
|
1276
1362
|
function cryptoSign(msg, sk, randomizedSigning) {
|
|
1277
1363
|
const msgBytes = messageToBytes(msg);
|
|
1278
|
-
if (!msgBytes) {
|
|
1279
|
-
throw new Error('message must be Uint8Array or hex string');
|
|
1280
|
-
}
|
|
1281
1364
|
|
|
1282
1365
|
const sm = new Uint8Array(CryptoBytes + msgBytes.length);
|
|
1283
1366
|
const mLen = msgBytes.length;
|
|
@@ -1286,9 +1369,11 @@ function cryptoSign(msg, sk, randomizedSigning) {
|
|
|
1286
1369
|
}
|
|
1287
1370
|
const result = cryptoSignSignature(sm, msgBytes, sk, randomizedSigning);
|
|
1288
1371
|
|
|
1372
|
+
/* c8 ignore start */
|
|
1289
1373
|
if (result !== 0) {
|
|
1290
1374
|
throw new Error('failed to sign');
|
|
1291
1375
|
}
|
|
1376
|
+
/* c8 ignore stop */
|
|
1292
1377
|
return sm;
|
|
1293
1378
|
}
|
|
1294
1379
|
|
|
@@ -1347,9 +1432,6 @@ function cryptoSignVerify(sig, m, pk) {
|
|
|
1347
1432
|
} catch {
|
|
1348
1433
|
return false;
|
|
1349
1434
|
}
|
|
1350
|
-
if (!mBytes) {
|
|
1351
|
-
return false;
|
|
1352
|
-
}
|
|
1353
1435
|
const muFull = sha3_js.shake256.create({}).update(mu.slice(0, TRBytes)).update(mBytes).xof(CRHBytes);
|
|
1354
1436
|
mu.set(muFull);
|
|
1355
1437
|
|
package/dist/mjs/dilithium5.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { shake128, shake256 } from '@noble/hashes/sha3.js';
|
|
2
|
-
import pkg from 'randombytes';
|
|
3
2
|
import { hexToBytes as hexToBytes$1 } from '@noble/hashes/utils.js';
|
|
4
3
|
|
|
5
4
|
const Shake128Rate = 168;
|
|
@@ -366,6 +365,8 @@ function polyUniform(a, seed, nonce) {
|
|
|
366
365
|
|
|
367
366
|
let ctr = rejUniform(a.coeffs, 0, N, buf, bufLen);
|
|
368
367
|
|
|
368
|
+
// Note: With current parameters, needing extra blocks is vanishingly unlikely.
|
|
369
|
+
/* c8 ignore start */
|
|
369
370
|
while (ctr < N) {
|
|
370
371
|
off = bufLen % 3;
|
|
371
372
|
for (let i = 0; i < off; ++i) buf[i] = buf[bufLen - off + i];
|
|
@@ -374,6 +375,7 @@ function polyUniform(a, seed, nonce) {
|
|
|
374
375
|
bufLen = Stream128BlockBytes + off;
|
|
375
376
|
ctr += rejUniform(a.coeffs, ctr, N - ctr, buf, bufLen);
|
|
376
377
|
}
|
|
378
|
+
/* c8 ignore stop */
|
|
377
379
|
}
|
|
378
380
|
|
|
379
381
|
function rejEta(aP, aOffset, len, buf, bufLen) {
|
|
@@ -467,10 +469,13 @@ function polyChallenge(cP, seed) {
|
|
|
467
469
|
}
|
|
468
470
|
for (let i = N - TAU; i < N; ++i) {
|
|
469
471
|
do {
|
|
472
|
+
// Note: Re-squeezing here is extremely unlikely with TAU=60.
|
|
473
|
+
/* c8 ignore start */
|
|
470
474
|
if (pos >= Shake256Rate) {
|
|
471
475
|
shake256SqueezeBlocks(buf, 0, 1, state);
|
|
472
476
|
pos = 0;
|
|
473
477
|
}
|
|
478
|
+
/* c8 ignore stop */
|
|
474
479
|
|
|
475
480
|
b = buf[pos++];
|
|
476
481
|
} while (b > i);
|
|
@@ -1015,19 +1020,98 @@ function unpackSig(cP, z, hP, sig) {
|
|
|
1015
1020
|
return 0;
|
|
1016
1021
|
}
|
|
1017
1022
|
|
|
1018
|
-
const
|
|
1023
|
+
const MAX_BYTES = 65536;
|
|
1024
|
+
const MAX_UINT32 = 0xffffffff;
|
|
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
|
+
function getWebCrypto() {
|
|
1035
|
+
const scope = getGlobalScope();
|
|
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
|
+
|
|
1063
|
+
return null;
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
function randomBytes(size) {
|
|
1067
|
+
if (!Number.isSafeInteger(size) || size < 0) {
|
|
1068
|
+
throw new RangeError('size must be a non-negative integer');
|
|
1069
|
+
}
|
|
1070
|
+
if (size > MAX_UINT32) {
|
|
1071
|
+
throw new RangeError('requested too many random bytes');
|
|
1072
|
+
}
|
|
1073
|
+
if (size === 0) return new Uint8Array(0);
|
|
1074
|
+
|
|
1075
|
+
const cryptoObj = getWebCrypto();
|
|
1076
|
+
if (cryptoObj && typeof cryptoObj.getRandomValues === 'function') {
|
|
1077
|
+
const out = new Uint8Array(size);
|
|
1078
|
+
for (let i = 0; i < size; i += MAX_BYTES) {
|
|
1079
|
+
cryptoObj.getRandomValues(out.subarray(i, Math.min(size, i + MAX_BYTES)));
|
|
1080
|
+
}
|
|
1081
|
+
return out;
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
const nodeRandomBytes = getNodeRandomBytes();
|
|
1085
|
+
if (nodeRandomBytes) {
|
|
1086
|
+
return nodeRandomBytes(size);
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
throw new Error('Secure random number generation is not supported by this environment');
|
|
1090
|
+
}
|
|
1019
1091
|
|
|
1020
1092
|
/**
|
|
1021
1093
|
* Convert hex string to Uint8Array with strict validation.
|
|
1094
|
+
*
|
|
1095
|
+
* NOTE: This function accepts multiple hex formats (with/without 0x prefix,
|
|
1096
|
+
* leading/trailing whitespace). While user-friendly, this flexibility could
|
|
1097
|
+
* mask input errors. Applications requiring strict format validation should
|
|
1098
|
+
* validate hex format before calling cryptographic functions, e.g.:
|
|
1099
|
+
* - Reject strings with 0x prefix if raw hex is expected
|
|
1100
|
+
* - Reject strings with whitespace
|
|
1101
|
+
* - Enforce consistent casing (lowercase/uppercase)
|
|
1102
|
+
*
|
|
1022
1103
|
* @param {string} hex - Hex string (optional 0x prefix, even length).
|
|
1023
1104
|
* @returns {Uint8Array} Decoded bytes.
|
|
1024
1105
|
* @private
|
|
1025
1106
|
*/
|
|
1026
1107
|
function hexToBytes(hex) {
|
|
1108
|
+
/* c8 ignore start */
|
|
1027
1109
|
if (typeof hex !== 'string') {
|
|
1028
1110
|
throw new Error('message must be a hex string');
|
|
1029
1111
|
}
|
|
1112
|
+
/* c8 ignore stop */
|
|
1030
1113
|
let clean = hex.trim();
|
|
1114
|
+
// Accepts both "0x..." and raw hex formats for convenience
|
|
1031
1115
|
if (clean.startsWith('0x') || clean.startsWith('0X')) {
|
|
1032
1116
|
clean = clean.slice(2);
|
|
1033
1117
|
}
|
|
@@ -1047,7 +1131,7 @@ function messageToBytes(message) {
|
|
|
1047
1131
|
if (message instanceof Uint8Array) {
|
|
1048
1132
|
return message;
|
|
1049
1133
|
}
|
|
1050
|
-
|
|
1134
|
+
throw new Error('message must be Uint8Array or hex string');
|
|
1051
1135
|
}
|
|
1052
1136
|
|
|
1053
1137
|
/**
|
|
@@ -1159,9 +1243,6 @@ function cryptoSignSignature(sig, m, sk, randomizedSigning) {
|
|
|
1159
1243
|
}
|
|
1160
1244
|
|
|
1161
1245
|
const mBytes = messageToBytes(m);
|
|
1162
|
-
if (!mBytes) {
|
|
1163
|
-
throw new Error('message must be Uint8Array or hex string');
|
|
1164
|
-
}
|
|
1165
1246
|
|
|
1166
1247
|
const rho = new Uint8Array(SeedBytes);
|
|
1167
1248
|
const tr = new Uint8Array(TRBytes);
|
|
@@ -1240,15 +1321,19 @@ function cryptoSignSignature(sig, m, sk, randomizedSigning) {
|
|
|
1240
1321
|
polyVecKPointWisePolyMontgomery(h, cp, t0);
|
|
1241
1322
|
polyVecKInvNTTToMont(h);
|
|
1242
1323
|
polyVecKReduce(h);
|
|
1324
|
+
/* c8 ignore start */
|
|
1243
1325
|
if (polyVecKChkNorm(h, GAMMA2) !== 0) {
|
|
1244
1326
|
continue;
|
|
1245
1327
|
}
|
|
1328
|
+
/* c8 ignore stop */
|
|
1246
1329
|
|
|
1247
1330
|
polyVecKAdd(w0, w0, h);
|
|
1248
1331
|
const n = polyVecKMakeHint(h, w0, w1);
|
|
1332
|
+
/* c8 ignore start */
|
|
1249
1333
|
if (n > OMEGA) {
|
|
1250
1334
|
continue;
|
|
1251
1335
|
}
|
|
1336
|
+
/* c8 ignore stop */
|
|
1252
1337
|
|
|
1253
1338
|
packSig(sig, sig, z, h);
|
|
1254
1339
|
return 0;
|
|
@@ -1273,9 +1358,6 @@ function cryptoSignSignature(sig, m, sk, randomizedSigning) {
|
|
|
1273
1358
|
*/
|
|
1274
1359
|
function cryptoSign(msg, sk, randomizedSigning) {
|
|
1275
1360
|
const msgBytes = messageToBytes(msg);
|
|
1276
|
-
if (!msgBytes) {
|
|
1277
|
-
throw new Error('message must be Uint8Array or hex string');
|
|
1278
|
-
}
|
|
1279
1361
|
|
|
1280
1362
|
const sm = new Uint8Array(CryptoBytes + msgBytes.length);
|
|
1281
1363
|
const mLen = msgBytes.length;
|
|
@@ -1284,9 +1366,11 @@ function cryptoSign(msg, sk, randomizedSigning) {
|
|
|
1284
1366
|
}
|
|
1285
1367
|
const result = cryptoSignSignature(sm, msgBytes, sk, randomizedSigning);
|
|
1286
1368
|
|
|
1369
|
+
/* c8 ignore start */
|
|
1287
1370
|
if (result !== 0) {
|
|
1288
1371
|
throw new Error('failed to sign');
|
|
1289
1372
|
}
|
|
1373
|
+
/* c8 ignore stop */
|
|
1290
1374
|
return sm;
|
|
1291
1375
|
}
|
|
1292
1376
|
|
|
@@ -1345,9 +1429,6 @@ function cryptoSignVerify(sig, m, pk) {
|
|
|
1345
1429
|
} catch {
|
|
1346
1430
|
return false;
|
|
1347
1431
|
}
|
|
1348
|
-
if (!mBytes) {
|
|
1349
|
-
return false;
|
|
1350
|
-
}
|
|
1351
1432
|
const muFull = shake256.create({}).update(mu.slice(0, TRBytes)).update(mBytes).xof(CRHBytes);
|
|
1352
1433
|
mu.set(muFull);
|
|
1353
1434
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theqrl/dilithium5",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"description": "Dilithium-5 cryptography",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dilithium",
|
|
@@ -31,10 +31,12 @@
|
|
|
31
31
|
"url": "git+https://github.com/theQRL/qrypto.js.git"
|
|
32
32
|
},
|
|
33
33
|
"scripts": {
|
|
34
|
-
"test": "../../node_modules/mocha/bin/mocha.js --timeout 10000",
|
|
34
|
+
"test": "../../node_modules/mocha/bin/mocha.js --require ../../scripts/node-test-setup.cjs --timeout 10000",
|
|
35
|
+
"test:browser": "playwright test",
|
|
35
36
|
"build": "rollup src/index.js --file ./dist/cjs/dilithium5.js --format cjs && rollup src/index.js --file ./dist/mjs/dilithium5.js --format esm && ./fixup",
|
|
36
37
|
"lint-check": "eslint 'src/**/*.js' 'test/**/*.js'",
|
|
37
38
|
"lint": "eslint --fix 'src/**/*.js' 'test/**/*.js'",
|
|
39
|
+
"coverage": "c8 npm run test",
|
|
38
40
|
"report-coverage": "c8 --reporter=text-lcov npm run test > coverage.lcov"
|
|
39
41
|
},
|
|
40
42
|
"bugs": {
|
|
@@ -47,6 +49,9 @@
|
|
|
47
49
|
}
|
|
48
50
|
},
|
|
49
51
|
"type": "module",
|
|
52
|
+
"engines": {
|
|
53
|
+
"node": ">=18.20.0"
|
|
54
|
+
},
|
|
50
55
|
"devDependencies": {
|
|
51
56
|
"@eslint/js": "^9.39.0",
|
|
52
57
|
"c8": "^10.1.3",
|
|
@@ -61,7 +66,6 @@
|
|
|
61
66
|
"rollup": "^4.55.1"
|
|
62
67
|
},
|
|
63
68
|
"dependencies": {
|
|
64
|
-
"@noble/hashes": "^2.0.1"
|
|
65
|
-
"randombytes": "^2.1.0"
|
|
69
|
+
"@noble/hashes": "^2.0.1"
|
|
66
70
|
}
|
|
67
71
|
}
|
package/src/index.d.ts
CHANGED
|
@@ -56,7 +56,7 @@ export function cryptoSignKeypair(
|
|
|
56
56
|
/**
|
|
57
57
|
* Create a signature for a message
|
|
58
58
|
* @param sig - Output buffer for signature (must be CryptoBytes length minimum)
|
|
59
|
-
* @param m - Message to sign (hex string or Uint8Array)
|
|
59
|
+
* @param m - Message to sign (hex string or Uint8Array; strings are parsed as hex only)
|
|
60
60
|
* @param sk - Secret key
|
|
61
61
|
* @param randomizedSigning - If true, use random nonce; if false, deterministic
|
|
62
62
|
* @returns 0 on success
|
|
@@ -86,7 +86,7 @@ export function cryptoSign(
|
|
|
86
86
|
/**
|
|
87
87
|
* Verify a signature
|
|
88
88
|
* @param sig - Signature to verify
|
|
89
|
-
* @param m - Message that was signed (hex string or Uint8Array)
|
|
89
|
+
* @param m - Message that was signed (hex string or Uint8Array; strings are parsed as hex only)
|
|
90
90
|
* @param pk - Public key
|
|
91
91
|
* @returns true if signature is valid, false otherwise
|
|
92
92
|
*/
|