@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/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 toRawX = (point) => point.toRawBytes(true).slice(1);
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 _Point = exports.secp256k1.ProjectivePoint;
122
- const Gmul = (priv) => _Point.fromPrivateKey(priv);
123
- const GmulAdd = (Q, a, b) => _Point.BASE.multiplyAndAddUnsafe(Q, a, b);
124
- function schnorrGetScalar(priv) {
125
- // Let d' = int(sk)
126
- // Fail if d' = 0 or d' n
127
- // Let P = d'⋅G
128
- // Let d = d' if has_even_y(P), otherwise let d = n - d' .
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 _Point(x, y, _1n); // y(P) = y if y mod 2 = 0 or y(P) = p-y otherwise.
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 toRawX(Gmul(privateKey)); // Let d' = int(sk). Fail if d' = 0 or d' n. Return bytes(d'⋅G)
146
+ return schnorrGetExtPubKey(privateKey).bytes; // d'=int(sk). Fail if d'=0 or d'≥n. Ret bytes(d'⋅G)
149
147
  }
150
- /**
151
- * Synchronously creates Schnorr signature. Improved security: verifies itself before
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
- // checks for isWithinCurveOrder
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, x: rx, scalar: k } = schnorrGetScalar(k_); // Let R = k'⋅G.
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((0, utils_js_1.bytesToNumberBE)((0, utils_js_1.ensureBytes)(publicKey, 32))); // P = lift_x(int(pk)); fail if that fails
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), toRawX(P), m); // int(challenge(bytes(r)||bytes(P)||m)) mod n
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: { lift_x, int: utils_js_1.bytesToNumberBE, taggedHash },
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 normalizePrivateKey?: ((key: cutils.PrivKey) => cutils.PrivKey) | undefined;
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.0",
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 index.js",
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.2.0",
34
- "micro-should": "0.3.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"