@noble/curves 1.9.5 → 2.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +267 -421
- package/abstract/bls.d.ts +49 -111
- package/abstract/bls.d.ts.map +1 -1
- package/abstract/bls.js +108 -152
- package/abstract/bls.js.map +1 -1
- package/abstract/curve.d.ts +7 -48
- package/abstract/curve.d.ts.map +1 -1
- package/abstract/curve.js +22 -47
- package/abstract/curve.js.map +1 -1
- package/abstract/edwards.d.ts +17 -68
- package/abstract/edwards.d.ts.map +1 -1
- package/abstract/edwards.js +98 -175
- package/abstract/edwards.js.map +1 -1
- package/abstract/fft.js +14 -27
- package/abstract/fft.js.map +1 -1
- package/abstract/hash-to-curve.d.ts +11 -24
- package/abstract/hash-to-curve.d.ts.map +1 -1
- package/abstract/hash-to-curve.js +30 -35
- package/abstract/hash-to-curve.js.map +1 -1
- package/abstract/modular.d.ts +5 -17
- package/abstract/modular.d.ts.map +1 -1
- package/abstract/modular.js +166 -167
- package/abstract/modular.js.map +1 -1
- package/abstract/montgomery.d.ts +4 -9
- package/abstract/montgomery.d.ts.map +1 -1
- package/abstract/montgomery.js +17 -20
- package/abstract/montgomery.js.map +1 -1
- package/abstract/oprf.d.ts +282 -0
- package/abstract/oprf.d.ts.map +1 -0
- package/abstract/oprf.js +297 -0
- package/abstract/oprf.js.map +1 -0
- package/abstract/poseidon.js +20 -24
- package/abstract/poseidon.js.map +1 -1
- package/abstract/tower.d.ts +9 -7
- package/abstract/tower.d.ts.map +1 -1
- package/abstract/tower.js +600 -364
- package/abstract/tower.js.map +1 -1
- package/abstract/weierstrass.d.ts +12 -145
- package/abstract/weierstrass.d.ts.map +1 -1
- package/abstract/weierstrass.js +153 -377
- package/abstract/weierstrass.js.map +1 -1
- package/bls12-381.d.ts +2 -2
- package/bls12-381.d.ts.map +1 -1
- package/bls12-381.js +174 -216
- package/bls12-381.js.map +1 -1
- package/bn254.d.ts +58 -10
- package/bn254.d.ts.map +1 -1
- package/bn254.js +70 -130
- package/bn254.js.map +1 -1
- package/ed25519.d.ts +12 -31
- package/ed25519.d.ts.map +1 -1
- package/ed25519.js +104 -146
- package/ed25519.js.map +1 -1
- package/ed448.d.ts +14 -33
- package/ed448.d.ts.map +1 -1
- package/ed448.js +105 -132
- package/ed448.js.map +1 -1
- package/index.js +1 -1
- package/misc.d.ts +10 -14
- package/misc.d.ts.map +1 -1
- package/misc.js +51 -60
- package/misc.js.map +1 -1
- package/nist.d.ts +11 -14
- package/nist.d.ts.map +1 -1
- package/nist.js +46 -55
- package/nist.js.map +1 -1
- package/package.json +9 -224
- package/secp256k1.d.ts +7 -23
- package/secp256k1.d.ts.map +1 -1
- package/secp256k1.js +72 -83
- package/secp256k1.js.map +1 -1
- package/src/abstract/bls.ts +197 -344
- package/src/abstract/curve.ts +10 -83
- package/src/abstract/edwards.ts +96 -223
- package/src/abstract/hash-to-curve.ts +32 -45
- package/src/abstract/modular.ts +144 -130
- package/src/abstract/montgomery.ts +21 -22
- package/src/abstract/oprf.ts +600 -0
- package/src/abstract/tower.ts +627 -382
- package/src/abstract/weierstrass.ts +101 -482
- package/src/bls12-381.ts +148 -176
- package/src/bn254.ts +67 -122
- package/src/ed25519.ts +65 -118
- package/src/ed448.ts +63 -113
- package/src/index.ts +1 -1
- package/src/misc.ts +66 -49
- package/src/nist.ts +48 -57
- package/src/secp256k1.ts +56 -88
- package/src/utils.ts +41 -61
- package/src/webcrypto.ts +362 -0
- package/utils.d.ts +28 -19
- package/utils.d.ts.map +1 -1
- package/utils.js +45 -121
- package/utils.js.map +1 -1
- package/webcrypto.d.ts +47 -0
- package/webcrypto.d.ts.map +1 -0
- package/webcrypto.js +231 -0
- package/webcrypto.js.map +1 -0
- package/esm/_shortw_utils.d.ts +0 -19
- package/esm/_shortw_utils.d.ts.map +0 -1
- package/esm/_shortw_utils.js +0 -16
- package/esm/_shortw_utils.js.map +0 -1
- package/esm/abstract/bls.d.ts +0 -190
- package/esm/abstract/bls.d.ts.map +0 -1
- package/esm/abstract/bls.js +0 -408
- package/esm/abstract/bls.js.map +0 -1
- package/esm/abstract/curve.d.ts +0 -231
- package/esm/abstract/curve.d.ts.map +0 -1
- package/esm/abstract/curve.js +0 -465
- package/esm/abstract/curve.js.map +0 -1
- package/esm/abstract/edwards.d.ts +0 -237
- package/esm/abstract/edwards.d.ts.map +0 -1
- package/esm/abstract/edwards.js +0 -632
- package/esm/abstract/edwards.js.map +0 -1
- package/esm/abstract/fft.d.ts +0 -122
- package/esm/abstract/fft.d.ts.map +0 -1
- package/esm/abstract/fft.js +0 -425
- package/esm/abstract/fft.js.map +0 -1
- package/esm/abstract/hash-to-curve.d.ts +0 -102
- package/esm/abstract/hash-to-curve.d.ts.map +0 -1
- package/esm/abstract/hash-to-curve.js +0 -203
- package/esm/abstract/hash-to-curve.js.map +0 -1
- package/esm/abstract/modular.d.ts +0 -171
- package/esm/abstract/modular.d.ts.map +0 -1
- package/esm/abstract/modular.js +0 -530
- package/esm/abstract/modular.js.map +0 -1
- package/esm/abstract/montgomery.d.ts +0 -30
- package/esm/abstract/montgomery.d.ts.map +0 -1
- package/esm/abstract/montgomery.js +0 -157
- package/esm/abstract/montgomery.js.map +0 -1
- package/esm/abstract/poseidon.d.ts +0 -68
- package/esm/abstract/poseidon.d.ts.map +0 -1
- package/esm/abstract/poseidon.js +0 -296
- package/esm/abstract/poseidon.js.map +0 -1
- package/esm/abstract/tower.d.ts +0 -93
- package/esm/abstract/tower.d.ts.map +0 -1
- package/esm/abstract/tower.js +0 -502
- package/esm/abstract/tower.js.map +0 -1
- package/esm/abstract/utils.d.ts +0 -5
- package/esm/abstract/utils.d.ts.map +0 -1
- package/esm/abstract/utils.js +0 -7
- package/esm/abstract/utils.js.map +0 -1
- package/esm/abstract/weierstrass.d.ts +0 -412
- package/esm/abstract/weierstrass.d.ts.map +0 -1
- package/esm/abstract/weierstrass.js +0 -1428
- package/esm/abstract/weierstrass.js.map +0 -1
- package/esm/bls12-381.d.ts +0 -16
- package/esm/bls12-381.d.ts.map +0 -1
- package/esm/bls12-381.js +0 -738
- package/esm/bls12-381.js.map +0 -1
- package/esm/bn254.d.ts +0 -18
- package/esm/bn254.d.ts.map +0 -1
- package/esm/bn254.js +0 -246
- package/esm/bn254.js.map +0 -1
- package/esm/ed25519.d.ts +0 -106
- package/esm/ed25519.d.ts.map +0 -1
- package/esm/ed25519.js +0 -467
- package/esm/ed25519.js.map +0 -1
- package/esm/ed448.d.ts +0 -101
- package/esm/ed448.d.ts.map +0 -1
- package/esm/ed448.js +0 -448
- package/esm/ed448.js.map +0 -1
- package/esm/index.d.ts +0 -2
- package/esm/index.d.ts.map +0 -1
- package/esm/index.js +0 -17
- package/esm/index.js.map +0 -1
- package/esm/jubjub.d.ts +0 -12
- package/esm/jubjub.d.ts.map +0 -1
- package/esm/jubjub.js +0 -12
- package/esm/jubjub.js.map +0 -1
- package/esm/misc.d.ts +0 -19
- package/esm/misc.d.ts.map +0 -1
- package/esm/misc.js +0 -109
- package/esm/misc.js.map +0 -1
- package/esm/nist.d.ts +0 -21
- package/esm/nist.d.ts.map +0 -1
- package/esm/nist.js +0 -132
- package/esm/nist.js.map +0 -1
- package/esm/p256.d.ts +0 -16
- package/esm/p256.d.ts.map +0 -1
- package/esm/p256.js +0 -16
- package/esm/p256.js.map +0 -1
- package/esm/p384.d.ts +0 -16
- package/esm/p384.d.ts.map +0 -1
- package/esm/p384.js +0 -16
- package/esm/p384.js.map +0 -1
- package/esm/p521.d.ts +0 -16
- package/esm/p521.d.ts.map +0 -1
- package/esm/p521.js +0 -16
- package/esm/p521.js.map +0 -1
- package/esm/package.json +0 -4
- package/esm/pasta.d.ts +0 -10
- package/esm/pasta.d.ts.map +0 -1
- package/esm/pasta.js +0 -10
- package/esm/pasta.js.map +0 -1
- package/esm/secp256k1.d.ts +0 -89
- package/esm/secp256k1.d.ts.map +0 -1
- package/esm/secp256k1.js +0 -292
- package/esm/secp256k1.js.map +0 -1
- package/esm/utils.d.ts +0 -110
- package/esm/utils.d.ts.map +0 -1
- package/esm/utils.js +0 -322
- package/esm/utils.js.map +0 -1
- package/src/_shortw_utils.ts +0 -21
- package/src/abstract/utils.ts +0 -7
- package/src/jubjub.ts +0 -12
- package/src/p256.ts +0 -15
- package/src/p384.ts +0 -15
- package/src/p521.ts +0 -15
- package/src/package.json +0 -3
- package/src/pasta.ts +0 -9
|
@@ -9,13 +9,13 @@ import type { CHash } from '../utils.ts';
|
|
|
9
9
|
import {
|
|
10
10
|
_validateObject,
|
|
11
11
|
abytes,
|
|
12
|
+
asciiToBytes,
|
|
12
13
|
bytesToNumberBE,
|
|
13
14
|
concatBytes,
|
|
14
15
|
isBytes,
|
|
15
16
|
isHash,
|
|
16
|
-
utf8ToBytes,
|
|
17
17
|
} from '../utils.ts';
|
|
18
|
-
import type { AffinePoint,
|
|
18
|
+
import type { AffinePoint, PC_ANY, PC_F, PC_P } from './curve.ts';
|
|
19
19
|
import { FpInvertBatch, mod, type IField } from './modular.ts';
|
|
20
20
|
|
|
21
21
|
export type UnicodeOrBytes = string | Uint8Array;
|
|
@@ -40,8 +40,6 @@ export type H2CHashOpts = {
|
|
|
40
40
|
expand: 'xmd' | 'xof';
|
|
41
41
|
hash: CHash;
|
|
42
42
|
};
|
|
43
|
-
// todo: remove
|
|
44
|
-
export type Opts = H2COpts;
|
|
45
43
|
|
|
46
44
|
// Octet Stream to Integer. "spec" implementation of os2ip is 2.5x slower vs bytesToNumberBE.
|
|
47
45
|
const os2ip = bytesToNumberBE;
|
|
@@ -71,9 +69,12 @@ function anum(item: unknown): void {
|
|
|
71
69
|
if (!Number.isSafeInteger(item)) throw new Error('number expected');
|
|
72
70
|
}
|
|
73
71
|
|
|
72
|
+
// User can always use utf8 if they want, by passing Uint8Array.
|
|
73
|
+
// If string is passed, we treat it as ASCII: other formats are likely a mistake.
|
|
74
74
|
function normDST(DST: UnicodeOrBytes): Uint8Array {
|
|
75
|
-
if (!isBytes(DST) && typeof DST !== 'string')
|
|
76
|
-
|
|
75
|
+
if (!isBytes(DST) && typeof DST !== 'string')
|
|
76
|
+
throw new Error('DST must be Uint8Array or ascii string');
|
|
77
|
+
return typeof DST === 'string' ? asciiToBytes(DST) : DST;
|
|
77
78
|
}
|
|
78
79
|
|
|
79
80
|
/**
|
|
@@ -90,7 +91,7 @@ export function expand_message_xmd(
|
|
|
90
91
|
anum(lenInBytes);
|
|
91
92
|
DST = normDST(DST);
|
|
92
93
|
// https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3
|
|
93
|
-
if (DST.length > 255) DST = H(concatBytes(
|
|
94
|
+
if (DST.length > 255) DST = H(concatBytes(asciiToBytes('H2C-OVERSIZE-DST-'), DST));
|
|
94
95
|
const { outputLen: b_in_bytes, blockLen: r_in_bytes } = H;
|
|
95
96
|
const ell = Math.ceil(lenInBytes / b_in_bytes);
|
|
96
97
|
if (lenInBytes > 65535 || ell > 255) throw new Error('expand_message_xmd: invalid lenInBytes');
|
|
@@ -129,7 +130,7 @@ export function expand_message_xof(
|
|
|
129
130
|
// DST = H('H2C-OVERSIZE-DST-' || a_very_long_DST, Math.ceil((lenInBytes * k) / 8));
|
|
130
131
|
if (DST.length > 255) {
|
|
131
132
|
const dkLen = Math.ceil((2 * k) / 8);
|
|
132
|
-
DST = H.create({ dkLen }).update(
|
|
133
|
+
DST = H.create({ dkLen }).update(asciiToBytes('H2C-OVERSIZE-DST-')).update(DST).digest();
|
|
133
134
|
}
|
|
134
135
|
if (lenInBytes > 65535 || DST.length > 255)
|
|
135
136
|
throw new Error('expand_message_xof: invalid lenInBytes');
|
|
@@ -210,30 +211,16 @@ export function isogenyMap<T, F extends IField<T>>(field: F, map: XYRatio<T>): X
|
|
|
210
211
|
};
|
|
211
212
|
}
|
|
212
213
|
|
|
213
|
-
/** Point interface, which curves must implement to work correctly with the module. */
|
|
214
|
-
export interface H2CPoint<T> extends Group<H2CPoint<T>> {
|
|
215
|
-
add(rhs: H2CPoint<T>): H2CPoint<T>;
|
|
216
|
-
toAffine(iz?: bigint): AffinePoint<T>;
|
|
217
|
-
clearCofactor(): H2CPoint<T>;
|
|
218
|
-
assertValidity(): void;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
export interface H2CPointConstructor<T> extends GroupConstructor<H2CPoint<T>> {
|
|
222
|
-
fromAffine(ap: AffinePoint<T>): H2CPoint<T>;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
214
|
export type MapToCurve<T> = (scalar: bigint[]) => AffinePoint<T>;
|
|
226
215
|
|
|
227
216
|
// Separated from initialization opts, so users won't accidentally change per-curve parameters
|
|
228
217
|
// (changing DST is ok!)
|
|
229
218
|
export type htfBasicOpts = { DST: UnicodeOrBytes };
|
|
230
|
-
export type H2CMethod<
|
|
219
|
+
export type H2CMethod<P> = (msg: Uint8Array, options?: htfBasicOpts) => P;
|
|
231
220
|
// TODO: remove
|
|
232
|
-
export type
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
hashToCurve: H2CMethod<T>;
|
|
236
|
-
hashToScalar: (msg: Uint8Array, options: htfBasicOpts) => bigint;
|
|
221
|
+
export type H2CHasherBase<P> = {
|
|
222
|
+
hashToCurve: H2CMethod<P>;
|
|
223
|
+
hashToScalar: (msg: Uint8Array, options?: htfBasicOpts) => bigint;
|
|
237
224
|
};
|
|
238
225
|
/**
|
|
239
226
|
* RFC 9380 methods, with cofactor clearing. See https://www.rfc-editor.org/rfc/rfc9380#section-3.
|
|
@@ -242,44 +229,44 @@ export type H2CHasherBase<T> = {
|
|
|
242
229
|
* * encodeToCurve: `map(hash(input))`, encodes NON-UNIFORM bytes to curve (WITH hashing)
|
|
243
230
|
* * mapToCurve: `map(scalars)`, encodes NON-UNIFORM scalars to curve (NO hashing)
|
|
244
231
|
*/
|
|
245
|
-
export type H2CHasher<
|
|
246
|
-
|
|
247
|
-
|
|
232
|
+
export type H2CHasher<PC extends PC_ANY> = H2CHasherBase<PC_P<PC>> & {
|
|
233
|
+
Point: PC;
|
|
234
|
+
encodeToCurve: H2CMethod<PC_P<PC>>;
|
|
235
|
+
mapToCurve: MapToCurve<PC_F<PC>>;
|
|
248
236
|
defaults: H2COpts & { encodeDST?: UnicodeOrBytes };
|
|
249
237
|
};
|
|
250
|
-
// TODO: remove
|
|
251
|
-
export type Hasher<T> = H2CHasher<T>;
|
|
252
238
|
|
|
253
|
-
export const _DST_scalar: Uint8Array =
|
|
239
|
+
export const _DST_scalar: Uint8Array = asciiToBytes('HashToScalar-');
|
|
254
240
|
|
|
255
241
|
/** Creates hash-to-curve methods from EC Point and mapToCurve function. See {@link H2CHasher}. */
|
|
256
|
-
export function createHasher<
|
|
257
|
-
Point:
|
|
258
|
-
mapToCurve: MapToCurve<
|
|
242
|
+
export function createHasher<PC extends PC_ANY>(
|
|
243
|
+
Point: PC,
|
|
244
|
+
mapToCurve: MapToCurve<PC_F<PC>>,
|
|
259
245
|
defaults: H2COpts & { encodeDST?: UnicodeOrBytes }
|
|
260
|
-
): H2CHasher<
|
|
246
|
+
): H2CHasher<PC> {
|
|
261
247
|
if (typeof mapToCurve !== 'function') throw new Error('mapToCurve() must be defined');
|
|
262
|
-
function map(num: bigint[]) {
|
|
263
|
-
return Point.fromAffine(mapToCurve(num))
|
|
248
|
+
function map(num: bigint[]): PC_P<PC> {
|
|
249
|
+
return Point.fromAffine(mapToCurve(num)) as PC_P<PC>;
|
|
264
250
|
}
|
|
265
|
-
function clear(initial:
|
|
251
|
+
function clear(initial: PC_P<PC>): PC_P<PC> {
|
|
266
252
|
const P = initial.clearCofactor();
|
|
267
|
-
if (P.equals(Point.ZERO)) return Point.ZERO
|
|
253
|
+
if (P.equals(Point.ZERO)) return Point.ZERO as PC_P<PC>; // zero will throw in assert
|
|
268
254
|
P.assertValidity();
|
|
269
|
-
return P
|
|
255
|
+
return P as PC_P<PC>;
|
|
270
256
|
}
|
|
271
257
|
|
|
272
258
|
return {
|
|
273
259
|
defaults,
|
|
260
|
+
Point,
|
|
274
261
|
|
|
275
|
-
hashToCurve(msg: Uint8Array, options?: htfBasicOpts):
|
|
262
|
+
hashToCurve(msg: Uint8Array, options?: htfBasicOpts): PC_P<PC> {
|
|
276
263
|
const opts = Object.assign({}, defaults, options);
|
|
277
264
|
const u = hash_to_field(msg, 2, opts);
|
|
278
265
|
const u0 = map(u[0]);
|
|
279
266
|
const u1 = map(u[1]);
|
|
280
|
-
return clear(u0.add(u1));
|
|
267
|
+
return clear(u0.add(u1) as PC_P<PC>);
|
|
281
268
|
},
|
|
282
|
-
encodeToCurve(msg: Uint8Array, options?: htfBasicOpts):
|
|
269
|
+
encodeToCurve(msg: Uint8Array, options?: htfBasicOpts): PC_P<PC> {
|
|
283
270
|
const optsDst = defaults.encodeDST ? { DST: defaults.encodeDST } : {};
|
|
284
271
|
const opts = Object.assign({}, defaults, optsDst, options);
|
|
285
272
|
const u = hash_to_field(msg, 1, opts);
|
|
@@ -287,7 +274,7 @@ export function createHasher<T>(
|
|
|
287
274
|
return clear(u0);
|
|
288
275
|
},
|
|
289
276
|
/** See {@link H2CHasher} */
|
|
290
|
-
mapToCurve(scalars: bigint[]):
|
|
277
|
+
mapToCurve(scalars: bigint[]): PC_P<PC> {
|
|
291
278
|
if (!Array.isArray(scalars)) throw new Error('expected array of bigints');
|
|
292
279
|
for (const i of scalars)
|
|
293
280
|
if (typeof i !== 'bigint') throw new Error('expected array of bigints');
|
package/src/abstract/modular.ts
CHANGED
|
@@ -7,17 +7,16 @@
|
|
|
7
7
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
8
8
|
import {
|
|
9
9
|
_validateObject,
|
|
10
|
+
abytes,
|
|
10
11
|
anumber,
|
|
11
|
-
bitMask,
|
|
12
12
|
bytesToNumberBE,
|
|
13
13
|
bytesToNumberLE,
|
|
14
|
-
ensureBytes,
|
|
15
14
|
numberToBytesBE,
|
|
16
15
|
numberToBytesLE,
|
|
17
16
|
} from '../utils.ts';
|
|
18
17
|
|
|
19
18
|
// prettier-ignore
|
|
20
|
-
const _0n = BigInt(0), _1n = BigInt(1), _2n = /* @__PURE__ */ BigInt(2), _3n = /* @__PURE__ */ BigInt(3);
|
|
19
|
+
const _0n = BigInt(0), _1n = /* @__PURE__ */ BigInt(1), _2n = /* @__PURE__ */ BigInt(2), _3n = /* @__PURE__ */ BigInt(3);
|
|
21
20
|
// prettier-ignore
|
|
22
21
|
const _4n = /* @__PURE__ */ BigInt(4), _5n = /* @__PURE__ */ BigInt(5), _7n = /* @__PURE__ */ BigInt(7);
|
|
23
22
|
// prettier-ignore
|
|
@@ -227,10 +226,9 @@ export const isNegativeLE = (num: bigint, modulo: bigint): boolean =>
|
|
|
227
226
|
/** Field is not always over prime: for example, Fp2 has ORDER(q)=p^m. */
|
|
228
227
|
export interface IField<T> {
|
|
229
228
|
ORDER: bigint;
|
|
230
|
-
isLE: boolean;
|
|
231
229
|
BYTES: number;
|
|
232
230
|
BITS: number;
|
|
233
|
-
|
|
231
|
+
isLE: boolean;
|
|
234
232
|
ZERO: T;
|
|
235
233
|
ONE: T;
|
|
236
234
|
// 1-arg
|
|
@@ -260,7 +258,6 @@ export interface IField<T> {
|
|
|
260
258
|
// [RFC9380](https://www.rfc-editor.org/rfc/rfc9380#section-4.1).
|
|
261
259
|
// NOTE: sgn0 is 'negative in LE', which is same as odd. And negative in LE is kinda strange definition anyway.
|
|
262
260
|
isOdd?(num: T): boolean; // Odd instead of even since we have it for Fp2
|
|
263
|
-
allowedLengths?: number[];
|
|
264
261
|
// legendre?(num: T): T;
|
|
265
262
|
invertBatch: (lst: T[]) => T[];
|
|
266
263
|
toBytes(num: T): Uint8Array;
|
|
@@ -277,7 +274,6 @@ const FIELD_FIELDS = [
|
|
|
277
274
|
export function validateField<T>(field: IField<T>): IField<T> {
|
|
278
275
|
const initial = {
|
|
279
276
|
ORDER: 'bigint',
|
|
280
|
-
MASK: 'bigint',
|
|
281
277
|
BYTES: 'number',
|
|
282
278
|
BITS: 'number',
|
|
283
279
|
} as Record<string, string>;
|
|
@@ -381,12 +377,147 @@ export function nLength(n: bigint, nBitLength?: number): NLength {
|
|
|
381
377
|
type FpField = IField<bigint> & Required<Pick<IField<bigint>, 'isOdd'>>;
|
|
382
378
|
type SqrtFn = (n: bigint) => bigint;
|
|
383
379
|
type FieldOpts = Partial<{
|
|
384
|
-
sqrt: SqrtFn;
|
|
385
380
|
isLE: boolean;
|
|
386
381
|
BITS: number;
|
|
387
|
-
|
|
382
|
+
sqrt: SqrtFn;
|
|
388
383
|
allowedLengths?: readonly number[]; // for P521 (adds padding for smaller sizes)
|
|
384
|
+
modFromBytes: boolean; // bls12-381 requires mod(n) instead of rejecting keys >= n
|
|
389
385
|
}>;
|
|
386
|
+
class _Field implements IField<bigint> {
|
|
387
|
+
readonly ORDER: bigint;
|
|
388
|
+
readonly BITS: number;
|
|
389
|
+
readonly BYTES: number;
|
|
390
|
+
readonly isLE: boolean;
|
|
391
|
+
readonly ZERO = _0n;
|
|
392
|
+
readonly ONE = _1n;
|
|
393
|
+
readonly _lengths?: number[];
|
|
394
|
+
private _sqrt: ReturnType<typeof FpSqrt> | undefined; // cached sqrt
|
|
395
|
+
private readonly _mod?: boolean;
|
|
396
|
+
constructor(ORDER: bigint, opts: FieldOpts = {}) {
|
|
397
|
+
if (ORDER <= _0n) throw new Error('invalid field: expected ORDER > 0, got ' + ORDER);
|
|
398
|
+
let _nbitLength: number | undefined = undefined;
|
|
399
|
+
this.isLE = false;
|
|
400
|
+
if (opts != null && typeof opts === 'object') {
|
|
401
|
+
if (typeof opts.BITS === 'number') _nbitLength = opts.BITS;
|
|
402
|
+
if (typeof opts.sqrt === 'function') this.sqrt = opts.sqrt;
|
|
403
|
+
if (typeof opts.isLE === 'boolean') this.isLE = opts.isLE;
|
|
404
|
+
if (opts.allowedLengths) this._lengths = opts.allowedLengths?.slice();
|
|
405
|
+
if (typeof opts.modFromBytes === 'boolean') this._mod = opts.modFromBytes;
|
|
406
|
+
}
|
|
407
|
+
const { nBitLength, nByteLength } = nLength(ORDER, _nbitLength);
|
|
408
|
+
if (nByteLength > 2048) throw new Error('invalid field: expected ORDER of <= 2048 bytes');
|
|
409
|
+
this.ORDER = ORDER;
|
|
410
|
+
this.BITS = nBitLength;
|
|
411
|
+
this.BYTES = nByteLength;
|
|
412
|
+
this._sqrt = undefined;
|
|
413
|
+
Object.preventExtensions(this);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
create(num: bigint) {
|
|
417
|
+
return mod(num, this.ORDER);
|
|
418
|
+
}
|
|
419
|
+
isValid(num: bigint) {
|
|
420
|
+
if (typeof num !== 'bigint')
|
|
421
|
+
throw new Error('invalid field element: expected bigint, got ' + typeof num);
|
|
422
|
+
return _0n <= num && num < this.ORDER; // 0 is valid element, but it's not invertible
|
|
423
|
+
}
|
|
424
|
+
is0(num: bigint) {
|
|
425
|
+
return num === _0n;
|
|
426
|
+
}
|
|
427
|
+
// is valid and invertible
|
|
428
|
+
isValidNot0(num: bigint) {
|
|
429
|
+
return !this.is0(num) && this.isValid(num);
|
|
430
|
+
}
|
|
431
|
+
isOdd(num: bigint) {
|
|
432
|
+
return (num & _1n) === _1n;
|
|
433
|
+
}
|
|
434
|
+
neg(num: bigint) {
|
|
435
|
+
return mod(-num, this.ORDER);
|
|
436
|
+
}
|
|
437
|
+
eql(lhs: bigint, rhs: bigint) {
|
|
438
|
+
return lhs === rhs;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
sqr(num: bigint) {
|
|
442
|
+
return mod(num * num, this.ORDER);
|
|
443
|
+
}
|
|
444
|
+
add(lhs: bigint, rhs: bigint) {
|
|
445
|
+
return mod(lhs + rhs, this.ORDER);
|
|
446
|
+
}
|
|
447
|
+
sub(lhs: bigint, rhs: bigint) {
|
|
448
|
+
return mod(lhs - rhs, this.ORDER);
|
|
449
|
+
}
|
|
450
|
+
mul(lhs: bigint, rhs: bigint) {
|
|
451
|
+
return mod(lhs * rhs, this.ORDER);
|
|
452
|
+
}
|
|
453
|
+
pow(num: bigint, power: bigint): bigint {
|
|
454
|
+
return FpPow(this, num, power);
|
|
455
|
+
}
|
|
456
|
+
div(lhs: bigint, rhs: bigint) {
|
|
457
|
+
return mod(lhs * invert(rhs, this.ORDER), this.ORDER);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
// Same as above, but doesn't normalize
|
|
461
|
+
sqrN(num: bigint) {
|
|
462
|
+
return num * num;
|
|
463
|
+
}
|
|
464
|
+
addN(lhs: bigint, rhs: bigint) {
|
|
465
|
+
return lhs + rhs;
|
|
466
|
+
}
|
|
467
|
+
subN(lhs: bigint, rhs: bigint) {
|
|
468
|
+
return lhs - rhs;
|
|
469
|
+
}
|
|
470
|
+
mulN(lhs: bigint, rhs: bigint) {
|
|
471
|
+
return lhs * rhs;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
inv(num: bigint) {
|
|
475
|
+
return invert(num, this.ORDER);
|
|
476
|
+
}
|
|
477
|
+
sqrt(num: bigint): bigint {
|
|
478
|
+
// Caching _sqrt speeds up sqrt9mod16 by 5x and tonneli-shanks by 10%
|
|
479
|
+
if (!this._sqrt) this._sqrt = FpSqrt(this.ORDER);
|
|
480
|
+
return this._sqrt(this, num);
|
|
481
|
+
}
|
|
482
|
+
toBytes(num: bigint) {
|
|
483
|
+
return this.isLE ? numberToBytesLE(num, this.BYTES) : numberToBytesBE(num, this.BYTES);
|
|
484
|
+
}
|
|
485
|
+
fromBytes(bytes: Uint8Array, skipValidation = false) {
|
|
486
|
+
abytes(bytes);
|
|
487
|
+
const { _lengths: allowedLengths, BYTES, isLE, ORDER, _mod: modFromBytes } = this;
|
|
488
|
+
if (allowedLengths) {
|
|
489
|
+
if (!allowedLengths.includes(bytes.length) || bytes.length > BYTES) {
|
|
490
|
+
throw new Error(
|
|
491
|
+
'Field.fromBytes: expected ' + allowedLengths + ' bytes, got ' + bytes.length
|
|
492
|
+
);
|
|
493
|
+
}
|
|
494
|
+
const padded = new Uint8Array(BYTES);
|
|
495
|
+
// isLE add 0 to right, !isLE to the left.
|
|
496
|
+
padded.set(bytes, isLE ? 0 : padded.length - bytes.length);
|
|
497
|
+
bytes = padded;
|
|
498
|
+
}
|
|
499
|
+
if (bytes.length !== BYTES)
|
|
500
|
+
throw new Error('Field.fromBytes: expected ' + BYTES + ' bytes, got ' + bytes.length);
|
|
501
|
+
let scalar = isLE ? bytesToNumberLE(bytes) : bytesToNumberBE(bytes);
|
|
502
|
+
if (modFromBytes) scalar = mod(scalar, ORDER);
|
|
503
|
+
if (!skipValidation)
|
|
504
|
+
if (!this.isValid(scalar))
|
|
505
|
+
throw new Error('invalid field element: outside of range 0..ORDER');
|
|
506
|
+
// NOTE: we don't validate scalar here, please use isValid. This done such way because some
|
|
507
|
+
// protocol may allow non-reduced scalar that reduced later or changed some other way.
|
|
508
|
+
return scalar;
|
|
509
|
+
}
|
|
510
|
+
// TODO: we don't need it here, move out to separate fn
|
|
511
|
+
invertBatch(lst: bigint[]): bigint[] {
|
|
512
|
+
return FpInvertBatch(this, lst);
|
|
513
|
+
}
|
|
514
|
+
// We can't move this out because Fp6, Fp12 implement it
|
|
515
|
+
// and it's unclear what to return in there.
|
|
516
|
+
cmov(a: bigint, b: bigint, condition: boolean) {
|
|
517
|
+
return condition ? b : a;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
|
|
390
521
|
/**
|
|
391
522
|
* Creates a finite field. Major performance optimizations:
|
|
392
523
|
* * 1. Denormalized operations like mulN instead of mul.
|
|
@@ -406,104 +537,8 @@ type FieldOpts = Partial<{
|
|
|
406
537
|
* @param isLE (default: false) if encoding / decoding should be in little-endian
|
|
407
538
|
* @param redef optional faster redefinitions of sqrt and other methods
|
|
408
539
|
*/
|
|
409
|
-
export function Field(
|
|
410
|
-
ORDER
|
|
411
|
-
bitLenOrOpts?: number | FieldOpts, // TODO: use opts only in v2?
|
|
412
|
-
isLE = false,
|
|
413
|
-
opts: { sqrt?: SqrtFn } = {}
|
|
414
|
-
): Readonly<FpField> {
|
|
415
|
-
if (ORDER <= _0n) throw new Error('invalid field: expected ORDER > 0, got ' + ORDER);
|
|
416
|
-
let _nbitLength: number | undefined = undefined;
|
|
417
|
-
let _sqrt: SqrtFn | undefined = undefined;
|
|
418
|
-
let modFromBytes: boolean = false;
|
|
419
|
-
let allowedLengths: undefined | readonly number[] = undefined;
|
|
420
|
-
if (typeof bitLenOrOpts === 'object' && bitLenOrOpts != null) {
|
|
421
|
-
if (opts.sqrt || isLE) throw new Error('cannot specify opts in two arguments');
|
|
422
|
-
const _opts = bitLenOrOpts;
|
|
423
|
-
if (_opts.BITS) _nbitLength = _opts.BITS;
|
|
424
|
-
if (_opts.sqrt) _sqrt = _opts.sqrt;
|
|
425
|
-
if (typeof _opts.isLE === 'boolean') isLE = _opts.isLE;
|
|
426
|
-
if (typeof _opts.modFromBytes === 'boolean') modFromBytes = _opts.modFromBytes;
|
|
427
|
-
allowedLengths = _opts.allowedLengths;
|
|
428
|
-
} else {
|
|
429
|
-
if (typeof bitLenOrOpts === 'number') _nbitLength = bitLenOrOpts;
|
|
430
|
-
if (opts.sqrt) _sqrt = opts.sqrt;
|
|
431
|
-
}
|
|
432
|
-
const { nBitLength: BITS, nByteLength: BYTES } = nLength(ORDER, _nbitLength);
|
|
433
|
-
if (BYTES > 2048) throw new Error('invalid field: expected ORDER of <= 2048 bytes');
|
|
434
|
-
let sqrtP: ReturnType<typeof FpSqrt>; // cached sqrtP
|
|
435
|
-
const f: Readonly<FpField> = Object.freeze({
|
|
436
|
-
ORDER,
|
|
437
|
-
isLE,
|
|
438
|
-
BITS,
|
|
439
|
-
BYTES,
|
|
440
|
-
MASK: bitMask(BITS),
|
|
441
|
-
ZERO: _0n,
|
|
442
|
-
ONE: _1n,
|
|
443
|
-
allowedLengths: allowedLengths,
|
|
444
|
-
create: (num) => mod(num, ORDER),
|
|
445
|
-
isValid: (num) => {
|
|
446
|
-
if (typeof num !== 'bigint')
|
|
447
|
-
throw new Error('invalid field element: expected bigint, got ' + typeof num);
|
|
448
|
-
return _0n <= num && num < ORDER; // 0 is valid element, but it's not invertible
|
|
449
|
-
},
|
|
450
|
-
is0: (num) => num === _0n,
|
|
451
|
-
// is valid and invertible
|
|
452
|
-
isValidNot0: (num: bigint) => !f.is0(num) && f.isValid(num),
|
|
453
|
-
isOdd: (num) => (num & _1n) === _1n,
|
|
454
|
-
neg: (num) => mod(-num, ORDER),
|
|
455
|
-
eql: (lhs, rhs) => lhs === rhs,
|
|
456
|
-
|
|
457
|
-
sqr: (num) => mod(num * num, ORDER),
|
|
458
|
-
add: (lhs, rhs) => mod(lhs + rhs, ORDER),
|
|
459
|
-
sub: (lhs, rhs) => mod(lhs - rhs, ORDER),
|
|
460
|
-
mul: (lhs, rhs) => mod(lhs * rhs, ORDER),
|
|
461
|
-
pow: (num, power) => FpPow(f, num, power),
|
|
462
|
-
div: (lhs, rhs) => mod(lhs * invert(rhs, ORDER), ORDER),
|
|
463
|
-
|
|
464
|
-
// Same as above, but doesn't normalize
|
|
465
|
-
sqrN: (num) => num * num,
|
|
466
|
-
addN: (lhs, rhs) => lhs + rhs,
|
|
467
|
-
subN: (lhs, rhs) => lhs - rhs,
|
|
468
|
-
mulN: (lhs, rhs) => lhs * rhs,
|
|
469
|
-
|
|
470
|
-
inv: (num) => invert(num, ORDER),
|
|
471
|
-
sqrt:
|
|
472
|
-
_sqrt ||
|
|
473
|
-
((n) => {
|
|
474
|
-
if (!sqrtP) sqrtP = FpSqrt(ORDER);
|
|
475
|
-
return sqrtP(f, n);
|
|
476
|
-
}),
|
|
477
|
-
toBytes: (num) => (isLE ? numberToBytesLE(num, BYTES) : numberToBytesBE(num, BYTES)),
|
|
478
|
-
fromBytes: (bytes, skipValidation = true) => {
|
|
479
|
-
if (allowedLengths) {
|
|
480
|
-
if (!allowedLengths.includes(bytes.length) || bytes.length > BYTES) {
|
|
481
|
-
throw new Error(
|
|
482
|
-
'Field.fromBytes: expected ' + allowedLengths + ' bytes, got ' + bytes.length
|
|
483
|
-
);
|
|
484
|
-
}
|
|
485
|
-
const padded = new Uint8Array(BYTES);
|
|
486
|
-
// isLE add 0 to right, !isLE to the left.
|
|
487
|
-
padded.set(bytes, isLE ? 0 : padded.length - bytes.length);
|
|
488
|
-
bytes = padded;
|
|
489
|
-
}
|
|
490
|
-
if (bytes.length !== BYTES)
|
|
491
|
-
throw new Error('Field.fromBytes: expected ' + BYTES + ' bytes, got ' + bytes.length);
|
|
492
|
-
let scalar = isLE ? bytesToNumberLE(bytes) : bytesToNumberBE(bytes);
|
|
493
|
-
if (modFromBytes) scalar = mod(scalar, ORDER);
|
|
494
|
-
if (!skipValidation)
|
|
495
|
-
if (!f.isValid(scalar)) throw new Error('invalid field element: outside of range 0..ORDER');
|
|
496
|
-
// NOTE: we don't validate scalar here, please use isValid. This done such way because some
|
|
497
|
-
// protocol may allow non-reduced scalar that reduced later or changed some other way.
|
|
498
|
-
return scalar;
|
|
499
|
-
},
|
|
500
|
-
// TODO: we don't need it here, move out to separate fn
|
|
501
|
-
invertBatch: (lst) => FpInvertBatch(f, lst),
|
|
502
|
-
// We can't move this out because Fp6, Fp12 implement it
|
|
503
|
-
// and it's unclear what to return in there.
|
|
504
|
-
cmov: (a, b, c) => (c ? b : a),
|
|
505
|
-
} as FpField);
|
|
506
|
-
return Object.freeze(f);
|
|
540
|
+
export function Field(ORDER: bigint, opts: FieldOpts = {}): Readonly<FpField> {
|
|
541
|
+
return new _Field(ORDER, opts);
|
|
507
542
|
}
|
|
508
543
|
|
|
509
544
|
// Generic random scalar, we can do same for other fields if via Fp2.mul(Fp2.ONE, Fp2.random)?
|
|
@@ -532,28 +567,6 @@ export function FpSqrtEven<T>(Fp: IField<T>, elm: T): T {
|
|
|
532
567
|
return Fp.isOdd(root) ? Fp.neg(root) : root;
|
|
533
568
|
}
|
|
534
569
|
|
|
535
|
-
/**
|
|
536
|
-
* "Constant-time" private key generation utility.
|
|
537
|
-
* Same as mapKeyToField, but accepts less bytes (40 instead of 48 for 32-byte field).
|
|
538
|
-
* Which makes it slightly more biased, less secure.
|
|
539
|
-
* @deprecated use `mapKeyToField` instead
|
|
540
|
-
*/
|
|
541
|
-
export function hashToPrivateScalar(
|
|
542
|
-
hash: string | Uint8Array,
|
|
543
|
-
groupOrder: bigint,
|
|
544
|
-
isLE = false
|
|
545
|
-
): bigint {
|
|
546
|
-
hash = ensureBytes('privateHash', hash);
|
|
547
|
-
const hashLen = hash.length;
|
|
548
|
-
const minLen = nLength(groupOrder).nByteLength + 8;
|
|
549
|
-
if (minLen < 24 || hashLen < minLen || hashLen > 1024)
|
|
550
|
-
throw new Error(
|
|
551
|
-
'hashToPrivateScalar: expected ' + minLen + '-1024 bytes of input, got ' + hashLen
|
|
552
|
-
);
|
|
553
|
-
const num = isLE ? bytesToNumberLE(hash) : bytesToNumberBE(hash);
|
|
554
|
-
return mod(num, groupOrder - _1n) + _1n;
|
|
555
|
-
}
|
|
556
|
-
|
|
557
570
|
/**
|
|
558
571
|
* Returns total number of bytes consumed by the field element.
|
|
559
572
|
* For example, 32 bytes for usual 256-bit weierstrass curve.
|
|
@@ -587,11 +600,12 @@ export function getMinHashLength(fieldOrder: bigint): number {
|
|
|
587
600
|
* FIPS 186-5, A.2 https://csrc.nist.gov/publications/detail/fips/186/5/final
|
|
588
601
|
* RFC 9380, https://www.rfc-editor.org/rfc/rfc9380#section-5
|
|
589
602
|
* @param hash hash output from SHA3 or a similar function
|
|
590
|
-
* @param groupOrder size of subgroup - (e.g. secp256k1.
|
|
603
|
+
* @param groupOrder size of subgroup - (e.g. secp256k1.Point.Fn.ORDER)
|
|
591
604
|
* @param isLE interpret hash bytes as LE num
|
|
592
605
|
* @returns valid private scalar
|
|
593
606
|
*/
|
|
594
607
|
export function mapHashToField(key: Uint8Array, fieldOrder: bigint, isLE = false): Uint8Array {
|
|
608
|
+
abytes(key);
|
|
595
609
|
const len = key.length;
|
|
596
610
|
const fieldLen = getFieldBytesLength(fieldOrder);
|
|
597
611
|
const minLen = getMinHashLength(fieldOrder);
|
|
@@ -10,9 +10,10 @@ import {
|
|
|
10
10
|
abytes,
|
|
11
11
|
aInRange,
|
|
12
12
|
bytesToNumberLE,
|
|
13
|
-
|
|
13
|
+
copyBytes,
|
|
14
14
|
numberToBytesLE,
|
|
15
15
|
randomBytes,
|
|
16
|
+
type CryptoKeys,
|
|
16
17
|
} from '../utils.ts';
|
|
17
18
|
import type { CurveLengths } from './curve.ts';
|
|
18
19
|
import { mod } from './modular.ts';
|
|
@@ -20,7 +21,6 @@ import { mod } from './modular.ts';
|
|
|
20
21
|
const _0n = BigInt(0);
|
|
21
22
|
const _1n = BigInt(1);
|
|
22
23
|
const _2n = BigInt(2);
|
|
23
|
-
type Hex = string | Uint8Array;
|
|
24
24
|
|
|
25
25
|
export type CurveType = {
|
|
26
26
|
P: bigint; // finite field prime
|
|
@@ -31,20 +31,17 @@ export type CurveType = {
|
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
export type MontgomeryECDH = {
|
|
34
|
-
scalarMult: (scalar:
|
|
35
|
-
scalarMultBase: (scalar:
|
|
36
|
-
getSharedSecret: (secretKeyA:
|
|
37
|
-
getPublicKey: (secretKey:
|
|
34
|
+
scalarMult: (scalar: Uint8Array, u: Uint8Array) => Uint8Array;
|
|
35
|
+
scalarMultBase: (scalar: Uint8Array) => Uint8Array;
|
|
36
|
+
getSharedSecret: (secretKeyA: Uint8Array, publicKeyB: Uint8Array) => Uint8Array;
|
|
37
|
+
getPublicKey: (secretKey: Uint8Array) => Uint8Array;
|
|
38
38
|
utils: {
|
|
39
39
|
randomSecretKey: () => Uint8Array;
|
|
40
|
-
/** @deprecated use `randomSecretKey` */
|
|
41
|
-
randomPrivateKey: () => Uint8Array;
|
|
42
40
|
};
|
|
43
41
|
GuBytes: Uint8Array;
|
|
44
42
|
lengths: CurveLengths;
|
|
45
43
|
keygen: (seed?: Uint8Array) => { secretKey: Uint8Array; publicKey: Uint8Array };
|
|
46
44
|
};
|
|
47
|
-
export type CurveFn = MontgomeryECDH;
|
|
48
45
|
|
|
49
46
|
function validateOpts(curve: CurveType) {
|
|
50
47
|
_validateObject(curve, {
|
|
@@ -82,8 +79,8 @@ export function montgomery(curveDef: CurveType): MontgomeryECDH {
|
|
|
82
79
|
function encodeU(u: bigint): Uint8Array {
|
|
83
80
|
return numberToBytesLE(modP(u), fieldLen);
|
|
84
81
|
}
|
|
85
|
-
function decodeU(u:
|
|
86
|
-
const _u =
|
|
82
|
+
function decodeU(u: Uint8Array): bigint {
|
|
83
|
+
const _u = copyBytes(abytes(u, fieldLen, 'uCoordinate'));
|
|
87
84
|
// RFC: When receiving such an array, implementations of X25519
|
|
88
85
|
// (but not X448) MUST mask the most significant bit in the final byte.
|
|
89
86
|
if (is25519) _u[31] &= 127; // 0b0111_1111
|
|
@@ -93,10 +90,10 @@ export function montgomery(curveDef: CurveType): MontgomeryECDH {
|
|
|
93
90
|
// - 1 through 2^448 - 1 for X448.
|
|
94
91
|
return modP(bytesToNumberLE(_u));
|
|
95
92
|
}
|
|
96
|
-
function decodeScalar(scalar:
|
|
97
|
-
return bytesToNumberLE(adjustScalarBytes(
|
|
93
|
+
function decodeScalar(scalar: Uint8Array): bigint {
|
|
94
|
+
return bytesToNumberLE(adjustScalarBytes(copyBytes(abytes(scalar, fieldLen, 'scalar'))));
|
|
98
95
|
}
|
|
99
|
-
function scalarMult(scalar:
|
|
96
|
+
function scalarMult(scalar: Uint8Array, u: Uint8Array): Uint8Array {
|
|
100
97
|
const pu = montgomeryLadder(decodeU(u), decodeScalar(scalar));
|
|
101
98
|
// Some public keys are useless, of low-order. Curve author doesn't think
|
|
102
99
|
// it needs to be validated, but we do it nonetheless.
|
|
@@ -105,7 +102,7 @@ export function montgomery(curveDef: CurveType): MontgomeryECDH {
|
|
|
105
102
|
return encodeU(pu);
|
|
106
103
|
}
|
|
107
104
|
// Computes public key from private. By doing scalar multiplication of base point.
|
|
108
|
-
function scalarMultBase(scalar:
|
|
105
|
+
function scalarMultBase(scalar: Uint8Array): Uint8Array {
|
|
109
106
|
return scalarMult(scalar, GuBytes);
|
|
110
107
|
}
|
|
111
108
|
|
|
@@ -165,12 +162,12 @@ export function montgomery(curveDef: CurveType): MontgomeryECDH {
|
|
|
165
162
|
return modP(x_2 * z2); // Return x_2 * (z_2^(p - 2))
|
|
166
163
|
}
|
|
167
164
|
const lengths = {
|
|
168
|
-
|
|
169
|
-
|
|
165
|
+
secretKey: fieldLen,
|
|
166
|
+
publicKey: fieldLen,
|
|
170
167
|
seed: fieldLen,
|
|
171
168
|
};
|
|
172
169
|
const randomSecretKey = (seed = randomBytes_(fieldLen)) => {
|
|
173
|
-
abytes(seed, lengths.seed);
|
|
170
|
+
abytes(seed, lengths.seed, 'seed');
|
|
174
171
|
return seed;
|
|
175
172
|
};
|
|
176
173
|
function keygen(seed?: Uint8Array) {
|
|
@@ -181,14 +178,16 @@ export function montgomery(curveDef: CurveType): MontgomeryECDH {
|
|
|
181
178
|
randomSecretKey,
|
|
182
179
|
randomPrivateKey: randomSecretKey,
|
|
183
180
|
};
|
|
184
|
-
|
|
181
|
+
|
|
182
|
+
return Object.freeze({
|
|
185
183
|
keygen,
|
|
186
|
-
getSharedSecret: (secretKey:
|
|
187
|
-
|
|
184
|
+
getSharedSecret: (secretKey: Uint8Array, publicKey: Uint8Array) =>
|
|
185
|
+
scalarMult(secretKey, publicKey),
|
|
186
|
+
getPublicKey: (secretKey: Uint8Array): Uint8Array => scalarMultBase(secretKey),
|
|
188
187
|
scalarMult,
|
|
189
188
|
scalarMultBase,
|
|
190
189
|
utils,
|
|
191
190
|
GuBytes: GuBytes.slice(),
|
|
192
191
|
lengths,
|
|
193
|
-
};
|
|
192
|
+
}) satisfies CryptoKeys;
|
|
194
193
|
}
|