@noble/curves 0.1.0 → 0.2.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 +339 -20
- package/lib/edwards.d.ts +108 -0
- package/lib/edwards.js +554 -0
- package/lib/esm/edwards.js +550 -0
- package/lib/esm/group.js +107 -0
- package/lib/esm/modular.js +19 -1
- package/lib/esm/montgomery.js +189 -0
- package/lib/esm/utils.js +62 -5
- package/lib/esm/{shortw.js → weierstrass.js} +81 -159
- package/lib/group.d.ts +33 -0
- package/lib/group.js +111 -0
- package/lib/modular.d.ts +7 -1
- package/lib/modular.js +23 -3
- package/lib/montgomery.d.ts +20 -0
- package/lib/montgomery.js +191 -0
- package/lib/utils.d.ts +26 -2
- package/lib/utils.js +71 -7
- package/lib/{shortw.d.ts → weierstrass.d.ts} +22 -35
- package/lib/{shortw.js → weierstrass.js} +80 -158
- package/package.json +23 -11
|
@@ -1,33 +1,34 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
3
|
-
// Implementation of Short
|
|
3
|
+
// Implementation of Short Weierstrass curve. The formula is: y² = x³ + ax + b
|
|
4
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
5
|
exports.weierstrass = void 0;
|
|
6
6
|
// TODO: sync vs async naming
|
|
7
7
|
// TODO: default randomBytes
|
|
8
|
+
// Differences from @noble/secp256k1 1.7:
|
|
9
|
+
// 1. Different double() formula (but same addition)
|
|
10
|
+
// 2. Different sqrt() function
|
|
11
|
+
// 3. truncateHash() truncateOnly mode
|
|
12
|
+
// 4. DRBG supports outputLen bigger than outputLen of hmac
|
|
8
13
|
const mod = require("./modular.js");
|
|
9
14
|
const utils_js_1 = require("./utils.js");
|
|
15
|
+
const group_js_1 = require("./group.js");
|
|
10
16
|
// Should be separate from overrides, since overrides can use information about curve (for example nBits)
|
|
11
17
|
function validateOpts(curve) {
|
|
12
|
-
|
|
18
|
+
const opts = (0, utils_js_1.validateOpts)(curve);
|
|
19
|
+
if (typeof opts.hash !== 'function' || !Number.isSafeInteger(opts.hash.outputLen))
|
|
13
20
|
throw new Error('Invalid hash function');
|
|
14
|
-
if (typeof
|
|
21
|
+
if (typeof opts.hmac !== 'function')
|
|
15
22
|
throw new Error('Invalid hmac function');
|
|
16
|
-
if (typeof
|
|
23
|
+
if (typeof opts.randomBytes !== 'function')
|
|
17
24
|
throw new Error('Invalid randomBytes function');
|
|
18
|
-
for (const i of ['a', 'b'
|
|
19
|
-
if (typeof
|
|
20
|
-
throw new Error(`Invalid curve param ${i}=${
|
|
25
|
+
for (const i of ['a', 'b']) {
|
|
26
|
+
if (typeof opts[i] !== 'bigint')
|
|
27
|
+
throw new Error(`Invalid curve param ${i}=${opts[i]} (${typeof opts[i]})`);
|
|
21
28
|
}
|
|
22
|
-
|
|
23
|
-
if (curve[i] === undefined)
|
|
24
|
-
continue; // Optional
|
|
25
|
-
if (!Number.isSafeInteger(curve[i]))
|
|
26
|
-
throw new Error(`Invalid curve param ${i}=${curve[i]} (${typeof curve[i]})`);
|
|
27
|
-
}
|
|
28
|
-
const endo = curve.endo;
|
|
29
|
+
const endo = opts.endo;
|
|
29
30
|
if (endo) {
|
|
30
|
-
if (
|
|
31
|
+
if (opts.a !== _0n) {
|
|
31
32
|
throw new Error('Endomorphism can only be defined for Koblitz curves that have a=0');
|
|
32
33
|
}
|
|
33
34
|
if (typeof endo !== 'object' ||
|
|
@@ -36,10 +37,8 @@ function validateOpts(curve) {
|
|
|
36
37
|
throw new Error('Expected endomorphism with beta: bigint and splitScalar: function');
|
|
37
38
|
}
|
|
38
39
|
}
|
|
39
|
-
const nBitLength = curve.n.toString(2).length; // Bit size of CURVE.n
|
|
40
|
-
const nByteLength = Math.ceil(nBitLength / 8); // Byte size of CURVE.n
|
|
41
40
|
// Set defaults
|
|
42
|
-
return Object.freeze({ lowS: true,
|
|
41
|
+
return Object.freeze({ lowS: true, ...opts });
|
|
43
42
|
}
|
|
44
43
|
// TODO: convert bits to bytes aligned to 32 bits? (224 for example)
|
|
45
44
|
// DER encoding utilities
|
|
@@ -66,7 +65,7 @@ function parseDERInt(data) {
|
|
|
66
65
|
if (res[0] === 0x00 && res[1] <= 0x7f) {
|
|
67
66
|
throw new DERError('Invalid signature integer: trailing length');
|
|
68
67
|
}
|
|
69
|
-
return { data: (0, utils_js_1.
|
|
68
|
+
return { data: (0, utils_js_1.bytesToNumberBE)(res), left: data.subarray(len + 2) };
|
|
70
69
|
}
|
|
71
70
|
function parseDERSignature(data) {
|
|
72
71
|
if (data.length < 2 || data[0] != 0x30) {
|
|
@@ -104,8 +103,8 @@ class HmacDrbg {
|
|
|
104
103
|
if (typeof hmacFn !== 'function')
|
|
105
104
|
throw new Error('hmacFn must be a function');
|
|
106
105
|
// Step B, Step C: set hashLen to 8*ceil(hlen/8)
|
|
107
|
-
this.v = new Uint8Array(
|
|
108
|
-
this.k = new Uint8Array(
|
|
106
|
+
this.v = new Uint8Array(hashLen).fill(1);
|
|
107
|
+
this.k = new Uint8Array(hashLen).fill(0);
|
|
109
108
|
this.counter = 0;
|
|
110
109
|
}
|
|
111
110
|
hmacSync(...values) {
|
|
@@ -141,7 +140,10 @@ class HmacDrbg {
|
|
|
141
140
|
// Use only input from curveOpts!
|
|
142
141
|
function weierstrass(curveDef) {
|
|
143
142
|
const CURVE = validateOpts(curveDef);
|
|
143
|
+
const CURVE_ORDER = CURVE.n;
|
|
144
144
|
// Lengths
|
|
145
|
+
// All curves has same field / group length as for now, but it can be different for other curves
|
|
146
|
+
const groupLen = CURVE.nByteLength;
|
|
145
147
|
const fieldLen = CURVE.nByteLength; // 32 (length of one field element)
|
|
146
148
|
if (fieldLen > 2048)
|
|
147
149
|
throw new Error('Field lengths over 2048 are not supported');
|
|
@@ -191,15 +193,15 @@ function weierstrass(curveDef) {
|
|
|
191
193
|
num = BigInt(key);
|
|
192
194
|
}
|
|
193
195
|
else if (typeof key === 'string') {
|
|
194
|
-
key = key.padStart(2 *
|
|
195
|
-
if (key.length !== 2 *
|
|
196
|
-
throw new Error(`Expected ${
|
|
196
|
+
key = key.padStart(2 * groupLen, '0'); // Eth-like hexes
|
|
197
|
+
if (key.length !== 2 * groupLen)
|
|
198
|
+
throw new Error(`Expected ${groupLen} bytes of private key`);
|
|
197
199
|
num = (0, utils_js_1.hexToNumber)(key);
|
|
198
200
|
}
|
|
199
201
|
else if (key instanceof Uint8Array) {
|
|
200
|
-
if (key.length !==
|
|
201
|
-
throw new Error(`Expected ${
|
|
202
|
-
num = (0, utils_js_1.
|
|
202
|
+
if (key.length !== groupLen)
|
|
203
|
+
throw new Error(`Expected ${groupLen} bytes of private key`);
|
|
204
|
+
num = (0, utils_js_1.bytesToNumberBE)(key);
|
|
203
205
|
}
|
|
204
206
|
else {
|
|
205
207
|
throw new TypeError('Expected valid private key');
|
|
@@ -224,11 +226,11 @@ function weierstrass(curveDef) {
|
|
|
224
226
|
throw new Error(`Unknown type of public key: ${publicKey}`);
|
|
225
227
|
}
|
|
226
228
|
function isBiggerThanHalfOrder(number) {
|
|
227
|
-
const HALF =
|
|
229
|
+
const HALF = CURVE_ORDER >> _1n;
|
|
228
230
|
return number > HALF;
|
|
229
231
|
}
|
|
230
232
|
function normalizeS(s) {
|
|
231
|
-
return isBiggerThanHalfOrder(s) ? mod.mod(-s,
|
|
233
|
+
return isBiggerThanHalfOrder(s) ? mod.mod(-s, CURVE_ORDER) : s;
|
|
232
234
|
}
|
|
233
235
|
function normalizeScalar(num) {
|
|
234
236
|
if (typeof num === 'number' && Number.isSafeInteger(num) && num > 0)
|
|
@@ -243,7 +245,7 @@ function weierstrass(curveDef) {
|
|
|
243
245
|
const { n, nBitLength } = CURVE;
|
|
244
246
|
const byteLength = hash.length;
|
|
245
247
|
const delta = byteLength * 8 - nBitLength; // size of curve.n (252 bits)
|
|
246
|
-
let h = (0, utils_js_1.
|
|
248
|
+
let h = (0, utils_js_1.bytesToNumberBE)(hash);
|
|
247
249
|
if (delta > 0)
|
|
248
250
|
h = h >> BigInt(delta);
|
|
249
251
|
if (!truncateOnly && h >= n)
|
|
@@ -311,6 +313,22 @@ function weierstrass(curveDef) {
|
|
|
311
313
|
double() {
|
|
312
314
|
const { x: X1, y: Y1, z: Z1 } = this;
|
|
313
315
|
const { a } = CURVE;
|
|
316
|
+
// Faster algorithm: when a=0
|
|
317
|
+
// From: https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l
|
|
318
|
+
// Cost: 2M + 5S + 6add + 3*2 + 1*3 + 1*8.
|
|
319
|
+
if (a === _0n) {
|
|
320
|
+
const A = modP(X1 * X1);
|
|
321
|
+
const B = modP(Y1 * Y1);
|
|
322
|
+
const C = modP(B * B);
|
|
323
|
+
const x1b = X1 + B;
|
|
324
|
+
const D = modP(_2n * (modP(x1b * x1b) - A - C));
|
|
325
|
+
const E = modP(_3n * A);
|
|
326
|
+
const F = modP(E * E);
|
|
327
|
+
const X3 = modP(F - _2n * D);
|
|
328
|
+
const Y3 = modP(E * (D - X3) - _8n * C);
|
|
329
|
+
const Z3 = modP(_2n * Y1 * Z1);
|
|
330
|
+
return new JacobianPoint(X3, Y3, Z3);
|
|
331
|
+
}
|
|
314
332
|
const XX = modP(X1 * X1);
|
|
315
333
|
const YY = modP(Y1 * Y1);
|
|
316
334
|
const YYYY = modP(YY * YY);
|
|
@@ -332,9 +350,6 @@ function weierstrass(curveDef) {
|
|
|
332
350
|
add(other) {
|
|
333
351
|
if (!(other instanceof JacobianPoint))
|
|
334
352
|
throw new TypeError('JacobianPoint expected');
|
|
335
|
-
// TODO: remove
|
|
336
|
-
if (this.equals(JacobianPoint.ZERO))
|
|
337
|
-
return other;
|
|
338
353
|
const { x: X1, y: Y1, z: Z1 } = this;
|
|
339
354
|
const { x: X2, y: Y2, z: Z2 } = other;
|
|
340
355
|
if (X2 === _0n || Y2 === _0n)
|
|
@@ -377,17 +392,8 @@ function weierstrass(curveDef) {
|
|
|
377
392
|
let n = normalizeScalar(scalar);
|
|
378
393
|
if (n === _1n)
|
|
379
394
|
return this;
|
|
380
|
-
if (!CURVE.endo)
|
|
381
|
-
|
|
382
|
-
let d = this;
|
|
383
|
-
while (n > _0n) {
|
|
384
|
-
if (n & _1n)
|
|
385
|
-
p = p.add(d);
|
|
386
|
-
d = d.double();
|
|
387
|
-
n >>= _1n;
|
|
388
|
-
}
|
|
389
|
-
return p;
|
|
390
|
-
}
|
|
395
|
+
if (!CURVE.endo)
|
|
396
|
+
return wnaf.unsafeLadder(this, n);
|
|
391
397
|
// Apply endomorphism
|
|
392
398
|
let { k1neg, k1, k2neg, k2 } = CURVE.endo.splitScalar(n);
|
|
393
399
|
let k1p = P0;
|
|
@@ -409,99 +415,23 @@ function weierstrass(curveDef) {
|
|
|
409
415
|
k2p = new JacobianPoint(modP(k2p.x * CURVE.endo.beta), k2p.y, k2p.z);
|
|
410
416
|
return k1p.add(k2p);
|
|
411
417
|
}
|
|
412
|
-
/**
|
|
413
|
-
* Creates a wNAF precomputation window. Used for caching.
|
|
414
|
-
* Default window size is set by `utils.precompute()` and is equal to 8.
|
|
415
|
-
* Which means we are caching 65536 points: 256 points for every bit from 0 to 256.
|
|
416
|
-
* @returns 65K precomputed points, depending on W
|
|
417
|
-
*/
|
|
418
|
-
precomputeWindow(W) {
|
|
419
|
-
const windows = CURVE.endo
|
|
420
|
-
? Math.ceil(CURVE.nBitLength / 2) / W + 1
|
|
421
|
-
: CURVE.nBitLength / W + 1;
|
|
422
|
-
const points = [];
|
|
423
|
-
let p = this;
|
|
424
|
-
let base = p;
|
|
425
|
-
for (let window = 0; window < windows; window++) {
|
|
426
|
-
base = p;
|
|
427
|
-
points.push(base);
|
|
428
|
-
for (let i = 1; i < 2 ** (W - 1); i++) {
|
|
429
|
-
base = base.add(p);
|
|
430
|
-
points.push(base);
|
|
431
|
-
}
|
|
432
|
-
p = base.double();
|
|
433
|
-
}
|
|
434
|
-
return points;
|
|
435
|
-
}
|
|
436
418
|
/**
|
|
437
419
|
* Implements w-ary non-adjacent form for calculating ec multiplication.
|
|
438
|
-
* @param n
|
|
439
|
-
* @param affinePoint optional 2d point to save cached precompute windows on it.
|
|
440
|
-
* @returns real and fake (for const-time) points
|
|
441
420
|
*/
|
|
442
421
|
wNAF(n, affinePoint) {
|
|
443
422
|
if (!affinePoint && this.equals(JacobianPoint.BASE))
|
|
444
423
|
affinePoint = Point.BASE;
|
|
445
424
|
const W = (affinePoint && affinePoint._WINDOW_SIZE) || 1;
|
|
446
|
-
if (256 % W) {
|
|
447
|
-
throw new Error('Point#wNAF: Invalid precomputation window, must be power of 2');
|
|
448
|
-
}
|
|
449
425
|
// Calculate precomputes on a first run, reuse them after
|
|
450
426
|
let precomputes = affinePoint && pointPrecomputes.get(affinePoint);
|
|
451
427
|
if (!precomputes) {
|
|
452
|
-
precomputes =
|
|
428
|
+
precomputes = wnaf.precomputeWindow(this, W);
|
|
453
429
|
if (affinePoint && W !== 1) {
|
|
454
430
|
precomputes = JacobianPoint.normalizeZ(precomputes);
|
|
455
431
|
pointPrecomputes.set(affinePoint, precomputes);
|
|
456
432
|
}
|
|
457
433
|
}
|
|
458
|
-
|
|
459
|
-
let p = JacobianPoint.ZERO;
|
|
460
|
-
// Should be G (base) point, since otherwise f can be infinity point in the end
|
|
461
|
-
let f = JacobianPoint.BASE;
|
|
462
|
-
const nBits = CURVE.endo ? CURVE.nBitLength / 2 : CURVE.nBitLength;
|
|
463
|
-
const windows = 1 + Math.ceil(nBits / W); // W=8 17
|
|
464
|
-
const windowSize = 2 ** (W - 1); // W=8 128
|
|
465
|
-
const mask = BigInt(2 ** W - 1); // Create mask with W ones: 0b11111111 for W=8
|
|
466
|
-
const maxNumber = 2 ** W; // W=8 256
|
|
467
|
-
const shiftBy = BigInt(W); // W=8 8
|
|
468
|
-
for (let window = 0; window < windows; window++) {
|
|
469
|
-
const offset = window * windowSize;
|
|
470
|
-
// Extract W bits.
|
|
471
|
-
let wbits = Number(n & mask);
|
|
472
|
-
// Shift number by W bits.
|
|
473
|
-
n >>= shiftBy;
|
|
474
|
-
// If the bits are bigger than max size, we'll split those.
|
|
475
|
-
// +224 => 256 - 32
|
|
476
|
-
if (wbits > windowSize) {
|
|
477
|
-
wbits -= maxNumber;
|
|
478
|
-
n += _1n;
|
|
479
|
-
}
|
|
480
|
-
// This code was first written with assumption that 'f' and 'p' will never be infinity point:
|
|
481
|
-
// since each addition is multiplied by 2 ** W, it cannot cancel each other. However,
|
|
482
|
-
// there is negate now: it is possible that negated element from low value
|
|
483
|
-
// would be the same as high element, which will create carry into next window.
|
|
484
|
-
// It's not obvious how this can fail, but still worth investigating later.
|
|
485
|
-
// Check if we're onto Zero point.
|
|
486
|
-
// Add random point inside current window to f.
|
|
487
|
-
const offset1 = offset;
|
|
488
|
-
const offset2 = offset + Math.abs(wbits) - 1;
|
|
489
|
-
const cond1 = window % 2 !== 0;
|
|
490
|
-
const cond2 = wbits < 0;
|
|
491
|
-
if (wbits === 0) {
|
|
492
|
-
// The most important part for const-time getPublicKey
|
|
493
|
-
f = f.add(constTimeNegate(cond1, precomputes[offset1]));
|
|
494
|
-
}
|
|
495
|
-
else {
|
|
496
|
-
p = p.add(constTimeNegate(cond2, precomputes[offset2]));
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
// JIT-compiler should not eliminate f here, since it will later be used in normalizeZ()
|
|
500
|
-
// Even if the variable is still unused, there are some checks which will
|
|
501
|
-
// throw an exception, so compiler needs to prove they won't happen, which is hard.
|
|
502
|
-
// At this point there is a way to F be infinity-point even if p is not,
|
|
503
|
-
// which makes it less const-time: around 1 bigint multiply.
|
|
504
|
-
return { p, f };
|
|
434
|
+
return wnaf.wNAF(W, precomputes, n);
|
|
505
435
|
}
|
|
506
436
|
/**
|
|
507
437
|
* Constant time multiplication.
|
|
@@ -521,8 +451,8 @@ function weierstrass(curveDef) {
|
|
|
521
451
|
const { k1neg, k1, k2neg, k2 } = CURVE.endo.splitScalar(n);
|
|
522
452
|
let { p: k1p, f: f1p } = this.wNAF(k1, affinePoint);
|
|
523
453
|
let { p: k2p, f: f2p } = this.wNAF(k2, affinePoint);
|
|
524
|
-
k1p = constTimeNegate(k1neg, k1p);
|
|
525
|
-
k2p = constTimeNegate(k2neg, k2p);
|
|
454
|
+
k1p = wnaf.constTimeNegate(k1neg, k1p);
|
|
455
|
+
k2p = wnaf.constTimeNegate(k2neg, k2p);
|
|
526
456
|
k2p = new JacobianPoint(modP(k2p.x * CURVE.endo.beta), k2p.y, k2p.z);
|
|
527
457
|
point = k1p.add(k2p);
|
|
528
458
|
fake = f1p.add(f2p);
|
|
@@ -561,11 +491,7 @@ function weierstrass(curveDef) {
|
|
|
561
491
|
}
|
|
562
492
|
JacobianPoint.BASE = new JacobianPoint(CURVE.Gx, CURVE.Gy, _1n);
|
|
563
493
|
JacobianPoint.ZERO = new JacobianPoint(_0n, _1n, _0n);
|
|
564
|
-
|
|
565
|
-
function constTimeNegate(condition, item) {
|
|
566
|
-
const neg = item.negate();
|
|
567
|
-
return condition ? neg : item;
|
|
568
|
-
}
|
|
494
|
+
const wnaf = (0, group_js_1.wNAF)(JacobianPoint, CURVE.endo ? CURVE.nBitLength / 2 : CURVE.nBitLength);
|
|
569
495
|
// Stores precomputed values for points.
|
|
570
496
|
const pointPrecomputes = new WeakMap();
|
|
571
497
|
/**
|
|
@@ -586,13 +512,12 @@ function weierstrass(curveDef) {
|
|
|
586
512
|
return this.y % _2n === _0n;
|
|
587
513
|
}
|
|
588
514
|
/**
|
|
589
|
-
* Supports compressed ECDSA
|
|
590
|
-
* @param bytes 33 bytes
|
|
515
|
+
* Supports compressed ECDSA points
|
|
591
516
|
* @returns Point instance
|
|
592
517
|
*/
|
|
593
518
|
static fromCompressedHex(bytes) {
|
|
594
519
|
const P = CURVE.P;
|
|
595
|
-
const x = (0, utils_js_1.
|
|
520
|
+
const x = (0, utils_js_1.bytesToNumberBE)(bytes.subarray(1));
|
|
596
521
|
if (!isValidFieldElement(x))
|
|
597
522
|
throw new Error('Point is not on curve');
|
|
598
523
|
const y2 = weierstrassEquation(x); // y² = x³ + ax + b
|
|
@@ -607,15 +532,15 @@ function weierstrass(curveDef) {
|
|
|
607
532
|
return point;
|
|
608
533
|
}
|
|
609
534
|
static fromUncompressedHex(bytes) {
|
|
610
|
-
const x = (0, utils_js_1.
|
|
611
|
-
const y = (0, utils_js_1.
|
|
535
|
+
const x = (0, utils_js_1.bytesToNumberBE)(bytes.subarray(1, fieldLen + 1));
|
|
536
|
+
const y = (0, utils_js_1.bytesToNumberBE)(bytes.subarray(fieldLen + 1, 2 * fieldLen + 1));
|
|
612
537
|
const point = new Point(x, y);
|
|
613
538
|
point.assertValidity();
|
|
614
539
|
return point;
|
|
615
540
|
}
|
|
616
541
|
/**
|
|
617
542
|
* Converts hash string or Uint8Array to Point.
|
|
618
|
-
* @param hex
|
|
543
|
+
* @param hex short/long ECDSA hex
|
|
619
544
|
*/
|
|
620
545
|
static fromHex(hex) {
|
|
621
546
|
const bytes = (0, utils_js_1.ensureBytes)(hex);
|
|
@@ -647,7 +572,8 @@ function weierstrass(curveDef) {
|
|
|
647
572
|
}
|
|
648
573
|
// A point on curve is valid if it conforms to equation.
|
|
649
574
|
assertValidity() {
|
|
650
|
-
|
|
575
|
+
// Some 3rd-party test vectors require different wording between here & `fromCompressedHex`
|
|
576
|
+
const msg = 'Point is not on elliptic curve';
|
|
651
577
|
const { x, y } = this;
|
|
652
578
|
if (!isValidFieldElement(x) || !isValidFieldElement(y))
|
|
653
579
|
throw new Error(msg);
|
|
@@ -657,6 +583,8 @@ function weierstrass(curveDef) {
|
|
|
657
583
|
throw new Error(msg);
|
|
658
584
|
}
|
|
659
585
|
equals(other) {
|
|
586
|
+
if (!(other instanceof Point))
|
|
587
|
+
throw new TypeError('Point#equals: expected Point');
|
|
660
588
|
return this.x === other.x && this.y === other.y;
|
|
661
589
|
}
|
|
662
590
|
// Returns the same point with inverted `y`
|
|
@@ -784,7 +712,7 @@ function weierstrass(curveDef) {
|
|
|
784
712
|
}
|
|
785
713
|
normalizeS() {
|
|
786
714
|
return this.hasHighS()
|
|
787
|
-
? new Signature(this.r, mod.mod(-this.s,
|
|
715
|
+
? new Signature(this.r, mod.mod(-this.s, CURVE_ORDER), this.recovery)
|
|
788
716
|
: this;
|
|
789
717
|
}
|
|
790
718
|
// DER-encoded
|
|
@@ -822,26 +750,20 @@ function weierstrass(curveDef) {
|
|
|
822
750
|
}
|
|
823
751
|
},
|
|
824
752
|
_bigintToBytes: numToField,
|
|
753
|
+
_bigintToString: numToFieldStr,
|
|
825
754
|
_normalizePrivateKey: normalizePrivateKey,
|
|
755
|
+
_normalizePublicKey: normalizePublicKey,
|
|
756
|
+
_isWithinCurveOrder: isWithinCurveOrder,
|
|
757
|
+
_isValidFieldElement: isValidFieldElement,
|
|
758
|
+
_weierstrassEquation: weierstrassEquation,
|
|
826
759
|
/**
|
|
827
|
-
*
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
*
|
|
832
|
-
*
|
|
760
|
+
* Converts some bytes to a valid private key. Needs at least (nBitLength+64) bytes.
|
|
761
|
+
*/
|
|
762
|
+
hashToPrivateKey: (hash) => numToField((0, utils_js_1.hashToPrivateScalar)(hash, CURVE_ORDER)),
|
|
763
|
+
/**
|
|
764
|
+
* Produces cryptographically secure private key from random of size (nBitLength+64)
|
|
765
|
+
* as per FIPS 186 B.4.1 with modulo bias being neglible.
|
|
833
766
|
*/
|
|
834
|
-
hashToPrivateKey: (hash) => {
|
|
835
|
-
hash = (0, utils_js_1.ensureBytes)(hash);
|
|
836
|
-
const minLen = fieldLen + 8;
|
|
837
|
-
if (hash.length < minLen || hash.length > 1024) {
|
|
838
|
-
throw new Error(`Expected ${minLen}-1024 bytes of private key as per FIPS 186`);
|
|
839
|
-
}
|
|
840
|
-
const num = mod.mod((0, utils_js_1.bytesToNumber)(hash), CURVE.n - _1n) + _1n;
|
|
841
|
-
return numToField(num);
|
|
842
|
-
},
|
|
843
|
-
// Takes curve order + 64 bits from CSPRNG
|
|
844
|
-
// so that modulo bias is neglible, matches FIPS 186 B.4.1.
|
|
845
767
|
randomPrivateKey: () => utils.hashToPrivateKey(CURVE.randomBytes(fieldLen + 8)),
|
|
846
768
|
/**
|
|
847
769
|
* 1. Returns cached point which you can use to pass to `getSharedSecret` or `#multiply` by it.
|
|
@@ -860,8 +782,8 @@ function weierstrass(curveDef) {
|
|
|
860
782
|
};
|
|
861
783
|
/**
|
|
862
784
|
* Computes public key for a private key.
|
|
863
|
-
* @param privateKey
|
|
864
|
-
* @param isCompressed whether to return compact
|
|
785
|
+
* @param privateKey private key
|
|
786
|
+
* @param isCompressed whether to return compact, or full key
|
|
865
787
|
* @returns Public key, full by default; short when isCompressed=true
|
|
866
788
|
*/
|
|
867
789
|
function getPublicKey(privateKey, isCompressed = false) {
|
|
@@ -903,11 +825,11 @@ function weierstrass(curveDef) {
|
|
|
903
825
|
// RFC6979 methods
|
|
904
826
|
function bits2int(bytes) {
|
|
905
827
|
const slice = bytes.length > fieldLen ? bytes.slice(0, fieldLen) : bytes;
|
|
906
|
-
return (0, utils_js_1.
|
|
828
|
+
return (0, utils_js_1.bytesToNumberBE)(slice);
|
|
907
829
|
}
|
|
908
830
|
function bits2octets(bytes) {
|
|
909
831
|
const z1 = bits2int(bytes);
|
|
910
|
-
const z2 = mod.mod(z1,
|
|
832
|
+
const z2 = mod.mod(z1, CURVE_ORDER);
|
|
911
833
|
return int2octets(z2 < _0n ? z1 : z2);
|
|
912
834
|
}
|
|
913
835
|
function int2octets(num) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@noble/curves",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Minimal, zero-dependency JS implementation of elliptic curve cryptography",
|
|
5
5
|
"files": [
|
|
6
6
|
"index.js",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"lib/esm"
|
|
9
9
|
],
|
|
10
10
|
"scripts": {
|
|
11
|
-
"bench": "node
|
|
11
|
+
"bench": "node curve-definitions/benchmark/index.js",
|
|
12
12
|
"build": "tsc && tsc -p tsconfig.esm.json",
|
|
13
13
|
"build:release": "rollup -c rollup.config.js",
|
|
14
14
|
"lint": "prettier --check 'src/**/*.{js,ts}' 'curve-definitions/src/**/*.{js,ts}'",
|
|
@@ -32,15 +32,25 @@
|
|
|
32
32
|
},
|
|
33
33
|
"main": "index.js",
|
|
34
34
|
"exports": {
|
|
35
|
+
"./edwards": {
|
|
36
|
+
"types": "./lib/edwards.d.ts",
|
|
37
|
+
"import": "./lib/esm/edwards.js",
|
|
38
|
+
"default": "./lib/edwards.js"
|
|
39
|
+
},
|
|
35
40
|
"./modular": {
|
|
36
41
|
"types": "./lib/modular.d.ts",
|
|
37
42
|
"import": "./lib/esm/modular.js",
|
|
38
43
|
"default": "./lib/modular.js"
|
|
39
44
|
},
|
|
40
|
-
"./
|
|
41
|
-
"types": "./lib/
|
|
42
|
-
"import": "./lib/esm/
|
|
43
|
-
"default": "./lib/
|
|
45
|
+
"./montgomery": {
|
|
46
|
+
"types": "./lib/montgomery.d.ts",
|
|
47
|
+
"import": "./lib/esm/montgomery.js",
|
|
48
|
+
"default": "./lib/montgomery.js"
|
|
49
|
+
},
|
|
50
|
+
"./weierstrass": {
|
|
51
|
+
"types": "./lib/weierstrass.d.ts",
|
|
52
|
+
"import": "./lib/esm/weierstrass.js",
|
|
53
|
+
"default": "./lib/weierstrass.js"
|
|
44
54
|
},
|
|
45
55
|
"./utils": {
|
|
46
56
|
"types": "./lib/utils.d.ts",
|
|
@@ -53,14 +63,16 @@
|
|
|
53
63
|
"curve",
|
|
54
64
|
"cryptography",
|
|
55
65
|
"hyperelliptic",
|
|
66
|
+
"weierstrass",
|
|
67
|
+
"edwards",
|
|
68
|
+
"montgomery",
|
|
69
|
+
"secp256k1",
|
|
70
|
+
"ed25519",
|
|
71
|
+
"ed448",
|
|
56
72
|
"p256",
|
|
57
73
|
"p384",
|
|
58
74
|
"p521",
|
|
59
75
|
"nist",
|
|
60
|
-
"weierstrass",
|
|
61
|
-
"edwards",
|
|
62
|
-
"montgomery",
|
|
63
|
-
"hashes",
|
|
64
76
|
"ecc",
|
|
65
77
|
"ecdsa",
|
|
66
78
|
"eddsa",
|
|
@@ -72,4 +84,4 @@
|
|
|
72
84
|
"url": "https://paulmillr.com/funding/"
|
|
73
85
|
}
|
|
74
86
|
]
|
|
75
|
-
}
|
|
87
|
+
}
|