@noble/curves 1.7.0 → 1.8.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 (194) hide show
  1. package/README.md +24 -8
  2. package/_shortw_utils.d.ts +8 -54
  3. package/_shortw_utils.d.ts.map +1 -1
  4. package/_shortw_utils.js +6 -2
  5. package/_shortw_utils.js.map +1 -1
  6. package/abstract/bls.d.ts +8 -6
  7. package/abstract/bls.d.ts.map +1 -1
  8. package/abstract/bls.js +17 -1
  9. package/abstract/bls.js.map +1 -1
  10. package/abstract/curve.d.ts +26 -31
  11. package/abstract/curve.d.ts.map +1 -1
  12. package/abstract/curve.js +19 -12
  13. package/abstract/curve.js.map +1 -1
  14. package/abstract/edwards.d.ts +12 -23
  15. package/abstract/edwards.d.ts.map +1 -1
  16. package/abstract/edwards.js +5 -1
  17. package/abstract/edwards.js.map +1 -1
  18. package/abstract/hash-to-curve.d.ts +28 -8
  19. package/abstract/hash-to-curve.d.ts.map +1 -1
  20. package/abstract/hash-to-curve.js +15 -10
  21. package/abstract/hash-to-curve.js.map +1 -1
  22. package/abstract/modular.d.ts +30 -5
  23. package/abstract/modular.d.ts.map +1 -1
  24. package/abstract/modular.js +36 -16
  25. package/abstract/modular.js.map +1 -1
  26. package/abstract/montgomery.d.ts.map +1 -1
  27. package/abstract/montgomery.js +6 -1
  28. package/abstract/montgomery.js.map +1 -1
  29. package/abstract/poseidon.d.ts +9 -0
  30. package/abstract/poseidon.d.ts.map +1 -1
  31. package/abstract/poseidon.js +9 -1
  32. package/abstract/poseidon.js.map +1 -1
  33. package/abstract/tower.d.ts +12 -1
  34. package/abstract/tower.d.ts.map +1 -1
  35. package/abstract/tower.js +14 -11
  36. package/abstract/tower.js.map +1 -1
  37. package/abstract/utils.d.ts +10 -5
  38. package/abstract/utils.d.ts.map +1 -1
  39. package/abstract/utils.js +5 -1
  40. package/abstract/utils.js.map +1 -1
  41. package/abstract/weierstrass.d.ts +46 -80
  42. package/abstract/weierstrass.d.ts.map +1 -1
  43. package/abstract/weierstrass.js +34 -7
  44. package/abstract/weierstrass.js.map +1 -1
  45. package/bls12-381.d.ts +11 -0
  46. package/bls12-381.d.ts.map +1 -1
  47. package/bls12-381.js +72 -59
  48. package/bls12-381.js.map +1 -1
  49. package/bn254.d.ts +4 -3
  50. package/bn254.d.ts.map +1 -1
  51. package/bn254.js +24 -20
  52. package/bn254.js.map +1 -1
  53. package/ed25519.d.ts +24 -4
  54. package/ed25519.d.ts.map +1 -1
  55. package/ed25519.js +30 -6
  56. package/ed25519.js.map +1 -1
  57. package/ed448.d.ts +23 -8
  58. package/ed448.d.ts.map +1 -1
  59. package/ed448.js +30 -8
  60. package/ed448.js.map +1 -1
  61. package/esm/_shortw_utils.d.ts +8 -54
  62. package/esm/_shortw_utils.d.ts.map +1 -1
  63. package/esm/_shortw_utils.js +6 -2
  64. package/esm/_shortw_utils.js.map +1 -1
  65. package/esm/abstract/bls.d.ts +8 -6
  66. package/esm/abstract/bls.d.ts.map +1 -1
  67. package/esm/abstract/bls.js +17 -1
  68. package/esm/abstract/bls.js.map +1 -1
  69. package/esm/abstract/curve.d.ts +26 -31
  70. package/esm/abstract/curve.d.ts.map +1 -1
  71. package/esm/abstract/curve.js +19 -12
  72. package/esm/abstract/curve.js.map +1 -1
  73. package/esm/abstract/edwards.d.ts +12 -23
  74. package/esm/abstract/edwards.d.ts.map +1 -1
  75. package/esm/abstract/edwards.js +5 -1
  76. package/esm/abstract/edwards.js.map +1 -1
  77. package/esm/abstract/hash-to-curve.d.ts +28 -8
  78. package/esm/abstract/hash-to-curve.d.ts.map +1 -1
  79. package/esm/abstract/hash-to-curve.js +15 -10
  80. package/esm/abstract/hash-to-curve.js.map +1 -1
  81. package/esm/abstract/modular.d.ts +30 -5
  82. package/esm/abstract/modular.d.ts.map +1 -1
  83. package/esm/abstract/modular.js +36 -16
  84. package/esm/abstract/modular.js.map +1 -1
  85. package/esm/abstract/montgomery.d.ts.map +1 -1
  86. package/esm/abstract/montgomery.js +6 -1
  87. package/esm/abstract/montgomery.js.map +1 -1
  88. package/esm/abstract/poseidon.d.ts +9 -0
  89. package/esm/abstract/poseidon.d.ts.map +1 -1
  90. package/esm/abstract/poseidon.js +9 -1
  91. package/esm/abstract/poseidon.js.map +1 -1
  92. package/esm/abstract/tower.d.ts +12 -1
  93. package/esm/abstract/tower.d.ts.map +1 -1
  94. package/esm/abstract/tower.js +14 -11
  95. package/esm/abstract/tower.js.map +1 -1
  96. package/esm/abstract/utils.d.ts +10 -5
  97. package/esm/abstract/utils.d.ts.map +1 -1
  98. package/esm/abstract/utils.js +4 -0
  99. package/esm/abstract/utils.js.map +1 -1
  100. package/esm/abstract/weierstrass.d.ts +46 -80
  101. package/esm/abstract/weierstrass.d.ts.map +1 -1
  102. package/esm/abstract/weierstrass.js +32 -6
  103. package/esm/abstract/weierstrass.js.map +1 -1
  104. package/esm/bls12-381.d.ts +11 -0
  105. package/esm/bls12-381.d.ts.map +1 -1
  106. package/esm/bls12-381.js +72 -59
  107. package/esm/bls12-381.js.map +1 -1
  108. package/esm/bn254.d.ts +4 -3
  109. package/esm/bn254.d.ts.map +1 -1
  110. package/esm/bn254.js +24 -20
  111. package/esm/bn254.js.map +1 -1
  112. package/esm/ed25519.d.ts +24 -4
  113. package/esm/ed25519.d.ts.map +1 -1
  114. package/esm/ed25519.js +31 -7
  115. package/esm/ed25519.js.map +1 -1
  116. package/esm/ed448.d.ts +23 -8
  117. package/esm/ed448.d.ts.map +1 -1
  118. package/esm/ed448.js +31 -9
  119. package/esm/ed448.js.map +1 -1
  120. package/esm/index.js +4 -0
  121. package/esm/index.js.map +1 -1
  122. package/esm/jubjub.d.ts +4 -8
  123. package/esm/jubjub.d.ts.map +1 -1
  124. package/esm/jubjub.js +6 -5
  125. package/esm/jubjub.js.map +1 -1
  126. package/esm/p256.d.ts +10 -104
  127. package/esm/p256.d.ts.map +1 -1
  128. package/esm/p256.js +9 -2
  129. package/esm/p256.js.map +1 -1
  130. package/esm/p384.d.ts +10 -104
  131. package/esm/p384.d.ts.map +1 -1
  132. package/esm/p384.js +9 -2
  133. package/esm/p384.js.map +1 -1
  134. package/esm/p521.d.ts +11 -104
  135. package/esm/p521.d.ts.map +1 -1
  136. package/esm/p521.js +11 -3
  137. package/esm/p521.js.map +1 -1
  138. package/esm/pasta.d.ts +5 -2
  139. package/esm/pasta.d.ts.map +1 -1
  140. package/esm/pasta.js +6 -2
  141. package/esm/pasta.js.map +1 -1
  142. package/esm/secp256k1.d.ts +29 -57
  143. package/esm/secp256k1.d.ts.map +1 -1
  144. package/esm/secp256k1.js +33 -7
  145. package/esm/secp256k1.js.map +1 -1
  146. package/index.js +4 -0
  147. package/index.js.map +1 -1
  148. package/jubjub.d.ts +4 -8
  149. package/jubjub.d.ts.map +1 -1
  150. package/jubjub.js +6 -5
  151. package/jubjub.js.map +1 -1
  152. package/p256.d.ts +10 -104
  153. package/p256.d.ts.map +1 -1
  154. package/p256.js +9 -2
  155. package/p256.js.map +1 -1
  156. package/p384.d.ts +10 -104
  157. package/p384.d.ts.map +1 -1
  158. package/p384.js +9 -2
  159. package/p384.js.map +1 -1
  160. package/p521.d.ts +11 -104
  161. package/p521.d.ts.map +1 -1
  162. package/p521.js +11 -3
  163. package/p521.js.map +1 -1
  164. package/package.json +10 -8
  165. package/pasta.d.ts +5 -2
  166. package/pasta.d.ts.map +1 -1
  167. package/pasta.js +6 -2
  168. package/pasta.js.map +1 -1
  169. package/secp256k1.d.ts +29 -57
  170. package/secp256k1.d.ts.map +1 -1
  171. package/secp256k1.js +33 -7
  172. package/secp256k1.js.map +1 -1
  173. package/src/_shortw_utils.ts +18 -8
  174. package/src/abstract/bls.ts +17 -17
  175. package/src/abstract/curve.ts +50 -17
  176. package/src/abstract/edwards.ts +11 -5
  177. package/src/abstract/hash-to-curve.ts +41 -16
  178. package/src/abstract/modular.ts +55 -27
  179. package/src/abstract/montgomery.ts +7 -1
  180. package/src/abstract/poseidon.ts +28 -6
  181. package/src/abstract/tower.ts +59 -14
  182. package/src/abstract/utils.ts +26 -19
  183. package/src/abstract/weierstrass.ts +68 -35
  184. package/src/bls12-381.ts +72 -60
  185. package/src/bn254.ts +32 -24
  186. package/src/ed25519.ts +50 -20
  187. package/src/ed448.ts +48 -21
  188. package/src/index.ts +4 -0
  189. package/src/jubjub.ts +10 -10
  190. package/src/p256.ts +15 -9
  191. package/src/p384.ts +15 -9
  192. package/src/p521.ts +17 -10
  193. package/src/pasta.ts +15 -7
  194. package/src/secp256k1.ts +55 -13
