@noble/curves 0.5.1 → 0.5.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 CHANGED
@@ -201,8 +201,6 @@ export type CurveFn = {
201
201
  ExtendedPoint: ExtendedPointConstructor;
202
202
  Signature: SignatureConstructor;
203
203
  utils: {
204
- mod: (a: bigint, b?: bigint) => bigint;
205
- invert: (number: bigint, modulo?: bigint) => bigint;
206
204
  randomPrivateKey: () => Uint8Array;
207
205
  getExtendedPublicKey: (key: PrivKey) => {
208
206
  head: Uint8Array;
@@ -306,6 +304,7 @@ export type CurveFn = {
306
304
  getPublicKey: (privateKey: PrivKey, isCompressed?: boolean) => Uint8Array;
307
305
  getSharedSecret: (privateA: PrivKey, publicB: PubKey, isCompressed?: boolean) => Uint8Array;
308
306
  sign: (msgHash: Hex, privKey: PrivKey, opts?: SignOpts) => SignatureType;
307
+ signUnhashed: (msg: Uint8Array, privKey: PrivKey, opts?: SignOpts) => SignatureType;
309
308
  verify: (
310
309
  signature: Hex | SignatureType,
311
310
  msgHash: Hex,
@@ -316,8 +315,6 @@ export type CurveFn = {
316
315
  ProjectivePoint: ProjectivePointConstructor;
317
316
  Signature: SignatureConstructor;
318
317
  utils: {
319
- mod: (a: bigint) => bigint;
320
- invert: (number: bigint) => bigint;
321
318
  isValidPrivateKey(privateKey: PrivKey): boolean;
322
319
  hashToPrivateKey: (hash: Hex) => Uint8Array;
323
320
  randomPrivateKey: () => Uint8Array;
@@ -47,10 +47,8 @@ export declare function createCurve(curveDef: CurveDef, defHash: CHash): Readonl
47
47
  }>;
48
48
  getPublicKey: (privateKey: import("./abstract/utils.js").PrivKey, isCompressed?: boolean | undefined) => Uint8Array;
49
49
  getSharedSecret: (privateA: import("./abstract/utils.js").PrivKey, publicB: import("./abstract/weierstrass.js").PubKey, isCompressed?: boolean | undefined) => Uint8Array;
50
- sign: (msgHash: import("./abstract/utils.js").Hex, privKey: import("./abstract/utils.js").PrivKey, opts?: {
51
- lowS?: boolean | undefined;
52
- extraEntropy?: (true | import("./abstract/utils.js").Hex) | undefined;
53
- } | undefined) => import("./abstract/weierstrass.js").SignatureType;
50
+ sign: (msgHash: import("./abstract/utils.js").Hex, privKey: import("./abstract/utils.js").PrivKey, opts?: import("./abstract/weierstrass.js").SignOpts | undefined) => import("./abstract/weierstrass.js").SignatureType;
51
+ signUnhashed: (msg: Uint8Array, privKey: import("./abstract/utils.js").PrivKey, opts?: import("./abstract/weierstrass.js").SignOpts | undefined) => import("./abstract/weierstrass.js").SignatureType;
54
52
  verify: (signature: import("./abstract/utils.js").Hex | import("./abstract/weierstrass.js").SignatureType, msgHash: import("./abstract/utils.js").Hex, publicKey: import("./abstract/weierstrass.js").PubKey, opts?: {
55
53
  lowS?: boolean | undefined;
56
54
  } | undefined) => boolean;
@@ -58,8 +56,6 @@ export declare function createCurve(curveDef: CurveDef, defHash: CHash): Readonl
58
56
  ProjectivePoint: import("./abstract/weierstrass.js").ProjectiveConstructor<bigint>;
59
57
  Signature: import("./abstract/weierstrass.js").SignatureConstructor;
60
58
  utils: {
61
- mod: (a: bigint, b?: bigint | undefined) => bigint;
62
- invert: (number: bigint, modulo?: bigint | undefined) => bigint;
63
59
  _bigintToBytes: (num: bigint) => Uint8Array;
64
60
  _bigintToString: (num: bigint) => string;
65
61
  _normalizePrivateKey: (key: import("./abstract/utils.js").PrivKey) => bigint;
@@ -1,8 +1,20 @@
1
1
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
2
+ /**
3
+ * BLS (Barreto-Lynn-Scott) family of pairing-friendly curves.
4
+ * Implements BLS (Boneh-Lynn-Shacham) signatures.
5
+ * Consists of two curves: G1 and G2:
6
+ * - G1 is a subgroup of (x, y) E(Fq) over y² = x³ + 4.
7
+ * - G2 is a subgroup of ((x₁, x₂+i), (y₁, y₂+i)) E(Fq²) over y² = x³ + 4(1 + i) where i is √-1
8
+ * - Gt, created by bilinear (ate) pairing e(G1, G2), consists of p-th roots of unity in
9
+ * Fq^k where k is embedding degree. Only degree 12 is currently supported, 24 is not.
10
+ * Pairing is used to aggregate and verify signatures.
11
+ * We are using Fp for private keys (shorter) and Fp₂ for signatures (longer).
12
+ * Some projects may prefer to swap this relation, it is not supported for now.
13
+ */
2
14
  import * as mod from './modular.js';
3
- import * as utils from './utils.js';
15
+ import * as ut from './utils.js';
4
16
  import { Hex, PrivKey } from './utils.js';
5
- import { htfOpts, stringToBytes, hash_to_field, expand_message_xmd } from './hash-to-curve.js';
17
+ import { htfOpts, stringToBytes, hash_to_field as hashToField, expand_message_xmd as expandMessageXMD } from './hash-to-curve.js';
6
18
  import { CurvePointsType, PointType, CurvePointsRes } from './weierstrass.js';
7
19
  declare type Fp = bigint;
8
20
  export declare type SignatureCoder<Fp2> = {
@@ -34,7 +46,7 @@ export declare type CurveType<Fp, Fp2, Fp6, Fp12> = {
34
46
  finalExponentiate(num: Fp12): Fp12;
35
47
  };
36
48
  htfDefaults: htfOpts;
37
- hash: utils.CHash;
49
+ hash: ut.CHash;
38
50
  randomBytes: (bytesLength?: number) => Uint8Array;
39
51
  };
40
52
  export declare type CurveFn<Fp, Fp2, Fp6, Fp12> = {
@@ -66,12 +78,9 @@ export declare type CurveFn<Fp, Fp2, Fp6, Fp12> = {
66
78
  };
67
79
  verifyBatch: (signature: Hex | PointType<Fp2>, messages: (Hex | PointType<Fp2>)[], publicKeys: (Hex | PointType<Fp>)[]) => boolean;
68
80
  utils: {
69
- bytesToHex: typeof utils.bytesToHex;
70
- hexToBytes: typeof utils.hexToBytes;
71
81
  stringToBytes: typeof stringToBytes;
72
- hashToField: typeof hash_to_field;
73
- expandMessageXMD: typeof expand_message_xmd;
74
- mod: typeof mod.mod;
82
+ hashToField: typeof hashToField;
83
+ expandMessageXMD: typeof expandMessageXMD;
75
84
  getDSTLabel: () => string;
76
85
  setDSTLabel(newLabel: string): void;
77
86
  };
@@ -1,24 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.bls = void 0;
4
- /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
5
- // Barreto-Lynn-Scott Curves. A family of pairing friendly curves, with embedding degree = 12 or 24
6
- // NOTE: only 12 supported for now
7
- // Constructed from pair of weierstrass curves, based pairing logic
8
- const mod = require("./modular.js");
9
- const utils_js_1 = require("./utils.js");
10
- // Types
11
- const utils_js_2 = require("./utils.js");
4
+ const ut = require("./utils.js");
12
5
  const hash_to_curve_js_1 = require("./hash-to-curve.js");
13
6
  const weierstrass_js_1 = require("./weierstrass.js");
14
7
  function bls(CURVE) {
15
8
  // Fields looks pretty specific for curve, so for now we need to pass them with options
16
- const Fp = CURVE.Fp;
17
- const Fr = CURVE.Fr;
18
- const Fp2 = CURVE.Fp2;
19
- const Fp6 = CURVE.Fp6;
20
- const Fp12 = CURVE.Fp12;
21
- const BLS_X_LEN = (0, utils_js_1.bitLen)(CURVE.x);
9
+ const { Fp, Fr, Fp2, Fp6, Fp12 } = CURVE;
10
+ const BLS_X_LEN = ut.bitLen(CURVE.x);
11
+ const groupLen = 32; // TODO: calculate; hardcoded for now
22
12
  // Pre-compute coefficients for sparse multiplication
23
13
  // Point addition and point double calculations is reused for coefficients
24
14
  function calcPairingPrecomputes(x, y) {
@@ -42,7 +32,7 @@ function bls(CURVE) {
42
32
  Rx = Fp2.div(Fp2.mul(Fp2.mul(Fp2.sub(t0, t3), Rx), Ry), 2n); // ((T0 - T3) * Rx * Ry) / 2
43
33
  Ry = Fp2.sub(Fp2.square(Fp2.div(Fp2.add(t0, t3), 2n)), Fp2.mul(Fp2.square(t2), 3n)); // ((T0 + T3) / 2)² - 3 * T2²
44
34
  Rz = Fp2.mul(t0, t4); // T0 * T4
45
- if ((0, utils_js_1.bitGet)(CURVE.x, i)) {
35
+ if (ut.bitGet(CURVE.x, i)) {
46
36
  // Addition
47
37
  let t0 = Fp2.sub(Ry, Fp2.mul(Qy, Rz)); // Ry - Qy * Rz
48
38
  let t1 = Fp2.sub(Rx, Fp2.mul(Qx, Rz)); // Rx - Qx * Rz
@@ -63,13 +53,14 @@ function bls(CURVE) {
63
53
  return ell_coeff;
64
54
  }
65
55
  function millerLoop(ell, g1) {
56
+ const { x } = CURVE;
66
57
  const Px = g1[0];
67
58
  const Py = g1[1];
68
59
  let f12 = Fp12.ONE;
69
60
  for (let j = 0, i = BLS_X_LEN - 2; i >= 0; i--, j++) {
70
61
  const E = ell[j];
71
62
  f12 = Fp12.multiplyBy014(f12, E[0], Fp2.mul(E[1], Px), Fp2.mul(E[2], Py));
72
- if ((0, utils_js_1.bitGet)(CURVE.x, i)) {
63
+ if (ut.bitGet(x, i)) {
73
64
  j += 1;
74
65
  const F = ell[j];
75
66
  f12 = Fp12.multiplyBy014(f12, F[0], Fp2.mul(F[1], Px), Fp2.mul(F[2], Py));
@@ -79,79 +70,25 @@ function bls(CURVE) {
79
70
  }
80
71
  return Fp12.conjugate(f12);
81
72
  }
82
- // bls12-381 is a construction of two curves:
83
- // 1. Fp: (x, y)
84
- // 2. Fp₂: ((x₁, x₂+i), (y₁, y₂+i)) - (complex numbers)
85
- //
86
- // Bilinear Pairing (ate pairing) is used to combine both elements into a paired one:
87
- // Fp₁₂ = e(Fp, Fp2)
88
- // where Fp₁₂ = 12-degree polynomial
89
- // Pairing is used to verify signatures.
90
- //
91
- // We are using Fp for private keys (shorter) and Fp2 for signatures (longer).
92
- // Some projects may prefer to swap this relation, it is not supported for now.
93
- const htfDefaults = { ...CURVE.htfDefaults };
94
- function isWithinCurveOrder(num) {
95
- return 0 < num && num < CURVE.r;
96
- }
97
73
  const utils = {
98
- hexToBytes: utils_js_2.hexToBytes,
99
- bytesToHex: utils_js_2.bytesToHex,
100
- mod: mod.mod,
74
+ hexToBytes: ut.hexToBytes,
75
+ bytesToHex: ut.bytesToHex,
101
76
  stringToBytes: hash_to_curve_js_1.stringToBytes,
102
77
  // TODO: do we need to export it here?
103
78
  hashToField: (msg, count, options = {}) => (0, hash_to_curve_js_1.hash_to_field)(msg, count, { ...CURVE.htfDefaults, ...options }),
104
79
  expandMessageXMD: (msg, DST, lenInBytes, H = CURVE.hash) => (0, hash_to_curve_js_1.expand_message_xmd)(msg, DST, lenInBytes, H),
105
- /**
106
- * Can take 40 or more bytes of uniform input e.g. from CSPRNG or KDF
107
- * and convert them into private key, with the modulo bias being negligible.
108
- * As per FIPS 186 B.1.1.
109
- * https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/
110
- * @param hash hash output from sha512, or a similar function
111
- * @returns valid private key
112
- */
113
- hashToPrivateKey: (hash) => {
114
- hash = (0, utils_js_1.ensureBytes)(hash);
115
- if (hash.length < 40 || hash.length > 1024)
116
- throw new Error('Expected 40-1024 bytes of private key as per FIPS 186');
117
- // hashToPrivateScalar(hash, CURVE.r)
118
- // NOTE: doesn't add +/-1
119
- const num = mod.mod((0, utils_js_1.bytesToNumberBE)(hash), CURVE.r);
120
- // This should never happen
121
- if (num === 0n || num === 1n)
122
- throw new Error('Invalid private key');
123
- return (0, utils_js_1.numberToBytesBE)(num, 32);
124
- },
125
- randomBytes: (bytesLength = 32) => CURVE.randomBytes(bytesLength),
126
- // NIST SP 800-56A rev 3, section 5.6.1.2.2
127
- // https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/
128
- randomPrivateKey: () => utils.hashToPrivateKey(utils.randomBytes(40)),
129
- getDSTLabel: () => htfDefaults.DST,
80
+ hashToPrivateKey: (hash) => Fr.toBytes(ut.hashToPrivateScalar(hash, CURVE.r)),
81
+ randomBytes: (bytesLength = groupLen) => CURVE.randomBytes(bytesLength),
82
+ randomPrivateKey: () => utils.hashToPrivateKey(utils.randomBytes(groupLen + 8)),
83
+ getDSTLabel: () => CURVE.htfDefaults.DST,
130
84
  setDSTLabel(newLabel) {
131
85
  // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3.1
132
86
  if (typeof newLabel !== 'string' || newLabel.length > 2048 || newLabel.length === 0) {
133
87
  throw new TypeError('Invalid DST');
134
88
  }
135
- htfDefaults.DST = newLabel;
89
+ CURVE.htfDefaults.DST = newLabel;
136
90
  },
137
91
  };
138
- function normalizePrivKey(key) {
139
- let int;
140
- if (key instanceof Uint8Array && key.length === 32)
141
- int = (0, utils_js_1.bytesToNumberBE)(key);
142
- else if (typeof key === 'string' && key.length === 64)
143
- int = BigInt(`0x${key}`);
144
- else if (typeof key === 'number' && key > 0 && Number.isSafeInteger(key))
145
- int = BigInt(key);
146
- else if (typeof key === 'bigint' && key > 0n)
147
- int = key;
148
- else
149
- throw new TypeError('Expected valid private key');
150
- int = mod.mod(int, CURVE.r);
151
- if (!isWithinCurveOrder(int))
152
- throw new Error('Private key must be 0 < key < CURVE.r');
153
- return int;
154
- }
155
92
  // Point on G1 curve: (x, y)
156
93
  const G1 = (0, weierstrass_js_1.weierstrassPoints)({
157
94
  n: Fr.ORDER,
@@ -205,7 +142,7 @@ function bls(CURVE) {
205
142
  function sign(message, privateKey) {
206
143
  const msgPoint = normP2Hash(message);
207
144
  msgPoint.assertValidity();
208
- const sigPoint = msgPoint.multiply(normalizePrivKey(privateKey));
145
+ const sigPoint = msgPoint.multiply(G1.normalizePrivateKey(privateKey));
209
146
  if (message instanceof G2.Point)
210
147
  return sigPoint;
211
148
  return Signature.encode(sigPoint);
@@ -1,18 +1,13 @@
1
1
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
2
2
  import * as mod from './modular.js';
3
- import { BasicCurve, Hex, PrivKey } from './utils.js';
3
+ import * as ut from './utils.js';
4
+ import { Hex, PrivKey } from './utils.js';
4
5
  import { Group, GroupConstructor } from './group.js';
5
6
  import { htfOpts } from './hash-to-curve.js';
6
- export declare type CHash = {
7
- (message: Uint8Array | string): Uint8Array;
8
- blockLen: number;
9
- outputLen: number;
10
- create(): any;
11
- };
12
- export declare type CurveType = BasicCurve<bigint> & {
7
+ export declare type CurveType = ut.BasicCurve<bigint> & {
13
8
  a: bigint;
14
9
  d: bigint;
15
- hash: CHash;
10
+ hash: ut.CHash;
16
11
  randomBytes: (bytesLength?: number) => Uint8Array;
17
12
  adjustScalarBytes?: (bytes: Uint8Array) => Uint8Array;
18
13
  domain?: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array;
@@ -20,8 +15,7 @@ export declare type CurveType = BasicCurve<bigint> & {
20
15
  isValid: boolean;
21
16
  value: bigint;
22
17
  };
23
- preHash?: CHash;
24
- clearCofactor?: (c: ExtendedPointConstructor, point: ExtendedPointType) => ExtendedPointType;
18
+ preHash?: ut.CHash;
25
19
  htfDefaults?: htfOpts;
26
20
  mapToCurve?: (scalar: bigint[]) => {
27
21
  x: bigint;
@@ -41,7 +35,7 @@ declare function validateOpts(curve: CurveType): Readonly<{
41
35
  readonly allowInfinityPoint?: boolean | undefined;
42
36
  readonly a: bigint;
43
37
  readonly d: bigint;
44
- readonly hash: CHash;
38
+ readonly hash: ut.CHash;
45
39
  readonly randomBytes: (bytesLength?: number | undefined) => Uint8Array;
46
40
  readonly adjustScalarBytes?: ((bytes: Uint8Array) => Uint8Array) | undefined;
47
41
  readonly domain?: ((data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array) | undefined;
@@ -49,8 +43,7 @@ declare function validateOpts(curve: CurveType): Readonly<{
49
43
  isValid: boolean;
50
44
  value: bigint;
51
45
  }) | undefined;
52
- readonly preHash?: CHash | undefined;
53
- readonly clearCofactor?: ((c: ExtendedPointConstructor, point: ExtendedPointType) => ExtendedPointType) | undefined;
46
+ readonly preHash?: ut.CHash | undefined;
54
47
  readonly htfDefaults?: htfOpts | undefined;
55
48
  readonly mapToCurve?: ((scalar: bigint[]) => {
56
49
  x: bigint;
@@ -113,8 +106,6 @@ export declare type CurveFn = {
113
106
  ExtendedPoint: ExtendedPointConstructor;
114
107
  Signature: SignatureConstructor;
115
108
  utils: {
116
- mod: (a: bigint) => bigint;
117
- invert: (number: bigint) => bigint;
118
109
  randomPrivateKey: () => Uint8Array;
119
110
  getExtendedPublicKey: (key: PrivKey) => {
120
111
  head: Uint8Array;