@noble/curves 0.3.1 → 0.4.0

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.
Files changed (70) hide show
  1. package/README.md +2 -1
  2. package/lib/bls.d.ts +79 -0
  3. package/lib/bls.js +304 -0
  4. package/lib/edwards.d.ts +10 -6
  5. package/lib/edwards.js +16 -11
  6. package/lib/esm/bls.js +300 -0
  7. package/lib/esm/edwards.js +17 -12
  8. package/lib/esm/group.js +2 -2
  9. package/lib/esm/hashToCurve.js +105 -0
  10. package/lib/esm/modular.js +131 -50
  11. package/lib/esm/utils.js +25 -19
  12. package/lib/esm/weierstrass.js +351 -272
  13. package/lib/group.js +2 -2
  14. package/lib/hashToCurve.d.ts +13 -0
  15. package/lib/hashToCurve.js +112 -0
  16. package/lib/modular.d.ts +37 -17
  17. package/lib/modular.js +138 -54
  18. package/lib/utils.d.ts +28 -10
  19. package/lib/utils.js +31 -22
  20. package/lib/weierstrass.d.ts +106 -69
  21. package/lib/weierstrass.js +352 -272
  22. package/package.json +23 -44
  23. package/lib/crypto.d.ts +0 -4
  24. package/lib/crypto.js +0 -8
  25. package/lib/cryptoBrowser.d.ts +0 -4
  26. package/lib/cryptoBrowser.js +0 -7
  27. package/lib/definitions/_shortw_utils.d.ts +0 -63
  28. package/lib/definitions/_shortw_utils.js +0 -18
  29. package/lib/definitions/bn.d.ts +0 -7
  30. package/lib/definitions/bn.js +0 -23
  31. package/lib/definitions/ed25519.d.ts +0 -49
  32. package/lib/definitions/ed25519.js +0 -308
  33. package/lib/definitions/ed448.d.ts +0 -3
  34. package/lib/definitions/ed448.js +0 -127
  35. package/lib/definitions/index.d.ts +0 -0
  36. package/lib/definitions/index.js +0 -2
  37. package/lib/definitions/jubjub.d.ts +0 -7
  38. package/lib/definitions/jubjub.js +0 -55
  39. package/lib/definitions/p192.d.ts +0 -112
  40. package/lib/definitions/p192.js +0 -23
  41. package/lib/definitions/p224.d.ts +0 -112
  42. package/lib/definitions/p224.js +0 -24
  43. package/lib/definitions/p256.d.ts +0 -112
  44. package/lib/definitions/p256.js +0 -23
  45. package/lib/definitions/p384.d.ts +0 -112
  46. package/lib/definitions/p384.js +0 -24
  47. package/lib/definitions/p521.d.ts +0 -113
  48. package/lib/definitions/p521.js +0 -36
  49. package/lib/definitions/pasta.d.ts +0 -2
  50. package/lib/definitions/pasta.js +0 -32
  51. package/lib/definitions/secp256k1.d.ts +0 -87
  52. package/lib/definitions/secp256k1.js +0 -245
  53. package/lib/definitions/stark.d.ts +0 -62
  54. package/lib/definitions/stark.js +0 -248
  55. package/lib/esm/crypto.js +0 -5
  56. package/lib/esm/cryptoBrowser.js +0 -4
  57. package/lib/esm/definitions/_shortw_utils.js +0 -13
  58. package/lib/esm/definitions/bn.js +0 -20
  59. package/lib/esm/definitions/ed25519.js +0 -304
  60. package/lib/esm/definitions/ed448.js +0 -124
  61. package/lib/esm/definitions/index.js +0 -2
  62. package/lib/esm/definitions/jubjub.js +0 -50
  63. package/lib/esm/definitions/p192.js +0 -20
  64. package/lib/esm/definitions/p224.js +0 -21
  65. package/lib/esm/definitions/p256.js +0 -20
  66. package/lib/esm/definitions/p384.js +0 -21
  67. package/lib/esm/definitions/p521.js +0 -33
  68. package/lib/esm/definitions/pasta.js +0 -29
  69. package/lib/esm/definitions/secp256k1.js +0 -241
  70. package/lib/esm/definitions/stark.js +0 -227
