@theqrl/dilithium5 1.1.1 → 1.1.5
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 +9 -1
- package/dist/cjs/dilithium5.d.cts +309 -0
- package/dist/cjs/dilithium5.js +71 -28
- package/dist/mjs/dilithium5.d.mts +309 -0
- package/dist/mjs/dilithium5.js +71 -28
- package/package.json +41 -16
- package/src/index.d.ts +115 -0
package/README.md
CHANGED
|
@@ -55,7 +55,7 @@ console.log(new TextDecoder().decode(extracted)); // "Hello, quantum world!"
|
|
|
55
55
|
|
|
56
56
|
Generate a keypair from a seed.
|
|
57
57
|
|
|
58
|
-
- `seed`: `Uint8Array(32)` or `
|
|
58
|
+
- `seed`: `Uint8Array(32)`, `null`, or `undefined` for random
|
|
59
59
|
- `pk`: `Uint8Array(2592)` - output buffer for public key
|
|
60
60
|
- `sk`: `Uint8Array(4896)` - output buffer for secret key
|
|
61
61
|
- Returns: The seed used (useful when `seed` is `null`)
|
|
@@ -102,10 +102,17 @@ Verify a detached signature.
|
|
|
102
102
|
|
|
103
103
|
Zero out sensitive data (best-effort, see security notes).
|
|
104
104
|
|
|
105
|
+
- `buffer`: `Uint8Array` - the buffer to zero
|
|
106
|
+
- Throws: `TypeError` if buffer is not a `Uint8Array`
|
|
107
|
+
|
|
105
108
|
#### `isZero(buffer)`
|
|
106
109
|
|
|
107
110
|
Check if buffer is all zeros (constant-time).
|
|
108
111
|
|
|
112
|
+
- `buffer`: `Uint8Array` - the buffer to check
|
|
113
|
+
- Returns: `true` if all bytes are zero
|
|
114
|
+
- Throws: `TypeError` if buffer is not a `Uint8Array`
|
|
115
|
+
|
|
109
116
|
## Interoperability with go-qrllib
|
|
110
117
|
|
|
111
118
|
go-qrllib pre-hashes seeds with SHAKE256 before key generation. To generate matching keys:
|
|
@@ -137,6 +144,7 @@ See [SECURITY.md](../../SECURITY.md) for important information about:
|
|
|
137
144
|
|
|
138
145
|
- JavaScript memory security limitations
|
|
139
146
|
- Constant-time verification
|
|
147
|
+
- **Signing timing variability** — signing is not constant-time due to the algorithm's rejection sampling loop; see SECURITY.md for measured impact and deployment mitigations
|
|
140
148
|
- Secure key handling recommendations
|
|
141
149
|
|
|
142
150
|
## Requirements
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript definitions for @theqrl/dilithium5
|
|
3
|
+
* Dilithium-5 post-quantum digital signature scheme
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Constants
|
|
7
|
+
export const Shake128Rate: number;
|
|
8
|
+
export const Shake256Rate: number;
|
|
9
|
+
export const Stream128BlockBytes: number;
|
|
10
|
+
export const Stream256BlockBytes: number;
|
|
11
|
+
export const SeedBytes: number;
|
|
12
|
+
export const CRHBytes: number;
|
|
13
|
+
export const TRBytes: number;
|
|
14
|
+
export const N: number;
|
|
15
|
+
export const Q: number;
|
|
16
|
+
export const QInv: number;
|
|
17
|
+
export const D: number;
|
|
18
|
+
export const K: number;
|
|
19
|
+
export const L: number;
|
|
20
|
+
export const ETA: number;
|
|
21
|
+
export const TAU: number;
|
|
22
|
+
export const BETA: number;
|
|
23
|
+
export const GAMMA1: number;
|
|
24
|
+
export const GAMMA2: number;
|
|
25
|
+
export const OMEGA: number;
|
|
26
|
+
export const PolyT1PackedBytes: number;
|
|
27
|
+
export const PolyT0PackedBytes: number;
|
|
28
|
+
export const PolyETAPackedBytes: number;
|
|
29
|
+
export const PolyZPackedBytes: number;
|
|
30
|
+
export const PolyVecHPackedBytes: number;
|
|
31
|
+
export const PolyW1PackedBytes: number;
|
|
32
|
+
export const CryptoPublicKeyBytes: number;
|
|
33
|
+
export const CryptoSecretKeyBytes: number;
|
|
34
|
+
export const CryptoBytes: number;
|
|
35
|
+
export const PolyUniformNBlocks: number;
|
|
36
|
+
export const PolyUniformETANBlocks: number;
|
|
37
|
+
export const PolyUniformGamma1NBlocks: number;
|
|
38
|
+
export const zetas: readonly number[];
|
|
39
|
+
|
|
40
|
+
// Core signing functions
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Generate a Dilithium-5 key pair
|
|
44
|
+
* @param seed - Optional 32-byte seed for deterministic key generation (null for random)
|
|
45
|
+
* @param pk - Output buffer for public key (must be CryptoPublicKeyBytes length)
|
|
46
|
+
* @param sk - Output buffer for secret key (must be CryptoSecretKeyBytes length)
|
|
47
|
+
* @returns The seed used for key generation
|
|
48
|
+
* @throws Error if pk/sk buffers are wrong size or null
|
|
49
|
+
*/
|
|
50
|
+
export function cryptoSignKeypair(
|
|
51
|
+
seed: Uint8Array | null,
|
|
52
|
+
pk: Uint8Array,
|
|
53
|
+
sk: Uint8Array
|
|
54
|
+
): Uint8Array;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Create a signature for a message
|
|
58
|
+
* @param sig - Output buffer for signature (must be CryptoBytes length minimum)
|
|
59
|
+
* @param m - Message to sign (hex string or Uint8Array; strings are parsed as hex only)
|
|
60
|
+
* @param sk - Secret key
|
|
61
|
+
* @param randomizedSigning - If true, use random nonce; if false, deterministic
|
|
62
|
+
* @returns 0 on success
|
|
63
|
+
* @throws Error if sk is wrong size
|
|
64
|
+
*/
|
|
65
|
+
export function cryptoSignSignature(
|
|
66
|
+
sig: Uint8Array,
|
|
67
|
+
m: Uint8Array | string,
|
|
68
|
+
sk: Uint8Array,
|
|
69
|
+
randomizedSigning: boolean
|
|
70
|
+
): number;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Sign a message, returning signature concatenated with message
|
|
74
|
+
* @param msg - Message to sign
|
|
75
|
+
* @param sk - Secret key
|
|
76
|
+
* @param randomizedSigning - If true, use random nonce; if false, deterministic
|
|
77
|
+
* @returns Signed message (signature || message)
|
|
78
|
+
* @throws Error if signing fails
|
|
79
|
+
*/
|
|
80
|
+
export function cryptoSign(
|
|
81
|
+
msg: Uint8Array | string,
|
|
82
|
+
sk: Uint8Array,
|
|
83
|
+
randomizedSigning: boolean
|
|
84
|
+
): Uint8Array;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Verify a signature
|
|
88
|
+
* @param sig - Signature to verify
|
|
89
|
+
* @param m - Message that was signed (hex string or Uint8Array; strings are parsed as hex only)
|
|
90
|
+
* @param pk - Public key
|
|
91
|
+
* @returns true if signature is valid, false otherwise
|
|
92
|
+
*/
|
|
93
|
+
export function cryptoSignVerify(
|
|
94
|
+
sig: Uint8Array,
|
|
95
|
+
m: Uint8Array | string,
|
|
96
|
+
pk: Uint8Array
|
|
97
|
+
): boolean;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Open a signed message (verify and extract message)
|
|
101
|
+
* @param sm - Signed message (signature || message)
|
|
102
|
+
* @param pk - Public key
|
|
103
|
+
* @returns Message if valid, undefined if verification fails
|
|
104
|
+
*/
|
|
105
|
+
export function cryptoSignOpen(
|
|
106
|
+
sm: Uint8Array,
|
|
107
|
+
pk: Uint8Array
|
|
108
|
+
): Uint8Array | undefined;
|
|
109
|
+
|
|
110
|
+
// Utility functions
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Zero out a buffer (best-effort, see SECURITY.md for limitations)
|
|
114
|
+
* @param buffer - Buffer to zero
|
|
115
|
+
* @throws TypeError if buffer is not Uint8Array
|
|
116
|
+
*/
|
|
117
|
+
export function zeroize(buffer: Uint8Array): void;
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Check if buffer is all zeros using constant-time comparison
|
|
121
|
+
* @param buffer - Buffer to check
|
|
122
|
+
* @returns true if all bytes are zero
|
|
123
|
+
* @throws TypeError if buffer is not Uint8Array
|
|
124
|
+
*/
|
|
125
|
+
export function isZero(buffer: Uint8Array): boolean;
|
|
126
|
+
|
|
127
|
+
// Internal classes (exported but primarily for internal use)
|
|
128
|
+
|
|
129
|
+
export class Poly {
|
|
130
|
+
coeffs: Int32Array;
|
|
131
|
+
constructor();
|
|
132
|
+
copy(poly: Poly): void;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export class PolyVecK {
|
|
136
|
+
vec: Poly[];
|
|
137
|
+
constructor();
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export class PolyVecL {
|
|
141
|
+
vec: Poly[];
|
|
142
|
+
constructor();
|
|
143
|
+
copy(polyVecL: PolyVecL): void;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export class KeccakState {
|
|
147
|
+
constructor();
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Internal functions (exported but primarily for internal use)
|
|
151
|
+
export function polyNTT(a: Poly): void;
|
|
152
|
+
export function polyInvNTTToMont(a: Poly): void;
|
|
153
|
+
export function polyChallenge(c: Poly, seed: Uint8Array): void;
|
|
154
|
+
export function ntt(a: Int32Array): void;
|
|
155
|
+
export function invNTTToMont(a: Int32Array): void;
|
|
156
|
+
export function montgomeryReduce(a: bigint): bigint;
|
|
157
|
+
export function reduce32(a: number): number;
|
|
158
|
+
export function cAddQ(a: number): number;
|
|
159
|
+
export function decompose(a0: Int32Array, i: number, a: number): number;
|
|
160
|
+
export function power2round(a0: Int32Array, i: number, a: number): number;
|
|
161
|
+
export function makeHint(a0: number, a1: number): number;
|
|
162
|
+
export function useHint(a: number, hint: number): number;
|
|
163
|
+
export function packPk(pk: Uint8Array, rho: Uint8Array, t1: PolyVecK): void;
|
|
164
|
+
export function packSk(
|
|
165
|
+
sk: Uint8Array,
|
|
166
|
+
rho: Uint8Array,
|
|
167
|
+
tr: Uint8Array,
|
|
168
|
+
key: Uint8Array,
|
|
169
|
+
t0: PolyVecK,
|
|
170
|
+
s1: PolyVecL,
|
|
171
|
+
s2: PolyVecK
|
|
172
|
+
): void;
|
|
173
|
+
export function packSig(
|
|
174
|
+
sig: Uint8Array,
|
|
175
|
+
c: Uint8Array,
|
|
176
|
+
z: PolyVecL,
|
|
177
|
+
h: PolyVecK
|
|
178
|
+
): void;
|
|
179
|
+
export function unpackPk(rho: Uint8Array, t1: PolyVecK, pk: Uint8Array): void;
|
|
180
|
+
export function unpackSk(
|
|
181
|
+
rho: Uint8Array,
|
|
182
|
+
tr: Uint8Array,
|
|
183
|
+
key: Uint8Array,
|
|
184
|
+
t0: PolyVecK,
|
|
185
|
+
s1: PolyVecL,
|
|
186
|
+
s2: PolyVecK,
|
|
187
|
+
sk: Uint8Array
|
|
188
|
+
): void;
|
|
189
|
+
export function unpackSig(
|
|
190
|
+
c: Uint8Array,
|
|
191
|
+
z: PolyVecL,
|
|
192
|
+
h: PolyVecK,
|
|
193
|
+
sig: Uint8Array
|
|
194
|
+
): number;
|
|
195
|
+
|
|
196
|
+
// FIPS 202 SHAKE primitives (low-level XOF interface, primarily internal)
|
|
197
|
+
export function shake128Init(state: KeccakState): void;
|
|
198
|
+
export function shake128Absorb(state: KeccakState, input: Uint8Array): void;
|
|
199
|
+
export function shake128Finalize(state: KeccakState): void;
|
|
200
|
+
export function shake128SqueezeBlocks(
|
|
201
|
+
out: Uint8Array,
|
|
202
|
+
outputOffset: number,
|
|
203
|
+
nBlocks: number,
|
|
204
|
+
state: KeccakState
|
|
205
|
+
): void;
|
|
206
|
+
export function shake256Init(state: KeccakState): void;
|
|
207
|
+
export function shake256Absorb(state: KeccakState, input: Uint8Array): void;
|
|
208
|
+
export function shake256Finalize(state: KeccakState): void;
|
|
209
|
+
export function shake256SqueezeBlocks(
|
|
210
|
+
out: Uint8Array,
|
|
211
|
+
outputOffset: number,
|
|
212
|
+
nBlocks: number,
|
|
213
|
+
state: KeccakState
|
|
214
|
+
): void;
|
|
215
|
+
|
|
216
|
+
// Dilithium-specific stream initializers
|
|
217
|
+
export function dilithiumShake128StreamInit(
|
|
218
|
+
state: KeccakState,
|
|
219
|
+
seed: Uint8Array,
|
|
220
|
+
nonce: number
|
|
221
|
+
): void;
|
|
222
|
+
export function dilithiumShake256StreamInit(
|
|
223
|
+
state: KeccakState,
|
|
224
|
+
seed: Uint8Array,
|
|
225
|
+
nonce: number
|
|
226
|
+
): void;
|
|
227
|
+
|
|
228
|
+
// Polynomial operations (internal)
|
|
229
|
+
export function polyReduce(a: Poly): void;
|
|
230
|
+
export function polyCAddQ(a: Poly): void;
|
|
231
|
+
export function polyAdd(c: Poly, a: Poly, b: Poly): void;
|
|
232
|
+
export function polySub(c: Poly, a: Poly, b: Poly): void;
|
|
233
|
+
export function polyShiftL(a: Poly): void;
|
|
234
|
+
export function polyPointWiseMontgomery(c: Poly, a: Poly, b: Poly): void;
|
|
235
|
+
export function polyPower2round(a1: Poly, a0: Poly, a: Poly): void;
|
|
236
|
+
export function polyDecompose(a1: Poly, a0: Poly, a: Poly): void;
|
|
237
|
+
export function polyMakeHint(h: Poly, a0: Poly, a1: Poly): number;
|
|
238
|
+
export function polyUseHint(b: Poly, a: Poly, h: Poly): void;
|
|
239
|
+
export function polyChkNorm(a: Poly, b: number): number;
|
|
240
|
+
export function rejUniform(
|
|
241
|
+
a: Int32Array,
|
|
242
|
+
aOffset: number,
|
|
243
|
+
len: number,
|
|
244
|
+
buf: Uint8Array,
|
|
245
|
+
bufLen: number
|
|
246
|
+
): number;
|
|
247
|
+
export function polyUniform(a: Poly, seed: Uint8Array, nonce: number): void;
|
|
248
|
+
export function rejEta(
|
|
249
|
+
a: Int32Array,
|
|
250
|
+
aOffset: number,
|
|
251
|
+
len: number,
|
|
252
|
+
buf: Uint8Array,
|
|
253
|
+
bufLen: number
|
|
254
|
+
): number;
|
|
255
|
+
export function polyUniformEta(a: Poly, seed: Uint8Array, nonce: number): void;
|
|
256
|
+
export function polyZUnpack(r: Poly, a: Uint8Array, aOffset: number): void;
|
|
257
|
+
export function polyUniformGamma1(a: Poly, seed: Uint8Array, nonce: number): void;
|
|
258
|
+
export function polyEtaPack(r: Uint8Array, rOffset: number, a: Poly): void;
|
|
259
|
+
export function polyEtaUnpack(r: Poly, a: Uint8Array, aOffset: number): void;
|
|
260
|
+
export function polyT1Pack(r: Uint8Array, rOffset: number, a: Poly): void;
|
|
261
|
+
export function polyT1Unpack(r: Poly, a: Uint8Array, aOffset: number): void;
|
|
262
|
+
export function polyT0Pack(r: Uint8Array, rOffset: number, a: Poly): void;
|
|
263
|
+
export function polyT0Unpack(r: Poly, a: Uint8Array, aOffset: number): void;
|
|
264
|
+
export function polyZPack(r: Uint8Array, rOffset: number, a: Poly): void;
|
|
265
|
+
export function polyW1Pack(r: Uint8Array, rOffset: number, a: Poly): void;
|
|
266
|
+
|
|
267
|
+
// Polynomial vector operations (internal)
|
|
268
|
+
export function polyVecMatrixExpand(mat: PolyVecL[], rho: Uint8Array): void;
|
|
269
|
+
export function polyVecMatrixPointWiseMontgomery(
|
|
270
|
+
t: PolyVecK,
|
|
271
|
+
mat: PolyVecL[],
|
|
272
|
+
v: PolyVecL
|
|
273
|
+
): void;
|
|
274
|
+
export function polyVecLUniformEta(v: PolyVecL, seed: Uint8Array, nonce: number): void;
|
|
275
|
+
export function polyVecLUniformGamma1(v: PolyVecL, seed: Uint8Array, nonce: number): void;
|
|
276
|
+
export function polyVecLReduce(v: PolyVecL): void;
|
|
277
|
+
export function polyVecLAdd(w: PolyVecL, u: PolyVecL, v: PolyVecL): void;
|
|
278
|
+
export function polyVecLNTT(v: PolyVecL): void;
|
|
279
|
+
export function polyVecLInvNTTToMont(v: PolyVecL): void;
|
|
280
|
+
export function polyVecLPointWisePolyMontgomery(
|
|
281
|
+
r: PolyVecL,
|
|
282
|
+
a: Poly,
|
|
283
|
+
v: PolyVecL
|
|
284
|
+
): void;
|
|
285
|
+
export function polyVecLPointWiseAccMontgomery(
|
|
286
|
+
w: Poly,
|
|
287
|
+
u: PolyVecL,
|
|
288
|
+
v: PolyVecL
|
|
289
|
+
): void;
|
|
290
|
+
export function polyVecLChkNorm(v: PolyVecL, bound: number): number;
|
|
291
|
+
export function polyVecKUniformEta(v: PolyVecK, seed: Uint8Array, nonce: number): void;
|
|
292
|
+
export function polyVecKReduce(v: PolyVecK): void;
|
|
293
|
+
export function polyVecKCAddQ(v: PolyVecK): void;
|
|
294
|
+
export function polyVecKAdd(w: PolyVecK, u: PolyVecK, v: PolyVecK): void;
|
|
295
|
+
export function polyVecKSub(w: PolyVecK, u: PolyVecK, v: PolyVecK): void;
|
|
296
|
+
export function polyVecKShiftL(v: PolyVecK): void;
|
|
297
|
+
export function polyVecKNTT(v: PolyVecK): void;
|
|
298
|
+
export function polyVecKInvNTTToMont(v: PolyVecK): void;
|
|
299
|
+
export function polyVecKPointWisePolyMontgomery(
|
|
300
|
+
r: PolyVecK,
|
|
301
|
+
a: Poly,
|
|
302
|
+
v: PolyVecK
|
|
303
|
+
): void;
|
|
304
|
+
export function polyVecKChkNorm(v: PolyVecK, bound: number): number;
|
|
305
|
+
export function polyVecKPower2round(v1: PolyVecK, v0: PolyVecK, v: PolyVecK): void;
|
|
306
|
+
export function polyVecKDecompose(v1: PolyVecK, v0: PolyVecK, v: PolyVecK): void;
|
|
307
|
+
export function polyVecKMakeHint(h: PolyVecK, v0: PolyVecK, v1: PolyVecK): number;
|
|
308
|
+
export function polyVecKUseHint(w: PolyVecK, u: PolyVecK, h: PolyVecK): void;
|
|
309
|
+
export function polyVecKPackW1(r: Uint8Array, w1: PolyVecK): void;
|
package/dist/cjs/dilithium5.js
CHANGED
|
@@ -537,12 +537,16 @@ function montgomeryReduce(a) {
|
|
|
537
537
|
return t;
|
|
538
538
|
}
|
|
539
539
|
|
|
540
|
+
// Partial reduction modulo Q. Input must satisfy |a| < 2^31 - 2^22.
|
|
541
|
+
// Output is in (-Q, Q). Mirrors the reference C implementation.
|
|
540
542
|
function reduce32(a) {
|
|
541
543
|
let t = (a + (1 << 22)) >> 23;
|
|
542
544
|
t = a - t * Q;
|
|
543
545
|
return t;
|
|
544
546
|
}
|
|
545
547
|
|
|
548
|
+
// Conditional add Q: if a is negative, add Q. Input must satisfy -Q < a < 2^31.
|
|
549
|
+
// Output is in [0, Q). Mirrors the reference C implementation.
|
|
546
550
|
function cAddQ(a) {
|
|
547
551
|
let ar = a;
|
|
548
552
|
ar += (ar >> 31) & Q;
|
|
@@ -551,7 +555,7 @@ function cAddQ(a) {
|
|
|
551
555
|
|
|
552
556
|
function ntt(a) {
|
|
553
557
|
let k = 0;
|
|
554
|
-
let j
|
|
558
|
+
let j;
|
|
555
559
|
|
|
556
560
|
for (let len = 128; len > 0; len >>= 1) {
|
|
557
561
|
for (let start = 0; start < N; start = j + len) {
|
|
@@ -567,7 +571,7 @@ function ntt(a) {
|
|
|
567
571
|
|
|
568
572
|
function invNTTToMont(a) {
|
|
569
573
|
const f = 41978n; // mont^2/256
|
|
570
|
-
let j
|
|
574
|
+
let j;
|
|
571
575
|
let k = 256;
|
|
572
576
|
|
|
573
577
|
for (let len = 1; len < N; len <<= 1) {
|
|
@@ -704,10 +708,7 @@ function polyChkNorm(a, b) {
|
|
|
704
708
|
}
|
|
705
709
|
|
|
706
710
|
for (let i = 0; i < N; i++) {
|
|
707
|
-
|
|
708
|
-
t = a.coeffs[i] - (t & (2 * a.coeffs[i]));
|
|
709
|
-
|
|
710
|
-
if (t >= b) {
|
|
711
|
+
if (Math.abs(a.coeffs[i]) >= b) {
|
|
711
712
|
return 1;
|
|
712
713
|
}
|
|
713
714
|
}
|
|
@@ -826,6 +827,8 @@ function polyUniformGamma1(a, seed, nonce) {
|
|
|
826
827
|
}
|
|
827
828
|
|
|
828
829
|
function polyChallenge(cP, seed) {
|
|
830
|
+
if (seed.length !== SeedBytes) throw new Error('invalid seed length');
|
|
831
|
+
|
|
829
832
|
let b;
|
|
830
833
|
let pos;
|
|
831
834
|
const c = cP;
|
|
@@ -833,7 +836,7 @@ function polyChallenge(cP, seed) {
|
|
|
833
836
|
|
|
834
837
|
const state = new KeccakState();
|
|
835
838
|
shake256Init(state);
|
|
836
|
-
shake256Absorb(state, seed
|
|
839
|
+
shake256Absorb(state, seed);
|
|
837
840
|
shake256Finalize(state);
|
|
838
841
|
shake256SqueezeBlocks(buf, 0, 1, state);
|
|
839
842
|
|
|
@@ -1246,6 +1249,9 @@ function packPk(pkp, rho, t1) {
|
|
|
1246
1249
|
}
|
|
1247
1250
|
|
|
1248
1251
|
function unpackPk(rhop, t1, pk) {
|
|
1252
|
+
if (!(pk instanceof Uint8Array) || pk.length !== CryptoPublicKeyBytes) {
|
|
1253
|
+
throw new Error(`pk must be a Uint8Array of ${CryptoPublicKeyBytes} bytes`);
|
|
1254
|
+
}
|
|
1249
1255
|
const rho = rhop;
|
|
1250
1256
|
for (let i = 0; i < SeedBytes; ++i) {
|
|
1251
1257
|
rho[i] = pk[i];
|
|
@@ -1290,6 +1296,9 @@ function packSk(skp, rho, tr, key, t0, s1, s2) {
|
|
|
1290
1296
|
}
|
|
1291
1297
|
|
|
1292
1298
|
function unpackSk(rhoP, trP, keyP, t0, s1, s2, sk) {
|
|
1299
|
+
if (!(sk instanceof Uint8Array) || sk.length !== CryptoSecretKeyBytes) {
|
|
1300
|
+
throw new Error(`sk must be a Uint8Array of ${CryptoSecretKeyBytes} bytes`);
|
|
1301
|
+
}
|
|
1293
1302
|
let skOffset = 0;
|
|
1294
1303
|
const rho = rhoP;
|
|
1295
1304
|
const tr = trP;
|
|
@@ -1345,6 +1354,12 @@ function packSig(sigP, c, z, h) {
|
|
|
1345
1354
|
for (let i = 0; i < K; ++i) {
|
|
1346
1355
|
for (let j = 0; j < N; ++j) {
|
|
1347
1356
|
if (h.vec[i].coeffs[j] !== 0) {
|
|
1357
|
+
if (h.vec[i].coeffs[j] !== 1) {
|
|
1358
|
+
throw new Error('hint coefficients must be binary (0 or 1)');
|
|
1359
|
+
}
|
|
1360
|
+
if (k >= OMEGA) {
|
|
1361
|
+
throw new Error(`hint count exceeds OMEGA (${OMEGA})`);
|
|
1362
|
+
}
|
|
1348
1363
|
sig[sigOffset + k++] = j;
|
|
1349
1364
|
}
|
|
1350
1365
|
}
|
|
@@ -1353,7 +1368,12 @@ function packSig(sigP, c, z, h) {
|
|
|
1353
1368
|
}
|
|
1354
1369
|
}
|
|
1355
1370
|
|
|
1371
|
+
// Returns 0 on success, 1 on failure. On failure, output buffers (c, z, h)
|
|
1372
|
+
// may contain partial data and must not be used.
|
|
1356
1373
|
function unpackSig(cP, z, hP, sig) {
|
|
1374
|
+
if (!(sig instanceof Uint8Array) || sig.length !== CryptoBytes) {
|
|
1375
|
+
throw new Error(`sig must be a Uint8Array of ${CryptoBytes} bytes`);
|
|
1376
|
+
}
|
|
1357
1377
|
let sigOffset = 0;
|
|
1358
1378
|
const c = cP;
|
|
1359
1379
|
const h = hP;
|
|
@@ -1453,6 +1473,8 @@ function randomBytes(size) {
|
|
|
1453
1473
|
*
|
|
1454
1474
|
* @param {Uint8Array} buffer - The buffer to zero
|
|
1455
1475
|
* @returns {void}
|
|
1476
|
+
* @throws {TypeError} If buffer is not a Uint8Array
|
|
1477
|
+
* @throws {Error} If zeroization verification fails
|
|
1456
1478
|
*/
|
|
1457
1479
|
function zeroize(buffer) {
|
|
1458
1480
|
if (!(buffer instanceof Uint8Array)) {
|
|
@@ -1475,6 +1497,7 @@ function zeroize(buffer) {
|
|
|
1475
1497
|
*
|
|
1476
1498
|
* @param {Uint8Array} buffer - The buffer to check
|
|
1477
1499
|
* @returns {boolean} True if all bytes are zero
|
|
1500
|
+
* @throws {TypeError} If buffer is not a Uint8Array
|
|
1478
1501
|
*/
|
|
1479
1502
|
function isZero(buffer) {
|
|
1480
1503
|
if (!(buffer instanceof Uint8Array)) {
|
|
@@ -1490,16 +1513,12 @@ function isZero(buffer) {
|
|
|
1490
1513
|
/**
|
|
1491
1514
|
* Convert hex string to Uint8Array with strict validation.
|
|
1492
1515
|
*
|
|
1493
|
-
*
|
|
1494
|
-
*
|
|
1495
|
-
* mask input errors. Applications requiring strict format validation should
|
|
1496
|
-
* validate hex format before calling cryptographic functions, e.g.:
|
|
1497
|
-
* - Reject strings with 0x prefix if raw hex is expected
|
|
1498
|
-
* - Reject strings with whitespace
|
|
1499
|
-
* - Enforce consistent casing (lowercase/uppercase)
|
|
1516
|
+
* Accepts an optional 0x/0X prefix. Leading/trailing whitespace is rejected.
|
|
1517
|
+
* Empty strings and whitespace-only strings are rejected.
|
|
1500
1518
|
*
|
|
1501
|
-
* @param {string} hex - Hex string (optional 0x prefix, even length).
|
|
1519
|
+
* @param {string} hex - Hex string (optional 0x prefix, even length, no whitespace).
|
|
1502
1520
|
* @returns {Uint8Array} Decoded bytes.
|
|
1521
|
+
* @throws {Error} If input is not a valid hex string
|
|
1503
1522
|
* @private
|
|
1504
1523
|
*/
|
|
1505
1524
|
function hexToBytes(hex) {
|
|
@@ -1508,11 +1527,16 @@ function hexToBytes(hex) {
|
|
|
1508
1527
|
throw new Error('message must be a hex string');
|
|
1509
1528
|
}
|
|
1510
1529
|
/* c8 ignore stop */
|
|
1511
|
-
|
|
1512
|
-
|
|
1530
|
+
if (hex !== hex.trim()) {
|
|
1531
|
+
throw new Error('hex string must not have leading or trailing whitespace');
|
|
1532
|
+
}
|
|
1533
|
+
let clean = hex;
|
|
1513
1534
|
if (clean.startsWith('0x') || clean.startsWith('0X')) {
|
|
1514
1535
|
clean = clean.slice(2);
|
|
1515
1536
|
}
|
|
1537
|
+
if (clean.length === 0) {
|
|
1538
|
+
throw new Error('hex string must not be empty');
|
|
1539
|
+
}
|
|
1516
1540
|
if (clean.length % 2 !== 0) {
|
|
1517
1541
|
throw new Error('hex string must have an even length');
|
|
1518
1542
|
}
|
|
@@ -1522,6 +1546,14 @@ function hexToBytes(hex) {
|
|
|
1522
1546
|
return hexToBytes$1(clean);
|
|
1523
1547
|
}
|
|
1524
1548
|
|
|
1549
|
+
/**
|
|
1550
|
+
* Convert a message to Uint8Array.
|
|
1551
|
+
*
|
|
1552
|
+
* @param {string|Uint8Array} message - Message as hex string (optional 0x prefix) or Uint8Array.
|
|
1553
|
+
* @returns {Uint8Array} Message bytes.
|
|
1554
|
+
* @throws {Error} If message is not a Uint8Array or valid hex string
|
|
1555
|
+
* @private
|
|
1556
|
+
*/
|
|
1525
1557
|
function messageToBytes(message) {
|
|
1526
1558
|
if (typeof message === 'string') {
|
|
1527
1559
|
return hexToBytes(message);
|
|
@@ -1535,8 +1567,8 @@ function messageToBytes(message) {
|
|
|
1535
1567
|
/**
|
|
1536
1568
|
* Generate a Dilithium-5 key pair.
|
|
1537
1569
|
*
|
|
1538
|
-
* @param {Uint8Array|null} passedSeed - Optional 32-byte seed for deterministic key generation.
|
|
1539
|
-
* Pass null for random key generation.
|
|
1570
|
+
* @param {Uint8Array|null} [passedSeed=null] - Optional 32-byte seed for deterministic key generation.
|
|
1571
|
+
* Pass null or undefined for random key generation.
|
|
1540
1572
|
* @param {Uint8Array} pk - Output buffer for public key (must be CryptoPublicKeyBytes = 2592 bytes)
|
|
1541
1573
|
* @param {Uint8Array} sk - Output buffer for secret key (must be CryptoSecretKeyBytes = 4896 bytes)
|
|
1542
1574
|
* @returns {Uint8Array} The seed used for key generation (useful when passedSeed is null)
|
|
@@ -1557,9 +1589,9 @@ function cryptoSignKeypair(passedSeed, pk, sk) {
|
|
|
1557
1589
|
}
|
|
1558
1590
|
} catch (e) {
|
|
1559
1591
|
if (e instanceof TypeError) {
|
|
1560
|
-
throw new Error(`pk/sk cannot be null
|
|
1592
|
+
throw new Error(`pk/sk cannot be null`, { cause: e });
|
|
1561
1593
|
} else {
|
|
1562
|
-
throw new Error(`${e.message}
|
|
1594
|
+
throw new Error(`${e.message}`, { cause: e });
|
|
1563
1595
|
}
|
|
1564
1596
|
}
|
|
1565
1597
|
|
|
@@ -1637,15 +1669,25 @@ function cryptoSignKeypair(passedSeed, pk, sk) {
|
|
|
1637
1669
|
* @param {boolean} randomizedSigning - If true, use random nonce for hedged signing.
|
|
1638
1670
|
* If false, use deterministic nonce derived from message and key.
|
|
1639
1671
|
* @returns {number} 0 on success
|
|
1640
|
-
* @throws {
|
|
1672
|
+
* @throws {TypeError} If sig is not a Uint8Array or is smaller than CryptoBytes
|
|
1673
|
+
* @throws {TypeError} If sk is not a Uint8Array
|
|
1674
|
+
* @throws {TypeError} If randomizedSigning is not a boolean
|
|
1675
|
+
* @throws {Error} If sk length does not equal CryptoSecretKeyBytes
|
|
1676
|
+
* @throws {Error} If message is not a Uint8Array or valid hex string
|
|
1641
1677
|
*
|
|
1642
1678
|
* @example
|
|
1643
1679
|
* const sig = new Uint8Array(CryptoBytes);
|
|
1644
1680
|
* cryptoSignSignature(sig, message, sk, false);
|
|
1645
1681
|
*/
|
|
1646
1682
|
function cryptoSignSignature(sig, m, sk, randomizedSigning) {
|
|
1647
|
-
if (!sig || sig.length < CryptoBytes) {
|
|
1648
|
-
throw new
|
|
1683
|
+
if (!(sig instanceof Uint8Array) || sig.length < CryptoBytes) {
|
|
1684
|
+
throw new TypeError(`sig must be at least ${CryptoBytes} bytes and a Uint8Array`);
|
|
1685
|
+
}
|
|
1686
|
+
if (!(sk instanceof Uint8Array)) {
|
|
1687
|
+
throw new TypeError('sk must be a Uint8Array');
|
|
1688
|
+
}
|
|
1689
|
+
if (typeof randomizedSigning !== 'boolean') {
|
|
1690
|
+
throw new TypeError('randomizedSigning must be a boolean');
|
|
1649
1691
|
}
|
|
1650
1692
|
if (sk.length !== CryptoSecretKeyBytes) {
|
|
1651
1693
|
throw new Error(`invalid sk length ${sk.length} | Expected length ${CryptoSecretKeyBytes}`);
|
|
@@ -1708,7 +1750,7 @@ function cryptoSignSignature(sig, m, sk, randomizedSigning) {
|
|
|
1708
1750
|
.xof(SeedBytes);
|
|
1709
1751
|
sig.set(cHash);
|
|
1710
1752
|
|
|
1711
|
-
polyChallenge(cp, sig);
|
|
1753
|
+
polyChallenge(cp, sig.slice(0, SeedBytes));
|
|
1712
1754
|
polyNTT(cp);
|
|
1713
1755
|
|
|
1714
1756
|
// Compute z, reject if it reveals secret
|
|
@@ -1768,7 +1810,8 @@ function cryptoSignSignature(sig, m, sk, randomizedSigning) {
|
|
|
1768
1810
|
* @param {Uint8Array} sk - Secret key (must be CryptoSecretKeyBytes = 4896 bytes)
|
|
1769
1811
|
* @param {boolean} randomizedSigning - If true, use random nonce; if false, deterministic
|
|
1770
1812
|
* @returns {Uint8Array} Signed message (CryptoBytes + msg.length bytes)
|
|
1771
|
-
* @throws {
|
|
1813
|
+
* @throws {TypeError} If sk or randomizedSigning fail type validation (see cryptoSignSignature)
|
|
1814
|
+
* @throws {Error} If signing fails or message/sk are invalid
|
|
1772
1815
|
*
|
|
1773
1816
|
* @example
|
|
1774
1817
|
* const signedMsg = cryptoSign(message, sk, false);
|
|
@@ -1822,10 +1865,10 @@ function cryptoSignVerify(sig, m, pk) {
|
|
|
1822
1865
|
const w1 = new PolyVecK();
|
|
1823
1866
|
const h = new PolyVecK();
|
|
1824
1867
|
|
|
1825
|
-
if (sig.length !== CryptoBytes) {
|
|
1868
|
+
if (!(sig instanceof Uint8Array) || sig.length !== CryptoBytes) {
|
|
1826
1869
|
return false;
|
|
1827
1870
|
}
|
|
1828
|
-
if (pk.length !== CryptoPublicKeyBytes) {
|
|
1871
|
+
if (!(pk instanceof Uint8Array) || pk.length !== CryptoPublicKeyBytes) {
|
|
1829
1872
|
return false;
|
|
1830
1873
|
}
|
|
1831
1874
|
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript definitions for @theqrl/dilithium5
|
|
3
|
+
* Dilithium-5 post-quantum digital signature scheme
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Constants
|
|
7
|
+
export const Shake128Rate: number;
|
|
8
|
+
export const Shake256Rate: number;
|
|
9
|
+
export const Stream128BlockBytes: number;
|
|
10
|
+
export const Stream256BlockBytes: number;
|
|
11
|
+
export const SeedBytes: number;
|
|
12
|
+
export const CRHBytes: number;
|
|
13
|
+
export const TRBytes: number;
|
|
14
|
+
export const N: number;
|
|
15
|
+
export const Q: number;
|
|
16
|
+
export const QInv: number;
|
|
17
|
+
export const D: number;
|
|
18
|
+
export const K: number;
|
|
19
|
+
export const L: number;
|
|
20
|
+
export const ETA: number;
|
|
21
|
+
export const TAU: number;
|
|
22
|
+
export const BETA: number;
|
|
23
|
+
export const GAMMA1: number;
|
|
24
|
+
export const GAMMA2: number;
|
|
25
|
+
export const OMEGA: number;
|
|
26
|
+
export const PolyT1PackedBytes: number;
|
|
27
|
+
export const PolyT0PackedBytes: number;
|
|
28
|
+
export const PolyETAPackedBytes: number;
|
|
29
|
+
export const PolyZPackedBytes: number;
|
|
30
|
+
export const PolyVecHPackedBytes: number;
|
|
31
|
+
export const PolyW1PackedBytes: number;
|
|
32
|
+
export const CryptoPublicKeyBytes: number;
|
|
33
|
+
export const CryptoSecretKeyBytes: number;
|
|
34
|
+
export const CryptoBytes: number;
|
|
35
|
+
export const PolyUniformNBlocks: number;
|
|
36
|
+
export const PolyUniformETANBlocks: number;
|
|
37
|
+
export const PolyUniformGamma1NBlocks: number;
|
|
38
|
+
export const zetas: readonly number[];
|
|
39
|
+
|
|
40
|
+
// Core signing functions
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Generate a Dilithium-5 key pair
|
|
44
|
+
* @param seed - Optional 32-byte seed for deterministic key generation (null for random)
|
|
45
|
+
* @param pk - Output buffer for public key (must be CryptoPublicKeyBytes length)
|
|
46
|
+
* @param sk - Output buffer for secret key (must be CryptoSecretKeyBytes length)
|
|
47
|
+
* @returns The seed used for key generation
|
|
48
|
+
* @throws Error if pk/sk buffers are wrong size or null
|
|
49
|
+
*/
|
|
50
|
+
export function cryptoSignKeypair(
|
|
51
|
+
seed: Uint8Array | null,
|
|
52
|
+
pk: Uint8Array,
|
|
53
|
+
sk: Uint8Array
|
|
54
|
+
): Uint8Array;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Create a signature for a message
|
|
58
|
+
* @param sig - Output buffer for signature (must be CryptoBytes length minimum)
|
|
59
|
+
* @param m - Message to sign (hex string or Uint8Array; strings are parsed as hex only)
|
|
60
|
+
* @param sk - Secret key
|
|
61
|
+
* @param randomizedSigning - If true, use random nonce; if false, deterministic
|
|
62
|
+
* @returns 0 on success
|
|
63
|
+
* @throws Error if sk is wrong size
|
|
64
|
+
*/
|
|
65
|
+
export function cryptoSignSignature(
|
|
66
|
+
sig: Uint8Array,
|
|
67
|
+
m: Uint8Array | string,
|
|
68
|
+
sk: Uint8Array,
|
|
69
|
+
randomizedSigning: boolean
|
|
70
|
+
): number;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Sign a message, returning signature concatenated with message
|
|
74
|
+
* @param msg - Message to sign
|
|
75
|
+
* @param sk - Secret key
|
|
76
|
+
* @param randomizedSigning - If true, use random nonce; if false, deterministic
|
|
77
|
+
* @returns Signed message (signature || message)
|
|
78
|
+
* @throws Error if signing fails
|
|
79
|
+
*/
|
|
80
|
+
export function cryptoSign(
|
|
81
|
+
msg: Uint8Array | string,
|
|
82
|
+
sk: Uint8Array,
|
|
83
|
+
randomizedSigning: boolean
|
|
84
|
+
): Uint8Array;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Verify a signature
|
|
88
|
+
* @param sig - Signature to verify
|
|
89
|
+
* @param m - Message that was signed (hex string or Uint8Array; strings are parsed as hex only)
|
|
90
|
+
* @param pk - Public key
|
|
91
|
+
* @returns true if signature is valid, false otherwise
|
|
92
|
+
*/
|
|
93
|
+
export function cryptoSignVerify(
|
|
94
|
+
sig: Uint8Array,
|
|
95
|
+
m: Uint8Array | string,
|
|
96
|
+
pk: Uint8Array
|
|
97
|
+
): boolean;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Open a signed message (verify and extract message)
|
|
101
|
+
* @param sm - Signed message (signature || message)
|
|
102
|
+
* @param pk - Public key
|
|
103
|
+
* @returns Message if valid, undefined if verification fails
|
|
104
|
+
*/
|
|
105
|
+
export function cryptoSignOpen(
|
|
106
|
+
sm: Uint8Array,
|
|
107
|
+
pk: Uint8Array
|
|
108
|
+
): Uint8Array | undefined;
|
|
109
|
+
|
|
110
|
+
// Utility functions
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Zero out a buffer (best-effort, see SECURITY.md for limitations)
|
|
114
|
+
* @param buffer - Buffer to zero
|
|
115
|
+
* @throws TypeError if buffer is not Uint8Array
|
|
116
|
+
*/
|
|
117
|
+
export function zeroize(buffer: Uint8Array): void;
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Check if buffer is all zeros using constant-time comparison
|
|
121
|
+
* @param buffer - Buffer to check
|
|
122
|
+
* @returns true if all bytes are zero
|
|
123
|
+
* @throws TypeError if buffer is not Uint8Array
|
|
124
|
+
*/
|
|
125
|
+
export function isZero(buffer: Uint8Array): boolean;
|
|
126
|
+
|
|
127
|
+
// Internal classes (exported but primarily for internal use)
|
|
128
|
+
|
|
129
|
+
export class Poly {
|
|
130
|
+
coeffs: Int32Array;
|
|
131
|
+
constructor();
|
|
132
|
+
copy(poly: Poly): void;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export class PolyVecK {
|
|
136
|
+
vec: Poly[];
|
|
137
|
+
constructor();
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export class PolyVecL {
|
|
141
|
+
vec: Poly[];
|
|
142
|
+
constructor();
|
|
143
|
+
copy(polyVecL: PolyVecL): void;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export class KeccakState {
|
|
147
|
+
constructor();
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Internal functions (exported but primarily for internal use)
|
|
151
|
+
export function polyNTT(a: Poly): void;
|
|
152
|
+
export function polyInvNTTToMont(a: Poly): void;
|
|
153
|
+
export function polyChallenge(c: Poly, seed: Uint8Array): void;
|
|
154
|
+
export function ntt(a: Int32Array): void;
|
|
155
|
+
export function invNTTToMont(a: Int32Array): void;
|
|
156
|
+
export function montgomeryReduce(a: bigint): bigint;
|
|
157
|
+
export function reduce32(a: number): number;
|
|
158
|
+
export function cAddQ(a: number): number;
|
|
159
|
+
export function decompose(a0: Int32Array, i: number, a: number): number;
|
|
160
|
+
export function power2round(a0: Int32Array, i: number, a: number): number;
|
|
161
|
+
export function makeHint(a0: number, a1: number): number;
|
|
162
|
+
export function useHint(a: number, hint: number): number;
|
|
163
|
+
export function packPk(pk: Uint8Array, rho: Uint8Array, t1: PolyVecK): void;
|
|
164
|
+
export function packSk(
|
|
165
|
+
sk: Uint8Array,
|
|
166
|
+
rho: Uint8Array,
|
|
167
|
+
tr: Uint8Array,
|
|
168
|
+
key: Uint8Array,
|
|
169
|
+
t0: PolyVecK,
|
|
170
|
+
s1: PolyVecL,
|
|
171
|
+
s2: PolyVecK
|
|
172
|
+
): void;
|
|
173
|
+
export function packSig(
|
|
174
|
+
sig: Uint8Array,
|
|
175
|
+
c: Uint8Array,
|
|
176
|
+
z: PolyVecL,
|
|
177
|
+
h: PolyVecK
|
|
178
|
+
): void;
|
|
179
|
+
export function unpackPk(rho: Uint8Array, t1: PolyVecK, pk: Uint8Array): void;
|
|
180
|
+
export function unpackSk(
|
|
181
|
+
rho: Uint8Array,
|
|
182
|
+
tr: Uint8Array,
|
|
183
|
+
key: Uint8Array,
|
|
184
|
+
t0: PolyVecK,
|
|
185
|
+
s1: PolyVecL,
|
|
186
|
+
s2: PolyVecK,
|
|
187
|
+
sk: Uint8Array
|
|
188
|
+
): void;
|
|
189
|
+
export function unpackSig(
|
|
190
|
+
c: Uint8Array,
|
|
191
|
+
z: PolyVecL,
|
|
192
|
+
h: PolyVecK,
|
|
193
|
+
sig: Uint8Array
|
|
194
|
+
): number;
|
|
195
|
+
|
|
196
|
+
// FIPS 202 SHAKE primitives (low-level XOF interface, primarily internal)
|
|
197
|
+
export function shake128Init(state: KeccakState): void;
|
|
198
|
+
export function shake128Absorb(state: KeccakState, input: Uint8Array): void;
|
|
199
|
+
export function shake128Finalize(state: KeccakState): void;
|
|
200
|
+
export function shake128SqueezeBlocks(
|
|
201
|
+
out: Uint8Array,
|
|
202
|
+
outputOffset: number,
|
|
203
|
+
nBlocks: number,
|
|
204
|
+
state: KeccakState
|
|
205
|
+
): void;
|
|
206
|
+
export function shake256Init(state: KeccakState): void;
|
|
207
|
+
export function shake256Absorb(state: KeccakState, input: Uint8Array): void;
|
|
208
|
+
export function shake256Finalize(state: KeccakState): void;
|
|
209
|
+
export function shake256SqueezeBlocks(
|
|
210
|
+
out: Uint8Array,
|
|
211
|
+
outputOffset: number,
|
|
212
|
+
nBlocks: number,
|
|
213
|
+
state: KeccakState
|
|
214
|
+
): void;
|
|
215
|
+
|
|
216
|
+
// Dilithium-specific stream initializers
|
|
217
|
+
export function dilithiumShake128StreamInit(
|
|
218
|
+
state: KeccakState,
|
|
219
|
+
seed: Uint8Array,
|
|
220
|
+
nonce: number
|
|
221
|
+
): void;
|
|
222
|
+
export function dilithiumShake256StreamInit(
|
|
223
|
+
state: KeccakState,
|
|
224
|
+
seed: Uint8Array,
|
|
225
|
+
nonce: number
|
|
226
|
+
): void;
|
|
227
|
+
|
|
228
|
+
// Polynomial operations (internal)
|
|
229
|
+
export function polyReduce(a: Poly): void;
|
|
230
|
+
export function polyCAddQ(a: Poly): void;
|
|
231
|
+
export function polyAdd(c: Poly, a: Poly, b: Poly): void;
|
|
232
|
+
export function polySub(c: Poly, a: Poly, b: Poly): void;
|
|
233
|
+
export function polyShiftL(a: Poly): void;
|
|
234
|
+
export function polyPointWiseMontgomery(c: Poly, a: Poly, b: Poly): void;
|
|
235
|
+
export function polyPower2round(a1: Poly, a0: Poly, a: Poly): void;
|
|
236
|
+
export function polyDecompose(a1: Poly, a0: Poly, a: Poly): void;
|
|
237
|
+
export function polyMakeHint(h: Poly, a0: Poly, a1: Poly): number;
|
|
238
|
+
export function polyUseHint(b: Poly, a: Poly, h: Poly): void;
|
|
239
|
+
export function polyChkNorm(a: Poly, b: number): number;
|
|
240
|
+
export function rejUniform(
|
|
241
|
+
a: Int32Array,
|
|
242
|
+
aOffset: number,
|
|
243
|
+
len: number,
|
|
244
|
+
buf: Uint8Array,
|
|
245
|
+
bufLen: number
|
|
246
|
+
): number;
|
|
247
|
+
export function polyUniform(a: Poly, seed: Uint8Array, nonce: number): void;
|
|
248
|
+
export function rejEta(
|
|
249
|
+
a: Int32Array,
|
|
250
|
+
aOffset: number,
|
|
251
|
+
len: number,
|
|
252
|
+
buf: Uint8Array,
|
|
253
|
+
bufLen: number
|
|
254
|
+
): number;
|
|
255
|
+
export function polyUniformEta(a: Poly, seed: Uint8Array, nonce: number): void;
|
|
256
|
+
export function polyZUnpack(r: Poly, a: Uint8Array, aOffset: number): void;
|
|
257
|
+
export function polyUniformGamma1(a: Poly, seed: Uint8Array, nonce: number): void;
|
|
258
|
+
export function polyEtaPack(r: Uint8Array, rOffset: number, a: Poly): void;
|
|
259
|
+
export function polyEtaUnpack(r: Poly, a: Uint8Array, aOffset: number): void;
|
|
260
|
+
export function polyT1Pack(r: Uint8Array, rOffset: number, a: Poly): void;
|
|
261
|
+
export function polyT1Unpack(r: Poly, a: Uint8Array, aOffset: number): void;
|
|
262
|
+
export function polyT0Pack(r: Uint8Array, rOffset: number, a: Poly): void;
|
|
263
|
+
export function polyT0Unpack(r: Poly, a: Uint8Array, aOffset: number): void;
|
|
264
|
+
export function polyZPack(r: Uint8Array, rOffset: number, a: Poly): void;
|
|
265
|
+
export function polyW1Pack(r: Uint8Array, rOffset: number, a: Poly): void;
|
|
266
|
+
|
|
267
|
+
// Polynomial vector operations (internal)
|
|
268
|
+
export function polyVecMatrixExpand(mat: PolyVecL[], rho: Uint8Array): void;
|
|
269
|
+
export function polyVecMatrixPointWiseMontgomery(
|
|
270
|
+
t: PolyVecK,
|
|
271
|
+
mat: PolyVecL[],
|
|
272
|
+
v: PolyVecL
|
|
273
|
+
): void;
|
|
274
|
+
export function polyVecLUniformEta(v: PolyVecL, seed: Uint8Array, nonce: number): void;
|
|
275
|
+
export function polyVecLUniformGamma1(v: PolyVecL, seed: Uint8Array, nonce: number): void;
|
|
276
|
+
export function polyVecLReduce(v: PolyVecL): void;
|
|
277
|
+
export function polyVecLAdd(w: PolyVecL, u: PolyVecL, v: PolyVecL): void;
|
|
278
|
+
export function polyVecLNTT(v: PolyVecL): void;
|
|
279
|
+
export function polyVecLInvNTTToMont(v: PolyVecL): void;
|
|
280
|
+
export function polyVecLPointWisePolyMontgomery(
|
|
281
|
+
r: PolyVecL,
|
|
282
|
+
a: Poly,
|
|
283
|
+
v: PolyVecL
|
|
284
|
+
): void;
|
|
285
|
+
export function polyVecLPointWiseAccMontgomery(
|
|
286
|
+
w: Poly,
|
|
287
|
+
u: PolyVecL,
|
|
288
|
+
v: PolyVecL
|
|
289
|
+
): void;
|
|
290
|
+
export function polyVecLChkNorm(v: PolyVecL, bound: number): number;
|
|
291
|
+
export function polyVecKUniformEta(v: PolyVecK, seed: Uint8Array, nonce: number): void;
|
|
292
|
+
export function polyVecKReduce(v: PolyVecK): void;
|
|
293
|
+
export function polyVecKCAddQ(v: PolyVecK): void;
|
|
294
|
+
export function polyVecKAdd(w: PolyVecK, u: PolyVecK, v: PolyVecK): void;
|
|
295
|
+
export function polyVecKSub(w: PolyVecK, u: PolyVecK, v: PolyVecK): void;
|
|
296
|
+
export function polyVecKShiftL(v: PolyVecK): void;
|
|
297
|
+
export function polyVecKNTT(v: PolyVecK): void;
|
|
298
|
+
export function polyVecKInvNTTToMont(v: PolyVecK): void;
|
|
299
|
+
export function polyVecKPointWisePolyMontgomery(
|
|
300
|
+
r: PolyVecK,
|
|
301
|
+
a: Poly,
|
|
302
|
+
v: PolyVecK
|
|
303
|
+
): void;
|
|
304
|
+
export function polyVecKChkNorm(v: PolyVecK, bound: number): number;
|
|
305
|
+
export function polyVecKPower2round(v1: PolyVecK, v0: PolyVecK, v: PolyVecK): void;
|
|
306
|
+
export function polyVecKDecompose(v1: PolyVecK, v0: PolyVecK, v: PolyVecK): void;
|
|
307
|
+
export function polyVecKMakeHint(h: PolyVecK, v0: PolyVecK, v1: PolyVecK): number;
|
|
308
|
+
export function polyVecKUseHint(w: PolyVecK, u: PolyVecK, h: PolyVecK): void;
|
|
309
|
+
export function polyVecKPackW1(r: Uint8Array, w1: PolyVecK): void;
|
package/dist/mjs/dilithium5.js
CHANGED
|
@@ -158,12 +158,16 @@ function montgomeryReduce(a) {
|
|
|
158
158
|
return t;
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
+
// Partial reduction modulo Q. Input must satisfy |a| < 2^31 - 2^22.
|
|
162
|
+
// Output is in (-Q, Q). Mirrors the reference C implementation.
|
|
161
163
|
function reduce32(a) {
|
|
162
164
|
let t = (a + (1 << 22)) >> 23;
|
|
163
165
|
t = a - t * Q;
|
|
164
166
|
return t;
|
|
165
167
|
}
|
|
166
168
|
|
|
169
|
+
// Conditional add Q: if a is negative, add Q. Input must satisfy -Q < a < 2^31.
|
|
170
|
+
// Output is in [0, Q). Mirrors the reference C implementation.
|
|
167
171
|
function cAddQ(a) {
|
|
168
172
|
let ar = a;
|
|
169
173
|
ar += (ar >> 31) & Q;
|
|
@@ -172,7 +176,7 @@ function cAddQ(a) {
|
|
|
172
176
|
|
|
173
177
|
function ntt(a) {
|
|
174
178
|
let k = 0;
|
|
175
|
-
let j
|
|
179
|
+
let j;
|
|
176
180
|
|
|
177
181
|
for (let len = 128; len > 0; len >>= 1) {
|
|
178
182
|
for (let start = 0; start < N; start = j + len) {
|
|
@@ -188,7 +192,7 @@ function ntt(a) {
|
|
|
188
192
|
|
|
189
193
|
function invNTTToMont(a) {
|
|
190
194
|
const f = 41978n; // mont^2/256
|
|
191
|
-
let j
|
|
195
|
+
let j;
|
|
192
196
|
let k = 256;
|
|
193
197
|
|
|
194
198
|
for (let len = 1; len < N; len <<= 1) {
|
|
@@ -325,10 +329,7 @@ function polyChkNorm(a, b) {
|
|
|
325
329
|
}
|
|
326
330
|
|
|
327
331
|
for (let i = 0; i < N; i++) {
|
|
328
|
-
|
|
329
|
-
t = a.coeffs[i] - (t & (2 * a.coeffs[i]));
|
|
330
|
-
|
|
331
|
-
if (t >= b) {
|
|
332
|
+
if (Math.abs(a.coeffs[i]) >= b) {
|
|
332
333
|
return 1;
|
|
333
334
|
}
|
|
334
335
|
}
|
|
@@ -447,6 +448,8 @@ function polyUniformGamma1(a, seed, nonce) {
|
|
|
447
448
|
}
|
|
448
449
|
|
|
449
450
|
function polyChallenge(cP, seed) {
|
|
451
|
+
if (seed.length !== SeedBytes) throw new Error('invalid seed length');
|
|
452
|
+
|
|
450
453
|
let b;
|
|
451
454
|
let pos;
|
|
452
455
|
const c = cP;
|
|
@@ -454,7 +457,7 @@ function polyChallenge(cP, seed) {
|
|
|
454
457
|
|
|
455
458
|
const state = new KeccakState();
|
|
456
459
|
shake256Init(state);
|
|
457
|
-
shake256Absorb(state, seed
|
|
460
|
+
shake256Absorb(state, seed);
|
|
458
461
|
shake256Finalize(state);
|
|
459
462
|
shake256SqueezeBlocks(buf, 0, 1, state);
|
|
460
463
|
|
|
@@ -867,6 +870,9 @@ function packPk(pkp, rho, t1) {
|
|
|
867
870
|
}
|
|
868
871
|
|
|
869
872
|
function unpackPk(rhop, t1, pk) {
|
|
873
|
+
if (!(pk instanceof Uint8Array) || pk.length !== CryptoPublicKeyBytes) {
|
|
874
|
+
throw new Error(`pk must be a Uint8Array of ${CryptoPublicKeyBytes} bytes`);
|
|
875
|
+
}
|
|
870
876
|
const rho = rhop;
|
|
871
877
|
for (let i = 0; i < SeedBytes; ++i) {
|
|
872
878
|
rho[i] = pk[i];
|
|
@@ -911,6 +917,9 @@ function packSk(skp, rho, tr, key, t0, s1, s2) {
|
|
|
911
917
|
}
|
|
912
918
|
|
|
913
919
|
function unpackSk(rhoP, trP, keyP, t0, s1, s2, sk) {
|
|
920
|
+
if (!(sk instanceof Uint8Array) || sk.length !== CryptoSecretKeyBytes) {
|
|
921
|
+
throw new Error(`sk must be a Uint8Array of ${CryptoSecretKeyBytes} bytes`);
|
|
922
|
+
}
|
|
914
923
|
let skOffset = 0;
|
|
915
924
|
const rho = rhoP;
|
|
916
925
|
const tr = trP;
|
|
@@ -966,6 +975,12 @@ function packSig(sigP, c, z, h) {
|
|
|
966
975
|
for (let i = 0; i < K; ++i) {
|
|
967
976
|
for (let j = 0; j < N; ++j) {
|
|
968
977
|
if (h.vec[i].coeffs[j] !== 0) {
|
|
978
|
+
if (h.vec[i].coeffs[j] !== 1) {
|
|
979
|
+
throw new Error('hint coefficients must be binary (0 or 1)');
|
|
980
|
+
}
|
|
981
|
+
if (k >= OMEGA) {
|
|
982
|
+
throw new Error(`hint count exceeds OMEGA (${OMEGA})`);
|
|
983
|
+
}
|
|
969
984
|
sig[sigOffset + k++] = j;
|
|
970
985
|
}
|
|
971
986
|
}
|
|
@@ -974,7 +989,12 @@ function packSig(sigP, c, z, h) {
|
|
|
974
989
|
}
|
|
975
990
|
}
|
|
976
991
|
|
|
992
|
+
// Returns 0 on success, 1 on failure. On failure, output buffers (c, z, h)
|
|
993
|
+
// may contain partial data and must not be used.
|
|
977
994
|
function unpackSig(cP, z, hP, sig) {
|
|
995
|
+
if (!(sig instanceof Uint8Array) || sig.length !== CryptoBytes) {
|
|
996
|
+
throw new Error(`sig must be a Uint8Array of ${CryptoBytes} bytes`);
|
|
997
|
+
}
|
|
978
998
|
let sigOffset = 0;
|
|
979
999
|
const c = cP;
|
|
980
1000
|
const h = hP;
|
|
@@ -1074,6 +1094,8 @@ function randomBytes(size) {
|
|
|
1074
1094
|
*
|
|
1075
1095
|
* @param {Uint8Array} buffer - The buffer to zero
|
|
1076
1096
|
* @returns {void}
|
|
1097
|
+
* @throws {TypeError} If buffer is not a Uint8Array
|
|
1098
|
+
* @throws {Error} If zeroization verification fails
|
|
1077
1099
|
*/
|
|
1078
1100
|
function zeroize(buffer) {
|
|
1079
1101
|
if (!(buffer instanceof Uint8Array)) {
|
|
@@ -1096,6 +1118,7 @@ function zeroize(buffer) {
|
|
|
1096
1118
|
*
|
|
1097
1119
|
* @param {Uint8Array} buffer - The buffer to check
|
|
1098
1120
|
* @returns {boolean} True if all bytes are zero
|
|
1121
|
+
* @throws {TypeError} If buffer is not a Uint8Array
|
|
1099
1122
|
*/
|
|
1100
1123
|
function isZero(buffer) {
|
|
1101
1124
|
if (!(buffer instanceof Uint8Array)) {
|
|
@@ -1111,16 +1134,12 @@ function isZero(buffer) {
|
|
|
1111
1134
|
/**
|
|
1112
1135
|
* Convert hex string to Uint8Array with strict validation.
|
|
1113
1136
|
*
|
|
1114
|
-
*
|
|
1115
|
-
*
|
|
1116
|
-
* mask input errors. Applications requiring strict format validation should
|
|
1117
|
-
* validate hex format before calling cryptographic functions, e.g.:
|
|
1118
|
-
* - Reject strings with 0x prefix if raw hex is expected
|
|
1119
|
-
* - Reject strings with whitespace
|
|
1120
|
-
* - Enforce consistent casing (lowercase/uppercase)
|
|
1137
|
+
* Accepts an optional 0x/0X prefix. Leading/trailing whitespace is rejected.
|
|
1138
|
+
* Empty strings and whitespace-only strings are rejected.
|
|
1121
1139
|
*
|
|
1122
|
-
* @param {string} hex - Hex string (optional 0x prefix, even length).
|
|
1140
|
+
* @param {string} hex - Hex string (optional 0x prefix, even length, no whitespace).
|
|
1123
1141
|
* @returns {Uint8Array} Decoded bytes.
|
|
1142
|
+
* @throws {Error} If input is not a valid hex string
|
|
1124
1143
|
* @private
|
|
1125
1144
|
*/
|
|
1126
1145
|
function hexToBytes(hex) {
|
|
@@ -1129,11 +1148,16 @@ function hexToBytes(hex) {
|
|
|
1129
1148
|
throw new Error('message must be a hex string');
|
|
1130
1149
|
}
|
|
1131
1150
|
/* c8 ignore stop */
|
|
1132
|
-
|
|
1133
|
-
|
|
1151
|
+
if (hex !== hex.trim()) {
|
|
1152
|
+
throw new Error('hex string must not have leading or trailing whitespace');
|
|
1153
|
+
}
|
|
1154
|
+
let clean = hex;
|
|
1134
1155
|
if (clean.startsWith('0x') || clean.startsWith('0X')) {
|
|
1135
1156
|
clean = clean.slice(2);
|
|
1136
1157
|
}
|
|
1158
|
+
if (clean.length === 0) {
|
|
1159
|
+
throw new Error('hex string must not be empty');
|
|
1160
|
+
}
|
|
1137
1161
|
if (clean.length % 2 !== 0) {
|
|
1138
1162
|
throw new Error('hex string must have an even length');
|
|
1139
1163
|
}
|
|
@@ -1143,6 +1167,14 @@ function hexToBytes(hex) {
|
|
|
1143
1167
|
return hexToBytes$1(clean);
|
|
1144
1168
|
}
|
|
1145
1169
|
|
|
1170
|
+
/**
|
|
1171
|
+
* Convert a message to Uint8Array.
|
|
1172
|
+
*
|
|
1173
|
+
* @param {string|Uint8Array} message - Message as hex string (optional 0x prefix) or Uint8Array.
|
|
1174
|
+
* @returns {Uint8Array} Message bytes.
|
|
1175
|
+
* @throws {Error} If message is not a Uint8Array or valid hex string
|
|
1176
|
+
* @private
|
|
1177
|
+
*/
|
|
1146
1178
|
function messageToBytes(message) {
|
|
1147
1179
|
if (typeof message === 'string') {
|
|
1148
1180
|
return hexToBytes(message);
|
|
@@ -1156,8 +1188,8 @@ function messageToBytes(message) {
|
|
|
1156
1188
|
/**
|
|
1157
1189
|
* Generate a Dilithium-5 key pair.
|
|
1158
1190
|
*
|
|
1159
|
-
* @param {Uint8Array|null} passedSeed - Optional 32-byte seed for deterministic key generation.
|
|
1160
|
-
* Pass null for random key generation.
|
|
1191
|
+
* @param {Uint8Array|null} [passedSeed=null] - Optional 32-byte seed for deterministic key generation.
|
|
1192
|
+
* Pass null or undefined for random key generation.
|
|
1161
1193
|
* @param {Uint8Array} pk - Output buffer for public key (must be CryptoPublicKeyBytes = 2592 bytes)
|
|
1162
1194
|
* @param {Uint8Array} sk - Output buffer for secret key (must be CryptoSecretKeyBytes = 4896 bytes)
|
|
1163
1195
|
* @returns {Uint8Array} The seed used for key generation (useful when passedSeed is null)
|
|
@@ -1178,9 +1210,9 @@ function cryptoSignKeypair(passedSeed, pk, sk) {
|
|
|
1178
1210
|
}
|
|
1179
1211
|
} catch (e) {
|
|
1180
1212
|
if (e instanceof TypeError) {
|
|
1181
|
-
throw new Error(`pk/sk cannot be null
|
|
1213
|
+
throw new Error(`pk/sk cannot be null`, { cause: e });
|
|
1182
1214
|
} else {
|
|
1183
|
-
throw new Error(`${e.message}
|
|
1215
|
+
throw new Error(`${e.message}`, { cause: e });
|
|
1184
1216
|
}
|
|
1185
1217
|
}
|
|
1186
1218
|
|
|
@@ -1258,15 +1290,25 @@ function cryptoSignKeypair(passedSeed, pk, sk) {
|
|
|
1258
1290
|
* @param {boolean} randomizedSigning - If true, use random nonce for hedged signing.
|
|
1259
1291
|
* If false, use deterministic nonce derived from message and key.
|
|
1260
1292
|
* @returns {number} 0 on success
|
|
1261
|
-
* @throws {
|
|
1293
|
+
* @throws {TypeError} If sig is not a Uint8Array or is smaller than CryptoBytes
|
|
1294
|
+
* @throws {TypeError} If sk is not a Uint8Array
|
|
1295
|
+
* @throws {TypeError} If randomizedSigning is not a boolean
|
|
1296
|
+
* @throws {Error} If sk length does not equal CryptoSecretKeyBytes
|
|
1297
|
+
* @throws {Error} If message is not a Uint8Array or valid hex string
|
|
1262
1298
|
*
|
|
1263
1299
|
* @example
|
|
1264
1300
|
* const sig = new Uint8Array(CryptoBytes);
|
|
1265
1301
|
* cryptoSignSignature(sig, message, sk, false);
|
|
1266
1302
|
*/
|
|
1267
1303
|
function cryptoSignSignature(sig, m, sk, randomizedSigning) {
|
|
1268
|
-
if (!sig || sig.length < CryptoBytes) {
|
|
1269
|
-
throw new
|
|
1304
|
+
if (!(sig instanceof Uint8Array) || sig.length < CryptoBytes) {
|
|
1305
|
+
throw new TypeError(`sig must be at least ${CryptoBytes} bytes and a Uint8Array`);
|
|
1306
|
+
}
|
|
1307
|
+
if (!(sk instanceof Uint8Array)) {
|
|
1308
|
+
throw new TypeError('sk must be a Uint8Array');
|
|
1309
|
+
}
|
|
1310
|
+
if (typeof randomizedSigning !== 'boolean') {
|
|
1311
|
+
throw new TypeError('randomizedSigning must be a boolean');
|
|
1270
1312
|
}
|
|
1271
1313
|
if (sk.length !== CryptoSecretKeyBytes) {
|
|
1272
1314
|
throw new Error(`invalid sk length ${sk.length} | Expected length ${CryptoSecretKeyBytes}`);
|
|
@@ -1329,7 +1371,7 @@ function cryptoSignSignature(sig, m, sk, randomizedSigning) {
|
|
|
1329
1371
|
.xof(SeedBytes);
|
|
1330
1372
|
sig.set(cHash);
|
|
1331
1373
|
|
|
1332
|
-
polyChallenge(cp, sig);
|
|
1374
|
+
polyChallenge(cp, sig.slice(0, SeedBytes));
|
|
1333
1375
|
polyNTT(cp);
|
|
1334
1376
|
|
|
1335
1377
|
// Compute z, reject if it reveals secret
|
|
@@ -1389,7 +1431,8 @@ function cryptoSignSignature(sig, m, sk, randomizedSigning) {
|
|
|
1389
1431
|
* @param {Uint8Array} sk - Secret key (must be CryptoSecretKeyBytes = 4896 bytes)
|
|
1390
1432
|
* @param {boolean} randomizedSigning - If true, use random nonce; if false, deterministic
|
|
1391
1433
|
* @returns {Uint8Array} Signed message (CryptoBytes + msg.length bytes)
|
|
1392
|
-
* @throws {
|
|
1434
|
+
* @throws {TypeError} If sk or randomizedSigning fail type validation (see cryptoSignSignature)
|
|
1435
|
+
* @throws {Error} If signing fails or message/sk are invalid
|
|
1393
1436
|
*
|
|
1394
1437
|
* @example
|
|
1395
1438
|
* const signedMsg = cryptoSign(message, sk, false);
|
|
@@ -1443,10 +1486,10 @@ function cryptoSignVerify(sig, m, pk) {
|
|
|
1443
1486
|
const w1 = new PolyVecK();
|
|
1444
1487
|
const h = new PolyVecK();
|
|
1445
1488
|
|
|
1446
|
-
if (sig.length !== CryptoBytes) {
|
|
1489
|
+
if (!(sig instanceof Uint8Array) || sig.length !== CryptoBytes) {
|
|
1447
1490
|
return false;
|
|
1448
1491
|
}
|
|
1449
|
-
if (pk.length !== CryptoPublicKeyBytes) {
|
|
1492
|
+
if (!(pk instanceof Uint8Array) || pk.length !== CryptoPublicKeyBytes) {
|
|
1450
1493
|
return false;
|
|
1451
1494
|
}
|
|
1452
1495
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theqrl/dilithium5",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.5",
|
|
4
4
|
"description": "Dilithium-5 cryptography",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dilithium",
|
|
@@ -44,8 +44,14 @@
|
|
|
44
44
|
},
|
|
45
45
|
"exports": {
|
|
46
46
|
".": {
|
|
47
|
-
"import":
|
|
48
|
-
|
|
47
|
+
"import": {
|
|
48
|
+
"types": "./dist/mjs/dilithium5.d.mts",
|
|
49
|
+
"default": "./dist/mjs/dilithium5.js"
|
|
50
|
+
},
|
|
51
|
+
"require": {
|
|
52
|
+
"types": "./dist/cjs/dilithium5.d.cts",
|
|
53
|
+
"default": "./dist/cjs/dilithium5.js"
|
|
54
|
+
}
|
|
49
55
|
}
|
|
50
56
|
},
|
|
51
57
|
"type": "module",
|
|
@@ -53,20 +59,39 @@
|
|
|
53
59
|
"node": ">=20.19.0"
|
|
54
60
|
},
|
|
55
61
|
"devDependencies": {
|
|
56
|
-
"@eslint/js": "
|
|
57
|
-
"@rollup/plugin-node-resolve": "
|
|
58
|
-
"c8": "
|
|
59
|
-
"chai": "
|
|
60
|
-
"eslint": "
|
|
61
|
-
"eslint-config-prettier": "
|
|
62
|
-
"eslint-plugin-import-x": "
|
|
63
|
-
"eslint-plugin-prettier": "
|
|
64
|
-
"globals": "
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"
|
|
62
|
+
"@eslint/js": "10.0.1",
|
|
63
|
+
"@rollup/plugin-node-resolve": "16.0.3",
|
|
64
|
+
"c8": "11.0.0",
|
|
65
|
+
"chai": "6.2.2",
|
|
66
|
+
"eslint": "10.0.3",
|
|
67
|
+
"eslint-config-prettier": "10.1.8",
|
|
68
|
+
"eslint-plugin-import-x": "4.16.2",
|
|
69
|
+
"eslint-plugin-prettier": "5.5.5",
|
|
70
|
+
"globals": "17.4.0",
|
|
71
|
+
"minimatch": "10.2.4",
|
|
72
|
+
"mocha": "11.7.5",
|
|
73
|
+
"prettier": "3.8.1",
|
|
74
|
+
"rollup": "4.59.0",
|
|
75
|
+
"serialize-javascript": "7.0.4",
|
|
76
|
+
"tar": "7.5.11"
|
|
68
77
|
},
|
|
69
78
|
"dependencies": {
|
|
70
|
-
"@noble/hashes": "
|
|
79
|
+
"@noble/hashes": "2.0.1"
|
|
80
|
+
},
|
|
81
|
+
"overrides": {
|
|
82
|
+
"diff": "8.0.3",
|
|
83
|
+
"minimatch": "10.2.4"
|
|
84
|
+
},
|
|
85
|
+
"c8": {
|
|
86
|
+
"include": [
|
|
87
|
+
"src/**"
|
|
88
|
+
],
|
|
89
|
+
"exclude": [
|
|
90
|
+
"**/dist/**",
|
|
91
|
+
"**/test/**",
|
|
92
|
+
"**/browser-tests/**",
|
|
93
|
+
"**/*.d.ts"
|
|
94
|
+
],
|
|
95
|
+
"all": true
|
|
71
96
|
}
|
|
72
97
|
}
|
package/src/index.d.ts
CHANGED
|
@@ -192,3 +192,118 @@ export function unpackSig(
|
|
|
192
192
|
h: PolyVecK,
|
|
193
193
|
sig: Uint8Array
|
|
194
194
|
): number;
|
|
195
|
+
|
|
196
|
+
// FIPS 202 SHAKE primitives (low-level XOF interface, primarily internal)
|
|
197
|
+
export function shake128Init(state: KeccakState): void;
|
|
198
|
+
export function shake128Absorb(state: KeccakState, input: Uint8Array): void;
|
|
199
|
+
export function shake128Finalize(state: KeccakState): void;
|
|
200
|
+
export function shake128SqueezeBlocks(
|
|
201
|
+
out: Uint8Array,
|
|
202
|
+
outputOffset: number,
|
|
203
|
+
nBlocks: number,
|
|
204
|
+
state: KeccakState
|
|
205
|
+
): void;
|
|
206
|
+
export function shake256Init(state: KeccakState): void;
|
|
207
|
+
export function shake256Absorb(state: KeccakState, input: Uint8Array): void;
|
|
208
|
+
export function shake256Finalize(state: KeccakState): void;
|
|
209
|
+
export function shake256SqueezeBlocks(
|
|
210
|
+
out: Uint8Array,
|
|
211
|
+
outputOffset: number,
|
|
212
|
+
nBlocks: number,
|
|
213
|
+
state: KeccakState
|
|
214
|
+
): void;
|
|
215
|
+
|
|
216
|
+
// Dilithium-specific stream initializers
|
|
217
|
+
export function dilithiumShake128StreamInit(
|
|
218
|
+
state: KeccakState,
|
|
219
|
+
seed: Uint8Array,
|
|
220
|
+
nonce: number
|
|
221
|
+
): void;
|
|
222
|
+
export function dilithiumShake256StreamInit(
|
|
223
|
+
state: KeccakState,
|
|
224
|
+
seed: Uint8Array,
|
|
225
|
+
nonce: number
|
|
226
|
+
): void;
|
|
227
|
+
|
|
228
|
+
// Polynomial operations (internal)
|
|
229
|
+
export function polyReduce(a: Poly): void;
|
|
230
|
+
export function polyCAddQ(a: Poly): void;
|
|
231
|
+
export function polyAdd(c: Poly, a: Poly, b: Poly): void;
|
|
232
|
+
export function polySub(c: Poly, a: Poly, b: Poly): void;
|
|
233
|
+
export function polyShiftL(a: Poly): void;
|
|
234
|
+
export function polyPointWiseMontgomery(c: Poly, a: Poly, b: Poly): void;
|
|
235
|
+
export function polyPower2round(a1: Poly, a0: Poly, a: Poly): void;
|
|
236
|
+
export function polyDecompose(a1: Poly, a0: Poly, a: Poly): void;
|
|
237
|
+
export function polyMakeHint(h: Poly, a0: Poly, a1: Poly): number;
|
|
238
|
+
export function polyUseHint(b: Poly, a: Poly, h: Poly): void;
|
|
239
|
+
export function polyChkNorm(a: Poly, b: number): number;
|
|
240
|
+
export function rejUniform(
|
|
241
|
+
a: Int32Array,
|
|
242
|
+
aOffset: number,
|
|
243
|
+
len: number,
|
|
244
|
+
buf: Uint8Array,
|
|
245
|
+
bufLen: number
|
|
246
|
+
): number;
|
|
247
|
+
export function polyUniform(a: Poly, seed: Uint8Array, nonce: number): void;
|
|
248
|
+
export function rejEta(
|
|
249
|
+
a: Int32Array,
|
|
250
|
+
aOffset: number,
|
|
251
|
+
len: number,
|
|
252
|
+
buf: Uint8Array,
|
|
253
|
+
bufLen: number
|
|
254
|
+
): number;
|
|
255
|
+
export function polyUniformEta(a: Poly, seed: Uint8Array, nonce: number): void;
|
|
256
|
+
export function polyZUnpack(r: Poly, a: Uint8Array, aOffset: number): void;
|
|
257
|
+
export function polyUniformGamma1(a: Poly, seed: Uint8Array, nonce: number): void;
|
|
258
|
+
export function polyEtaPack(r: Uint8Array, rOffset: number, a: Poly): void;
|
|
259
|
+
export function polyEtaUnpack(r: Poly, a: Uint8Array, aOffset: number): void;
|
|
260
|
+
export function polyT1Pack(r: Uint8Array, rOffset: number, a: Poly): void;
|
|
261
|
+
export function polyT1Unpack(r: Poly, a: Uint8Array, aOffset: number): void;
|
|
262
|
+
export function polyT0Pack(r: Uint8Array, rOffset: number, a: Poly): void;
|
|
263
|
+
export function polyT0Unpack(r: Poly, a: Uint8Array, aOffset: number): void;
|
|
264
|
+
export function polyZPack(r: Uint8Array, rOffset: number, a: Poly): void;
|
|
265
|
+
export function polyW1Pack(r: Uint8Array, rOffset: number, a: Poly): void;
|
|
266
|
+
|
|
267
|
+
// Polynomial vector operations (internal)
|
|
268
|
+
export function polyVecMatrixExpand(mat: PolyVecL[], rho: Uint8Array): void;
|
|
269
|
+
export function polyVecMatrixPointWiseMontgomery(
|
|
270
|
+
t: PolyVecK,
|
|
271
|
+
mat: PolyVecL[],
|
|
272
|
+
v: PolyVecL
|
|
273
|
+
): void;
|
|
274
|
+
export function polyVecLUniformEta(v: PolyVecL, seed: Uint8Array, nonce: number): void;
|
|
275
|
+
export function polyVecLUniformGamma1(v: PolyVecL, seed: Uint8Array, nonce: number): void;
|
|
276
|
+
export function polyVecLReduce(v: PolyVecL): void;
|
|
277
|
+
export function polyVecLAdd(w: PolyVecL, u: PolyVecL, v: PolyVecL): void;
|
|
278
|
+
export function polyVecLNTT(v: PolyVecL): void;
|
|
279
|
+
export function polyVecLInvNTTToMont(v: PolyVecL): void;
|
|
280
|
+
export function polyVecLPointWisePolyMontgomery(
|
|
281
|
+
r: PolyVecL,
|
|
282
|
+
a: Poly,
|
|
283
|
+
v: PolyVecL
|
|
284
|
+
): void;
|
|
285
|
+
export function polyVecLPointWiseAccMontgomery(
|
|
286
|
+
w: Poly,
|
|
287
|
+
u: PolyVecL,
|
|
288
|
+
v: PolyVecL
|
|
289
|
+
): void;
|
|
290
|
+
export function polyVecLChkNorm(v: PolyVecL, bound: number): number;
|
|
291
|
+
export function polyVecKUniformEta(v: PolyVecK, seed: Uint8Array, nonce: number): void;
|
|
292
|
+
export function polyVecKReduce(v: PolyVecK): void;
|
|
293
|
+
export function polyVecKCAddQ(v: PolyVecK): void;
|
|
294
|
+
export function polyVecKAdd(w: PolyVecK, u: PolyVecK, v: PolyVecK): void;
|
|
295
|
+
export function polyVecKSub(w: PolyVecK, u: PolyVecK, v: PolyVecK): void;
|
|
296
|
+
export function polyVecKShiftL(v: PolyVecK): void;
|
|
297
|
+
export function polyVecKNTT(v: PolyVecK): void;
|
|
298
|
+
export function polyVecKInvNTTToMont(v: PolyVecK): void;
|
|
299
|
+
export function polyVecKPointWisePolyMontgomery(
|
|
300
|
+
r: PolyVecK,
|
|
301
|
+
a: Poly,
|
|
302
|
+
v: PolyVecK
|
|
303
|
+
): void;
|
|
304
|
+
export function polyVecKChkNorm(v: PolyVecK, bound: number): number;
|
|
305
|
+
export function polyVecKPower2round(v1: PolyVecK, v0: PolyVecK, v: PolyVecK): void;
|
|
306
|
+
export function polyVecKDecompose(v1: PolyVecK, v0: PolyVecK, v: PolyVecK): void;
|
|
307
|
+
export function polyVecKMakeHint(h: PolyVecK, v0: PolyVecK, v1: PolyVecK): number;
|
|
308
|
+
export function polyVecKUseHint(w: PolyVecK, u: PolyVecK, h: PolyVecK): void;
|
|
309
|
+
export function polyVecKPackW1(r: Uint8Array, w1: PolyVecK): void;
|