@noble/curves 0.6.0 → 0.6.2
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 +130 -92
- package/lib/_shortw_utils.d.ts +3 -3
- package/lib/abstract/curve.d.ts +3 -4
- package/lib/abstract/curve.js +13 -19
- package/lib/abstract/edwards.d.ts +5 -5
- package/lib/abstract/edwards.js +44 -26
- package/lib/abstract/hash-to-curve.js +1 -1
- package/lib/abstract/modular.d.ts +1 -1
- package/lib/abstract/modular.js +11 -13
- package/lib/abstract/montgomery.js +23 -65
- package/lib/abstract/utils.d.ts +17 -1
- package/lib/abstract/utils.js +57 -27
- package/lib/abstract/weierstrass.d.ts +10 -10
- package/lib/abstract/weierstrass.js +61 -79
- package/lib/esm/abstract/curve.js +11 -17
- package/lib/esm/abstract/edwards.js +46 -28
- package/lib/esm/abstract/hash-to-curve.js +1 -1
- package/lib/esm/abstract/modular.js +12 -14
- package/lib/esm/abstract/montgomery.js +24 -66
- package/lib/esm/abstract/poseidon.js +1 -1
- package/lib/esm/abstract/utils.js +55 -26
- package/lib/esm/abstract/weierstrass.js +62 -80
- package/lib/esm/p224.js +1 -1
- package/lib/esm/p521.js +1 -13
- package/lib/esm/secp256k1.js +34 -36
- package/lib/esm/stark.js +1 -1
- package/lib/p192.d.ts +6 -6
- package/lib/p224.d.ts +6 -6
- package/lib/p224.js +1 -1
- package/lib/p256.d.ts +6 -6
- package/lib/p384.d.ts +6 -6
- package/lib/p521.d.ts +16 -17
- package/lib/p521.js +1 -13
- package/lib/secp256k1.d.ts +17 -14
- package/lib/secp256k1.js +28 -30
- package/lib/stark.d.ts +3 -3
- package/lib/stark.js +1 -1
- package/package.json +4 -4
|
@@ -3,23 +3,24 @@
|
|
|
3
3
|
import * as mod from './modular.js';
|
|
4
4
|
import * as ut from './utils.js';
|
|
5
5
|
import { ensureBytes } from './utils.js';
|
|
6
|
-
import { wNAF,
|
|
6
|
+
import { wNAF, validateBasic } from './curve.js';
|
|
7
7
|
function validatePointOpts(curve) {
|
|
8
|
-
const opts =
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
8
|
+
const opts = validateBasic(curve);
|
|
9
|
+
ut.validateObject(opts, {
|
|
10
|
+
a: 'field',
|
|
11
|
+
b: 'field',
|
|
12
|
+
fromBytes: 'function',
|
|
13
|
+
toBytes: 'function',
|
|
14
|
+
}, {
|
|
15
|
+
allowedPrivateKeyLengths: 'array',
|
|
16
|
+
wrapPrivateKey: 'boolean',
|
|
17
|
+
isTorsionFree: 'function',
|
|
18
|
+
clearCofactor: 'function',
|
|
19
|
+
allowInfinityPoint: 'boolean',
|
|
20
|
+
});
|
|
21
|
+
const { endo, Fp, a } = opts;
|
|
21
22
|
if (endo) {
|
|
22
|
-
if (!Fp.eql(
|
|
23
|
+
if (!Fp.eql(a, Fp.ZERO)) {
|
|
23
24
|
throw new Error('Endomorphism can only be defined for Koblitz curves that have a=0');
|
|
24
25
|
}
|
|
25
26
|
if (typeof endo !== 'object' ||
|
|
@@ -28,11 +29,6 @@ function validatePointOpts(curve) {
|
|
|
28
29
|
throw new Error('Expected endomorphism with beta: bigint and splitScalar: function');
|
|
29
30
|
}
|
|
30
31
|
}
|
|
31
|
-
if (typeof opts.fromBytes !== 'function')
|
|
32
|
-
throw new Error('Invalid fromBytes function');
|
|
33
|
-
if (typeof opts.toBytes !== 'function')
|
|
34
|
-
throw new Error('Invalid fromBytes function');
|
|
35
|
-
// Set defaults
|
|
36
32
|
return Object.freeze({ ...opts });
|
|
37
33
|
}
|
|
38
34
|
// ASN.1 DER encoding utilities
|
|
@@ -113,39 +109,28 @@ export function weierstrassPoints(opts) {
|
|
|
113
109
|
if (!isWithinCurveOrder(num))
|
|
114
110
|
throw new Error('Expected valid bigint: 0 < bigint < curve.n');
|
|
115
111
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
* Supports two options, that are passed when CURVE is initialized:
|
|
119
|
-
* - `normalizePrivateKey()` executed before all checks
|
|
120
|
-
* - `wrapPrivateKey` when true, executed after most checks, but before `0 < key < n`
|
|
121
|
-
*/
|
|
112
|
+
// Validates if priv key is valid and converts it to bigint.
|
|
113
|
+
// Supports options CURVE.normalizePrivateKey and CURVE.wrapPrivateKey.
|
|
122
114
|
function normalizePrivateKey(key) {
|
|
123
|
-
const {
|
|
124
|
-
if (typeof
|
|
125
|
-
key
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
115
|
+
const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n } = CURVE;
|
|
116
|
+
if (lengths && typeof key !== 'bigint') {
|
|
117
|
+
if (key instanceof Uint8Array)
|
|
118
|
+
key = ut.bytesToHex(key);
|
|
119
|
+
// Normalize to hex string, pad. E.g. P521 would norm 130-132 char hex to 132-char bytes
|
|
120
|
+
if (typeof key !== 'string' || !lengths.includes(key.length))
|
|
121
|
+
throw new Error('Invalid key');
|
|
122
|
+
key = key.padStart(nByteLength * 2, '0');
|
|
130
123
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
// Validates individual octets
|
|
135
|
-
num = ut.bytesToNumberBE(ensureBytes(key));
|
|
136
|
-
}
|
|
137
|
-
else if (key instanceof Uint8Array) {
|
|
138
|
-
if (key.length !== groupLen)
|
|
139
|
-
throw new Error(`must be ${groupLen} bytes`);
|
|
140
|
-
num = ut.bytesToNumberBE(key);
|
|
124
|
+
let num;
|
|
125
|
+
try {
|
|
126
|
+
num = typeof key === 'bigint' ? key : ut.bytesToNumberBE(ensureBytes(key, nByteLength));
|
|
141
127
|
}
|
|
142
|
-
|
|
143
|
-
throw new Error(
|
|
128
|
+
catch (error) {
|
|
129
|
+
throw new Error(`private key must be ${nByteLength} bytes, hex or bigint, not ${typeof key}`);
|
|
144
130
|
}
|
|
145
|
-
// Useful for curves with cofactor != 1
|
|
146
131
|
if (wrapPrivateKey)
|
|
147
|
-
num = mod.mod(num, n);
|
|
148
|
-
assertGE(num);
|
|
132
|
+
num = mod.mod(num, n); // disabled by default, enabled for BLS
|
|
133
|
+
assertGE(num); // num in range [1..N-1]
|
|
149
134
|
return num;
|
|
150
135
|
}
|
|
151
136
|
const pointPrecomputes = new Map();
|
|
@@ -170,6 +155,8 @@ export function weierstrassPoints(opts) {
|
|
|
170
155
|
if (pz == null || !Fp.isValid(pz))
|
|
171
156
|
throw new Error('z required');
|
|
172
157
|
}
|
|
158
|
+
// Does not validate if the point is on-curve.
|
|
159
|
+
// Use fromHex instead, or call assertValidity() later.
|
|
173
160
|
static fromAffine(p) {
|
|
174
161
|
const { x, y } = p || {};
|
|
175
162
|
if (!p || !Fp.isValid(x) || !Fp.isValid(y))
|
|
@@ -499,14 +486,16 @@ export function weierstrassPoints(opts) {
|
|
|
499
486
|
};
|
|
500
487
|
}
|
|
501
488
|
function validateOpts(curve) {
|
|
502
|
-
const opts =
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
489
|
+
const opts = validateBasic(curve);
|
|
490
|
+
ut.validateObject(opts, {
|
|
491
|
+
hash: 'hash',
|
|
492
|
+
hmac: 'function',
|
|
493
|
+
randomBytes: 'function',
|
|
494
|
+
}, {
|
|
495
|
+
bits2int: 'function',
|
|
496
|
+
bits2int_modN: 'function',
|
|
497
|
+
lowS: 'boolean',
|
|
498
|
+
});
|
|
510
499
|
return Object.freeze({ lowS: true, ...opts });
|
|
511
500
|
}
|
|
512
501
|
const u8n = (data) => new Uint8Array(data); // creates Uint8Array
|
|
@@ -615,7 +604,7 @@ export function weierstrass(curveDef) {
|
|
|
615
604
|
return { x, y };
|
|
616
605
|
}
|
|
617
606
|
else {
|
|
618
|
-
throw new Error(`Point
|
|
607
|
+
throw new Error(`Point of length ${len} was invalid. Expected ${compressedLen} compressed bytes or ${uncompressedLen} uncompressed bytes`);
|
|
619
608
|
}
|
|
620
609
|
},
|
|
621
610
|
});
|
|
@@ -677,7 +666,7 @@ export function weierstrass(curveDef) {
|
|
|
677
666
|
const ir = invN(radj); // r^-1
|
|
678
667
|
const u1 = modN(-h * ir); // -hr^-1
|
|
679
668
|
const u2 = modN(s * ir); // sr^-1
|
|
680
|
-
const Q = Point.BASE.multiplyAndAddUnsafe(R, u1, u2); //
|
|
669
|
+
const Q = Point.BASE.multiplyAndAddUnsafe(R, u1, u2); // (sr^-1)R-(hr^-1)G = -(hr^-1)G + (sr^-1)
|
|
681
670
|
if (!Q)
|
|
682
671
|
throw new Error('point at infinify'); // unsafe is fine: no priv data leaked
|
|
683
672
|
Q.assertValidity();
|
|
@@ -800,9 +789,10 @@ export function weierstrass(curveDef) {
|
|
|
800
789
|
const ORDER_MASK = ut.bitMask(CURVE.nBitLength);
|
|
801
790
|
function int2octets(num) {
|
|
802
791
|
if (typeof num !== 'bigint')
|
|
803
|
-
throw new Error('
|
|
792
|
+
throw new Error('bigint expected');
|
|
804
793
|
if (!(_0n <= num && num < ORDER_MASK))
|
|
805
|
-
|
|
794
|
+
// n in [0..ORDER_MASK-1]
|
|
795
|
+
throw new Error(`bigint expected < 2^${CURVE.nBitLength}`);
|
|
806
796
|
// works with order, can have different size than numToField!
|
|
807
797
|
return ut.numberToBytesBE(num, CURVE.nByteLength);
|
|
808
798
|
}
|
|
@@ -812,6 +802,7 @@ export function weierstrass(curveDef) {
|
|
|
812
802
|
// NOTE: we cannot assume here that msgHash has same amount of bytes as curve order, this will be wrong at least for P521.
|
|
813
803
|
// Also it can be bigger for P224 + SHA256
|
|
814
804
|
function prepSig(msgHash, privateKey, opts = defaultSigOpts) {
|
|
805
|
+
const { hash, randomBytes } = CURVE;
|
|
815
806
|
if (msgHash == null)
|
|
816
807
|
throw new Error(`sign: expected valid message hash, not "${msgHash}"`);
|
|
817
808
|
if (['recovered', 'canonical'].some((k) => k in opts))
|
|
@@ -819,28 +810,20 @@ export function weierstrass(curveDef) {
|
|
|
819
810
|
throw new Error('sign() legacy options not supported');
|
|
820
811
|
let { lowS, prehash, extraEntropy: ent } = opts; // generates low-s sigs by default
|
|
821
812
|
if (prehash)
|
|
822
|
-
msgHash =
|
|
813
|
+
msgHash = hash(ensureBytes(msgHash));
|
|
823
814
|
if (lowS == null)
|
|
824
|
-
lowS = true; // RFC6979 3.2: we skip step A, because
|
|
825
|
-
//
|
|
826
|
-
//
|
|
827
|
-
//
|
|
828
|
-
// However, we cannot later call bits2octets (which is truncateHash + int2octets), since nested bits2int is broken
|
|
829
|
-
// for curves where nBitLength % 8 !== 0, so we unwrap it here as int2octets call.
|
|
830
|
-
// const bits2octets = (bits)=>int2octets(bytesToNumberBE(truncateHash(bits)))
|
|
815
|
+
lowS = true; // RFC6979 3.2: we skip step A, because we already provide hash
|
|
816
|
+
// We can't later call bits2octets, since nested bits2int is broken for curves
|
|
817
|
+
// with nBitLength % 8 !== 0. Because of that, we unwrap it here as int2octets call.
|
|
818
|
+
// const bits2octets = (bits) => int2octets(bits2int_modN(bits))
|
|
831
819
|
const h1int = bits2int_modN(ensureBytes(msgHash));
|
|
832
|
-
const
|
|
833
|
-
const
|
|
834
|
-
//
|
|
835
|
-
const seedArgs = [int2octets(d), h1octets];
|
|
820
|
+
const d = normalizePrivateKey(privateKey); // validate private key, convert to bigint
|
|
821
|
+
const seedArgs = [int2octets(d), int2octets(h1int)];
|
|
822
|
+
// extraEntropy. RFC6979 3.6: additional k' (optional).
|
|
836
823
|
if (ent != null) {
|
|
837
|
-
//
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
const e = ensureBytes(ent);
|
|
841
|
-
if (e.length !== Fp.BYTES)
|
|
842
|
-
throw new Error(`sign: Expected ${Fp.BYTES} bytes of extra data`);
|
|
843
|
-
seedArgs.push(e);
|
|
824
|
+
// K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k')
|
|
825
|
+
// Either pass as-is, or generate random bytes. Then validate for being ui8a of size BYTES
|
|
826
|
+
seedArgs.push(ensureBytes(ent === true ? randomBytes(Fp.BYTES) : ent, Fp.BYTES));
|
|
844
827
|
}
|
|
845
828
|
const seed = ut.concatBytes(...seedArgs); // Step D of RFC6979 3.2
|
|
846
829
|
const m = h1int; // NOTE: no need to call bits2int second time here, it is inside truncateHash!
|
|
@@ -950,7 +933,6 @@ export function weierstrass(curveDef) {
|
|
|
950
933
|
getSharedSecret,
|
|
951
934
|
sign,
|
|
952
935
|
verify,
|
|
953
|
-
// Point,
|
|
954
936
|
ProjectivePoint: Point,
|
|
955
937
|
Signature,
|
|
956
938
|
utils,
|
package/lib/esm/p224.js
CHANGED
|
@@ -8,7 +8,7 @@ export const P224 = createCurve({
|
|
|
8
8
|
// Params: a, b
|
|
9
9
|
a: BigInt('0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe'),
|
|
10
10
|
b: BigInt('0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4'),
|
|
11
|
-
// Field over which we'll do calculations;
|
|
11
|
+
// Field over which we'll do calculations;
|
|
12
12
|
Fp: Fp(BigInt('0xffffffffffffffffffffffffffffffff000000000000000000000001')),
|
|
13
13
|
// Curve order, total count of valid points in the field
|
|
14
14
|
n: BigInt('0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d'),
|
package/lib/esm/p521.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
2
2
|
import { createCurve } from './_shortw_utils.js';
|
|
3
3
|
import { sha512 } from '@noble/hashes/sha512';
|
|
4
|
-
import { bytesToHex } from './abstract/utils.js';
|
|
5
4
|
import { Fp as Field } from './abstract/modular.js';
|
|
6
5
|
import { mapToCurveSimpleSWU } from './abstract/weierstrass.js';
|
|
7
6
|
import * as htf from './abstract/hash-to-curve.js';
|
|
@@ -33,18 +32,7 @@ export const P521 = createCurve({
|
|
|
33
32
|
Gy: BigInt('0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650'),
|
|
34
33
|
h: BigInt(1),
|
|
35
34
|
lowS: false,
|
|
36
|
-
|
|
37
|
-
// Does not replace validation; invalid keys would still be rejected.
|
|
38
|
-
normalizePrivateKey(key) {
|
|
39
|
-
if (typeof key === 'bigint')
|
|
40
|
-
return key;
|
|
41
|
-
if (key instanceof Uint8Array)
|
|
42
|
-
key = bytesToHex(key);
|
|
43
|
-
if (typeof key !== 'string' || !([130, 131, 132].includes(key.length))) {
|
|
44
|
-
throw new Error('Invalid key');
|
|
45
|
-
}
|
|
46
|
-
return key.padStart(66 * 2, '0'); // ensure it's always 132 bytes
|
|
47
|
-
},
|
|
35
|
+
allowedPrivateKeyLengths: [130, 131, 132] // P521 keys are variable-length. Normalize to 132b
|
|
48
36
|
}, sha512);
|
|
49
37
|
export const secp521r1 = P521;
|
|
50
38
|
const { hashToCurve, encodeToCurve } = htf.hashToCurve(secp521r1.ProjectivePoint, (scalars) => mapSWU(scalars[0]), {
|
package/lib/esm/secp256k1.js
CHANGED
|
@@ -3,7 +3,7 @@ import { sha256 } from '@noble/hashes/sha256';
|
|
|
3
3
|
import { Fp as Field, mod, pow2 } from './abstract/modular.js';
|
|
4
4
|
import { createCurve } from './_shortw_utils.js';
|
|
5
5
|
import { mapToCurveSimpleSWU } from './abstract/weierstrass.js';
|
|
6
|
-
import { ensureBytes, concatBytes, bytesToNumberBE as
|
|
6
|
+
import { ensureBytes, concatBytes, bytesToNumberBE as bytesToInt, numberToBytesBE, } from './abstract/utils.js';
|
|
7
7
|
import { randomBytes } from '@noble/hashes/utils';
|
|
8
8
|
import * as htf from './abstract/hash-to-curve.js';
|
|
9
9
|
/**
|
|
@@ -112,20 +112,17 @@ function taggedHash(tag, ...messages) {
|
|
|
112
112
|
}
|
|
113
113
|
return sha256(concatBytes(tagP, ...messages));
|
|
114
114
|
}
|
|
115
|
-
const
|
|
115
|
+
const pointToBytes = (point) => point.toRawBytes(true).slice(1);
|
|
116
116
|
const numTo32b = (n) => numberToBytesBE(n, 32);
|
|
117
117
|
const modN = (x) => mod(x, secp256k1N);
|
|
118
|
-
const
|
|
119
|
-
const
|
|
120
|
-
const
|
|
121
|
-
function
|
|
122
|
-
|
|
123
|
-
//
|
|
124
|
-
//
|
|
125
|
-
|
|
126
|
-
const point = Gmul(priv);
|
|
127
|
-
const scalar = point.hasEvenY() ? priv : modN(-priv);
|
|
128
|
-
return { point, scalar, x: toRawX(point) };
|
|
118
|
+
const Point = secp256k1.ProjectivePoint;
|
|
119
|
+
const GmulAdd = (Q, a, b) => Point.BASE.multiplyAndAddUnsafe(Q, a, b);
|
|
120
|
+
const hex32ToInt = (key) => bytesToInt(ensureBytes(key, 32));
|
|
121
|
+
function schnorrGetExtPubKey(priv) {
|
|
122
|
+
let d = typeof priv === 'bigint' ? priv : hex32ToInt(priv);
|
|
123
|
+
const point = Point.fromPrivateKey(d); // P = d'⋅G; 0 < d' < n check is done inside
|
|
124
|
+
const scalar = point.hasEvenY() ? d : modN(-d); // d = d' if has_even_y(P), otherwise d = n-d'
|
|
125
|
+
return { point, scalar, bytes: pointToBytes(point) };
|
|
129
126
|
}
|
|
130
127
|
function lift_x(x) {
|
|
131
128
|
if (!fe(x))
|
|
@@ -134,37 +131,31 @@ function lift_x(x) {
|
|
|
134
131
|
let y = sqrtMod(c); // Let y = c^(p+1)/4 mod p.
|
|
135
132
|
if (y % 2n !== 0n)
|
|
136
133
|
y = mod(-y, secp256k1P); // Return the unique point P such that x(P) = x and
|
|
137
|
-
const p = new
|
|
134
|
+
const p = new Point(x, y, _1n); // y(P) = y if y mod 2 = 0 or y(P) = p-y otherwise.
|
|
138
135
|
p.assertValidity();
|
|
139
136
|
return p;
|
|
140
137
|
}
|
|
141
138
|
function challenge(...args) {
|
|
142
|
-
return modN(
|
|
139
|
+
return modN(bytesToInt(taggedHash(TAGS.challenge, ...args)));
|
|
143
140
|
}
|
|
141
|
+
// Schnorr's pubkey is just `x` of Point (BIP340)
|
|
144
142
|
function schnorrGetPublicKey(privateKey) {
|
|
145
|
-
return
|
|
143
|
+
return schnorrGetExtPubKey(privateKey).bytes; // d'=int(sk). Fail if d'=0 or d'≥n. Ret bytes(d'⋅G)
|
|
146
144
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
* producing an output.
|
|
150
|
-
* @param msg message (not message hash)
|
|
151
|
-
* @param privateKey private key
|
|
152
|
-
* @param auxRand random bytes that would be added to k. Bad RNG won't break it.
|
|
153
|
-
*/
|
|
145
|
+
// Creates Schnorr signature as per BIP340. Verifies itself before returning anything.
|
|
146
|
+
// auxRand is optional and is not the sole source of k generation: bad CSPRNG won't be dangerous
|
|
154
147
|
function schnorrSign(message, privateKey, auxRand = randomBytes(32)) {
|
|
155
148
|
if (message == null)
|
|
156
149
|
throw new Error(`sign: Expected valid message, not "${message}"`);
|
|
157
|
-
const m = ensureBytes(message);
|
|
158
|
-
|
|
159
|
-
const { x: px, scalar: d } = schnorrGetScalar(bytesToNum(ensureBytes(privateKey, 32)));
|
|
150
|
+
const m = ensureBytes(message); // checks for isWithinCurveOrder
|
|
151
|
+
const { bytes: px, scalar: d } = schnorrGetExtPubKey(privateKey);
|
|
160
152
|
const a = ensureBytes(auxRand, 32); // Auxiliary random data a: a 32-byte array
|
|
161
|
-
//
|
|
162
|
-
const t = numTo32b(d ^ bytesToNum(taggedHash(TAGS.aux, a))); // Let t be the byte-wise xor of bytes(d) and hash/aux(a)
|
|
153
|
+
const t = numTo32b(d ^ bytesToInt(taggedHash(TAGS.aux, a))); // Let t be the byte-wise xor of bytes(d) and hash/aux(a)
|
|
163
154
|
const rand = taggedHash(TAGS.nonce, t, px, m); // Let rand = hash/nonce(t || bytes(P) || m)
|
|
164
|
-
const k_ = modN(
|
|
155
|
+
const k_ = modN(bytesToInt(rand)); // Let k' = int(rand) mod n
|
|
165
156
|
if (k_ === _0n)
|
|
166
157
|
throw new Error('sign failed: k is zero'); // Fail if k' = 0.
|
|
167
|
-
const { point: R,
|
|
158
|
+
const { point: R, bytes: rx, scalar: k } = schnorrGetExtPubKey(k_); // Let R = k'⋅G.
|
|
168
159
|
const e = challenge(rx, px, m); // Let e = int(hash/challenge(bytes(R) || bytes(P) || m)) mod n.
|
|
169
160
|
const sig = new Uint8Array(64); // Let sig = bytes(R) || bytes((k + ed) mod n).
|
|
170
161
|
sig.set(numTo32b(R.px), 0);
|
|
@@ -179,16 +170,16 @@ function schnorrSign(message, privateKey, auxRand = randomBytes(32)) {
|
|
|
179
170
|
*/
|
|
180
171
|
function schnorrVerify(signature, message, publicKey) {
|
|
181
172
|
try {
|
|
182
|
-
const P = lift_x(
|
|
173
|
+
const P = lift_x(hex32ToInt(publicKey)); // P = lift_x(int(pk)); fail if that fails
|
|
183
174
|
const sig = ensureBytes(signature, 64);
|
|
184
|
-
const r =
|
|
175
|
+
const r = bytesToInt(sig.subarray(0, 32)); // Let r = int(sig[0:32]); fail if r ≥ p.
|
|
185
176
|
if (!fe(r))
|
|
186
177
|
return false;
|
|
187
|
-
const s =
|
|
178
|
+
const s = bytesToInt(sig.subarray(32, 64)); // Let s = int(sig[32:64]); fail if s ≥ n.
|
|
188
179
|
if (!ge(s))
|
|
189
180
|
return false;
|
|
190
181
|
const m = ensureBytes(message);
|
|
191
|
-
const e = challenge(numTo32b(r),
|
|
182
|
+
const e = challenge(numTo32b(r), pointToBytes(P), m); // int(challenge(bytes(r)||bytes(P)||m)) mod n
|
|
192
183
|
const R = GmulAdd(P, s, modN(-e)); // R = s⋅G - e⋅P
|
|
193
184
|
if (!R || !R.hasEvenY() || R.toAffine().x !== r)
|
|
194
185
|
return false; // -eP == (n-e)P
|
|
@@ -199,11 +190,18 @@ function schnorrVerify(signature, message, publicKey) {
|
|
|
199
190
|
}
|
|
200
191
|
}
|
|
201
192
|
export const schnorr = {
|
|
202
|
-
// Schnorr's pubkey is just `x` of Point (BIP340)
|
|
203
193
|
getPublicKey: schnorrGetPublicKey,
|
|
204
194
|
sign: schnorrSign,
|
|
205
195
|
verify: schnorrVerify,
|
|
206
|
-
utils: {
|
|
196
|
+
utils: {
|
|
197
|
+
getExtendedPublicKey: schnorrGetExtPubKey,
|
|
198
|
+
lift_x,
|
|
199
|
+
pointToBytes,
|
|
200
|
+
numberToBytesBE,
|
|
201
|
+
bytesToNumberBE: bytesToInt,
|
|
202
|
+
taggedHash,
|
|
203
|
+
mod,
|
|
204
|
+
},
|
|
207
205
|
};
|
|
208
206
|
const isoMap = htf.isogenyMap(Fp, [
|
|
209
207
|
// xNum
|
package/lib/esm/stark.js
CHANGED
|
@@ -95,7 +95,7 @@ function ensureBytes0x(hex) {
|
|
|
95
95
|
function normalizePrivateKey(privKey) {
|
|
96
96
|
return cutils.bytesToHex(ensureBytes0x(privKey)).padStart(64, '0');
|
|
97
97
|
}
|
|
98
|
-
function getPublicKey0x(privKey, isCompressed) {
|
|
98
|
+
function getPublicKey0x(privKey, isCompressed = false) {
|
|
99
99
|
return starkCurve.getPublicKey(normalizePrivateKey(privKey), isCompressed);
|
|
100
100
|
}
|
|
101
101
|
function getSharedSecret0x(privKeyA, pubKeyB) {
|
package/lib/p192.d.ts
CHANGED
|
@@ -9,11 +9,11 @@ export declare const P192: Readonly<{
|
|
|
9
9
|
readonly hEff?: bigint | undefined;
|
|
10
10
|
readonly Gx: bigint;
|
|
11
11
|
readonly Gy: bigint;
|
|
12
|
-
readonly wrapPrivateKey?: boolean | undefined;
|
|
13
12
|
readonly allowInfinityPoint?: boolean | undefined;
|
|
14
13
|
readonly a: bigint;
|
|
15
14
|
readonly b: bigint;
|
|
16
|
-
readonly
|
|
15
|
+
readonly allowedPrivateKeyLengths?: readonly number[] | undefined;
|
|
16
|
+
readonly wrapPrivateKey?: boolean | undefined;
|
|
17
17
|
readonly endo?: {
|
|
18
18
|
beta: bigint;
|
|
19
19
|
splitScalar: (k: bigint) => {
|
|
@@ -25,10 +25,10 @@ export declare const P192: Readonly<{
|
|
|
25
25
|
} | undefined;
|
|
26
26
|
readonly isTorsionFree?: ((c: import("./abstract/weierstrass.js").ProjConstructor<bigint>, point: import("./abstract/weierstrass.js").ProjPointType<bigint>) => boolean) | undefined;
|
|
27
27
|
readonly clearCofactor?: ((c: import("./abstract/weierstrass.js").ProjConstructor<bigint>, point: import("./abstract/weierstrass.js").ProjPointType<bigint>) => import("./abstract/weierstrass.js").ProjPointType<bigint>) | undefined;
|
|
28
|
-
lowS: boolean;
|
|
29
28
|
readonly hash: import("./abstract/utils.js").CHash;
|
|
30
29
|
readonly hmac: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array;
|
|
31
30
|
readonly randomBytes: (bytesLength?: number | undefined) => Uint8Array;
|
|
31
|
+
lowS: boolean;
|
|
32
32
|
readonly bits2int?: ((bytes: Uint8Array) => bigint) | undefined;
|
|
33
33
|
readonly bits2int_modN?: ((bytes: Uint8Array) => bigint) | undefined;
|
|
34
34
|
}>;
|
|
@@ -59,11 +59,11 @@ export declare const secp192r1: Readonly<{
|
|
|
59
59
|
readonly hEff?: bigint | undefined;
|
|
60
60
|
readonly Gx: bigint;
|
|
61
61
|
readonly Gy: bigint;
|
|
62
|
-
readonly wrapPrivateKey?: boolean | undefined;
|
|
63
62
|
readonly allowInfinityPoint?: boolean | undefined;
|
|
64
63
|
readonly a: bigint;
|
|
65
64
|
readonly b: bigint;
|
|
66
|
-
readonly
|
|
65
|
+
readonly allowedPrivateKeyLengths?: readonly number[] | undefined;
|
|
66
|
+
readonly wrapPrivateKey?: boolean | undefined;
|
|
67
67
|
readonly endo?: {
|
|
68
68
|
beta: bigint;
|
|
69
69
|
splitScalar: (k: bigint) => {
|
|
@@ -75,10 +75,10 @@ export declare const secp192r1: Readonly<{
|
|
|
75
75
|
} | undefined;
|
|
76
76
|
readonly isTorsionFree?: ((c: import("./abstract/weierstrass.js").ProjConstructor<bigint>, point: import("./abstract/weierstrass.js").ProjPointType<bigint>) => boolean) | undefined;
|
|
77
77
|
readonly clearCofactor?: ((c: import("./abstract/weierstrass.js").ProjConstructor<bigint>, point: import("./abstract/weierstrass.js").ProjPointType<bigint>) => import("./abstract/weierstrass.js").ProjPointType<bigint>) | undefined;
|
|
78
|
-
lowS: boolean;
|
|
79
78
|
readonly hash: import("./abstract/utils.js").CHash;
|
|
80
79
|
readonly hmac: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array;
|
|
81
80
|
readonly randomBytes: (bytesLength?: number | undefined) => Uint8Array;
|
|
81
|
+
lowS: boolean;
|
|
82
82
|
readonly bits2int?: ((bytes: Uint8Array) => bigint) | undefined;
|
|
83
83
|
readonly bits2int_modN?: ((bytes: Uint8Array) => bigint) | undefined;
|
|
84
84
|
}>;
|
package/lib/p224.d.ts
CHANGED
|
@@ -9,11 +9,11 @@ export declare const P224: Readonly<{
|
|
|
9
9
|
readonly hEff?: bigint | undefined;
|
|
10
10
|
readonly Gx: bigint;
|
|
11
11
|
readonly Gy: bigint;
|
|
12
|
-
readonly wrapPrivateKey?: boolean | undefined;
|
|
13
12
|
readonly allowInfinityPoint?: boolean | undefined;
|
|
14
13
|
readonly a: bigint;
|
|
15
14
|
readonly b: bigint;
|
|
16
|
-
readonly
|
|
15
|
+
readonly allowedPrivateKeyLengths?: readonly number[] | undefined;
|
|
16
|
+
readonly wrapPrivateKey?: boolean | undefined;
|
|
17
17
|
readonly endo?: {
|
|
18
18
|
beta: bigint;
|
|
19
19
|
splitScalar: (k: bigint) => {
|
|
@@ -25,10 +25,10 @@ export declare const P224: Readonly<{
|
|
|
25
25
|
} | undefined;
|
|
26
26
|
readonly isTorsionFree?: ((c: import("./abstract/weierstrass.js").ProjConstructor<bigint>, point: import("./abstract/weierstrass.js").ProjPointType<bigint>) => boolean) | undefined;
|
|
27
27
|
readonly clearCofactor?: ((c: import("./abstract/weierstrass.js").ProjConstructor<bigint>, point: import("./abstract/weierstrass.js").ProjPointType<bigint>) => import("./abstract/weierstrass.js").ProjPointType<bigint>) | undefined;
|
|
28
|
-
lowS: boolean;
|
|
29
28
|
readonly hash: import("./abstract/utils.js").CHash;
|
|
30
29
|
readonly hmac: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array;
|
|
31
30
|
readonly randomBytes: (bytesLength?: number | undefined) => Uint8Array;
|
|
31
|
+
lowS: boolean;
|
|
32
32
|
readonly bits2int?: ((bytes: Uint8Array) => bigint) | undefined;
|
|
33
33
|
readonly bits2int_modN?: ((bytes: Uint8Array) => bigint) | undefined;
|
|
34
34
|
}>;
|
|
@@ -59,11 +59,11 @@ export declare const secp224r1: Readonly<{
|
|
|
59
59
|
readonly hEff?: bigint | undefined;
|
|
60
60
|
readonly Gx: bigint;
|
|
61
61
|
readonly Gy: bigint;
|
|
62
|
-
readonly wrapPrivateKey?: boolean | undefined;
|
|
63
62
|
readonly allowInfinityPoint?: boolean | undefined;
|
|
64
63
|
readonly a: bigint;
|
|
65
64
|
readonly b: bigint;
|
|
66
|
-
readonly
|
|
65
|
+
readonly allowedPrivateKeyLengths?: readonly number[] | undefined;
|
|
66
|
+
readonly wrapPrivateKey?: boolean | undefined;
|
|
67
67
|
readonly endo?: {
|
|
68
68
|
beta: bigint;
|
|
69
69
|
splitScalar: (k: bigint) => {
|
|
@@ -75,10 +75,10 @@ export declare const secp224r1: Readonly<{
|
|
|
75
75
|
} | undefined;
|
|
76
76
|
readonly isTorsionFree?: ((c: import("./abstract/weierstrass.js").ProjConstructor<bigint>, point: import("./abstract/weierstrass.js").ProjPointType<bigint>) => boolean) | undefined;
|
|
77
77
|
readonly clearCofactor?: ((c: import("./abstract/weierstrass.js").ProjConstructor<bigint>, point: import("./abstract/weierstrass.js").ProjPointType<bigint>) => import("./abstract/weierstrass.js").ProjPointType<bigint>) | undefined;
|
|
78
|
-
lowS: boolean;
|
|
79
78
|
readonly hash: import("./abstract/utils.js").CHash;
|
|
80
79
|
readonly hmac: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array;
|
|
81
80
|
readonly randomBytes: (bytesLength?: number | undefined) => Uint8Array;
|
|
81
|
+
lowS: boolean;
|
|
82
82
|
readonly bits2int?: ((bytes: Uint8Array) => bigint) | undefined;
|
|
83
83
|
readonly bits2int_modN?: ((bytes: Uint8Array) => bigint) | undefined;
|
|
84
84
|
}>;
|
package/lib/p224.js
CHANGED
|
@@ -11,7 +11,7 @@ exports.P224 = (0, _shortw_utils_js_1.createCurve)({
|
|
|
11
11
|
// Params: a, b
|
|
12
12
|
a: BigInt('0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe'),
|
|
13
13
|
b: BigInt('0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4'),
|
|
14
|
-
// Field over which we'll do calculations;
|
|
14
|
+
// Field over which we'll do calculations;
|
|
15
15
|
Fp: (0, modular_js_1.Fp)(BigInt('0xffffffffffffffffffffffffffffffff000000000000000000000001')),
|
|
16
16
|
// Curve order, total count of valid points in the field
|
|
17
17
|
n: BigInt('0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d'),
|
package/lib/p256.d.ts
CHANGED
|
@@ -10,11 +10,11 @@ export declare const P256: Readonly<{
|
|
|
10
10
|
readonly hEff?: bigint | undefined;
|
|
11
11
|
readonly Gx: bigint;
|
|
12
12
|
readonly Gy: bigint;
|
|
13
|
-
readonly wrapPrivateKey?: boolean | undefined;
|
|
14
13
|
readonly allowInfinityPoint?: boolean | undefined;
|
|
15
14
|
readonly a: bigint;
|
|
16
15
|
readonly b: bigint;
|
|
17
|
-
readonly
|
|
16
|
+
readonly allowedPrivateKeyLengths?: readonly number[] | undefined;
|
|
17
|
+
readonly wrapPrivateKey?: boolean | undefined;
|
|
18
18
|
readonly endo?: {
|
|
19
19
|
beta: bigint;
|
|
20
20
|
splitScalar: (k: bigint) => {
|
|
@@ -26,10 +26,10 @@ export declare const P256: Readonly<{
|
|
|
26
26
|
} | undefined;
|
|
27
27
|
readonly isTorsionFree?: ((c: import("./abstract/weierstrass.js").ProjConstructor<bigint>, point: import("./abstract/weierstrass.js").ProjPointType<bigint>) => boolean) | undefined;
|
|
28
28
|
readonly clearCofactor?: ((c: import("./abstract/weierstrass.js").ProjConstructor<bigint>, point: import("./abstract/weierstrass.js").ProjPointType<bigint>) => import("./abstract/weierstrass.js").ProjPointType<bigint>) | undefined;
|
|
29
|
-
lowS: boolean;
|
|
30
29
|
readonly hash: import("./abstract/utils.js").CHash;
|
|
31
30
|
readonly hmac: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array;
|
|
32
31
|
readonly randomBytes: (bytesLength?: number | undefined) => Uint8Array;
|
|
32
|
+
lowS: boolean;
|
|
33
33
|
readonly bits2int?: ((bytes: Uint8Array) => bigint) | undefined;
|
|
34
34
|
readonly bits2int_modN?: ((bytes: Uint8Array) => bigint) | undefined;
|
|
35
35
|
}>;
|
|
@@ -60,11 +60,11 @@ export declare const secp256r1: Readonly<{
|
|
|
60
60
|
readonly hEff?: bigint | undefined;
|
|
61
61
|
readonly Gx: bigint;
|
|
62
62
|
readonly Gy: bigint;
|
|
63
|
-
readonly wrapPrivateKey?: boolean | undefined;
|
|
64
63
|
readonly allowInfinityPoint?: boolean | undefined;
|
|
65
64
|
readonly a: bigint;
|
|
66
65
|
readonly b: bigint;
|
|
67
|
-
readonly
|
|
66
|
+
readonly allowedPrivateKeyLengths?: readonly number[] | undefined;
|
|
67
|
+
readonly wrapPrivateKey?: boolean | undefined;
|
|
68
68
|
readonly endo?: {
|
|
69
69
|
beta: bigint;
|
|
70
70
|
splitScalar: (k: bigint) => {
|
|
@@ -76,10 +76,10 @@ export declare const secp256r1: Readonly<{
|
|
|
76
76
|
} | undefined;
|
|
77
77
|
readonly isTorsionFree?: ((c: import("./abstract/weierstrass.js").ProjConstructor<bigint>, point: import("./abstract/weierstrass.js").ProjPointType<bigint>) => boolean) | undefined;
|
|
78
78
|
readonly clearCofactor?: ((c: import("./abstract/weierstrass.js").ProjConstructor<bigint>, point: import("./abstract/weierstrass.js").ProjPointType<bigint>) => import("./abstract/weierstrass.js").ProjPointType<bigint>) | undefined;
|
|
79
|
-
lowS: boolean;
|
|
80
79
|
readonly hash: import("./abstract/utils.js").CHash;
|
|
81
80
|
readonly hmac: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array;
|
|
82
81
|
readonly randomBytes: (bytesLength?: number | undefined) => Uint8Array;
|
|
82
|
+
lowS: boolean;
|
|
83
83
|
readonly bits2int?: ((bytes: Uint8Array) => bigint) | undefined;
|
|
84
84
|
readonly bits2int_modN?: ((bytes: Uint8Array) => bigint) | undefined;
|
|
85
85
|
}>;
|
package/lib/p384.d.ts
CHANGED
|
@@ -10,11 +10,11 @@ export declare const P384: Readonly<{
|
|
|
10
10
|
readonly hEff?: bigint | undefined;
|
|
11
11
|
readonly Gx: bigint;
|
|
12
12
|
readonly Gy: bigint;
|
|
13
|
-
readonly wrapPrivateKey?: boolean | undefined;
|
|
14
13
|
readonly allowInfinityPoint?: boolean | undefined;
|
|
15
14
|
readonly a: bigint;
|
|
16
15
|
readonly b: bigint;
|
|
17
|
-
readonly
|
|
16
|
+
readonly allowedPrivateKeyLengths?: readonly number[] | undefined;
|
|
17
|
+
readonly wrapPrivateKey?: boolean | undefined;
|
|
18
18
|
readonly endo?: {
|
|
19
19
|
beta: bigint;
|
|
20
20
|
splitScalar: (k: bigint) => {
|
|
@@ -26,10 +26,10 @@ export declare const P384: Readonly<{
|
|
|
26
26
|
} | undefined;
|
|
27
27
|
readonly isTorsionFree?: ((c: import("./abstract/weierstrass.js").ProjConstructor<bigint>, point: import("./abstract/weierstrass.js").ProjPointType<bigint>) => boolean) | undefined;
|
|
28
28
|
readonly clearCofactor?: ((c: import("./abstract/weierstrass.js").ProjConstructor<bigint>, point: import("./abstract/weierstrass.js").ProjPointType<bigint>) => import("./abstract/weierstrass.js").ProjPointType<bigint>) | undefined;
|
|
29
|
-
lowS: boolean;
|
|
30
29
|
readonly hash: import("./abstract/utils.js").CHash;
|
|
31
30
|
readonly hmac: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array;
|
|
32
31
|
readonly randomBytes: (bytesLength?: number | undefined) => Uint8Array;
|
|
32
|
+
lowS: boolean;
|
|
33
33
|
readonly bits2int?: ((bytes: Uint8Array) => bigint) | undefined;
|
|
34
34
|
readonly bits2int_modN?: ((bytes: Uint8Array) => bigint) | undefined;
|
|
35
35
|
}>;
|
|
@@ -60,11 +60,11 @@ export declare const secp384r1: Readonly<{
|
|
|
60
60
|
readonly hEff?: bigint | undefined;
|
|
61
61
|
readonly Gx: bigint;
|
|
62
62
|
readonly Gy: bigint;
|
|
63
|
-
readonly wrapPrivateKey?: boolean | undefined;
|
|
64
63
|
readonly allowInfinityPoint?: boolean | undefined;
|
|
65
64
|
readonly a: bigint;
|
|
66
65
|
readonly b: bigint;
|
|
67
|
-
readonly
|
|
66
|
+
readonly allowedPrivateKeyLengths?: readonly number[] | undefined;
|
|
67
|
+
readonly wrapPrivateKey?: boolean | undefined;
|
|
68
68
|
readonly endo?: {
|
|
69
69
|
beta: bigint;
|
|
70
70
|
splitScalar: (k: bigint) => {
|
|
@@ -76,10 +76,10 @@ export declare const secp384r1: Readonly<{
|
|
|
76
76
|
} | undefined;
|
|
77
77
|
readonly isTorsionFree?: ((c: import("./abstract/weierstrass.js").ProjConstructor<bigint>, point: import("./abstract/weierstrass.js").ProjPointType<bigint>) => boolean) | undefined;
|
|
78
78
|
readonly clearCofactor?: ((c: import("./abstract/weierstrass.js").ProjConstructor<bigint>, point: import("./abstract/weierstrass.js").ProjPointType<bigint>) => import("./abstract/weierstrass.js").ProjPointType<bigint>) | undefined;
|
|
79
|
-
lowS: boolean;
|
|
80
79
|
readonly hash: import("./abstract/utils.js").CHash;
|
|
81
80
|
readonly hmac: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array;
|
|
82
81
|
readonly randomBytes: (bytesLength?: number | undefined) => Uint8Array;
|
|
82
|
+
lowS: boolean;
|
|
83
83
|
readonly bits2int?: ((bytes: Uint8Array) => bigint) | undefined;
|
|
84
84
|
readonly bits2int_modN?: ((bytes: Uint8Array) => bigint) | undefined;
|
|
85
85
|
}>;
|