@noble/curves 2.0.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +214 -122
- package/abstract/bls.d.ts +299 -16
- package/abstract/bls.d.ts.map +1 -1
- package/abstract/bls.js +89 -24
- package/abstract/bls.js.map +1 -1
- package/abstract/curve.d.ts +274 -27
- package/abstract/curve.d.ts.map +1 -1
- package/abstract/curve.js +177 -23
- package/abstract/curve.js.map +1 -1
- package/abstract/edwards.d.ts +166 -30
- package/abstract/edwards.d.ts.map +1 -1
- package/abstract/edwards.js +221 -86
- package/abstract/edwards.js.map +1 -1
- package/abstract/fft.d.ts +327 -10
- package/abstract/fft.d.ts.map +1 -1
- package/abstract/fft.js +155 -12
- package/abstract/fft.js.map +1 -1
- package/abstract/frost.d.ts +293 -0
- package/abstract/frost.d.ts.map +1 -0
- package/abstract/frost.js +704 -0
- package/abstract/frost.js.map +1 -0
- package/abstract/hash-to-curve.d.ts +173 -24
- package/abstract/hash-to-curve.d.ts.map +1 -1
- package/abstract/hash-to-curve.js +170 -31
- package/abstract/hash-to-curve.js.map +1 -1
- package/abstract/modular.d.ts +429 -37
- package/abstract/modular.d.ts.map +1 -1
- package/abstract/modular.js +414 -119
- package/abstract/modular.js.map +1 -1
- package/abstract/montgomery.d.ts +83 -12
- package/abstract/montgomery.d.ts.map +1 -1
- package/abstract/montgomery.js +32 -7
- package/abstract/montgomery.js.map +1 -1
- package/abstract/oprf.d.ts +164 -91
- package/abstract/oprf.d.ts.map +1 -1
- package/abstract/oprf.js +88 -29
- package/abstract/oprf.js.map +1 -1
- package/abstract/poseidon.d.ts +138 -7
- package/abstract/poseidon.d.ts.map +1 -1
- package/abstract/poseidon.js +178 -15
- package/abstract/poseidon.js.map +1 -1
- package/abstract/tower.d.ts +122 -3
- package/abstract/tower.d.ts.map +1 -1
- package/abstract/tower.js +323 -139
- package/abstract/tower.js.map +1 -1
- package/abstract/weierstrass.d.ts +339 -76
- package/abstract/weierstrass.d.ts.map +1 -1
- package/abstract/weierstrass.js +395 -205
- package/abstract/weierstrass.js.map +1 -1
- package/bls12-381.d.ts +16 -2
- package/bls12-381.d.ts.map +1 -1
- package/bls12-381.js +199 -209
- package/bls12-381.js.map +1 -1
- package/bn254.d.ts +11 -2
- package/bn254.d.ts.map +1 -1
- package/bn254.js +93 -38
- package/bn254.js.map +1 -1
- package/ed25519.d.ts +135 -14
- package/ed25519.d.ts.map +1 -1
- package/ed25519.js +207 -41
- package/ed25519.js.map +1 -1
- package/ed448.d.ts +108 -14
- package/ed448.d.ts.map +1 -1
- package/ed448.js +194 -42
- package/ed448.js.map +1 -1
- package/index.js +7 -1
- package/index.js.map +1 -1
- package/misc.d.ts +106 -7
- package/misc.d.ts.map +1 -1
- package/misc.js +141 -32
- package/misc.js.map +1 -1
- package/nist.d.ts +112 -11
- package/nist.d.ts.map +1 -1
- package/nist.js +139 -17
- package/nist.js.map +1 -1
- package/package.json +34 -6
- package/secp256k1.d.ts +92 -15
- package/secp256k1.d.ts.map +1 -1
- package/secp256k1.js +211 -28
- package/secp256k1.js.map +1 -1
- package/src/abstract/bls.ts +356 -69
- package/src/abstract/curve.ts +327 -44
- package/src/abstract/edwards.ts +367 -143
- package/src/abstract/fft.ts +371 -36
- package/src/abstract/frost.ts +1092 -0
- package/src/abstract/hash-to-curve.ts +255 -56
- package/src/abstract/modular.ts +591 -144
- package/src/abstract/montgomery.ts +114 -30
- package/src/abstract/oprf.ts +383 -194
- package/src/abstract/poseidon.ts +235 -35
- package/src/abstract/tower.ts +428 -159
- package/src/abstract/weierstrass.ts +710 -312
- package/src/bls12-381.ts +239 -236
- package/src/bn254.ts +107 -46
- package/src/ed25519.ts +234 -56
- package/src/ed448.ts +227 -57
- package/src/index.ts +7 -1
- package/src/misc.ts +154 -35
- package/src/nist.ts +143 -20
- package/src/secp256k1.ts +284 -41
- package/src/utils.ts +583 -81
- package/src/webcrypto.ts +302 -73
- package/utils.d.ts +457 -24
- package/utils.d.ts.map +1 -1
- package/utils.js +410 -53
- package/utils.js.map +1 -1
- package/webcrypto.d.ts +167 -25
- package/webcrypto.d.ts.map +1 -1
- package/webcrypto.js +165 -58
- package/webcrypto.js.map +1 -1
package/src/utils.ts
CHANGED
|
@@ -5,88 +5,441 @@
|
|
|
5
5
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
6
6
|
import {
|
|
7
7
|
abytes as abytes_,
|
|
8
|
-
anumber,
|
|
8
|
+
anumber as anumber_,
|
|
9
9
|
bytesToHex as bytesToHex_,
|
|
10
10
|
concatBytes as concatBytes_,
|
|
11
11
|
hexToBytes as hexToBytes_,
|
|
12
|
+
isBytes as isBytes_,
|
|
13
|
+
randomBytes as randomBytes_,
|
|
12
14
|
} from '@noble/hashes/utils.js';
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Bytes API type helpers for old + new TypeScript.
|
|
17
|
+
*
|
|
18
|
+
* TS 5.6 has `Uint8Array`, while TS 5.9+ made it generic `Uint8Array<ArrayBuffer>`.
|
|
19
|
+
* We can't use specific return type, because TS 5.6 will error.
|
|
20
|
+
* We can't use generic return type, because most TS 5.9 software will expect specific type.
|
|
21
|
+
*
|
|
22
|
+
* Maps typed-array input leaves to broad forms.
|
|
23
|
+
* These are compatibility adapters, not ownership guarantees.
|
|
24
|
+
*
|
|
25
|
+
* - `TArg` keeps byte inputs broad.
|
|
26
|
+
* - `TRet` marks byte outputs for TS 5.6 and TS 5.9+ compatibility.
|
|
27
|
+
*/
|
|
28
|
+
export type TypedArg<T> = T extends BigInt64Array
|
|
29
|
+
? BigInt64Array
|
|
30
|
+
: T extends BigUint64Array
|
|
31
|
+
? BigUint64Array
|
|
32
|
+
: T extends Float32Array
|
|
33
|
+
? Float32Array
|
|
34
|
+
: T extends Float64Array
|
|
35
|
+
? Float64Array
|
|
36
|
+
: T extends Int16Array
|
|
37
|
+
? Int16Array
|
|
38
|
+
: T extends Int32Array
|
|
39
|
+
? Int32Array
|
|
40
|
+
: T extends Int8Array
|
|
41
|
+
? Int8Array
|
|
42
|
+
: T extends Uint16Array
|
|
43
|
+
? Uint16Array
|
|
44
|
+
: T extends Uint32Array
|
|
45
|
+
? Uint32Array
|
|
46
|
+
: T extends Uint8ClampedArray
|
|
47
|
+
? Uint8ClampedArray
|
|
48
|
+
: T extends Uint8Array
|
|
49
|
+
? Uint8Array
|
|
50
|
+
: never;
|
|
51
|
+
/** Maps typed-array output leaves to narrow TS-compatible forms. */
|
|
52
|
+
export type TypedRet<T> = T extends BigInt64Array
|
|
53
|
+
? ReturnType<typeof BigInt64Array.of>
|
|
54
|
+
: T extends BigUint64Array
|
|
55
|
+
? ReturnType<typeof BigUint64Array.of>
|
|
56
|
+
: T extends Float32Array
|
|
57
|
+
? ReturnType<typeof Float32Array.of>
|
|
58
|
+
: T extends Float64Array
|
|
59
|
+
? ReturnType<typeof Float64Array.of>
|
|
60
|
+
: T extends Int16Array
|
|
61
|
+
? ReturnType<typeof Int16Array.of>
|
|
62
|
+
: T extends Int32Array
|
|
63
|
+
? ReturnType<typeof Int32Array.of>
|
|
64
|
+
: T extends Int8Array
|
|
65
|
+
? ReturnType<typeof Int8Array.of>
|
|
66
|
+
: T extends Uint16Array
|
|
67
|
+
? ReturnType<typeof Uint16Array.of>
|
|
68
|
+
: T extends Uint32Array
|
|
69
|
+
? ReturnType<typeof Uint32Array.of>
|
|
70
|
+
: T extends Uint8ClampedArray
|
|
71
|
+
? ReturnType<typeof Uint8ClampedArray.of>
|
|
72
|
+
: T extends Uint8Array
|
|
73
|
+
? ReturnType<typeof Uint8Array.of>
|
|
74
|
+
: never;
|
|
75
|
+
/** Recursively adapts byte-carrying API input types. See {@link TypedArg}. */
|
|
76
|
+
export type TArg<T> =
|
|
77
|
+
| T
|
|
78
|
+
| ([TypedArg<T>] extends [never]
|
|
79
|
+
? T extends (...args: infer A) => infer R
|
|
80
|
+
? ((...args: { [K in keyof A]: TRet<A[K]> }) => TArg<R>) & {
|
|
81
|
+
[K in keyof T]: T[K] extends (...args: any) => any ? T[K] : TArg<T[K]>;
|
|
82
|
+
}
|
|
83
|
+
: T extends [infer A, ...infer R]
|
|
84
|
+
? [TArg<A>, ...{ [K in keyof R]: TArg<R[K]> }]
|
|
85
|
+
: T extends readonly [infer A, ...infer R]
|
|
86
|
+
? readonly [TArg<A>, ...{ [K in keyof R]: TArg<R[K]> }]
|
|
87
|
+
: T extends (infer A)[]
|
|
88
|
+
? TArg<A>[]
|
|
89
|
+
: T extends readonly (infer A)[]
|
|
90
|
+
? readonly TArg<A>[]
|
|
91
|
+
: T extends Promise<infer A>
|
|
92
|
+
? Promise<TArg<A>>
|
|
93
|
+
: T extends object
|
|
94
|
+
? { [K in keyof T]: TArg<T[K]> }
|
|
95
|
+
: T
|
|
96
|
+
: TypedArg<T>);
|
|
97
|
+
/** Recursively adapts byte-carrying API output types. See {@link TypedArg}. */
|
|
98
|
+
export type TRet<T> = T extends unknown
|
|
99
|
+
? T &
|
|
100
|
+
([TypedRet<T>] extends [never]
|
|
101
|
+
? T extends (...args: infer A) => infer R
|
|
102
|
+
? ((...args: { [K in keyof A]: TArg<A[K]> }) => TRet<R>) & {
|
|
103
|
+
[K in keyof T]: T[K] extends (...args: any) => any ? T[K] : TRet<T[K]>;
|
|
104
|
+
}
|
|
105
|
+
: T extends [infer A, ...infer R]
|
|
106
|
+
? [TRet<A>, ...{ [K in keyof R]: TRet<R[K]> }]
|
|
107
|
+
: T extends readonly [infer A, ...infer R]
|
|
108
|
+
? readonly [TRet<A>, ...{ [K in keyof R]: TRet<R[K]> }]
|
|
109
|
+
: T extends (infer A)[]
|
|
110
|
+
? TRet<A>[]
|
|
111
|
+
: T extends readonly (infer A)[]
|
|
112
|
+
? readonly TRet<A>[]
|
|
113
|
+
: T extends Promise<infer A>
|
|
114
|
+
? Promise<TRet<A>>
|
|
115
|
+
: T extends object
|
|
116
|
+
? { [K in keyof T]: TRet<T[K]> }
|
|
117
|
+
: T
|
|
118
|
+
: TypedRet<T>)
|
|
119
|
+
: never;
|
|
120
|
+
/**
|
|
121
|
+
* Validates that a value is a byte array.
|
|
122
|
+
* @param value - Value to validate.
|
|
123
|
+
* @param length - Optional exact byte length.
|
|
124
|
+
* @param title - Optional field name.
|
|
125
|
+
* @returns Original byte array.
|
|
126
|
+
* @example
|
|
127
|
+
* Reject non-byte input before passing data into curve code.
|
|
128
|
+
*
|
|
129
|
+
* ```ts
|
|
130
|
+
* abytes(new Uint8Array(1));
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
133
|
+
export const abytes = <T extends TArg<Uint8Array>>(value: T, length?: number, title?: string): T =>
|
|
134
|
+
abytes_(value, length, title) as T;
|
|
135
|
+
/**
|
|
136
|
+
* Validates that a value is a non-negative safe integer.
|
|
137
|
+
* @param n - Value to validate.
|
|
138
|
+
* @param title - Optional field name.
|
|
139
|
+
* @example
|
|
140
|
+
* Validate a numeric length before allocating buffers.
|
|
141
|
+
*
|
|
142
|
+
* ```ts
|
|
143
|
+
* anumber(1);
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
export const anumber: typeof anumber_ = anumber_;
|
|
147
|
+
/**
|
|
148
|
+
* Encodes bytes as lowercase hex.
|
|
149
|
+
* @param bytes - Bytes to encode.
|
|
150
|
+
* @returns Lowercase hex string.
|
|
151
|
+
* @example
|
|
152
|
+
* Serialize bytes as hex for logging or fixtures.
|
|
153
|
+
*
|
|
154
|
+
* ```ts
|
|
155
|
+
* bytesToHex(Uint8Array.of(1, 2, 3));
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
158
|
+
export const bytesToHex: typeof bytesToHex_ = bytesToHex_;
|
|
159
|
+
/**
|
|
160
|
+
* Concatenates byte arrays.
|
|
161
|
+
* @param arrays - Byte arrays to join.
|
|
162
|
+
* @returns Concatenated bytes.
|
|
163
|
+
* @example
|
|
164
|
+
* Join domain-separated chunks into one buffer.
|
|
165
|
+
*
|
|
166
|
+
* ```ts
|
|
167
|
+
* concatBytes(Uint8Array.of(1), Uint8Array.of(2));
|
|
168
|
+
* ```
|
|
169
|
+
*/
|
|
170
|
+
export const concatBytes = (...arrays: TArg<Uint8Array[]>): TRet<Uint8Array> =>
|
|
171
|
+
concatBytes_(...arrays) as TRet<Uint8Array>;
|
|
172
|
+
/**
|
|
173
|
+
* Decodes lowercase or uppercase hex into bytes.
|
|
174
|
+
* @param hex - Hex string to decode.
|
|
175
|
+
* @returns Decoded bytes.
|
|
176
|
+
* @example
|
|
177
|
+
* Parse fixture hex into bytes before hashing.
|
|
178
|
+
*
|
|
179
|
+
* ```ts
|
|
180
|
+
* hexToBytes('0102');
|
|
181
|
+
* ```
|
|
182
|
+
*/
|
|
183
|
+
export const hexToBytes = (hex: string): TRet<Uint8Array> => hexToBytes_(hex) as TRet<Uint8Array>;
|
|
184
|
+
/**
|
|
185
|
+
* Checks whether a value is a Uint8Array.
|
|
186
|
+
* @param a - Value to inspect.
|
|
187
|
+
* @returns `true` when `a` is a Uint8Array.
|
|
188
|
+
* @example
|
|
189
|
+
* Branch on byte input before decoding it.
|
|
190
|
+
*
|
|
191
|
+
* ```ts
|
|
192
|
+
* isBytes(new Uint8Array(1));
|
|
193
|
+
* ```
|
|
194
|
+
*/
|
|
195
|
+
export const isBytes: typeof isBytes_ = isBytes_;
|
|
196
|
+
/**
|
|
197
|
+
* Reads random bytes from the platform CSPRNG.
|
|
198
|
+
* @param bytesLength - Number of random bytes to read.
|
|
199
|
+
* @returns Fresh random bytes.
|
|
200
|
+
* @example
|
|
201
|
+
* Generate a random seed for a keypair.
|
|
202
|
+
*
|
|
203
|
+
* ```ts
|
|
204
|
+
* randomBytes(2);
|
|
205
|
+
* ```
|
|
206
|
+
*/
|
|
207
|
+
export const randomBytes = (bytesLength?: number): TRet<Uint8Array> =>
|
|
208
|
+
randomBytes_(bytesLength) as TRet<Uint8Array>;
|
|
22
209
|
const _0n = /* @__PURE__ */ BigInt(0);
|
|
23
210
|
const _1n = /* @__PURE__ */ BigInt(1);
|
|
24
211
|
|
|
212
|
+
/** Callable hash interface with metadata and optional extendable output support. */
|
|
25
213
|
export type CHash = {
|
|
26
|
-
|
|
214
|
+
/**
|
|
215
|
+
* Hash one message.
|
|
216
|
+
* @param message - Message bytes to hash.
|
|
217
|
+
* @returns Digest bytes.
|
|
218
|
+
*/
|
|
219
|
+
(message: TArg<Uint8Array>): TRet<Uint8Array>;
|
|
220
|
+
/** Hash block length in bytes. */
|
|
27
221
|
blockLen: number;
|
|
222
|
+
/** Default output length in bytes. */
|
|
28
223
|
outputLen: number;
|
|
29
|
-
create(
|
|
224
|
+
/** Whether `.create()` can be used as an XOF stream. */
|
|
225
|
+
canXOF: boolean;
|
|
226
|
+
/**
|
|
227
|
+
* Create one stateful hash or XOF instance, for example SHAKE with a custom output length.
|
|
228
|
+
* @param opts - Optional extendable-output configuration:
|
|
229
|
+
* - `dkLen` (optional): Optional output length for XOF-style hashes.
|
|
230
|
+
* @returns Hash instance.
|
|
231
|
+
*/
|
|
232
|
+
create(opts?: { dkLen?: number }): any;
|
|
30
233
|
};
|
|
31
|
-
|
|
234
|
+
/** Plain callable hash interface. */
|
|
235
|
+
export type FHash = (message: TArg<Uint8Array>) => TRet<Uint8Array>;
|
|
236
|
+
/** HMAC callback signature. */
|
|
237
|
+
export type HmacFn = (key: TArg<Uint8Array>, message: TArg<Uint8Array>) => TRet<Uint8Array>;
|
|
238
|
+
/**
|
|
239
|
+
* Validates that a flag is boolean.
|
|
240
|
+
* @param value - Value to validate.
|
|
241
|
+
* @param title - Optional field name.
|
|
242
|
+
* @returns Original value.
|
|
243
|
+
* @throws On wrong argument types. {@link TypeError}
|
|
244
|
+
* @example
|
|
245
|
+
* Reject non-boolean option flags early.
|
|
246
|
+
*
|
|
247
|
+
* ```ts
|
|
248
|
+
* abool(true);
|
|
249
|
+
* ```
|
|
250
|
+
*/
|
|
32
251
|
export function abool(value: boolean, title: string = ''): boolean {
|
|
33
252
|
if (typeof value !== 'boolean') {
|
|
34
253
|
const prefix = title && `"${title}" `;
|
|
35
|
-
throw new
|
|
254
|
+
throw new TypeError(prefix + 'expected boolean, got type=' + typeof value);
|
|
36
255
|
}
|
|
37
256
|
return value;
|
|
38
257
|
}
|
|
39
258
|
|
|
40
|
-
|
|
41
|
-
|
|
259
|
+
/**
|
|
260
|
+
* Validates that a value is a non-negative bigint or safe integer.
|
|
261
|
+
* @param n - Value to validate.
|
|
262
|
+
* @returns The same validated value.
|
|
263
|
+
* @throws On wrong argument ranges or values. {@link RangeError}
|
|
264
|
+
* @example
|
|
265
|
+
* Validate one integer-like value before serializing it.
|
|
266
|
+
*
|
|
267
|
+
* ```ts
|
|
268
|
+
* abignumber(1n);
|
|
269
|
+
* ```
|
|
270
|
+
*/
|
|
271
|
+
export function abignumber<T extends number | bigint>(n: T): T {
|
|
42
272
|
if (typeof n === 'bigint') {
|
|
43
|
-
if (!isPosBig(n)) throw new
|
|
273
|
+
if (!isPosBig(n)) throw new RangeError('positive bigint expected, got ' + n);
|
|
44
274
|
} else anumber(n);
|
|
45
275
|
return n;
|
|
46
276
|
}
|
|
47
277
|
|
|
278
|
+
/**
|
|
279
|
+
* Validates that a value is a safe integer.
|
|
280
|
+
* @param value - Integer to validate.
|
|
281
|
+
* @param title - Optional field name.
|
|
282
|
+
* @throws On wrong argument types. {@link TypeError}
|
|
283
|
+
* @throws On wrong argument ranges or values. {@link RangeError}
|
|
284
|
+
* @example
|
|
285
|
+
* Validate a window size before scalar arithmetic uses it.
|
|
286
|
+
*
|
|
287
|
+
* ```ts
|
|
288
|
+
* asafenumber(1);
|
|
289
|
+
* ```
|
|
290
|
+
*/
|
|
48
291
|
export function asafenumber(value: number, title: string = ''): void {
|
|
292
|
+
if (typeof value !== 'number') {
|
|
293
|
+
const prefix = title && `"${title}" `;
|
|
294
|
+
throw new TypeError(prefix + 'expected number, got type=' + typeof value);
|
|
295
|
+
}
|
|
49
296
|
if (!Number.isSafeInteger(value)) {
|
|
50
297
|
const prefix = title && `"${title}" `;
|
|
51
|
-
throw new
|
|
298
|
+
throw new RangeError(prefix + 'expected safe integer, got ' + value);
|
|
52
299
|
}
|
|
53
300
|
}
|
|
54
301
|
|
|
302
|
+
/**
|
|
303
|
+
* Encodes a bigint into even-length big-endian hex.
|
|
304
|
+
* The historical "unpadded" name only means "no fixed-width field padding"; odd-length hex still
|
|
305
|
+
* gets one leading zero nibble so the result always represents whole bytes.
|
|
306
|
+
* @param num - Number to encode.
|
|
307
|
+
* @returns Big-endian hex string.
|
|
308
|
+
* @throws On wrong argument ranges or values. {@link RangeError}
|
|
309
|
+
* @example
|
|
310
|
+
* Encode a scalar into hex without a `0x` prefix.
|
|
311
|
+
*
|
|
312
|
+
* ```ts
|
|
313
|
+
* numberToHexUnpadded(255n);
|
|
314
|
+
* ```
|
|
315
|
+
*/
|
|
55
316
|
export function numberToHexUnpadded(num: number | bigint): string {
|
|
56
317
|
const hex = abignumber(num).toString(16);
|
|
57
318
|
return hex.length & 1 ? '0' + hex : hex;
|
|
58
319
|
}
|
|
59
320
|
|
|
321
|
+
/**
|
|
322
|
+
* Parses a big-endian hex string into bigint.
|
|
323
|
+
* Accepts odd-length hex through the native `BigInt('0x' + hex)` parser and currently surfaces the
|
|
324
|
+
* same native `SyntaxError` for malformed hex instead of wrapping it in a library-specific error.
|
|
325
|
+
* @param hex - Hex string without `0x`.
|
|
326
|
+
* @returns Parsed bigint value.
|
|
327
|
+
* @throws On wrong argument types. {@link TypeError}
|
|
328
|
+
* @example
|
|
329
|
+
* Parse a scalar from fixture hex.
|
|
330
|
+
*
|
|
331
|
+
* ```ts
|
|
332
|
+
* hexToNumber('ff');
|
|
333
|
+
* ```
|
|
334
|
+
*/
|
|
60
335
|
export function hexToNumber(hex: string): bigint {
|
|
61
|
-
if (typeof hex !== 'string') throw new
|
|
336
|
+
if (typeof hex !== 'string') throw new TypeError('hex string expected, got ' + typeof hex);
|
|
62
337
|
return hex === '' ? _0n : BigInt('0x' + hex); // Big Endian
|
|
63
338
|
}
|
|
64
339
|
|
|
65
340
|
// BE: Big Endian, LE: Little Endian
|
|
66
|
-
|
|
341
|
+
/**
|
|
342
|
+
* Parses big-endian bytes into bigint.
|
|
343
|
+
* @param bytes - Bytes in big-endian order.
|
|
344
|
+
* @returns Parsed bigint value.
|
|
345
|
+
* @throws On wrong argument types. {@link TypeError}
|
|
346
|
+
* @example
|
|
347
|
+
* Read a scalar encoded in network byte order.
|
|
348
|
+
*
|
|
349
|
+
* ```ts
|
|
350
|
+
* bytesToNumberBE(Uint8Array.of(1, 0));
|
|
351
|
+
* ```
|
|
352
|
+
*/
|
|
353
|
+
export function bytesToNumberBE(bytes: TArg<Uint8Array>): bigint {
|
|
67
354
|
return hexToNumber(bytesToHex_(bytes));
|
|
68
355
|
}
|
|
69
|
-
|
|
356
|
+
/**
|
|
357
|
+
* Parses little-endian bytes into bigint.
|
|
358
|
+
* @param bytes - Bytes in little-endian order.
|
|
359
|
+
* @returns Parsed bigint value.
|
|
360
|
+
* @throws On wrong argument types. {@link TypeError}
|
|
361
|
+
* @example
|
|
362
|
+
* Read a scalar encoded in little-endian form.
|
|
363
|
+
*
|
|
364
|
+
* ```ts
|
|
365
|
+
* bytesToNumberLE(Uint8Array.of(1, 0));
|
|
366
|
+
* ```
|
|
367
|
+
*/
|
|
368
|
+
export function bytesToNumberLE(bytes: TArg<Uint8Array>): bigint {
|
|
70
369
|
return hexToNumber(bytesToHex_(copyBytes(abytes_(bytes)).reverse()));
|
|
71
370
|
}
|
|
72
371
|
|
|
73
|
-
|
|
74
|
-
|
|
372
|
+
/**
|
|
373
|
+
* Encodes a bigint into fixed-length big-endian bytes.
|
|
374
|
+
* @param n - Number to encode.
|
|
375
|
+
* @param len - Output length in bytes. Must be greater than zero.
|
|
376
|
+
* @returns Big-endian byte array.
|
|
377
|
+
* @throws On wrong argument ranges or values. {@link RangeError}
|
|
378
|
+
* @example
|
|
379
|
+
* Serialize a scalar into a 32-byte field element.
|
|
380
|
+
*
|
|
381
|
+
* ```ts
|
|
382
|
+
* numberToBytesBE(255n, 2);
|
|
383
|
+
* ```
|
|
384
|
+
*/
|
|
385
|
+
export function numberToBytesBE(n: number | bigint, len: number): TRet<Uint8Array> {
|
|
386
|
+
anumber_(len);
|
|
387
|
+
if (len === 0) throw new RangeError('zero length');
|
|
75
388
|
n = abignumber(n);
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
389
|
+
const hex = n.toString(16);
|
|
390
|
+
// Detect overflow before hex parsing so oversized values don't leak the shared odd-hex error.
|
|
391
|
+
if (hex.length > len * 2) throw new RangeError('number too large');
|
|
392
|
+
return hexToBytes_(hex.padStart(len * 2, '0')) as TRet<Uint8Array>;
|
|
79
393
|
}
|
|
80
|
-
|
|
81
|
-
|
|
394
|
+
/**
|
|
395
|
+
* Encodes a bigint into fixed-length little-endian bytes.
|
|
396
|
+
* @param n - Number to encode.
|
|
397
|
+
* @param len - Output length in bytes.
|
|
398
|
+
* @returns Little-endian byte array.
|
|
399
|
+
* @throws On wrong argument ranges or values. {@link RangeError}
|
|
400
|
+
* @example
|
|
401
|
+
* Serialize a scalar for little-endian protocols.
|
|
402
|
+
*
|
|
403
|
+
* ```ts
|
|
404
|
+
* numberToBytesLE(255n, 2);
|
|
405
|
+
* ```
|
|
406
|
+
*/
|
|
407
|
+
export function numberToBytesLE(n: number | bigint, len: number): TRet<Uint8Array> {
|
|
408
|
+
return numberToBytesBE(n, len).reverse() as TRet<Uint8Array>;
|
|
82
409
|
}
|
|
83
410
|
// Unpadded, rarely used
|
|
84
|
-
|
|
85
|
-
|
|
411
|
+
/**
|
|
412
|
+
* Encodes a bigint into variable-length big-endian bytes.
|
|
413
|
+
* @param n - Number to encode.
|
|
414
|
+
* @returns Variable-length big-endian bytes.
|
|
415
|
+
* @throws On wrong argument ranges or values. {@link RangeError}
|
|
416
|
+
* @example
|
|
417
|
+
* Serialize a bigint without fixed-width padding.
|
|
418
|
+
*
|
|
419
|
+
* ```ts
|
|
420
|
+
* numberToVarBytesBE(255n);
|
|
421
|
+
* ```
|
|
422
|
+
*/
|
|
423
|
+
export function numberToVarBytesBE(n: number | bigint): TRet<Uint8Array> {
|
|
424
|
+
return hexToBytes_(numberToHexUnpadded(abignumber(n))) as TRet<Uint8Array>;
|
|
86
425
|
}
|
|
87
426
|
|
|
88
427
|
// Compares 2 u8a-s in kinda constant time
|
|
89
|
-
|
|
428
|
+
/**
|
|
429
|
+
* Compares two byte arrays in constant-ish time.
|
|
430
|
+
* @param a - Left byte array.
|
|
431
|
+
* @param b - Right byte array.
|
|
432
|
+
* @returns `true` when bytes match.
|
|
433
|
+
* @example
|
|
434
|
+
* Compare two encoded points without early exit.
|
|
435
|
+
*
|
|
436
|
+
* ```ts
|
|
437
|
+
* equalBytes(Uint8Array.of(1), Uint8Array.of(1));
|
|
438
|
+
* ```
|
|
439
|
+
*/
|
|
440
|
+
export function equalBytes(a: TArg<Uint8Array>, b: TArg<Uint8Array>): boolean {
|
|
441
|
+
a = abytes(a);
|
|
442
|
+
b = abytes(b);
|
|
90
443
|
if (a.length !== b.length) return false;
|
|
91
444
|
let diff = 0;
|
|
92
445
|
for (let i = 0; i < a.length; i++) diff |= a[i] ^ b[i];
|
|
@@ -96,39 +449,83 @@ export function equalBytes(a: Uint8Array, b: Uint8Array): boolean {
|
|
|
96
449
|
/**
|
|
97
450
|
* Copies Uint8Array. We can't use u8a.slice(), because u8a can be Buffer,
|
|
98
451
|
* and Buffer#slice creates mutable copy. Never use Buffers!
|
|
452
|
+
* @param bytes - Bytes to copy.
|
|
453
|
+
* @returns Detached copy.
|
|
454
|
+
* @example
|
|
455
|
+
* Make an isolated copy before mutating serialized bytes.
|
|
456
|
+
*
|
|
457
|
+
* ```ts
|
|
458
|
+
* copyBytes(Uint8Array.of(1, 2, 3));
|
|
459
|
+
* ```
|
|
99
460
|
*/
|
|
100
|
-
export function copyBytes(bytes: Uint8Array): Uint8Array {
|
|
101
|
-
|
|
461
|
+
export function copyBytes(bytes: TArg<Uint8Array>): TRet<Uint8Array> {
|
|
462
|
+
// `Uint8Array.from(...)` would also accept arrays / other typed arrays. Keep this helper strict
|
|
463
|
+
// because callers use it at byte-validation boundaries before mutating the detached copy.
|
|
464
|
+
return Uint8Array.from(abytes(bytes)) as TRet<Uint8Array>;
|
|
102
465
|
}
|
|
103
466
|
|
|
104
467
|
/**
|
|
105
468
|
* Decodes 7-bit ASCII string to Uint8Array, throws on non-ascii symbols
|
|
106
469
|
* Should be safe to use for things expected to be ASCII.
|
|
107
470
|
* Returns exact same result as `TextEncoder` for ASCII or throws.
|
|
471
|
+
* @param ascii - ASCII input text.
|
|
472
|
+
* @returns Encoded bytes.
|
|
473
|
+
* @throws On wrong argument types. {@link TypeError}
|
|
474
|
+
* @example
|
|
475
|
+
* Encode an ASCII domain-separation tag.
|
|
476
|
+
*
|
|
477
|
+
* ```ts
|
|
478
|
+
* asciiToBytes('ABC');
|
|
479
|
+
* ```
|
|
108
480
|
*/
|
|
109
|
-
export function asciiToBytes(ascii: string): Uint8Array {
|
|
481
|
+
export function asciiToBytes(ascii: string): TRet<Uint8Array> {
|
|
482
|
+
if (typeof ascii !== 'string') throw new TypeError('ascii string expected, got ' + typeof ascii);
|
|
110
483
|
return Uint8Array.from(ascii, (c, i) => {
|
|
111
484
|
const charCode = c.charCodeAt(0);
|
|
112
485
|
if (c.length !== 1 || charCode > 127) {
|
|
113
|
-
throw new
|
|
486
|
+
throw new RangeError(
|
|
114
487
|
`string contains non-ASCII character "${ascii[i]}" with code ${charCode} at position ${i}`
|
|
115
488
|
);
|
|
116
489
|
}
|
|
117
490
|
return charCode;
|
|
118
|
-
})
|
|
491
|
+
}) as TRet<Uint8Array>;
|
|
119
492
|
}
|
|
120
493
|
|
|
121
|
-
//
|
|
494
|
+
// Historical name: this accepts non-negative bigints, including zero.
|
|
122
495
|
const isPosBig = (n: bigint) => typeof n === 'bigint' && _0n <= n;
|
|
123
496
|
|
|
497
|
+
/**
|
|
498
|
+
* Checks whether a bigint lies inside a half-open range.
|
|
499
|
+
* @param n - Candidate value.
|
|
500
|
+
* @param min - Inclusive lower bound.
|
|
501
|
+
* @param max - Exclusive upper bound.
|
|
502
|
+
* @returns `true` when the value is inside the range.
|
|
503
|
+
* @example
|
|
504
|
+
* Check whether a candidate scalar fits the field order.
|
|
505
|
+
*
|
|
506
|
+
* ```ts
|
|
507
|
+
* inRange(2n, 1n, 3n);
|
|
508
|
+
* ```
|
|
509
|
+
*/
|
|
124
510
|
export function inRange(n: bigint, min: bigint, max: bigint): boolean {
|
|
125
511
|
return isPosBig(n) && isPosBig(min) && isPosBig(max) && min <= n && n < max;
|
|
126
512
|
}
|
|
127
513
|
|
|
128
514
|
/**
|
|
129
|
-
* Asserts min <= n < max
|
|
515
|
+
* Asserts `min <= n < max`. NOTE: upper bound is exclusive.
|
|
516
|
+
* @param title - Value label for error messages.
|
|
517
|
+
* @param n - Candidate value.
|
|
518
|
+
* @param min - Inclusive lower bound.
|
|
519
|
+
* @param max - Exclusive upper bound.
|
|
520
|
+
* Wrong-type inputs are not separated from out-of-range values here: they still flow through the
|
|
521
|
+
* shared `RangeError` path because this is only a throwing wrapper around `inRange(...)`.
|
|
522
|
+
* @throws On wrong argument ranges or values. {@link RangeError}
|
|
130
523
|
* @example
|
|
131
|
-
*
|
|
524
|
+
* Assert that a bigint stays within one half-open range.
|
|
525
|
+
*
|
|
526
|
+
* ```ts
|
|
527
|
+
* aInRange('x', 2n, 1n, 256n);
|
|
528
|
+
* ```
|
|
132
529
|
*/
|
|
133
530
|
export function aInRange(title: string, n: bigint, min: bigint, max: bigint): void {
|
|
134
531
|
// Why min <= n < max and not a (min < n < max) OR b (min <= n <= max)?
|
|
@@ -137,7 +534,7 @@ export function aInRange(title: string, n: bigint, min: bigint, max: bigint): vo
|
|
|
137
534
|
// - b would commonly require subtraction: `inRange('x', x, 0n, P - 1n)`
|
|
138
535
|
// - our way is the cleanest: `inRange('x', x, 0n, P)
|
|
139
536
|
if (!inRange(n, min, max))
|
|
140
|
-
throw new
|
|
537
|
+
throw new RangeError('expected valid ' + title + ': ' + min + ' <= n < ' + max + ', got ' + n);
|
|
141
538
|
}
|
|
142
539
|
|
|
143
540
|
// Bit operations
|
|
@@ -146,8 +543,20 @@ export function aInRange(title: string, n: bigint, min: bigint, max: bigint): vo
|
|
|
146
543
|
* Calculates amount of bits in a bigint.
|
|
147
544
|
* Same as `n.toString(2).length`
|
|
148
545
|
* TODO: merge with nLength in modular
|
|
546
|
+
* @param n - Value to inspect.
|
|
547
|
+
* @returns Bit length.
|
|
548
|
+
* @throws If the value is negative. {@link Error}
|
|
549
|
+
* @example
|
|
550
|
+
* Measure the bit length of a scalar before serialization.
|
|
551
|
+
*
|
|
552
|
+
* ```ts
|
|
553
|
+
* bitLen(8n);
|
|
554
|
+
* ```
|
|
149
555
|
*/
|
|
150
556
|
export function bitLen(n: bigint): number {
|
|
557
|
+
// Size callers in this repo only use non-negative orders / scalars, so negative inputs are a
|
|
558
|
+
// contract bug and must not silently collapse to zero bits.
|
|
559
|
+
if (n < _0n) throw new Error('expected non-negative bigint, got ' + n);
|
|
151
560
|
let len;
|
|
152
561
|
for (len = 0; n > _0n; n >>= _1n, len += 1);
|
|
153
562
|
return len;
|
|
@@ -157,6 +566,17 @@ export function bitLen(n: bigint): number {
|
|
|
157
566
|
* Gets single bit at position.
|
|
158
567
|
* NOTE: first bit position is 0 (same as arrays)
|
|
159
568
|
* Same as `!!+Array.from(n.toString(2)).reverse()[pos]`
|
|
569
|
+
* @param n - Source value.
|
|
570
|
+
* @param pos - Bit position. Negative positions are passed through to raw
|
|
571
|
+
* bigint shift semantics; because the mask is built as `1n << pos`,
|
|
572
|
+
* they currently collapse to `0n` and make the helper a no-op.
|
|
573
|
+
* @returns Bit as bigint.
|
|
574
|
+
* @example
|
|
575
|
+
* Gets single bit at position.
|
|
576
|
+
*
|
|
577
|
+
* ```ts
|
|
578
|
+
* bitGet(5n, 0);
|
|
579
|
+
* ```
|
|
160
580
|
*/
|
|
161
581
|
export function bitGet(n: bigint, pos: number): bigint {
|
|
162
582
|
return (n >> BigInt(pos)) & _1n;
|
|
@@ -164,52 +584,92 @@ export function bitGet(n: bigint, pos: number): bigint {
|
|
|
164
584
|
|
|
165
585
|
/**
|
|
166
586
|
* Sets single bit at position.
|
|
587
|
+
* @param n - Source value.
|
|
588
|
+
* @param pos - Bit position. Negative positions are passed through to raw bigint shift semantics,
|
|
589
|
+
* so they currently behave like left shifts.
|
|
590
|
+
* @param value - Whether the bit should be set.
|
|
591
|
+
* @returns Updated bigint.
|
|
592
|
+
* @example
|
|
593
|
+
* Sets single bit at position.
|
|
594
|
+
*
|
|
595
|
+
* ```ts
|
|
596
|
+
* bitSet(0n, 1, true);
|
|
597
|
+
* ```
|
|
167
598
|
*/
|
|
168
599
|
export function bitSet(n: bigint, pos: number, value: boolean): bigint {
|
|
169
|
-
|
|
600
|
+
const mask = _1n << BigInt(pos);
|
|
601
|
+
// Clearing needs AND-not here; OR with zero leaves an already-set bit untouched.
|
|
602
|
+
return value ? n | mask : n & ~mask;
|
|
170
603
|
}
|
|
171
604
|
|
|
172
605
|
/**
|
|
173
606
|
* Calculate mask for N bits. Not using ** operator with bigints because of old engines.
|
|
174
607
|
* Same as BigInt(`0b${Array(i).fill('1').join('')}`)
|
|
608
|
+
* @param n - Number of bits. Negative widths are currently passed through to raw bigint shift
|
|
609
|
+
* semantics and therefore produce `-1n`.
|
|
610
|
+
* @returns Bitmask value.
|
|
611
|
+
* @example
|
|
612
|
+
* Calculate mask for N bits.
|
|
613
|
+
*
|
|
614
|
+
* ```ts
|
|
615
|
+
* bitMask(4);
|
|
616
|
+
* ```
|
|
175
617
|
*/
|
|
176
618
|
export const bitMask = (n: number): bigint => (_1n << BigInt(n)) - _1n;
|
|
177
619
|
|
|
178
620
|
// DRBG
|
|
179
621
|
|
|
180
|
-
type Pred<T> = (v: Uint8Array) => T | undefined;
|
|
622
|
+
type Pred<T> = (v: TArg<Uint8Array>) => T | undefined;
|
|
181
623
|
/**
|
|
182
624
|
* Minimal HMAC-DRBG from NIST 800-90 for RFC6979 sigs.
|
|
183
|
-
* @
|
|
625
|
+
* @param hashLen - Hash output size in bytes. Callers are expected to pass a positive length; `0`
|
|
626
|
+
* is not rejected here and would make the internal generate loop non-progressing.
|
|
627
|
+
* @param qByteLen - Requested output size in bytes. Callers are expected to pass a positive length.
|
|
628
|
+
* @param hmacFn - HMAC implementation.
|
|
629
|
+
* @returns Function that will call DRBG until the predicate returns anything
|
|
630
|
+
* other than `undefined`.
|
|
631
|
+
* @throws On wrong argument types. {@link TypeError}
|
|
184
632
|
* @example
|
|
185
|
-
*
|
|
186
|
-
*
|
|
633
|
+
* Build a deterministic nonce generator for RFC6979-style signing.
|
|
634
|
+
*
|
|
635
|
+
* ```ts
|
|
636
|
+
* import { createHmacDrbg } from '@noble/curves/utils.js';
|
|
637
|
+
* import { hmac } from '@noble/hashes/hmac.js';
|
|
638
|
+
* import { sha256 } from '@noble/hashes/sha2.js';
|
|
639
|
+
* const drbg = createHmacDrbg(32, 32, (key, msg) => hmac(sha256, key, msg));
|
|
640
|
+
* const seed = new Uint8Array(32);
|
|
641
|
+
* drbg(seed, (bytes) => bytes);
|
|
642
|
+
* ```
|
|
187
643
|
*/
|
|
188
644
|
export function createHmacDrbg<T>(
|
|
189
645
|
hashLen: number,
|
|
190
646
|
qByteLen: number,
|
|
191
|
-
hmacFn:
|
|
192
|
-
): (seed: Uint8Array, predicate: Pred<T>) => T {
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
if (typeof hmacFn !== 'function') throw new
|
|
196
|
-
|
|
647
|
+
hmacFn: TArg<HmacFn>
|
|
648
|
+
): TRet<(seed: Uint8Array, predicate: Pred<T>) => T> {
|
|
649
|
+
anumber_(hashLen, 'hashLen');
|
|
650
|
+
anumber_(qByteLen, 'qByteLen');
|
|
651
|
+
if (typeof hmacFn !== 'function') throw new TypeError('hmacFn must be a function');
|
|
652
|
+
// creates Uint8Array
|
|
653
|
+
const u8n = (len: number): TRet<Uint8Array> => new Uint8Array(len) as TRet<Uint8Array>;
|
|
197
654
|
const NULL = Uint8Array.of();
|
|
198
655
|
const byte0 = Uint8Array.of(0x00);
|
|
199
656
|
const byte1 = Uint8Array.of(0x01);
|
|
200
657
|
const _maxDrbgIters = 1000;
|
|
201
658
|
|
|
202
|
-
// Step B, Step C: set hashLen to 8*ceil(hlen/8)
|
|
203
|
-
|
|
204
|
-
let
|
|
659
|
+
// Step B, Step C: set hashLen to 8*ceil(hlen/8).
|
|
660
|
+
// Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 signatures.
|
|
661
|
+
let v: Uint8Array = u8n(hashLen);
|
|
662
|
+
// Steps B and C of RFC6979 3.2.
|
|
663
|
+
let k: Uint8Array = u8n(hashLen);
|
|
205
664
|
let i = 0; // Iterations counter, will throw when over 1000
|
|
206
665
|
const reset = () => {
|
|
207
666
|
v.fill(1);
|
|
208
667
|
k.fill(0);
|
|
209
668
|
i = 0;
|
|
210
669
|
};
|
|
211
|
-
|
|
212
|
-
const
|
|
670
|
+
// hmac(k)(v, ...values)
|
|
671
|
+
const h = (...msgs: TArg<Uint8Array[]>) => (hmacFn as HmacFn)(k, concatBytes(v, ...msgs));
|
|
672
|
+
const reseed = (seed: TArg<Uint8Array> = NULL) => {
|
|
213
673
|
// HMAC-DRBG reseed() function. Steps D-G
|
|
214
674
|
k = h(byte0, seed); // k = hmac(k || v || 0x00 || seed)
|
|
215
675
|
v = h(); // v = hmac(k || v)
|
|
@@ -228,32 +688,55 @@ export function createHmacDrbg<T>(
|
|
|
228
688
|
out.push(sl);
|
|
229
689
|
len += v.length;
|
|
230
690
|
}
|
|
231
|
-
return
|
|
691
|
+
return concatBytes(...out);
|
|
232
692
|
};
|
|
233
|
-
const genUntil = (seed: Uint8Array
|
|
693
|
+
const genUntil = (seed: TArg<Uint8Array>, pred: TArg<Pred<T>>): T => {
|
|
234
694
|
reset();
|
|
235
695
|
reseed(seed); // Steps D-G
|
|
236
|
-
let res: T | undefined = undefined; // Step H: grind until
|
|
237
|
-
|
|
696
|
+
let res: T | undefined = undefined; // Step H: grind until the predicate accepts a candidate.
|
|
697
|
+
// Falsy values like 0 are valid outputs.
|
|
698
|
+
while ((res = (pred as Pred<T>)(gen())) === undefined) reseed();
|
|
238
699
|
reset();
|
|
239
700
|
return res;
|
|
240
701
|
};
|
|
241
|
-
return genUntil
|
|
702
|
+
return genUntil as TRet<(seed: Uint8Array, predicate: Pred<T>) => T>;
|
|
242
703
|
}
|
|
243
704
|
|
|
705
|
+
/**
|
|
706
|
+
* Validates declared required and optional field types on a plain object.
|
|
707
|
+
* Extra keys are intentionally ignored because many callers validate only the subset they use from
|
|
708
|
+
* richer option bags or runtime objects.
|
|
709
|
+
* @param object - Object to validate.
|
|
710
|
+
* @param fields - Required field types.
|
|
711
|
+
* @param optFields - Optional field types.
|
|
712
|
+
* @throws On wrong argument types. {@link TypeError}
|
|
713
|
+
* @example
|
|
714
|
+
* Check user options before building a curve helper.
|
|
715
|
+
*
|
|
716
|
+
* ```ts
|
|
717
|
+
* validateObject({ flag: true }, { flag: 'boolean' });
|
|
718
|
+
* ```
|
|
719
|
+
*/
|
|
244
720
|
export function validateObject(
|
|
245
721
|
object: Record<string, any>,
|
|
246
722
|
fields: Record<string, string> = {},
|
|
247
723
|
optFields: Record<string, string> = {}
|
|
248
724
|
): void {
|
|
249
|
-
if (
|
|
725
|
+
if (Object.prototype.toString.call(object) !== '[object Object]')
|
|
726
|
+
throw new TypeError('expected valid options object');
|
|
250
727
|
type Item = keyof typeof object;
|
|
251
728
|
function checkField(fieldName: Item, expectedType: string, isOpt: boolean) {
|
|
729
|
+
// Config/data fields must be explicit own properties, but runtime objects such as Field
|
|
730
|
+
// instances intentionally satisfy required method slots via their shared prototype.
|
|
731
|
+
if (!isOpt && expectedType !== 'function' && !Object.hasOwn(object, fieldName))
|
|
732
|
+
throw new TypeError(`param "${fieldName}" is invalid: expected own property`);
|
|
252
733
|
const val = object[fieldName];
|
|
253
734
|
if (isOpt && val === undefined) return;
|
|
254
735
|
const current = typeof val;
|
|
255
736
|
if (current !== expectedType || val === null)
|
|
256
|
-
throw new
|
|
737
|
+
throw new TypeError(
|
|
738
|
+
`param "${fieldName}" is invalid: expected ${expectedType}, got ${current}`
|
|
739
|
+
);
|
|
257
740
|
}
|
|
258
741
|
const iter = (f: typeof fields, isOpt: boolean) =>
|
|
259
742
|
Object.entries(f).forEach(([k, v]) => checkField(k, v, isOpt));
|
|
@@ -262,38 +745,44 @@ export function validateObject(
|
|
|
262
745
|
}
|
|
263
746
|
|
|
264
747
|
/**
|
|
265
|
-
*
|
|
748
|
+
* Throws not implemented error.
|
|
749
|
+
* @returns Never returns.
|
|
750
|
+
* @throws If the unfinished code path is reached. {@link Error}
|
|
751
|
+
* @example
|
|
752
|
+
* Surface the placeholder error from an unfinished code path.
|
|
753
|
+
*
|
|
754
|
+
* ```ts
|
|
755
|
+
* try {
|
|
756
|
+
* notImplemented();
|
|
757
|
+
* } catch {}
|
|
758
|
+
* ```
|
|
266
759
|
*/
|
|
267
760
|
export const notImplemented = (): never => {
|
|
268
761
|
throw new Error('not implemented');
|
|
269
762
|
};
|
|
270
763
|
|
|
271
|
-
/**
|
|
272
|
-
* Memoizes (caches) computation result.
|
|
273
|
-
* Uses WeakMap: the value is going auto-cleaned by GC after last reference is removed.
|
|
274
|
-
*/
|
|
275
|
-
export function memoized<T extends object, R, O extends any[]>(
|
|
276
|
-
fn: (arg: T, ...args: O) => R
|
|
277
|
-
): (arg: T, ...args: O) => R {
|
|
278
|
-
const map = new WeakMap<T, R>();
|
|
279
|
-
return (arg: T, ...args: O): R => {
|
|
280
|
-
const val = map.get(arg);
|
|
281
|
-
if (val !== undefined) return val;
|
|
282
|
-
const computed = fn(arg, ...args);
|
|
283
|
-
map.set(arg, computed);
|
|
284
|
-
return computed;
|
|
285
|
-
};
|
|
286
|
-
}
|
|
287
|
-
|
|
764
|
+
/** Generic keygen/getPublicKey interface shared by curve helpers. */
|
|
288
765
|
export interface CryptoKeys {
|
|
766
|
+
/** Public byte lengths for keys and optional seeds. */
|
|
289
767
|
lengths: { seed?: number; public?: number; secret?: number };
|
|
768
|
+
/**
|
|
769
|
+
* Generate one secret/public keypair.
|
|
770
|
+
* @param seed - Optional seed bytes for deterministic key generation.
|
|
771
|
+
* @returns Fresh secret/public keypair.
|
|
772
|
+
*/
|
|
290
773
|
keygen: (seed?: Uint8Array) => { secretKey: Uint8Array; publicKey: Uint8Array };
|
|
774
|
+
/**
|
|
775
|
+
* Derive one public key from a secret key.
|
|
776
|
+
* @param secretKey - Secret key bytes.
|
|
777
|
+
* @returns Public key bytes.
|
|
778
|
+
*/
|
|
291
779
|
getPublicKey: (secretKey: Uint8Array) => Uint8Array;
|
|
292
780
|
}
|
|
293
781
|
|
|
294
782
|
/** Generic interface for signatures. Has keygen, sign and verify. */
|
|
295
783
|
export interface Signer extends CryptoKeys {
|
|
296
784
|
// Interfaces are fun. We cannot just add new fields without copying old ones.
|
|
785
|
+
/** Public byte lengths for keys, signatures, and optional signing randomness. */
|
|
297
786
|
lengths: {
|
|
298
787
|
seed?: number;
|
|
299
788
|
public?: number;
|
|
@@ -301,6 +790,19 @@ export interface Signer extends CryptoKeys {
|
|
|
301
790
|
signRand?: number;
|
|
302
791
|
signature?: number;
|
|
303
792
|
};
|
|
793
|
+
/**
|
|
794
|
+
* Sign one message.
|
|
795
|
+
* @param msg - Message bytes to sign.
|
|
796
|
+
* @param secretKey - Secret key bytes.
|
|
797
|
+
* @returns Signature bytes.
|
|
798
|
+
*/
|
|
304
799
|
sign: (msg: Uint8Array, secretKey: Uint8Array) => Uint8Array;
|
|
800
|
+
/**
|
|
801
|
+
* Verify one signature.
|
|
802
|
+
* @param sig - Signature bytes.
|
|
803
|
+
* @param msg - Signed message bytes.
|
|
804
|
+
* @param publicKey - Public key bytes.
|
|
805
|
+
* @returns `true` when the signature is valid.
|
|
806
|
+
*/
|
|
305
807
|
verify: (sig: Uint8Array, msg: Uint8Array, publicKey: Uint8Array) => boolean;
|
|
306
808
|
}
|