@@ -1,20 +1,19 @@
1
+ /**
2
+ * Towered extension fields.
3
+ * Rather than implementing a massive 12th-degree extension directly, it is more efficient
4
+ * to build it up from smaller extensions: a tower of extensions.
5
+ *
6
+ * For BLS12-381, the Fp12 field is implemented as a quadratic (degree two) extension,
7
+ * on top of a cubic (degree three) extension, on top of a quadratic extension of Fp.
8
+ *
9
+ * For more info: "Pairings for beginners" by Costello, section 7.3.
10
+ * @module
11
+ */
1
12
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
2
13
  import * as mod from './modular.js';
3
14
  import { bitLen, bitMask, concatBytes, notImplemented } from './utils.js';
4
15
  import type { ProjConstructor, ProjPointType } from './weierstrass.js';
5
16
 
6
- /*
7
- Towered extension fields
8
-
9
- Rather than implementing a massive 12th-degree extension directly, it is more efficient
10
- to build it up from smaller extensions: a tower of extensions.
11
-
12
- For BLS12-381, the Fp12 field is implemented as a quadratic (degree two) extension,
13
- on top of a cubic (degree three) extension, on top of a quadratic extension of Fp.
14
-
15
- For more info: "Pairings for beginners" by Costello, section 7.3.
16
- */
17
-
18
17
  // Be friendly to bad ECMAScript parsers by not using bigint literals