@@ -1,4 +1,5 @@
1
1
  /*! @noble/curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
2
+ import * as utils from './utils.js';
2
3
  // Utilities for modular arithmetics
3
4
  const _0n = BigInt(0);
4
5
  const _1n = BigInt(1);
@@ -14,6 +15,7 @@ export function mod(a, b) {
14
15
  * @example
15
16
  * powMod(2n, 6n, 11n) // 64n % 11n == 9n
16
17
  */
18
+ // TODO: use field version && remove
17
19
  export function pow(num, power, modulo) {
18
20
  if (modulo <= _0n || power < _0n)
19
21
  throw new Error('Expected power/modulo > 0');
@@ -29,6 +31,7 @@ export function pow(num, power, modulo) {
29
31
  return res;
30
32
  }
31
33
  // Does x ^ (2 ^ power) mod p. pow2(30, 4) == 30 ^ (2 ^ 4)
34
+ // TODO: Fp version?
32
35
  export function pow2(x, power, modulo) {
33
36
  let res = x;
34
37
  while (power-- > _0n) {
@@ -60,56 +63,19 @@ export function invert(number, modulo) {
60
63
  throw new Error('invert: does not exist');
61
64
  return mod(x, modulo);
62
65
  }
63
- /**
64
- * Division over finite field.
65
- * `a/b mod p == a * invert(b) mod p`
66
- */
67
- export function div(numerator, denominator, modulo) {
68
- const num = mod(numerator, modulo);
69
- const iden = invert(denominator, modulo);
70
- return mod(num * iden, modulo);
71
- }
72
- /**
73
- * Takes a list of numbers, efficiently inverts all of them.
74
- * @param nums list of bigints
75
- * @param p modulo
76
- * @returns list of inverted bigints
77
- * @example
78
- * invertBatch([1n, 2n, 4n], 21n);
79
- * // => [1n, 11n, 16n]
80
- */
81
- export function invertBatch(nums, modulo) {
82
- const scratch = new Array(nums.length);
83
- // Walk from first to last, multiply them by each other MOD p
84
- const lastMultiplied = nums.reduce((acc, num, i) => {
85
- if (num === _0n)
86
- return acc;
87
- scratch[i] = acc;
88
- return mod(acc * num, modulo);
89
- }, _1n);
90
- // Invert last element
91
- const inverted = invert(lastMultiplied, modulo);
92
- // Walk from last to first, multiply them by inverted each other MOD p
93
- nums.reduceRight((acc, num, i) => {
94
- if (num === _0n)
95
- return acc;
96
- scratch[i] = mod(acc * scratch[i], modulo);
97
- return mod(acc * num, modulo);
98
- }, inverted);
99
- return scratch;
100
- }
101
66
  /**
102
67
  * Calculates Legendre symbol (a | p), which denotes the value of a^((p-1)/2) (mod p).
103
68
  * * (a | p) ≡ 1 if a is a square (mod p)
104
69
  * * (a | p) ≡ -1 if a is not a square (mod p)
105
70
  * * (a | p) ≡ 0 if a ≡ 0 (mod p)
106
71
  */
107
- export function legendre(num, P) {
108
- return pow(num, (P - _1n) / _2n, P);
72
+ export function legendre(num, fieldPrime) {
73
+ return pow(num, (fieldPrime - _1n) / _2n, fieldPrime);
109
74
  }
110
75
  /**
111
76
  * Calculates square root of a number in a finite field.
112
77
  */
78
+ // TODO: rewrite as generic Fp function && remove bls versions
113
79
  export function sqrt(number, modulo) {
114
80
  // prettier-ignore
115
81
  const _3n = BigInt(3), _4n = BigInt(4), _5n = BigInt(5), _8n = BigInt(8);
@@ -118,8 +84,17 @@ export function sqrt(number, modulo) {
118
84
  const p1div4 = (P + _1n) / _4n;
119
85
  // P ≡ 3 (mod 4)
120
86
  // sqrt n = n^((P+1)/4)
121
- if (P % _4n === _3n)
122
- return pow(n, p1div4, P);
87
+ if (P % _4n === _3n) {
88
+ // Not all roots possible!
89
+ // const ORDER =
90
+ // 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaabn;
91
+ // const NUM = 72057594037927816n;
92
+ // TODO: fix sqrtMod in secp256k1
93
+ const root = pow(n, p1div4, P);
94
+ if (mod(root * root, modulo) !== number)
95
+ throw new Error('Cannot find square root');
96
+ return root;
97
+ }
123
98
  // P ≡ 5 (mod 8)
124
99
  if (P % _8n === _5n) {
125
100
  const n2 = mod(n * _2n, P);
@@ -130,7 +105,6 @@ export function sqrt(number, modulo) {
130
105
  return r;
131
106
  }
132
107
  // Other cases: Tonelli-Shanks algorithm
133
- // Check whether n is square
134
108
  if (legendre(n, P) !== _1n)
135
109
  throw new Error('Cannot find square root');
136
110
  let q, s, z;
@@ -162,10 +136,117 @@ export function sqrt(number, modulo) {
162
136
  }
163
137
  // Little-endian check for first LE bit (last BE bit);
164
138
  export const isNegativeLE = (num, modulo) => (mod(num, modulo) & _1n) === _1n;
165
- // An idea on modular arithmetic for bls12-381:
166
- // const FIELD = {add, pow, sqrt, mul};
167
- // Functions will take field elements, no need for an additional class
168
- // Could be faster. 1 bigint field will just do operations and mod later:
169
- // instead of 'r = mod(r * b, P)' we will write r = mul(r, b);
170
- // Could be insecure without shape check, so it needs to be done.
171
- // Functions could be inlined by JIT.
139
+ // prettier-ignore
140
+ const FIELD_FIELDS = [
141
+ 'create', 'isValid', 'isZero', 'negate', 'invert', 'sqrt', 'square',
142
+ 'equals', 'add', 'subtract', 'multiply', 'pow', 'div',
143
+ 'addN', 'subtractN', 'multiplyN', 'squareN'
144
+ ];
145
+ export function validateField(field) {
146
+ for (const i of ['ORDER', 'MASK']) {
147
+ if (typeof field[i] !== 'bigint')
148
+ throw new Error(`Invalid field param ${i}=${field[i]} (${typeof field[i]})`);
149
+ }
150
+ for (const i of ['BYTES', 'BITS']) {
151
+ if (typeof field[i] !== 'number')
152
+ throw new Error(`Invalid field param ${i}=${field[i]} (${typeof field[i]})`);
153
+ }
154
+ for (const i of FIELD_FIELDS) {
155
+ if (typeof field[i] !== 'function')
156
+ throw new Error(`Invalid field param ${i}=${field[i]} (${typeof field[i]})`);
157
+ }
158
+ }
159
+ // Generic field functions
160
+ export function FpPow(f, num, power) {
161
+ // Should have same speed as pow for bigints
162
+ // TODO: benchmark!
163
+ if (power < _0n)
164
+ throw new Error('Expected power > 0');
165
+ if (power === _0n)
166
+ return f.ONE;
167
+ if (power === _1n)
168
+ return num;
169
+ let p = f.ONE;
170
+ let d = num;
171
+ while (power > _0n) {
172
+ if (power & _1n)
173
+ p = f.multiply(p, d);
174
+ d = f.square(d);
175
+ power >>= 1n;
176
+ }
177
+ return p;
178
+ }
179
+ export function FpInvertBatch(f, nums) {
180
+ const tmp = new Array(nums.length);
181
+ // Walk from first to last, multiply them by each other MOD p
182
+ const lastMultiplied = nums.reduce((acc, num, i) => {
183
+ if (f.isZero(num))
184
+ return acc;
185
+ tmp[i] = acc;
186
+ return f.multiply(acc, num);
187
+ }, f.ONE);
188
+ // Invert last element
189
+ const inverted = f.invert(lastMultiplied);
190
+ // Walk from last to first, multiply them by inverted each other MOD p
191
+ nums.reduceRight((acc, num, i) => {
192
+ if (f.isZero(num))
193
+ return acc;
194
+ tmp[i] = f.multiply(acc, tmp[i]);
195
+ return f.multiply(acc, num);
196
+ }, inverted);
197
+ return tmp;
198
+ }
199
+ export function FpDiv(f, lhs, rhs) {
200
+ return f.multiply(lhs, typeof rhs === 'bigint' ? invert(rhs, f.ORDER) : f.invert(rhs));
201
+ }
202
+ // NOTE: very fragile, always bench. Major performance points:
203
+ // - NonNormalized ops
204
+ // - Object.freeze
205
+ // - same shape of object (don't add/remove keys)
206
+ export function Fp(ORDER, bitLen, isLE = false, redef = {}) {
207
+ if (ORDER <= _0n)
208
+ throw new Error(`Expected Fp ORDER > 0, got ${ORDER}`);
209
+ const { nBitLength: BITS, nByteLength: BYTES } = utils.nLength(ORDER, bitLen);
210
+ if (BYTES > 2048)
211
+ throw new Error('Field lengths over 2048 bytes are not supported');
212
+ const sqrtP = (num) => sqrt(num, ORDER);
213
+ const f = Object.freeze({
214
+ ORDER,
215
+ BITS,
216
+ BYTES,
217
+ MASK: utils.bitMask(BITS),
218
+ ZERO: _0n,
219
+ ONE: _1n,
220
+ create: (num) => mod(num, ORDER),
221
+ isValid: (num) => {
222
+ if (typeof num !== 'bigint')
223
+ throw new Error(`Invalid field element: expected bigint, got ${typeof num}`);
224
+ return _0n <= num && num < ORDER;
225
+ },
226
+ isZero: (num) => num === _0n,
227
+ isOdd: (num) => (num & _1n) === _1n,
228
+ negate: (num) => mod(-num, ORDER),
229
+ equals: (lhs, rhs) => lhs === rhs,
230
+ square: (num) => mod(num * num, ORDER),
231
+ add: (lhs, rhs) => mod(lhs + rhs, ORDER),
232
+ subtract: (lhs, rhs) => mod(lhs - rhs, ORDER),
233
+ multiply: (lhs, rhs) => mod(lhs * rhs, ORDER),
234
+ pow: (num, power) => FpPow(f, num, power),
235
+ div: (lhs, rhs) => mod(lhs * invert(rhs, ORDER), ORDER),
236
+ // Same as above, but doesn't normalize
237
+ squareN: (num) => num * num,
238
+ addN: (lhs, rhs) => lhs + rhs,
239
+ subtractN: (lhs, rhs) => lhs - rhs,
240
+ multiplyN: (lhs, rhs) => lhs * rhs,
241
+ invert: (num) => invert(num, ORDER),
242
+ sqrt: redef.sqrt || sqrtP,
243
+ invertBatch: (lst) => FpInvertBatch(f, lst),
244
+ toBytes: (num) => isLE ? utils.numberToBytesLE(num, BYTES) : utils.numberToBytesBE(num, BYTES),
245
+ fromBytes: (bytes) => {
246
+ if (bytes.length !== BYTES)
247
+ throw new Error(`Fp.fromBytes: expected ${BYTES}, got ${bytes.length}`);
248
+ return isLE ? utils.bytesToNumberLE(bytes) : utils.bytesToNumberBE(bytes);
249
+ },
250
+ });
251
+ return Object.freeze(f);
252
+ }
package/lib/esm/utils.js CHANGED
@@ -1,12 +1,18 @@
1
1
  /*! @noble/curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
2
- // The import here is via the package name. This is to ensure
3
- // that exports mapping/resolution does fall into place.
4
- import { crypto } from '@noble/curves/crypto';
2
+ import * as mod from './modular.js';
3
+ const _0n = BigInt(0);
4
+ const _1n = BigInt(1);
5
+ const _2n = BigInt(2);
5
6
  export function validateOpts(curve) {
6
- for (const i of ['P', 'n', 'h', 'Gx', 'Gy']) {
7
+ mod.validateField(curve.Fp);
8
+ for (const i of ['n', 'h']) {
7
9
  if (typeof curve[i] !== 'bigint')
8
10
  throw new Error(`Invalid curve param ${i}=${curve[i]} (${typeof curve[i]})`);
9
11
  }
12
+ if (!curve.Fp.isValid(curve.Gx))
13
+ throw new Error('Invalid generator X coordinate Fp element');
14
+ if (!curve.Fp.isValid(curve.Gy))
15
+ throw new Error('Invalid generator Y coordinate Fp element');
10
16
  for (const i of ['nBitLength', 'nByteLength']) {
11
17
  if (curve[i] === undefined)
12
18
  continue; // Optional
@@ -16,7 +22,6 @@ export function validateOpts(curve) {
16
22
  // Set defaults
17
23
  return Object.freeze({ ...nLength(curve.n, curve.nBitLength), ...curve });
18
24
  }
19
- import * as mod from './modular.js';
20
25
  const hexes = Array.from({ length: 256 }, (v, i) => i.toString(16).padStart(2, '0'));
21
26
  export function bytesToHex(uint8a) {
22
27
  if (!(uint8a instanceof Uint8Array))
@@ -106,7 +111,6 @@ export function nLength(n, nBitLength) {
106
111
  * @param hash hash output from sha512, or a similar function
107
112
  * @returns valid private scalar
108
113
  */
109
- const _1n = BigInt(1);
110
114
  export function hashToPrivateScalar(hash, CURVE_ORDER, isLE = false) {
111
115
  hash = ensureBytes(hash);
112
116
  const orderLen = nLength(CURVE_ORDER).nByteLength;
@@ -125,17 +129,19 @@ export function equalBytes(b1, b2) {
125
129
  return false;
126
130
  return true;
127
131
  }
128
- /**
129
- * Cryptographically secure PRNG
130
- */
131
- export function randomBytes(bytesLength = 32) {
132
- if (crypto.web) {
133
- return crypto.web.getRandomValues(new Uint8Array(bytesLength));
134
- }
135
- else if (crypto.node) {
136
- return new Uint8Array(crypto.node.randomBytes(bytesLength).buffer);
137
- }
138
- else {
139
- throw new Error("The environment doesn't have randomBytes function");
140
- }
132
+ // Bit operations
133
+ // Amount of bits inside bigint (Same as n.toString(2).length)
134
+ export function bitLen(n) {
135
+ let len;
136
+ for (len = 0; n > 0n; n >>= _1n, len += 1)
137
+ ;
138
+ return len;
141
139
  }
140
+ // Gets single bit at position. NOTE: first bit position is 0 (same as arrays)
141
+ // Same as !!+Array.from(n.toString(2)).reverse()[pos]
142
+ export const bitGet = (n, pos) => (n >> BigInt(pos)) & 1n;
143
+ // Sets single bit at position
144
+ export const bitSet = (n, pos, value) => n | ((value ? _1n : _0n) << BigInt(pos));
145
+ // Return mask for N bits (Same as BigInt(`0b${Array(i).fill('1').join('')}`))
146
+ // Not using ** operator with bigints for old engines.
147
+ export const bitMask = (n) => (_2n << BigInt(n - 1)) - _1n;