@noble/post-quantum 0.6.0 → 0.6.1
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 +45 -32
- package/_crystals.d.ts +17 -15
- package/_crystals.d.ts.map +1 -1
- package/_crystals.js +13 -3
- package/_crystals.js.map +1 -1
- package/falcon.d.ts +7 -7
- package/falcon.d.ts.map +1 -1
- package/falcon.js +27 -20
- package/falcon.js.map +1 -1
- package/hybrid.d.ts +23 -23
- package/hybrid.d.ts.map +1 -1
- package/hybrid.js +37 -28
- package/hybrid.js.map +1 -1
- package/index.js +8 -0
- package/index.js.map +1 -1
- package/ml-dsa.d.ts +7 -7
- package/ml-dsa.d.ts.map +1 -1
- package/ml-dsa.js +54 -28
- package/ml-dsa.js.map +1 -1
- package/ml-kem.d.ts +4 -4
- package/ml-kem.d.ts.map +1 -1
- package/ml-kem.js +43 -26
- package/ml-kem.js.map +1 -1
- package/package.json +5 -5
- package/slh-dsa.d.ts +21 -21
- package/slh-dsa.d.ts.map +1 -1
- package/slh-dsa.js +57 -35
- package/slh-dsa.js.map +1 -1
- package/src/_crystals.ts +44 -27
- package/src/falcon.ts +150 -117
- package/src/hybrid.ts +145 -96
- package/src/index.ts +8 -0
- package/src/ml-dsa.ts +124 -69
- package/src/ml-kem.ts +114 -85
- package/src/slh-dsa.ts +211 -132
- package/src/utils.ts +174 -34
- package/utils.d.ts +81 -22
- package/utils.d.ts.map +1 -1
- package/utils.js +30 -8
- package/utils.js.map +1 -1
package/src/ml-dsa.ts
CHANGED
|
@@ -25,6 +25,8 @@ import {
|
|
|
25
25
|
type Signer,
|
|
26
26
|
type SigOpts,
|
|
27
27
|
splitCoder,
|
|
28
|
+
type TArg,
|
|
29
|
+
type TRet,
|
|
28
30
|
validateOpts,
|
|
29
31
|
validateSigOpts,
|
|
30
32
|
validateVerOpts,
|
|
@@ -41,7 +43,7 @@ export type DSAInternalOpts = {
|
|
|
41
43
|
*/
|
|
42
44
|
externalMu?: boolean;
|
|
43
45
|
};
|
|
44
|
-
function validateInternalOpts(opts: DSAInternalOpts) {
|
|
46
|
+
function validateInternalOpts(opts: TArg<DSAInternalOpts>) {
|
|
45
47
|
validateOpts(opts);
|
|
46
48
|
if (opts.externalMu !== undefined) abool(opts.externalMu, 'opts.externalMu');
|
|
47
49
|
}
|
|
@@ -49,16 +51,20 @@ function validateInternalOpts(opts: DSAInternalOpts) {
|
|
|
49
51
|
/** ML-DSA signer surface with access to the internal message formatting mode. */
|
|
50
52
|
export type DSAInternal = CryptoKeys & {
|
|
51
53
|
lengths: Signer['lengths'];
|
|
52
|
-
sign: (
|
|
54
|
+
sign: (
|
|
55
|
+
msg: TArg<Uint8Array>,
|
|
56
|
+
secretKey: TArg<Uint8Array>,
|
|
57
|
+
opts?: TArg<SigOpts & DSAInternalOpts>
|
|
58
|
+
) => TRet<Uint8Array>;
|
|
53
59
|
verify: (
|
|
54
|
-
sig: Uint8Array
|
|
55
|
-
msg: Uint8Array
|
|
56
|
-
pubKey: Uint8Array
|
|
57
|
-
opts?: VerOpts & DSAInternalOpts
|
|
60
|
+
sig: TArg<Uint8Array>,
|
|
61
|
+
msg: TArg<Uint8Array>,
|
|
62
|
+
pubKey: TArg<Uint8Array>,
|
|
63
|
+
opts?: TArg<VerOpts & DSAInternalOpts>
|
|
58
64
|
) => boolean;
|
|
59
65
|
};
|
|
60
66
|
/** Public ML-DSA signer surface. */
|
|
61
|
-
export type DSA = Signer & { internal: DSAInternal };
|
|
67
|
+
export type DSA = Signer & { internal: TRet<DSAInternal> };
|
|
62
68
|
|
|
63
69
|
// Constants
|
|
64
70
|
// FIPS 204 fixes ML-DSA over R = Z[X]/(X^256 + 1), so every polynomial has 256 coefficients.
|
|
@@ -106,15 +112,22 @@ export type DSAParam = {
|
|
|
106
112
|
* This is only the Table 1 subset used directly here: `BETA = TAU * ETA` is derived later,
|
|
107
113
|
* while `C_TILDE_BYTES`, `TR_BYTES`, `CRH_BYTES`, and `securityLevel` live in the preset wrappers.
|
|
108
114
|
*/
|
|
109
|
-
export const PARAMS: Record<string, DSAParam> = /* @__PURE__ */ (() =>
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
}
|
|
115
|
+
export const PARAMS: Record<string, DSAParam> = /* @__PURE__ */ (() =>
|
|
116
|
+
Object.freeze({
|
|
117
|
+
2: Object.freeze({
|
|
118
|
+
K: 4, L: 4, D, GAMMA1: 2 ** 17, GAMMA2: GAMMA2_1, TAU: 39, ETA: 2, OMEGA: 80
|
|
119
|
+
}),
|
|
120
|
+
3: Object.freeze({
|
|
121
|
+
K: 6, L: 5, D, GAMMA1: 2 ** 19, GAMMA2: GAMMA2_2, TAU: 49, ETA: 4, OMEGA: 55
|
|
122
|
+
}),
|
|
123
|
+
5: Object.freeze({
|
|
124
|
+
K: 8, L: 7, D, GAMMA1: 2 ** 19, GAMMA2: GAMMA2_2, TAU: 60, ETA: 2, OMEGA: 75
|
|
125
|
+
}),
|
|
126
|
+
} as const))();
|
|
114
127
|
|
|
115
128
|
// NOTE: there is a lot cases where negative numbers used (with smod instead of mod).
|
|
116
129
|
type Poly = Int32Array;
|
|
117
|
-
const newPoly = (n: number): Int32Array => new Int32Array(n)
|
|
130
|
+
const newPoly = (n: number): TRet<Int32Array> => new Int32Array(n) as TRet<Int32Array>;
|
|
118
131
|
|
|
119
132
|
// Shared CRYSTALS helper in the ML-DSA branch: non-Kyber mode, 8-bit bit-reversal,
|
|
120
133
|
// and Int32Array polys because ordinary-form coefficients can be negative / centered.
|
|
@@ -141,41 +154,50 @@ const polyCoder = (d: number, compress: IdNum = id, verify: IdNum = id) =>
|
|
|
141
154
|
});
|
|
142
155
|
|
|
143
156
|
// Mutates `a` in place; callers must pass same-length polynomials.
|
|
144
|
-
const polyAdd = (
|
|
157
|
+
const polyAdd = (a_: TArg<Poly>, b_: TArg<Poly>): TRet<Poly> => {
|
|
158
|
+
const a = a_ as Poly;
|
|
159
|
+
const b = b_ as Poly;
|
|
145
160
|
for (let i = 0; i < a.length; i++) a[i] = crystals.mod(a[i] + b[i]);
|
|
146
|
-
return a
|
|
161
|
+
return a as TRet<Poly>;
|
|
147
162
|
};
|
|
148
163
|
// Mutates `a` in place; callers must pass same-length polynomials.
|
|
149
|
-
const polySub = (
|
|
164
|
+
const polySub = (a_: TArg<Poly>, b_: TArg<Poly>): TRet<Poly> => {
|
|
165
|
+
const a = a_ as Poly;
|
|
166
|
+
const b = b_ as Poly;
|
|
150
167
|
for (let i = 0; i < a.length; i++) a[i] = crystals.mod(a[i] - b[i]);
|
|
151
|
-
return a
|
|
168
|
+
return a as TRet<Poly>;
|
|
152
169
|
};
|
|
153
170
|
|
|
154
171
|
// Mutates `p` in place and assumes it is a decoded `t1`-range polynomial.
|
|
155
|
-
const polyShiftl = (
|
|
172
|
+
const polyShiftl = (p_: TArg<Poly>): TRet<Poly> => {
|
|
173
|
+
const p = p_ as Poly;
|
|
156
174
|
for (let i = 0; i < N; i++) p[i] <<= D;
|
|
157
|
-
return p
|
|
175
|
+
return p as TRet<Poly>;
|
|
158
176
|
};
|
|
159
177
|
|
|
160
|
-
const polyChknorm = (
|
|
178
|
+
const polyChknorm = (p_: TArg<Poly>, B: number): boolean => {
|
|
179
|
+
const p = p_ as Poly;
|
|
161
180
|
// FIPS 204 Algorithms 7 and 8 express the same centered-norm check with explicit inequalities.
|
|
162
181
|
for (let i = 0; i < N; i++) if (Math.abs(crystals.smod(p[i])) >= B) return true;
|
|
163
182
|
return false;
|
|
164
183
|
};
|
|
165
184
|
|
|
166
185
|
// Both inputs must already be in NTT / `T_q` form.
|
|
167
|
-
const MultiplyNTTs = (
|
|
186
|
+
const MultiplyNTTs = (a_: TArg<Poly>, b_: TArg<Poly>): TRet<Poly> => {
|
|
187
|
+
const a = a_ as Poly;
|
|
188
|
+
const b = b_ as Poly;
|
|
168
189
|
// NOTE: we don't use montgomery reduction in code, since it requires 64 bit ints,
|
|
169
190
|
// which is not available in JS. mod(a[i] * b[i]) is ok, since Q is 23 bit,
|
|
170
191
|
// which means a[i] * b[i] is 46 bit, which is safe to use in JS. (number is 53 bits).
|
|
171
192
|
// Barrett reduction is slower than mod :(
|
|
172
193
|
const c = newPoly(N);
|
|
173
194
|
for (let i = 0; i < a.length; i++) c[i] = crystals.mod(a[i] * b[i]);
|
|
174
|
-
return c
|
|
195
|
+
return c as TRet<Poly>;
|
|
175
196
|
};
|
|
176
197
|
|
|
177
198
|
// Return poly in NTT representation
|
|
178
|
-
function RejNTTPoly(
|
|
199
|
+
function RejNTTPoly(xof_: TArg<XofGet>): TRet<Poly> {
|
|
200
|
+
const xof = xof_ as XofGet;
|
|
179
201
|
// Samples a polynomial ∈ Tq. xof() must return byte lengths divisible by 3.
|
|
180
202
|
const r = newPoly(N);
|
|
181
203
|
// NOTE: we can represent 3xu24 as 4xu32, but it doesn't improve perf :(
|
|
@@ -188,7 +210,7 @@ function RejNTTPoly(xof: XofGet) {
|
|
|
188
210
|
if (t < Q) r[j++] = t;
|
|
189
211
|
}
|
|
190
212
|
}
|
|
191
|
-
return r
|
|
213
|
+
return r as TRet<Poly>;
|
|
192
214
|
}
|
|
193
215
|
|
|
194
216
|
type DilithiumOpts = {
|
|
@@ -209,7 +231,8 @@ type DilithiumOpts = {
|
|
|
209
231
|
|
|
210
232
|
// Instantiate one ML-DSA parameter set from the Table 1 lattice constants plus the
|
|
211
233
|
// Table 2 byte lengths / hash-width choices used by the public wrappers below.
|
|
212
|
-
function getDilithium(
|
|
234
|
+
function getDilithium(opts_: TArg<DilithiumOpts>): TRet<DSA> {
|
|
235
|
+
const opts = opts_ as DilithiumOpts;
|
|
213
236
|
const { K, L, GAMMA1, GAMMA2, TAU, ETA, OMEGA } = opts;
|
|
214
237
|
const { CRH_BYTES, TR_BYTES, C_TILDE_BYTES, XOF128, XOF256, securityLevel } = opts;
|
|
215
238
|
|
|
@@ -270,30 +293,31 @@ function getDilithium(opts: DilithiumOpts) {
|
|
|
270
293
|
|
|
271
294
|
const hintCoder: BytesCoderLen<Poly[] | false> = {
|
|
272
295
|
bytesLen: OMEGA + K,
|
|
273
|
-
encode: (
|
|
296
|
+
encode: (h_: TArg<Poly[] | false>): TRet<Uint8Array> => {
|
|
297
|
+
const h = h_ as Poly[] | false;
|
|
274
298
|
if (h === false) throw new Error('hint.encode: hint is false'); // should never happen
|
|
275
299
|
const res = new Uint8Array(OMEGA + K);
|
|
276
300
|
for (let i = 0, k = 0; i < K; i++) {
|
|
277
301
|
for (let j = 0; j < N; j++) if (h[i][j] !== 0) res[k++] = j;
|
|
278
302
|
res[OMEGA + i] = k;
|
|
279
303
|
}
|
|
280
|
-
return res
|
|
304
|
+
return res as TRet<Uint8Array>;
|
|
281
305
|
},
|
|
282
|
-
decode: (buf: Uint8Array) => {
|
|
306
|
+
decode: (buf: TArg<Uint8Array>): TRet<Poly[] | false> => {
|
|
283
307
|
const h = [];
|
|
284
308
|
let k = 0;
|
|
285
309
|
for (let i = 0; i < K; i++) {
|
|
286
310
|
const hi = newPoly(N);
|
|
287
|
-
if (buf[OMEGA + i] < k || buf[OMEGA + i] > OMEGA) return false
|
|
311
|
+
if (buf[OMEGA + i] < k || buf[OMEGA + i] > OMEGA) return false as TRet<false>;
|
|
288
312
|
for (let j = k; j < buf[OMEGA + i]; j++) {
|
|
289
|
-
if (j > k && buf[j] <= buf[j - 1]) return false
|
|
313
|
+
if (j > k && buf[j] <= buf[j - 1]) return false as TRet<false>;
|
|
290
314
|
hi[buf[j]] = 1;
|
|
291
315
|
}
|
|
292
316
|
k = buf[OMEGA + i];
|
|
293
317
|
h.push(hi);
|
|
294
318
|
}
|
|
295
|
-
for (let j = k; j < OMEGA; j++) if (buf[j] !== 0) return false
|
|
296
|
-
return h
|
|
319
|
+
for (let j = k; j < OMEGA; j++) if (buf[j] !== 0) return false as TRet<false>;
|
|
320
|
+
return h as TRet<Poly[]>;
|
|
297
321
|
},
|
|
298
322
|
};
|
|
299
323
|
|
|
@@ -332,7 +356,8 @@ function getDilithium(opts: DilithiumOpts) {
|
|
|
332
356
|
// Return poly in ordinary representation.
|
|
333
357
|
// This helper returns ordinary-form `[-ETA, ETA]` coefficients for ExpandS; callers apply
|
|
334
358
|
// `NTT.encode()` later when needed.
|
|
335
|
-
function RejBoundedPoly(
|
|
359
|
+
function RejBoundedPoly(xof_: TArg<XofGet>): TRet<Poly> {
|
|
360
|
+
const xof = xof_ as XofGet;
|
|
336
361
|
// Samples an element a ∈ Rq with coeffcients in [−η, η] computed via rejection sampling from ρ.
|
|
337
362
|
const r: Poly = newPoly(N);
|
|
338
363
|
for (let j = 0; j < N; ) {
|
|
@@ -345,10 +370,10 @@ function getDilithium(opts: DilithiumOpts) {
|
|
|
345
370
|
if (j < N && d2 !== false) r[j++] = d2;
|
|
346
371
|
}
|
|
347
372
|
}
|
|
348
|
-
return r
|
|
373
|
+
return r as TRet<Poly>;
|
|
349
374
|
}
|
|
350
375
|
|
|
351
|
-
const SampleInBall = (seed: Uint8Array) => {
|
|
376
|
+
const SampleInBall = (seed: TArg<Uint8Array>): TRet<Poly> => {
|
|
352
377
|
// Samples a polynomial c ∈ Rq with coeffcients from {−1, 0, 1} and Hamming weight τ
|
|
353
378
|
const pre = newPoly(N);
|
|
354
379
|
const s = shake256.create({}).update(seed);
|
|
@@ -372,10 +397,11 @@ function getDilithium(opts: DilithiumOpts) {
|
|
|
372
397
|
maskBit = 0;
|
|
373
398
|
}
|
|
374
399
|
}
|
|
375
|
-
return pre
|
|
400
|
+
return pre as TRet<Poly>;
|
|
376
401
|
};
|
|
377
402
|
|
|
378
|
-
const polyPowerRound = (
|
|
403
|
+
const polyPowerRound = (p_: TArg<Poly>) => {
|
|
404
|
+
const p = p_ as Poly;
|
|
379
405
|
const res0 = newPoly(N);
|
|
380
406
|
const res1 = newPoly(N);
|
|
381
407
|
for (let i = 0; i < p.length; i++) {
|
|
@@ -385,13 +411,17 @@ function getDilithium(opts: DilithiumOpts) {
|
|
|
385
411
|
}
|
|
386
412
|
return { r0: res0, r1: res1 };
|
|
387
413
|
};
|
|
388
|
-
const polyUseHint = (
|
|
414
|
+
const polyUseHint = (u_: TArg<Poly>, h_: TArg<Poly>): TRet<Poly> => {
|
|
415
|
+
const u = u_ as Poly;
|
|
416
|
+
const h = h_ as Poly;
|
|
389
417
|
// In-place on `u`: verification only needs the recovered high bits, so reuse the
|
|
390
418
|
// temporary `wApprox` buffer instead of allocating another polynomial.
|
|
391
419
|
for (let i = 0; i < N; i++) u[i] = UseHint(h[i], u[i]);
|
|
392
|
-
return u
|
|
420
|
+
return u as TRet<Poly>;
|
|
393
421
|
};
|
|
394
|
-
const polyMakeHint = (
|
|
422
|
+
const polyMakeHint = (a_: TArg<Poly>, b_: TArg<Poly>) => {
|
|
423
|
+
const a = a_ as Poly;
|
|
424
|
+
const b = b_ as Poly;
|
|
395
425
|
const v = newPoly(N);
|
|
396
426
|
let cnt = 0;
|
|
397
427
|
for (let i = 0; i < N; i++) {
|
|
@@ -405,16 +435,16 @@ function getDilithium(opts: DilithiumOpts) {
|
|
|
405
435
|
const signRandBytes = 32;
|
|
406
436
|
const seedCoder = splitCoder('seed', 32, 64, 32);
|
|
407
437
|
// API & argument positions are exactly as in FIPS204.
|
|
408
|
-
const internal: DSAInternal = {
|
|
409
|
-
info: { type: 'internal-ml-dsa' },
|
|
410
|
-
lengths: {
|
|
438
|
+
const internal: TRet<DSAInternal> = Object.freeze({
|
|
439
|
+
info: Object.freeze({ type: 'internal-ml-dsa' }),
|
|
440
|
+
lengths: Object.freeze({
|
|
411
441
|
secretKey: secretCoder.bytesLen,
|
|
412
442
|
publicKey: publicCoder.bytesLen,
|
|
413
443
|
seed: 32,
|
|
414
444
|
signature: sigCoder.bytesLen,
|
|
415
445
|
signRand: signRandBytes,
|
|
416
|
-
},
|
|
417
|
-
keygen: (seed?: Uint8Array) => {
|
|
446
|
+
}),
|
|
447
|
+
keygen: (seed?: TArg<Uint8Array>) => {
|
|
418
448
|
// H(𝜉||IntegerToBytes(𝑘, 1)||IntegerToBytes(ℓ, 1), 128) 2: ▷ expand seed
|
|
419
449
|
const seedDst = new Uint8Array(32 + 2);
|
|
420
450
|
const randSeed = seed === undefined;
|
|
@@ -462,9 +492,12 @@ function getDilithium(opts: DilithiumOpts) {
|
|
|
462
492
|
// DSA44: { calls: 24, xofs: 24 }, DSA65: { calls: 41, xofs: 41 },
|
|
463
493
|
// DSA87: { calls: 71, xofs: 71 }
|
|
464
494
|
cleanBytes(rho, rhoPrime, K_, s1, s2, s1Hat, t, t0, t1, tr, seedDst);
|
|
465
|
-
return {
|
|
495
|
+
return {
|
|
496
|
+
publicKey: publicKey as TRet<Uint8Array>,
|
|
497
|
+
secretKey: secretKey as TRet<Uint8Array>,
|
|
498
|
+
};
|
|
466
499
|
},
|
|
467
|
-
getPublicKey: (secretKey: Uint8Array) => {
|
|
500
|
+
getPublicKey: (secretKey: TArg<Uint8Array>): TRet<Uint8Array> => {
|
|
468
501
|
// (ρ, K,tr, s1, s2, t0) ← skDecode(sk)
|
|
469
502
|
const [rho, _K, _tr, s1, s2, _t0] = secretCoder.decode(secretKey);
|
|
470
503
|
const xof = XOF128(rho);
|
|
@@ -487,7 +520,11 @@ function getDilithium(opts: DilithiumOpts) {
|
|
|
487
520
|
return publicCoder.encode([rho, t1]);
|
|
488
521
|
},
|
|
489
522
|
// NOTE: random is optional.
|
|
490
|
-
sign: (
|
|
523
|
+
sign: (
|
|
524
|
+
msg: TArg<Uint8Array>,
|
|
525
|
+
secretKey: TArg<Uint8Array>,
|
|
526
|
+
opts: TArg<SigOpts & DSAInternalOpts> = {}
|
|
527
|
+
): TRet<Uint8Array> => {
|
|
491
528
|
validateSigOpts(opts);
|
|
492
529
|
validateInternalOpts(opts);
|
|
493
530
|
let { extraEntropy: random, externalMu = false } = opts;
|
|
@@ -588,16 +625,16 @@ function getDilithium(opts: DilithiumOpts) {
|
|
|
588
625
|
// so only wipe the internally derived digest form here;
|
|
589
626
|
// zeroizing caller memory would break the caller's own reuse / verify path.
|
|
590
627
|
if (!externalMu) cleanBytes(mu);
|
|
591
|
-
return res
|
|
628
|
+
return res as TRet<Uint8Array>;
|
|
592
629
|
}
|
|
593
630
|
// @ts-ignore
|
|
594
631
|
throw new Error('Unreachable code path reached, report this error');
|
|
595
632
|
},
|
|
596
633
|
verify: (
|
|
597
|
-
sig: Uint8Array
|
|
598
|
-
msg: Uint8Array
|
|
599
|
-
publicKey: Uint8Array
|
|
600
|
-
opts: DSAInternalOpts = {}
|
|
634
|
+
sig: TArg<Uint8Array>,
|
|
635
|
+
msg: TArg<Uint8Array>,
|
|
636
|
+
publicKey: TArg<Uint8Array>,
|
|
637
|
+
opts: TArg<DSAInternalOpts> = {}
|
|
601
638
|
) => {
|
|
602
639
|
validateInternalOpts(opts);
|
|
603
640
|
const { externalMu = false } = opts;
|
|
@@ -649,51 +686,69 @@ function getDilithium(opts: DilithiumOpts) {
|
|
|
649
686
|
for (const t of z) if (polyChknorm(t, GAMMA1 - BETA)) return false;
|
|
650
687
|
return equalBytes(cTilde, c2);
|
|
651
688
|
},
|
|
652
|
-
};
|
|
653
|
-
return {
|
|
654
|
-
info: { type: 'ml-dsa' },
|
|
689
|
+
});
|
|
690
|
+
return Object.freeze({
|
|
691
|
+
info: Object.freeze({ type: 'ml-dsa' }),
|
|
655
692
|
internal,
|
|
656
693
|
securityLevel: securityLevel,
|
|
657
694
|
keygen: internal.keygen,
|
|
658
695
|
lengths: internal.lengths,
|
|
659
696
|
getPublicKey: internal.getPublicKey,
|
|
660
|
-
sign: (
|
|
697
|
+
sign: (
|
|
698
|
+
msg: TArg<Uint8Array>,
|
|
699
|
+
secretKey: TArg<Uint8Array>,
|
|
700
|
+
opts: TArg<SigOpts> = {}
|
|
701
|
+
): TRet<Uint8Array> => {
|
|
661
702
|
validateSigOpts(opts);
|
|
662
703
|
const M = getMessage(msg, opts.context);
|
|
663
704
|
const res = internal.sign(M, secretKey, opts);
|
|
664
705
|
cleanBytes(M);
|
|
665
|
-
return res
|
|
706
|
+
return res as TRet<Uint8Array>;
|
|
666
707
|
},
|
|
667
|
-
verify: (
|
|
708
|
+
verify: (
|
|
709
|
+
sig: TArg<Uint8Array>,
|
|
710
|
+
msg: TArg<Uint8Array>,
|
|
711
|
+
publicKey: TArg<Uint8Array>,
|
|
712
|
+
opts: TArg<VerOpts> = {}
|
|
713
|
+
) => {
|
|
668
714
|
validateVerOpts(opts);
|
|
669
715
|
return internal.verify(sig, getMessage(msg, opts.context), publicKey);
|
|
670
716
|
},
|
|
671
717
|
prehash: (hash: CHash) => {
|
|
672
718
|
checkHash(hash, securityLevel);
|
|
673
|
-
return {
|
|
674
|
-
info: { type: 'hashml-dsa' },
|
|
719
|
+
return Object.freeze({
|
|
720
|
+
info: Object.freeze({ type: 'hashml-dsa' }),
|
|
675
721
|
securityLevel: securityLevel,
|
|
676
722
|
lengths: internal.lengths,
|
|
677
723
|
keygen: internal.keygen,
|
|
678
724
|
getPublicKey: internal.getPublicKey,
|
|
679
|
-
sign: (
|
|
725
|
+
sign: (
|
|
726
|
+
msg: TArg<Uint8Array>,
|
|
727
|
+
secretKey: TArg<Uint8Array>,
|
|
728
|
+
opts: TArg<SigOpts> = {}
|
|
729
|
+
): TRet<Uint8Array> => {
|
|
680
730
|
validateSigOpts(opts);
|
|
681
731
|
const M = getMessagePrehash(hash, msg, opts.context);
|
|
682
732
|
const res = internal.sign(M, secretKey, opts);
|
|
683
733
|
cleanBytes(M);
|
|
684
|
-
return res
|
|
734
|
+
return res as TRet<Uint8Array>;
|
|
685
735
|
},
|
|
686
|
-
verify: (
|
|
736
|
+
verify: (
|
|
737
|
+
sig: TArg<Uint8Array>,
|
|
738
|
+
msg: TArg<Uint8Array>,
|
|
739
|
+
publicKey: TArg<Uint8Array>,
|
|
740
|
+
opts: TArg<VerOpts> = {}
|
|
741
|
+
) => {
|
|
687
742
|
validateVerOpts(opts);
|
|
688
743
|
return internal.verify(sig, getMessagePrehash(hash, msg, opts.context), publicKey);
|
|
689
744
|
},
|
|
690
|
-
};
|
|
745
|
+
});
|
|
691
746
|
},
|
|
692
|
-
};
|
|
747
|
+
});
|
|
693
748
|
}
|
|
694
749
|
|
|
695
750
|
/** ML-DSA-44 for 128-bit security level. Not recommended after 2030, as per ASD. */
|
|
696
|
-
export const ml_dsa44: DSA = /* @__PURE__ */ (() =>
|
|
751
|
+
export const ml_dsa44: TRet<DSA> = /* @__PURE__ */ (() =>
|
|
697
752
|
getDilithium({
|
|
698
753
|
...PARAMS[2],
|
|
699
754
|
CRH_BYTES: 64,
|
|
@@ -705,7 +760,7 @@ export const ml_dsa44: DSA = /* @__PURE__ */ (() =>
|
|
|
705
760
|
}))();
|
|
706
761
|
|
|
707
762
|
/** ML-DSA-65 for 192-bit security level. Not recommended after 2030, as per ASD. */
|
|
708
|
-
export const ml_dsa65: DSA = /* @__PURE__ */ (() =>
|
|
763
|
+
export const ml_dsa65: TRet<DSA> = /* @__PURE__ */ (() =>
|
|
709
764
|
getDilithium({
|
|
710
765
|
...PARAMS[3],
|
|
711
766
|
CRH_BYTES: 64,
|
|
@@ -717,7 +772,7 @@ export const ml_dsa65: DSA = /* @__PURE__ */ (() =>
|
|
|
717
772
|
}))();
|
|
718
773
|
|
|
719
774
|
/** ML-DSA-87 for 256-bit security level. OK after 2030, as per ASD. */
|
|
720
|
-
export const ml_dsa87: DSA = /* @__PURE__ */ (() =>
|
|
775
|
+
export const ml_dsa87: TRet<DSA> = /* @__PURE__ */ (() =>
|
|
721
776
|
getDilithium({
|
|
722
777
|
...PARAMS[5],
|
|
723
778
|
CRH_BYTES: 64,
|