19
18
  // prettier-ignore
20
19
  const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3);
@@ -75,7 +74,20 @@ function calcFrobeniusCoefficients<T>(
75
74
  }
76
75
 
77
76
  // This works same at least for bls12-381, bn254 and bls12-377
78
- export function psiFrobenius(Fp: mod.IField<Fp>, Fp2: Fp2Bls, base: Fp2) {
77
+ export function psiFrobenius(
78
+ Fp: mod.IField<Fp>,
79
+ Fp2: Fp2Bls,
80
+ base: Fp2
81
+ ): {
82
+ psi: (x: Fp2, y: Fp2) => [Fp2, Fp2];
83
+ psi2: (x: Fp2, y: Fp2) => [Fp2, Fp2];
84
+ G2psi: (c: ProjConstructor<Fp2>, P: ProjPointType<Fp2>) => ProjPointType<Fp2>;
85
+ G2psi2: (c: ProjConstructor<Fp2>, P: ProjPointType<Fp2>) => ProjPointType<Fp2>;
86
+ PSI_X: Fp2;
87
+ PSI_Y: Fp2;
88
+ PSI2_X: Fp2;
89
+ PSI2_Y: Fp2;
90
+ } {
79
91
  // Ψ endomorphism
80
92
  const PSI_X = Fp2.pow(base, (Fp.ORDER - _1n) / _3n); // u^((p-1)/3)
81
93
  const PSI_Y = Fp2.pow(base, (Fp.ORDER - _1n) / _2n); // u^((p-1)/2)
@@ -120,7 +132,37 @@ export type Tower12Opts = {
120
132
  Fp12finalExponentiate: (num: Fp12) => Fp12;
121
133
  };
122
134
 
123
- export function tower12(opts: Tower12Opts) {
135
+ export function tower12(opts: Tower12Opts): {
136
+ Fp: Readonly<mod.IField<bigint> & Required<Pick<mod.IField<bigint>, 'isOdd'>>>;
137
+ Fp2: mod.IField<Fp2> & {
138
+ NONRESIDUE: Fp2;
139
+ fromBigTuple: (tuple: BigintTuple | bigint[]) => Fp2;
140
+ reim: (num: Fp2) => { re: bigint; im: bigint };
141
+ mulByNonresidue: (num: Fp2) => Fp2;
142
+ mulByB: (num: Fp2) => Fp2;
143
+ frobeniusMap(num: Fp2, power: number): Fp2;
144
+ };
145
+ Fp6: mod.IField<Fp6> & {
146
+ fromBigSix: (tuple: BigintSix) => Fp6;
147
+ mulByNonresidue: (num: Fp6) => Fp6;
148
+ frobeniusMap(num: Fp6, power: number): Fp6;
149
+ mul1(num: Fp6, b1: Fp2): Fp6;
150
+ mul01(num: Fp6, b0: Fp2, b1: Fp2): Fp6;
151
+ mulByFp2(lhs: Fp6, rhs: Fp2): Fp6;
152
+ };
153
+ Fp4Square: (a: Fp2, b: Fp2) => { first: Fp2; second: Fp2 };
154
+ Fp12: mod.IField<Fp12> & {
155
+ fromBigTwelve: (t: BigintTwelve) => Fp12;
156
+ frobeniusMap(num: Fp12, power: number): Fp12;
157
+ mul014(num: Fp12, o0: Fp2, o1: Fp2, o4: Fp2): Fp12;
158
+ mul034(num: Fp12, o0: Fp2, o3: Fp2, o4: Fp2): Fp12;
159
+ mulByFp2(lhs: Fp12, rhs: Fp2): Fp12;
160
+ conjugate(num: Fp12): Fp12;
161
+ finalExponentiate(num: Fp12): Fp12;
162
+ _cyclotomicSquare(num: Fp12): Fp12;
163
+ _cyclotomicExp(num: Fp12, n: bigint): Fp12;
164
+ };
165
+ } {
124
166
  const { ORDER } = opts;
125
167
  // Fp
126
168
  const Fp = mod.Field(ORDER);
@@ -173,6 +215,7 @@ export function tower12(opts: Tower12Opts) {
173
215
  const Fp2Nonresidue = Fp2fromBigTuple(opts.FP2_NONRESIDUE);
174
216
  const Fp2: mod.IField<Fp2> & Fp2Utils = {
175
217
  ORDER: FP2_ORDER,
218
+ isLE: Fp.isLE,
176
219
  NONRESIDUE: Fp2Nonresidue,
177
220
  BITS: bitLen(FP2_ORDER),
178
221
  BYTES: Math.ceil(bitLen(FP2_ORDER) / 8),
@@ -339,6 +382,7 @@ export function tower12(opts: Tower12Opts) {
339
382
 
340
383
  const Fp6: mod.IField<Fp6> & Fp6Utils = {
341
384
  ORDER: Fp2.ORDER, // TODO: unused, but need to verify
385
+ isLE: Fp2.isLE,
342
386
  BITS: 3 * Fp2.BITS,
343
387
  BYTES: 3 * Fp2.BYTES,
344
388
  MASK: bitMask(3 * Fp2.BITS),
@@ -495,6 +539,7 @@ export function tower12(opts: Tower12Opts) {
495
539
 
496
540
  const Fp12: mod.IField<Fp12> & Fp12Utils = {
497
541
  ORDER: Fp2.ORDER, // TODO: unused, but need to verify
542
+ isLE: Fp6.isLE,
498
543
  BITS: 2 * Fp2.BITS,
499
544
  BYTES: 2 * Fp2.BYTES,
500
545
  MASK: bitMask(2 * Fp2.BITS),
@@ -1,4 +1,9 @@
1
+ /**
2
+ * Hex, bytes and number utilities.
3
+ * @module
4
+ */
1
5
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
6
+
2
7
  // 100 lines of code in the file are duplicated from noble-hashes (utils).
3
8
  // This is OK: `abstract` directory does not use noble-hashes.
4
9
  // User may opt-in into using different hashing library. This way, noble-hashes
@@ -155,7 +160,7 @@ export function concatBytes(...arrays: Uint8Array[]): Uint8Array {
155
160
  }
156
161
 
157
162
  // Compares 2 u8a-s in kinda constant time
158
- export function equalBytes(a: Uint8Array, b: Uint8Array) {
163
+ export function equalBytes(a: Uint8Array, b: Uint8Array): boolean {
159
164
  if (a.length !== b.length) return false;
160
165
  let diff = 0;
161
166
  for (let i = 0; i < a.length; i++) diff |= a[i] ^ b[i];
@@ -177,7 +182,7 @@ export function utf8ToBytes(str: string): Uint8Array {
177
182
  // Is positive bigint
178
183
  const isPosBig = (n: bigint) => typeof n === 'bigint' && _0n <= n;
179
184
 
180
- export function inRange(n: bigint, min: bigint, max: bigint) {
185
+ export function inRange(n: bigint, min: bigint, max: bigint): boolean {
181
186
  return isPosBig(n) && isPosBig(min) && isPosBig(max) && min <= n && n < max;
182
187
  }
183
188
 
@@ -186,7 +191,7 @@ export function inRange(n: bigint, min: bigint, max: bigint) {
186
191
  * @example
187
192
  * aInRange('x', x, 1n, 256n); // would assume x is in (1n..255n)
188
193
  */
189
- export function aInRange(title: string, n: bigint, min: bigint, max: bigint) {
194
+ export function aInRange(title: string, n: bigint, min: bigint, max: bigint): void {
190
195
  // Why min <= n < max and not a (min < n < max) OR b (min <= n <= max)?
191
196
  // consider P=256n, min=0n, max=P
192
197
  // - a for min=0 would require -1: `inRange('x', x, -1n, P)`
@@ -202,7 +207,7 @@ export function aInRange(title: string, n: bigint, min: bigint, max: bigint) {
202
207
  * Calculates amount of bits in a bigint.
203
208
  * Same as `n.toString(2).length`
204
209
  */
205
- export function bitLen(n: bigint) {
210
+ export function bitLen(n: bigint): number {
206
211
  let len;
207
212
  for (len = 0; n > _0n; n >>= _1n, len += 1);
208
213
  return len;
@@ -213,14 +218,14 @@ export function bitLen(n: bigint) {
213
218
  * NOTE: first bit position is 0 (same as arrays)
214
219
  * Same as `!!+Array.from(n.toString(2)).reverse()[pos]`
215
220
  */
216
- export function bitGet(n: bigint, pos: number) {
221
+ export function bitGet(n: bigint, pos: number): bigint {
217
222
  return (n >> BigInt(pos)) & _1n;
218
223
  }
219
224
 
220
225
  /**
221
226
  * Sets single bit at position.
222
227
  */
223
- export function bitSet(n: bigint, pos: number, value: boolean) {
228
+ export function bitSet(n: bigint, pos: number, value: boolean): bigint {
224
229
  return n | ((value ? _1n : _0n) << BigInt(pos));
225
230
  }
226
231
 
@@ -228,7 +233,7 @@ export function bitSet(n: bigint, pos: number, value: boolean) {
228
233
  * Calculate mask for N bits. Not using ** operator with bigints because of old engines.
229
234
  * Same as BigInt(`0b${Array(i).fill('1').join('')}`)
230
235
  */
231
- export const bitMask = (n: number) => (_2n << BigInt(n - 1)) - _1n;
236
+ export const bitMask = (n: number): bigint => (_2n << BigInt(n - 1)) - _1n;
232
237
 
233
238
  // DRBG
234
239
 
@@ -295,15 +300,15 @@ export function createHmacDrbg<T>(
295
300
  // Validating curves and fields
296
301
 
297
302
  const validatorFns = {
298
- bigint: (val: any) => typeof val === 'bigint',
299
- function: (val: any) => typeof val === 'function',
300
- boolean: (val: any) => typeof val === 'boolean',
301
- string: (val: any) => typeof val === 'string',
302
- stringOrUint8Array: (val: any) => typeof val === 'string' || isBytes(val),
303
- isSafeInteger: (val: any) => Number.isSafeInteger(val),
304
- array: (val: any) => Array.isArray(val),
305
- field: (val: any, object: any) => (object as any).Fp.isValid(val),
306
- hash: (val: any) => typeof val === 'function' && Number.isSafeInteger(val.outputLen),
303
+ bigint: (val: any): boolean => typeof val === 'bigint',
304
+ function: (val: any): boolean => typeof val === 'function',
305
+ boolean: (val: any): boolean => typeof val === 'boolean',
306
+ string: (val: any): boolean => typeof val === 'string',
307
+ stringOrUint8Array: (val: any): boolean => typeof val === 'string' || isBytes(val),
308
+ isSafeInteger: (val: any): boolean => Number.isSafeInteger(val),
309
+ array: (val: any): boolean => Array.isArray(val),
310
+ field: (val: any, object: any): any => (object as any).Fp.isValid(val),
311
+ hash: (val: any): boolean => typeof val === 'function' && Number.isSafeInteger(val.outputLen),
307
312
  } as const;
308
313
  type Validator = keyof typeof validatorFns;
309
314
  type ValMap<T extends Record<string, any>> = { [K in keyof T]?: Validator };
@@ -313,7 +318,7 @@ export function validateObject<T extends Record<string, any>>(
313
318
  object: T,
314
319
  validators: ValMap<T>,
315
320
  optValidators: ValMap<T> = {}
316
- ) {
321
+ ): T {
317
322
  const checkField = (fieldName: keyof T, type: Validator, isOptional: boolean) => {
318
323
  const checkVal = validatorFns[type];
319
324
  if (typeof checkVal !== 'function') throw new Error('invalid validator function');
@@ -342,7 +347,7 @@ export function validateObject<T extends Record<string, any>>(
342
347
  /**
343
348
  * throws not implemented error
344
349
  */
345
- export const notImplemented = () => {
350
+ export const notImplemented = (): never => {
346
351
  throw new Error('not implemented');
347
352
  };
348
353
 
@@ -350,7 +355,9 @@ export const notImplemented = () => {
350
355
  * Memoizes (caches) computation result.
351
356
  * Uses WeakMap: the value is going auto-cleaned by GC after last reference is removed.
352
357
  */
353
- export function memoized<T extends object, R, O extends any[]>(fn: (arg: T, ...args: O) => R) {
358
+ export function memoized<T extends object, R, O extends any[]>(
359
+ fn: (arg: T, ...args: O) => R
360
+ ): (arg: T, ...args: O) => R {
354
361
  const map = new WeakMap<T, R>();
355
362
  return (arg: T, ...args: O): R => {
356
363
  const val = map.get(arg);
@@ -1,5 +1,30 @@
1
+ /**
2
+ * Short Weierstrass curve methods. The formula is: y² = x³ + ax + b.
3
+ *
4
+ * ### Design rationale for types
5
+ *
6
+ * * Interaction between classes from different curves should fail:
7
+ * `k256.Point.BASE.add(p256.Point.BASE)`
8
+ * * For this purpose we want to use `instanceof` operator, which is fast and works during runtime
9
+ * * Different calls of `curve()` would return different classes -
10
+ * `curve(params) !== curve(params)`: if somebody decided to monkey-patch their curve,
11
+ * it won't affect others
12
+ *
13
+ * TypeScript can't infer types for classes created inside a function. Classes is one instance
14
+ * of nominative types in TypeScript and interfaces only check for shape, so it's hard to create
15
+ * unique type for every function call.
16
+ *
17
+ * We can use generic types via some param, like curve opts, but that would:
18
+ * 1. Enable interaction between `curve(params)` and `curve(params)` (curves of same params)
19
+ * which is hard to debug.
20
+ * 2. Params can be generic and we can't enforce them to be constant value:
21
+ * if somebody creates curve from non-constant params,
22
+ * it would be allowed to interact with other curves with non-constant params
23
+ *
24
+ * @todo https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#unique-symbol
25
+ * @module
26
+ */
1
27
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
2
- // Short Weierstrass curve. The formula is: y² = x³ + ax + b
3
28
  import {
4
29
  AffinePoint,
5
30
  BasicCurve,
@@ -44,28 +69,6 @@ function validateSigVerOpts(opts: SignOpts | VerOpts) {
44
69
  if (opts.prehash !== undefined) abool('prehash', opts.prehash);
45
70
  }
46
71
 
47
- /**
48
- * ### Design rationale for types
49
- *
50
- * * Interaction between classes from different curves should fail:
51
- * `k256.Point.BASE.add(p256.Point.BASE)`
52
- * * For this purpose we want to use `instanceof` operator, which is fast and works during runtime
53
- * * Different calls of `curve()` would return different classes -
54
- * `curve(params) !== curve(params)`: if somebody decided to monkey-patch their curve,
55
- * it won't affect others
56
- *
57
- * TypeScript can't infer types for classes created inside a function. Classes is one instance of nominative types in TypeScript and interfaces only check for shape, so it's hard to create unique type for every function call.
58
- *
59
- * We can use generic types via some param, like curve opts, but that would:
60
- * 1. Enable interaction between `curve(params)` and `curve(params)` (curves of same params)
61
- * which is hard to debug.
62
- * 2. Params can be generic and we can't enforce them to be constant value:
63
- * if somebody creates curve from non-constant params,
64
- * it would be allowed to interact with other curves with non-constant params
65
- *
66
- * TODO: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#unique-symbol
67
- */
68
-
69
72
  // Instance for 3d XYZ points
70
73
  export interface ProjPointType<T> extends Group<ProjPointType<T>> {
71
74
  readonly px: T;
@@ -102,7 +105,11 @@ export type CurvePointsType<T> = BasicWCurve<T> & {
102
105
  toBytes?: (c: ProjConstructor<T>, point: ProjPointType<T>, isCompressed: boolean) => Uint8Array;
103
106
  };
104
107
 
105
- function validatePointOpts<T>(curve: CurvePointsType<T>) {
108
+ export type CurvePointsTypeWithLength<T> = Readonly<
109
+ CurvePointsType<T> & { nByteLength: number; nBitLength: number }
110
+ >;
111
+
112
+ function validatePointOpts<T>(curve: CurvePointsType<T>): CurvePointsTypeWithLength<T> {
106
113
  const opts = validateBasic(curve);
107
114
  ut.validateObject(
108
115
  opts,
@@ -146,6 +153,31 @@ export type CurvePointsRes<T> = {
146
153
 
147
154
  const { bytesToNumberBE: b2n, hexToBytes: h2b } = ut;
148
155
 
156
+ export class DERErr extends Error {
157
+ constructor(m = '') {
158
+ super(m);
159
+ }
160
+ }
161
+ export type IDER = {
162
+ // asn.1 DER encoding utils
163
+ Err: typeof DERErr;
164
+ // Basic building block is TLV (Tag-Length-Value)
165
+ _tlv: {
166
+ encode: (tag: number, data: string) => string;
167
+ // v - value, l - left bytes (unparsed)
168
+ decode(tag: number, data: Uint8Array): { v: Uint8Array; l: Uint8Array };
169
+ };
170
+ // https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag,
171
+ // since we always use positive integers here. It must always be empty:
172
+ // - add zero byte if exists
173
+ // - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding)
174
+ _int: {
175
+ encode(num: bigint): string;
176
+ decode(data: Uint8Array): bigint;
177
+ };
178
+ toSig(hex: string | Uint8Array): { r: bigint; s: bigint };
179
+ hexFromSig(sig: { r: bigint; s: bigint }): string;
180
+ };
149
181
  /**
150
182
  * ASN.1 DER encoding utilities. ASN is very complex & fragile. Format:
151
183
  *
@@ -153,16 +185,12 @@ const { bytesToNumberBE: b2n, hexToBytes: h2b } = ut;
153
185
  *
154
186
  * Docs: https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/, https://luca.ntop.org/Teaching/Appunti/asn1.html
155
187
  */
156
- export const DER = {
188
+ export const DER: IDER = {
157
189
  // asn.1 DER encoding utils
158
- Err: class DERErr extends Error {
159
- constructor(m = '') {
160
- super(m);
161
- }
162
- },
190
+ Err: DERErr,
163
191
  // Basic building block is TLV (Tag-Length-Value)
164
192
  _tlv: {
165
- encode: (tag: number, data: string) => {
193
+ encode: (tag: number, data: string): string => {
166
194
  const { Err: E } = DER;
167
195
  if (tag < 0 || tag > 256) throw new E('tlv.encode: wrong tag');
168
196
  if (data.length & 1) throw new E('tlv.encode: unpadded data');
@@ -206,7 +234,7 @@ export const DER = {
206
234
  // - add zero byte if exists
207
235
  // - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding)
208
236
  _int: {
209
- encode(num: bigint) {
237
+ encode(num: bigint): string {
210
238
  const { Err: E } = DER;
211
239
  if (num < _0n) throw new E('integer: negative integers are not allowed');
212
240
  let hex = ut.numberToHexUnpadded(num);
@@ -737,7 +765,9 @@ export type CurveType = BasicWCurve<bigint> & {
737
765
  bits2int_modN?: (bytes: Uint8Array) => bigint;
738
766
  };
739
767
 
740
- function validateOpts(curve: CurveType) {
768
+ function validateOpts(
769
+ curve: CurveType
770
+ ): Readonly<CurveType & { nByteLength: number; nBitLength: number }> {
741
771
  const opts = validateBasic(curve);
742
772
  ut.validateObject(
743
773
  opts,
@@ -1214,7 +1244,10 @@ export function weierstrass(curveDef: CurveType): CurveFn {
1214
1244
  * @param Z
1215
1245
  * @returns
1216
1246
  */
1217
- export function SWUFpSqrtRatio<T>(Fp: mod.IField<T>, Z: T) {
1247
+ export function SWUFpSqrtRatio<T>(
1248
+ Fp: mod.IField<T>,
1249
+ Z: T
1250
+ ): (u: T, v: T) => { isValid: boolean; value: T } {
1218
1251
  // Generic implementation
1219
1252
  const q = Fp.ORDER;
1220
1253
  let l = _0n;
@@ -1293,7 +1326,7 @@ export function mapToCurveSimpleSWU<T>(
1293
1326
  B: T;
1294
1327
  Z: T;
1295
1328
  }
1296
- ) {
1329
+ ): (u: T) => { x: T; y: T } {
1297
1330
  mod.validateField(Fp);
1298
1331
  if (!Fp.isValid(opts.A) || !Fp.isValid(opts.B) || !Fp.isValid(opts.Z))
1299
1332
  throw new Error('mapToCurveSimpleSWU: invalid opts');
package/src/bls12-381.ts CHANGED
@@ -19,61 +19,72 @@ import { AffinePoint, mapToCurveSimpleSWU, ProjPointType } from './abstract/weie
19
19
  import { tower12, psiFrobenius } from './abstract/tower.js';
20
20
  import type { Fp, Fp2, Fp6, Fp12 } from './abstract/tower.js';
21
21
 
22
- /*
23
- bls12-381 is pairing-friendly Barreto-Lynn-Scott elliptic curve construction allowing to:
24
- - Construct zk-SNARKs at the 120-bit security
25
- - Efficiently verify N aggregate signatures with 1 pairing and N ec additions:
26
- the Boneh-Lynn-Shacham signature scheme is orders of magnitude more efficient than Schnorr
27
-
28
- ### Summary
29
- 1. BLS Relies on Bilinear Pairing (expensive)
30
- 2. Private Keys: 32 bytes
31
- 3. Public Keys: 48 bytes: 381 bit affine x coordinate, encoded into 48 big-endian bytes.
32
- 4. Signatures: 96 bytes: two 381 bit integers (affine x coordinate), encoded into two 48 big-endian byte arrays.
33
- - The signature is a point on the G2 subgroup, which is defined over a finite field
34
- with elements twice as big as the G1 curve (G2 is over Fp2 rather than Fp. Fp2 is analogous to the complex numbers).
35
- 5. The 12 stands for the Embedding degree.
36
-
37
- ### Formulas
38
- - `P = pk x G` - public keys
39
- - `S = pk x H(m)` - signing
40
- - `e(P, H(m)) == e(G, S)` - verification using pairings
41
- - `e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si))` - signature aggregation
42
-
43
- ### Compatibility and notes
44
- 1. It is compatible with Algorand, Chia, Dfinity, Ethereum, Filecoin, ZEC
45
- Filecoin uses little endian byte arrays for private keys - make sure to reverse byte order.
46
- 2. Some projects use G2 for public keys and G1 for signatures. It's called "short signature"
47
- 3. Curve security level is about 120 bits as per Barbulescu-Duquesne 2017
48
- https://hal.science/hal-01534101/file/main.pdf
49
- 4. Compatible with specs:
50
- [cfrg-pairing-friendly-curves-11](https://tools.ietf.org/html/draft-irtf-cfrg-pairing-friendly-curves-11),
51
- [cfrg-bls-signature-05](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature-05),
52
- [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380).
53
- */
22
+ /**
23
+ * bls12-381 is pairing-friendly Barreto-Lynn-Scott elliptic curve construction allowing to:
24
+ * * Construct zk-SNARKs at the ~120-bit security
25
+ * * Efficiently verify N aggregate signatures with 1 pairing and N ec additions:
26
+ * the Boneh-Lynn-Shacham signature scheme is orders of magnitude more efficient than Schnorr
27
+ *
28
+ * ### Summary
29
+ * 1. BLS Relies on Bilinear Pairing (expensive)
30
+ * 2. Private Keys: 32 bytes
31
+ * 3. Public Keys: 48 bytes: 381 bit affine x coordinate, encoded into 48 big-endian bytes.
32
+ * 4. Signatures: 96 bytes: two 381 bit integers (affine x coordinate), encoded into two 48 big-endian byte arrays.
33
+ * - The signature is a point on the G2 subgroup, which is defined over a finite field
34
+ * with elements twice as big as the G1 curve (G2 is over Fp2 rather than Fp. Fp2 is analogous to the
35
+ * complex numbers).
36
+ * - We also support reversed 96-byte pubkeys & 48-byte short signatures.
37
+ * 5. The 12 stands for the Embedding degree.
38
+ *
39
+ * ### Formulas
40
+ * - `P = pk x G` - public keys
41
+ * - `S = pk x H(m)` - signing
42
+ * - `e(P, H(m)) == e(G, S)` - verification using pairings
43
+ * - `e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si))` - signature aggregation
44
+ *
45
+ * ### Compatibility and notes
46
+ * 1. It is compatible with Algorand, Chia, Dfinity, Ethereum, Filecoin, ZEC.
47
+ * Filecoin uses little endian byte arrays for private keys - make sure to reverse byte order.
48
+ * 2. Some projects use G2 for public keys and G1 for signatures. It's called "short signature".
49
+ * 3. Curve security level is about 120 bits as per [Barbulescu-Duquesne 2017](https://hal.science/hal-01534101/file/main.pdf)
50
+ * 4. Compatible with specs:
51
+ * [cfrg-pairing-friendly-curves-11](https://tools.ietf.org/html/draft-irtf-cfrg-pairing-friendly-curves-11),
52
+ * [cfrg-bls-signature-05](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature-05),
53
+ * [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380).
54
+ *
55
+ * ### Params
56
+ * To verify curve parameters, see
57
+ * [pairing-friendly-curves spec](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-pairing-friendly-curves-11).
58
+ * Basic math is done over finite fields over p.
59
+ * More complicated math is done over polynominal extension fields.
60
+ * To simplify calculations in Fp12, we construct extension tower:
61
+ * - Fp₁₂ = Fp₆² => Fp₂³
62
+ * - Fp(u) / (u² - β) where β = -1
63
+ * - Fp₂(v) / (v³ - ξ) where ξ = u + 1
64
+ * - Fp₆(w) / (w² - γ) where γ = v
65
+ * Here goes constants && point encoding format
66
+ *
67
+ * Embedding degree (k): 12
68
+ * Seed (X): -15132376222941642752
69
+ * Fr: (x⁴-x²+1)
70
+ * Fp: ((x-1)² ⋅ r(x)/3+x)
71
+ * (E/Fp): Y²=X³+4
72
+ * (Eₜ/Fp²): Y² = X³+4(u+1) (M-type twist)
73
+ * Ate loop size: X
74
+ *
75
+ * ### Towers
76
+ * - Fp²[u] = Fp/u²+1
77
+ * - Fp⁶[v] = Fp²/v³-1-u
78
+ * - Fp¹²[w] = Fp⁶/w²-v
79
+ *
80
+ * @todo construct bls & bn fp/fr from seed.
81
+ * @module
82
+ */
54
83
 
55
84
  // Be friendly to bad ECMAScript parsers by not using bigint literals
56
85
  // prettier-ignore
57
86
  const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3), _4n = BigInt(4);
58
87
 
59
- /*
60
- Embedding degree (k): 12
61
- Seed (X): -15132376222941642752
62
- Fr: (x⁴-x²+1)
63
- Fp: ((x-1)² ⋅ r(x)/3+x)
64
- (E/Fp): Y²=X³+4
65
- (Eₜ/Fp²): Y² = X³+4(u+1) (M-type twist)
66
- Ate loop size: X
67
-
68
- Towers:
69
- - Fp²[u] = Fp/u²+1
70
- - Fp⁶[v] = Fp²/v³-1-u
71
- - Fp¹²[w] = Fp⁶/w²-v
72
-
73
-
74
- TODO: BLS & BN Fp/Fr can be constructed from seed.
75
- */
76
-
77
88
  // The BLS parameter x (seed) for BLS12-381. NOTE: it is negative!
78
89
  const BLS_X = BigInt('0xd201000000010000');
79
90
  const BLS_X_LEN = bitLen(BLS_X);
@@ -418,16 +429,17 @@ function signatureG2ToRawBytes(point: ProjPointType<Fp2>) {
418
429
  );
419
430
  }
420
431
 
421
- // To verify curve parameters, see pairing-friendly-curves spec:
422
- // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-pairing-friendly-curves-11
423
- // Basic math is done over finite fields over p.
424
- // More complicated math is done over polynominal extension fields.
425
- // To simplify calculations in Fp12, we construct extension tower:
426
- // Fp₁₂ = Fp₆² => Fp₂³
427
- // Fp(u) / (u² - β) where β = -1
428
- // Fp₂(v) / (v³ - ξ) where ξ = u + 1
429
- // Fp₆(w) / ( - γ) where γ = v
430
- // Here goes constants && point encoding format
432
+ /**
433
+ * bls12-381 pairing-friendly curve.
434
+ * @example
435
+ * import { bls12_381 as bls } from '@noble/curves/bls12-381';
436
+ * // G1 keys, G2 signatures
437
+ * const privateKey = '67d53f170b908cabb9eb326c3c337762d59289a8fec79f7bc9254b584b73265c';
438
+ * const message = '64726e3da8';
439
+ * const publicKey = bls.getPublicKey(privateKey);
440
+ * const signature = bls.sign(message, privateKey);
441
+ * const isValid = bls.verify(signature, message, publicKey);
442
+ */
431
443
  export const bls12_381: CurveFn = bls({
432
444
  // Fields
433
445
  fields: {
package/src/bn254.ts CHANGED
@@ -1,24 +1,10 @@
1
- /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
2
- import { sha256 } from '@noble/hashes/sha256';
3
- import { getHash } from './_shortw_utils.js';
4
- import { weierstrass } from './abstract/weierstrass.js';
5
- import { randomBytes } from '@noble/hashes/utils';
6
- import { bls, CurveFn, PostPrecomputeFn, PostPrecomputePointAddFn } from './abstract/bls.js';
7
- import { Field } from './abstract/modular.js';
8
- import { bitGet, bitLen, notImplemented } from './abstract/utils.js';
9
- import { tower12, psiFrobenius } from './abstract/tower.js';
10
- // Types
11
- import type { Fp, Fp2, Fp6, Fp12 } from './abstract/tower.js';
12
- // prettier-ignore
13
- const _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3);
14
- // prettier-ignore
15
- const _6n = BigInt(6);
1
+ /**
2
+ * bn254, previously known as alt_bn_128, when it had 128-bit security.
16
3
 
17
- /*
18
- bn254, previously known as alt_bn_128, when it had 128-bit security.
19
4
  Barbulescu-Duquesne 2017 shown it's weaker: just about 100 bits,
20
5
  so the naming has been adjusted to its prime bit count:
21
- https://hal.science/hal-01534101/file/main.pdf
6
+ https://hal.science/hal-01534101/file/main.pdf.
7
+ Compatible with EIP-196 and EIP-197.
22
8
 
23
9
  There are huge compatibility issues in the ecosystem:
24
10
 
@@ -42,9 +28,8 @@ because it at least has specs:
42
28
  - https://github.com/ethereum/py_pairing
43
29
  - https://github.com/ethereum/execution-specs/blob/master/src/ethereum/crypto/alt_bn128.py
44
30
  - Points are encoded differently in different implementations
45
- */
46
31
 
47
- /*
32
+ ### Params
48
33
  Seed (X): 4965661367192848881
49
34
  Fr: (36x⁴+36x³+18x²+6x+1)
50
35
  Fp: (36x⁴+36x³+24x²+6x+1)
@@ -52,11 +37,34 @@ Fp: (36x⁴+36x³+24x²+6x+1)
52
37
  (Et / Fp²): Y² = X³+3/(u+9) (D-type twist)
53
38
  Ate loop size: 6x+2
54
39
 
55
- Towers:
40
+ ### Towers
56
41
  - Fp²[u] = Fp/u²+1
57
42
  - Fp⁶[v] = Fp²/v³-9-u
58
43
  - Fp¹²[w] = Fp⁶/w²-v
59
- */
44
+
45
+ * @module
46
+ */
47
+ /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
48
+ import { sha256 } from '@noble/hashes/sha256';
49
+ import { getHash } from './_shortw_utils.js';
50
+ import { CurveFn, weierstrass } from './abstract/weierstrass.js';
51
+ import { randomBytes } from '@noble/hashes/utils';
52
+ import {
53
+ bls,
54
+ CurveFn as BLSCurveFn,
55
+ PostPrecomputeFn,
56
+ PostPrecomputePointAddFn,
57
+ } from './abstract/bls.js';
58
+ import { Field } from './abstract/modular.js';
59
+ import { bitGet, bitLen, notImplemented } from './abstract/utils.js';
60
+ import { tower12, psiFrobenius } from './abstract/tower.js';
61
+ // Types
62
+ import type { Fp, Fp2, Fp6, Fp12 } from './abstract/tower.js';
63
+ // prettier-ignore
64
+ const _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3);
65
+ // prettier-ignore
66
+ const _6n = BigInt(6);
67
+
60
68
  const BN_X = BigInt('4965661367192848881');
61
69
  const BN_X_LEN = bitLen(BN_X);
62
70
  const SIX_X_SQUARED = _6n * BN_X ** _2n;
@@ -166,7 +174,7 @@ export const _postPrecompute: PostPrecomputeFn = (
166
174
  * bn254 (a.k.a. alt_bn128) pairing-friendly curve.
167
175
  * Contains G1 / G2 operations and pairings.
168
176
  */
169
- export const bn254: CurveFn = bls({
177
+ export const bn254: BLSCurveFn = bls({
170
178
  // Fields
171
179
  fields: { Fp, Fp2, Fp6, Fp12, Fr },
172
180
  G1: {
@@ -234,7 +242,7 @@ export const bn254: CurveFn = bls({
234
242
  * This is very rare and probably not used anywhere.
235
243
  * Instead, you should use G1 / G2, defined above.
236
244
  */
237
- export const bn254_weierstrass = weierstrass({
245
+ export const bn254_weierstrass: CurveFn = weierstrass({
238
246
  a: BigInt(0),
239
247
  b: BigInt(3),
240
248
  Fp,