@noble/curves 0.6.0 → 0.6.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 +83 -53
- 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 +20 -25
- 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 +20 -64
- package/lib/abstract/utils.d.ts +4 -1
- package/lib/abstract/utils.js +48 -26
- package/lib/abstract/weierstrass.d.ts +10 -10
- package/lib/abstract/weierstrass.js +58 -79
- package/lib/esm/abstract/curve.js +11 -17
- package/lib/esm/abstract/edwards.js +22 -27
- package/lib/esm/abstract/hash-to-curve.js +1 -1
- package/lib/esm/abstract/modular.js +12 -14
- package/lib/esm/abstract/montgomery.js +21 -65
- package/lib/esm/abstract/poseidon.js +1 -1
- package/lib/esm/abstract/utils.js +46 -25
- package/lib/esm/abstract/weierstrass.js +59 -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
package/lib/secp256k1.js
CHANGED
|
@@ -115,20 +115,17 @@ function taggedHash(tag, ...messages) {
|
|
|
115
115
|
}
|
|
116
116
|
return (0, sha256_1.sha256)((0, utils_js_1.concatBytes)(tagP, ...messages));
|
|
117
117
|
}
|
|
118
|
-
const
|
|
118
|
+
const pointToBytes = (point) => point.toRawBytes(true).slice(1);
|
|
119
119
|
const numTo32b = (n) => (0, utils_js_1.numberToBytesBE)(n, 32);
|
|
120
120
|
const modN = (x) => (0, modular_js_1.mod)(x, secp256k1N);
|
|
121
|
-
const
|
|
122
|
-
const
|
|
123
|
-
const
|
|
124
|
-
function
|
|
125
|
-
|
|
126
|
-
//
|
|
127
|
-
//
|
|
128
|
-
|
|
129
|
-
const point = Gmul(priv);
|
|
130
|
-
const scalar = point.hasEvenY() ? priv : modN(-priv);
|
|
131
|
-
return { point, scalar, x: toRawX(point) };
|
|
121
|
+
const Point = exports.secp256k1.ProjectivePoint;
|
|
122
|
+
const GmulAdd = (Q, a, b) => Point.BASE.multiplyAndAddUnsafe(Q, a, b);
|
|
123
|
+
const hex32ToInt = (key) => (0, utils_js_1.bytesToNumberBE)((0, utils_js_1.ensureBytes)(key, 32));
|
|
124
|
+
function schnorrGetExtPubKey(priv) {
|
|
125
|
+
let d = typeof priv === 'bigint' ? priv : hex32ToInt(priv);
|
|
126
|
+
const point = Point.fromPrivateKey(d); // P = d'⋅G; 0 < d' < n check is done inside
|
|
127
|
+
const scalar = point.hasEvenY() ? d : modN(-d); // d = d' if has_even_y(P), otherwise d = n-d'
|
|
128
|
+
return { point, scalar, bytes: pointToBytes(point) };
|
|
132
129
|
}
|
|
133
130
|
function lift_x(x) {
|
|
134
131
|
if (!fe(x))
|
|
@@ -137,37 +134,31 @@ function lift_x(x) {
|
|
|
137
134
|
let y = sqrtMod(c); // Let y = c^(p+1)/4 mod p.
|
|
138
135
|
if (y % 2n !== 0n)
|
|
139
136
|
y = (0, modular_js_1.mod)(-y, secp256k1P); // Return the unique point P such that x(P) = x and
|
|
140
|
-
const p = new
|
|
137
|
+
const p = new Point(x, y, _1n); // y(P) = y if y mod 2 = 0 or y(P) = p-y otherwise.
|
|
141
138
|
p.assertValidity();
|
|
142
139
|
return p;
|
|
143
140
|
}
|
|
144
141
|
function challenge(...args) {
|
|
145
142
|
return modN((0, utils_js_1.bytesToNumberBE)(taggedHash(TAGS.challenge, ...args)));
|
|
146
143
|
}
|
|
144
|
+
// Schnorr's pubkey is just `x` of Point (BIP340)
|
|
147
145
|
function schnorrGetPublicKey(privateKey) {
|
|
148
|
-
return
|
|
146
|
+
return schnorrGetExtPubKey(privateKey).bytes; // d'=int(sk). Fail if d'=0 or d'≥n. Ret bytes(d'⋅G)
|
|
149
147
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
* producing an output.
|
|
153
|
-
* @param msg message (not message hash)
|
|
154
|
-
* @param privateKey private key
|
|
155
|
-
* @param auxRand random bytes that would be added to k. Bad RNG won't break it.
|
|
156
|
-
*/
|
|
148
|
+
// Creates Schnorr signature as per BIP340. Verifies itself before returning anything.
|
|
149
|
+
// auxRand is optional and is not the sole source of k generation: bad CSPRNG won't be dangerous
|
|
157
150
|
function schnorrSign(message, privateKey, auxRand = (0, utils_1.randomBytes)(32)) {
|
|
158
151
|
if (message == null)
|
|
159
152
|
throw new Error(`sign: Expected valid message, not "${message}"`);
|
|
160
|
-
const m = (0, utils_js_1.ensureBytes)(message);
|
|
161
|
-
|
|
162
|
-
const { x: px, scalar: d } = schnorrGetScalar((0, utils_js_1.bytesToNumberBE)((0, utils_js_1.ensureBytes)(privateKey, 32)));
|
|
153
|
+
const m = (0, utils_js_1.ensureBytes)(message); // checks for isWithinCurveOrder
|
|
154
|
+
const { bytes: px, scalar: d } = schnorrGetExtPubKey(privateKey);
|
|
163
155
|
const a = (0, utils_js_1.ensureBytes)(auxRand, 32); // Auxiliary random data a: a 32-byte array
|
|
164
|
-
// TODO: replace with proper xor?
|
|
165
156
|
const t = numTo32b(d ^ (0, utils_js_1.bytesToNumberBE)(taggedHash(TAGS.aux, a))); // Let t be the byte-wise xor of bytes(d) and hash/aux(a)
|
|
166
157
|
const rand = taggedHash(TAGS.nonce, t, px, m); // Let rand = hash/nonce(t || bytes(P) || m)
|
|
167
158
|
const k_ = modN((0, utils_js_1.bytesToNumberBE)(rand)); // Let k' = int(rand) mod n
|
|
168
159
|
if (k_ === _0n)
|
|
169
160
|
throw new Error('sign failed: k is zero'); // Fail if k' = 0.
|
|
170
|
-
const { point: R,
|
|
161
|
+
const { point: R, bytes: rx, scalar: k } = schnorrGetExtPubKey(k_); // Let R = k'⋅G.
|
|
171
162
|
const e = challenge(rx, px, m); // Let e = int(hash/challenge(bytes(R) || bytes(P) || m)) mod n.
|
|
172
163
|
const sig = new Uint8Array(64); // Let sig = bytes(R) || bytes((k + ed) mod n).
|
|
173
164
|
sig.set(numTo32b(R.px), 0);
|
|
@@ -182,7 +173,7 @@ function schnorrSign(message, privateKey, auxRand = (0, utils_1.randomBytes)(32)
|
|
|
182
173
|
*/
|
|
183
174
|
function schnorrVerify(signature, message, publicKey) {
|
|
184
175
|
try {
|
|
185
|
-
const P = lift_x((
|
|
176
|
+
const P = lift_x(hex32ToInt(publicKey)); // P = lift_x(int(pk)); fail if that fails
|
|
186
177
|
const sig = (0, utils_js_1.ensureBytes)(signature, 64);
|
|
187
178
|
const r = (0, utils_js_1.bytesToNumberBE)(sig.subarray(0, 32)); // Let r = int(sig[0:32]); fail if r ≥ p.
|
|
188
179
|
if (!fe(r))
|
|
@@ -191,7 +182,7 @@ function schnorrVerify(signature, message, publicKey) {
|
|
|
191
182
|
if (!ge(s))
|
|
192
183
|
return false;
|
|
193
184
|
const m = (0, utils_js_1.ensureBytes)(message);
|
|
194
|
-
const e = challenge(numTo32b(r),
|
|
185
|
+
const e = challenge(numTo32b(r), pointToBytes(P), m); // int(challenge(bytes(r)||bytes(P)||m)) mod n
|
|
195
186
|
const R = GmulAdd(P, s, modN(-e)); // R = s⋅G - e⋅P
|
|
196
187
|
if (!R || !R.hasEvenY() || R.toAffine().x !== r)
|
|
197
188
|
return false; // -eP == (n-e)P
|
|
@@ -202,11 +193,18 @@ function schnorrVerify(signature, message, publicKey) {
|
|
|
202
193
|
}
|
|
203
194
|
}
|
|
204
195
|
exports.schnorr = {
|
|
205
|
-
// Schnorr's pubkey is just `x` of Point (BIP340)
|
|
206
196
|
getPublicKey: schnorrGetPublicKey,
|
|
207
197
|
sign: schnorrSign,
|
|
208
198
|
verify: schnorrVerify,
|
|
209
|
-
utils: {
|
|
199
|
+
utils: {
|
|
200
|
+
getExtendedPublicKey: schnorrGetExtPubKey,
|
|
201
|
+
lift_x,
|
|
202
|
+
pointToBytes,
|
|
203
|
+
numberToBytesBE: utils_js_1.numberToBytesBE,
|
|
204
|
+
bytesToNumberBE: utils_js_1.bytesToNumberBE,
|
|
205
|
+
taggedHash,
|
|
206
|
+
mod: modular_js_1.mod,
|
|
207
|
+
},
|
|
210
208
|
};
|
|
211
209
|
const isoMap = htf.isogenyMap(Fp, [
|
|
212
210
|
// xNum
|
package/lib/stark.d.ts
CHANGED
|
@@ -16,11 +16,11 @@ declare const CURVE: Readonly<{
|
|
|
16
16
|
readonly hEff?: bigint | undefined;
|
|
17
17
|
readonly Gx: bigint;
|
|
18
18
|
readonly Gy: bigint;
|
|
19
|
-
readonly wrapPrivateKey?: boolean | undefined;
|
|
20
19
|
readonly allowInfinityPoint?: boolean | undefined;
|
|
21
20
|
readonly a: bigint;
|
|
22
21
|
readonly b: bigint;
|
|
23
|
-
readonly
|
|
22
|
+
readonly allowedPrivateKeyLengths?: readonly number[] | undefined;
|
|
23
|
+
readonly wrapPrivateKey?: boolean | undefined;
|
|
24
24
|
readonly endo?: {
|
|
25
25
|
beta: bigint;
|
|
26
26
|
splitScalar: (k: bigint) => {
|
|
@@ -32,10 +32,10 @@ declare const CURVE: Readonly<{
|
|
|
32
32
|
} | undefined;
|
|
33
33
|
readonly isTorsionFree?: ((c: import("./abstract/weierstrass.js").ProjConstructor<bigint>, point: ProjPointType<bigint>) => boolean) | undefined;
|
|
34
34
|
readonly clearCofactor?: ((c: import("./abstract/weierstrass.js").ProjConstructor<bigint>, point: ProjPointType<bigint>) => ProjPointType<bigint>) | undefined;
|
|
35
|
-
lowS: boolean;
|
|
36
35
|
readonly hash: cutils.CHash;
|
|
37
36
|
readonly hmac: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array;
|
|
38
37
|
readonly randomBytes: (bytesLength?: number | undefined) => Uint8Array;
|
|
38
|
+
lowS: boolean;
|
|
39
39
|
readonly bits2int?: ((bytes: Uint8Array) => bigint) | undefined;
|
|
40
40
|
readonly bits2int_modN?: ((bytes: Uint8Array) => bigint) | undefined;
|
|
41
41
|
}>, ProjectivePoint: import("./abstract/weierstrass.js").ProjConstructor<bigint>, Signature: import("./abstract/weierstrass.js").SignatureConstructor;
|
package/lib/stark.js
CHANGED
|
@@ -98,7 +98,7 @@ function ensureBytes0x(hex) {
|
|
|
98
98
|
function normalizePrivateKey(privKey) {
|
|
99
99
|
return cutils.bytesToHex(ensureBytes0x(privKey)).padStart(64, '0');
|
|
100
100
|
}
|
|
101
|
-
function getPublicKey0x(privKey, isCompressed) {
|
|
101
|
+
function getPublicKey0x(privKey, isCompressed = false) {
|
|
102
102
|
return exports.starkCurve.getPublicKey(normalizePrivateKey(privKey), isCompressed);
|
|
103
103
|
}
|
|
104
104
|
exports.getPublicKey = getPublicKey0x;
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@noble/curves",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "Minimal, auditable JS implementation of elliptic curve cryptography",
|
|
5
5
|
"files": [
|
|
6
6
|
"lib"
|
|
7
7
|
],
|
|
8
8
|
"scripts": {
|
|
9
|
-
"bench": "cd benchmark; node
|
|
9
|
+
"bench": "cd benchmark; node secp256k1.js; node curves.js; node stark.js; node bls.js",
|
|
10
10
|
"build": "tsc && tsc -p tsconfig.esm.json",
|
|
11
11
|
"build:release": "rollup -c rollup.config.js",
|
|
12
12
|
"lint": "prettier --check 'src/**/*.{js,ts}' 'test/*.js'",
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
"@scure/bip39": "~1.1.0",
|
|
31
31
|
"@types/node": "18.11.3",
|
|
32
32
|
"fast-check": "3.0.0",
|
|
33
|
-
"micro-bmark": "0.
|
|
34
|
-
"micro-should": "0.
|
|
33
|
+
"micro-bmark": "0.3.0",
|
|
34
|
+
"micro-should": "0.4.0",
|
|
35
35
|
"prettier": "2.8.3",
|
|
36
36
|
"rollup": "2.75.5",
|
|
37
37
|
"typescript": "4.7.3"
|