@noble/curves 1.9.5 → 2.0.0-beta.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.
Files changed (211) hide show
  1. package/README.md +267 -421
  2. package/abstract/bls.d.ts +49 -111
  3. package/abstract/bls.d.ts.map +1 -1
  4. package/abstract/bls.js +108 -152
  5. package/abstract/bls.js.map +1 -1
  6. package/abstract/curve.d.ts +7 -48
  7. package/abstract/curve.d.ts.map +1 -1
  8. package/abstract/curve.js +22 -47
  9. package/abstract/curve.js.map +1 -1
  10. package/abstract/edwards.d.ts +17 -68
  11. package/abstract/edwards.d.ts.map +1 -1
  12. package/abstract/edwards.js +98 -175
  13. package/abstract/edwards.js.map +1 -1
  14. package/abstract/fft.js +14 -27
  15. package/abstract/fft.js.map +1 -1
  16. package/abstract/hash-to-curve.d.ts +11 -24
  17. package/abstract/hash-to-curve.d.ts.map +1 -1
  18. package/abstract/hash-to-curve.js +30 -35
  19. package/abstract/hash-to-curve.js.map +1 -1
  20. package/abstract/modular.d.ts +5 -17
  21. package/abstract/modular.d.ts.map +1 -1
  22. package/abstract/modular.js +166 -167
  23. package/abstract/modular.js.map +1 -1
  24. package/abstract/montgomery.d.ts +4 -9
  25. package/abstract/montgomery.d.ts.map +1 -1
  26. package/abstract/montgomery.js +17 -20
  27. package/abstract/montgomery.js.map +1 -1
  28. package/abstract/oprf.d.ts +282 -0
  29. package/abstract/oprf.d.ts.map +1 -0
  30. package/abstract/oprf.js +297 -0
  31. package/abstract/oprf.js.map +1 -0
  32. package/abstract/poseidon.js +20 -24
  33. package/abstract/poseidon.js.map +1 -1
  34. package/abstract/tower.d.ts +9 -7
  35. package/abstract/tower.d.ts.map +1 -1
  36. package/abstract/tower.js +600 -364
  37. package/abstract/tower.js.map +1 -1
  38. package/abstract/weierstrass.d.ts +12 -145
  39. package/abstract/weierstrass.d.ts.map +1 -1
  40. package/abstract/weierstrass.js +153 -377
  41. package/abstract/weierstrass.js.map +1 -1
  42. package/bls12-381.d.ts +2 -2
  43. package/bls12-381.d.ts.map +1 -1
  44. package/bls12-381.js +174 -216
  45. package/bls12-381.js.map +1 -1
  46. package/bn254.d.ts +58 -10
  47. package/bn254.d.ts.map +1 -1
  48. package/bn254.js +70 -130
  49. package/bn254.js.map +1 -1
  50. package/ed25519.d.ts +12 -31
  51. package/ed25519.d.ts.map +1 -1
  52. package/ed25519.js +104 -146
  53. package/ed25519.js.map +1 -1
  54. package/ed448.d.ts +14 -33
  55. package/ed448.d.ts.map +1 -1
  56. package/ed448.js +105 -132
  57. package/ed448.js.map +1 -1
  58. package/index.js +1 -1
  59. package/misc.d.ts +10 -14
  60. package/misc.d.ts.map +1 -1
  61. package/misc.js +51 -60
  62. package/misc.js.map +1 -1
  63. package/nist.d.ts +11 -14
  64. package/nist.d.ts.map +1 -1
  65. package/nist.js +46 -55
  66. package/nist.js.map +1 -1
  67. package/package.json +9 -224
  68. package/secp256k1.d.ts +7 -23
  69. package/secp256k1.d.ts.map +1 -1
  70. package/secp256k1.js +72 -83
  71. package/secp256k1.js.map +1 -1
  72. package/src/abstract/bls.ts +197 -344
  73. package/src/abstract/curve.ts +10 -83
  74. package/src/abstract/edwards.ts +96 -223
  75. package/src/abstract/hash-to-curve.ts +32 -45
  76. package/src/abstract/modular.ts +144 -130
  77. package/src/abstract/montgomery.ts +21 -22
  78. package/src/abstract/oprf.ts +600 -0
  79. package/src/abstract/tower.ts +627 -382
  80. package/src/abstract/weierstrass.ts +101 -482
  81. package/src/bls12-381.ts +148 -176
  82. package/src/bn254.ts +67 -122
  83. package/src/ed25519.ts +65 -118
  84. package/src/ed448.ts +63 -113
  85. package/src/index.ts +1 -1
  86. package/src/misc.ts +66 -49
  87. package/src/nist.ts +48 -57
  88. package/src/secp256k1.ts +56 -88
  89. package/src/utils.ts +41 -61
  90. package/src/webcrypto.ts +362 -0
  91. package/utils.d.ts +28 -19
  92. package/utils.d.ts.map +1 -1
  93. package/utils.js +45 -121
  94. package/utils.js.map +1 -1
  95. package/webcrypto.d.ts +47 -0
  96. package/webcrypto.d.ts.map +1 -0
  97. package/webcrypto.js +231 -0
  98. package/webcrypto.js.map +1 -0
  99. package/esm/_shortw_utils.d.ts +0 -19
  100. package/esm/_shortw_utils.d.ts.map +0 -1
  101. package/esm/_shortw_utils.js +0 -16
  102. package/esm/_shortw_utils.js.map +0 -1
  103. package/esm/abstract/bls.d.ts +0 -190
  104. package/esm/abstract/bls.d.ts.map +0 -1
  105. package/esm/abstract/bls.js +0 -408
  106. package/esm/abstract/bls.js.map +0 -1
  107. package/esm/abstract/curve.d.ts +0 -231
  108. package/esm/abstract/curve.d.ts.map +0 -1
  109. package/esm/abstract/curve.js +0 -465
  110. package/esm/abstract/curve.js.map +0 -1
  111. package/esm/abstract/edwards.d.ts +0 -237
  112. package/esm/abstract/edwards.d.ts.map +0 -1
  113. package/esm/abstract/edwards.js +0 -632
  114. package/esm/abstract/edwards.js.map +0 -1
  115. package/esm/abstract/fft.d.ts +0 -122
  116. package/esm/abstract/fft.d.ts.map +0 -1
  117. package/esm/abstract/fft.js +0 -425
  118. package/esm/abstract/fft.js.map +0 -1
  119. package/esm/abstract/hash-to-curve.d.ts +0 -102
  120. package/esm/abstract/hash-to-curve.d.ts.map +0 -1
  121. package/esm/abstract/hash-to-curve.js +0 -203
  122. package/esm/abstract/hash-to-curve.js.map +0 -1
  123. package/esm/abstract/modular.d.ts +0 -171
  124. package/esm/abstract/modular.d.ts.map +0 -1
  125. package/esm/abstract/modular.js +0 -530
  126. package/esm/abstract/modular.js.map +0 -1
  127. package/esm/abstract/montgomery.d.ts +0 -30
  128. package/esm/abstract/montgomery.d.ts.map +0 -1
  129. package/esm/abstract/montgomery.js +0 -157
  130. package/esm/abstract/montgomery.js.map +0 -1
  131. package/esm/abstract/poseidon.d.ts +0 -68
  132. package/esm/abstract/poseidon.d.ts.map +0 -1
  133. package/esm/abstract/poseidon.js +0 -296
  134. package/esm/abstract/poseidon.js.map +0 -1
  135. package/esm/abstract/tower.d.ts +0 -93
  136. package/esm/abstract/tower.d.ts.map +0 -1
  137. package/esm/abstract/tower.js +0 -502
  138. package/esm/abstract/tower.js.map +0 -1
  139. package/esm/abstract/utils.d.ts +0 -5
  140. package/esm/abstract/utils.d.ts.map +0 -1
  141. package/esm/abstract/utils.js +0 -7
  142. package/esm/abstract/utils.js.map +0 -1
  143. package/esm/abstract/weierstrass.d.ts +0 -412
  144. package/esm/abstract/weierstrass.d.ts.map +0 -1
  145. package/esm/abstract/weierstrass.js +0 -1428
  146. package/esm/abstract/weierstrass.js.map +0 -1
  147. package/esm/bls12-381.d.ts +0 -16
  148. package/esm/bls12-381.d.ts.map +0 -1
  149. package/esm/bls12-381.js +0 -738
  150. package/esm/bls12-381.js.map +0 -1
  151. package/esm/bn254.d.ts +0 -18
  152. package/esm/bn254.d.ts.map +0 -1
  153. package/esm/bn254.js +0 -246
  154. package/esm/bn254.js.map +0 -1
  155. package/esm/ed25519.d.ts +0 -106
  156. package/esm/ed25519.d.ts.map +0 -1
  157. package/esm/ed25519.js +0 -467
  158. package/esm/ed25519.js.map +0 -1
  159. package/esm/ed448.d.ts +0 -101
  160. package/esm/ed448.d.ts.map +0 -1
  161. package/esm/ed448.js +0 -448
  162. package/esm/ed448.js.map +0 -1
  163. package/esm/index.d.ts +0 -2
  164. package/esm/index.d.ts.map +0 -1
  165. package/esm/index.js +0 -17
  166. package/esm/index.js.map +0 -1
  167. package/esm/jubjub.d.ts +0 -12
  168. package/esm/jubjub.d.ts.map +0 -1
  169. package/esm/jubjub.js +0 -12
  170. package/esm/jubjub.js.map +0 -1
  171. package/esm/misc.d.ts +0 -19
  172. package/esm/misc.d.ts.map +0 -1
  173. package/esm/misc.js +0 -109
  174. package/esm/misc.js.map +0 -1
  175. package/esm/nist.d.ts +0 -21
  176. package/esm/nist.d.ts.map +0 -1
  177. package/esm/nist.js +0 -132
  178. package/esm/nist.js.map +0 -1
  179. package/esm/p256.d.ts +0 -16
  180. package/esm/p256.d.ts.map +0 -1
  181. package/esm/p256.js +0 -16
  182. package/esm/p256.js.map +0 -1
  183. package/esm/p384.d.ts +0 -16
  184. package/esm/p384.d.ts.map +0 -1
  185. package/esm/p384.js +0 -16
  186. package/esm/p384.js.map +0 -1
  187. package/esm/p521.d.ts +0 -16
  188. package/esm/p521.d.ts.map +0 -1
  189. package/esm/p521.js +0 -16
  190. package/esm/p521.js.map +0 -1
  191. package/esm/package.json +0 -4
  192. package/esm/pasta.d.ts +0 -10
  193. package/esm/pasta.d.ts.map +0 -1
  194. package/esm/pasta.js +0 -10
  195. package/esm/pasta.js.map +0 -1
  196. package/esm/secp256k1.d.ts +0 -89
  197. package/esm/secp256k1.d.ts.map +0 -1
  198. package/esm/secp256k1.js +0 -292
  199. package/esm/secp256k1.js.map +0 -1
  200. package/esm/utils.d.ts +0 -110
  201. package/esm/utils.d.ts.map +0 -1
  202. package/esm/utils.js +0 -322
  203. package/esm/utils.js.map +0 -1
  204. package/src/_shortw_utils.ts +0 -21
  205. package/src/abstract/utils.ts +0 -7
  206. package/src/jubjub.ts +0 -12
  207. package/src/p256.ts +0 -15
  208. package/src/p384.ts +0 -15
  209. package/src/p521.ts +0 -15
  210. package/src/package.json +0 -3
  211. package/src/pasta.ts +0 -9
package/src/bls12-381.ts CHANGED
@@ -78,19 +78,19 @@ Filecoin uses little endian byte arrays for secret keys - make sure to reverse b
78
78
  */
79
79
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
80
80
  import { sha256 } from '@noble/hashes/sha2.js';
81
- import { bls, type CurveFn } from './abstract/bls.ts';
81
+ import { bls, type BlsCurvePairWithSignatures } from './abstract/bls.ts';
82
82
  import { Field, type IField } from './abstract/modular.ts';
83
83
  import {
84
84
  abytes,
85
- bitGet,
86
85
  bitLen,
87
86
  bitMask,
88
87
  bytesToHex,
89
88
  bytesToNumberBE,
90
89
  concatBytes,
91
- ensureBytes,
90
+ copyBytes,
91
+ hexToBytes,
92
92
  numberToBytesBE,
93
- type Hex,
93
+ randomBytes,
94
94
  } from './utils.ts';
95
95
  // Types
96
96
  import { isogenyMap } from './abstract/hash-to-curve.ts';
@@ -98,6 +98,7 @@ import type { BigintTuple, Fp, Fp12, Fp2, Fp6 } from './abstract/tower.ts';
98
98
  import { psiFrobenius, tower12 } from './abstract/tower.ts';
99
99
  import {
100
100
  mapToCurveSimpleSWU,
101
+ weierstrass,
101
102
  type AffinePoint,
102
103
  type WeierstrassOpts,
103
104
  type WeierstrassPoint,
@@ -147,10 +148,13 @@ const bls12_381_CURVE_G1: WeierstrassOpts<bigint> = {
147
148
  };
148
149
 
149
150
  // CURVE FIELDS
150
- export const bls12_381_Fr: IField<bigint> = Field(bls12_381_CURVE_G1.n, { modFromBytes: true });
151
- const { Fp, Fp2, Fp6, Fp4Square, Fp12 } = tower12({
152
- // Order of Fp
151
+ // r = z⁴ z² + 1; CURVE.n from other curves
152
+ export const bls12_381_Fr: IField<bigint> = Field(bls12_381_CURVE_G1.n, {
153
+ modFromBytes: true,
154
+ });
155
+ const { Fp, Fp2, Fp6, Fp12 } = tower12({
153
156
  ORDER: bls12_381_CURVE_G1.p,
157
+ X_LEN: BLS_X_LEN,
154
158
  // Finite extension field over irreducible polynominal.
155
159
  // Fp(u) / (u² - β) where β = -1
156
160
  FP2_NONRESIDUE: [_1n, _1n],
@@ -160,41 +164,6 @@ const { Fp, Fp2, Fp6, Fp4Square, Fp12 } = tower12({
160
164
  // (T0-T1) + (T0+T1)*i
161
165
  return { c0: Fp.sub(t0, t1), c1: Fp.add(t0, t1) };
162
166
  },
163
- // Fp12
164
- // A cyclotomic group is a subgroup of Fp^n defined by
165
- // GΦₙ(p) = {α ∈ Fpⁿ : α^Φₙ(p) = 1}
166
- // The result of any pairing is in a cyclotomic subgroup
167
- // https://eprint.iacr.org/2009/565.pdf
168
- Fp12cyclotomicSquare: ({ c0, c1 }): Fp12 => {
169
- const { c0: c0c0, c1: c0c1, c2: c0c2 } = c0;
170
- const { c0: c1c0, c1: c1c1, c2: c1c2 } = c1;
171
- const { first: t3, second: t4 } = Fp4Square(c0c0, c1c1);
172
- const { first: t5, second: t6 } = Fp4Square(c1c0, c0c2);
173
- const { first: t7, second: t8 } = Fp4Square(c0c1, c1c2);
174
- const t9 = Fp2.mulByNonresidue(t8); // T8 * (u + 1)
175
- return {
176
- c0: Fp6.create({
177
- c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), _2n), t3), // 2 * (T3 - c0c0) + T3
178
- c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1), _2n), t5), // 2 * (T5 - c0c1) + T5
179
- c2: Fp2.add(Fp2.mul(Fp2.sub(t7, c0c2), _2n), t7),
180
- }), // 2 * (T7 - c0c2) + T7
181
- c1: Fp6.create({
182
- c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0), _2n), t9), // 2 * (T9 + c1c0) + T9
183
- c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1), _2n), t4), // 2 * (T4 + c1c1) + T4
184
- c2: Fp2.add(Fp2.mul(Fp2.add(t6, c1c2), _2n), t6),
185
- }),
186
- }; // 2 * (T6 + c1c2) + T6
187
- },
188
- Fp12cyclotomicExp(num, n) {
189
- let z = Fp12.ONE;
190
- for (let i = BLS_X_LEN - 1; i >= 0; i--) {
191
- z = Fp12._cyclotomicSquare(z);
192
- if (bitGet(n, i)) z = Fp12.mul(z, num);
193
- }
194
- return z;
195
- },
196
- // https://eprint.iacr.org/2010/354.pdf
197
- // https://eprint.iacr.org/2009/565.pdf
198
167
  Fp12finalExponentiate: (num) => {
199
168
  const x = BLS_X;
200
169
  // this^(q⁶) / this
@@ -226,7 +195,7 @@ const { G2psi, G2psi2 } = psiFrobenius(Fp, Fp2, Fp2.div(Fp2.ONE, Fp2.NONRESIDUE)
226
195
  * hash: any function, e.g. BBS+ uses BLAKE2: see [github](https://github.com/hyperledger/aries-framework-go/issues/2247).
227
196
  * Parameter values come from [section 8.8.2 of RFC 9380](https://www.rfc-editor.org/rfc/rfc9380#section-8.8.2).
228
197
  */
229
- const htfDefaults = Object.freeze({
198
+ const hasher_opts = Object.freeze({
230
199
  DST: 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_',
231
200
  encodeDST: 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_',
232
201
  p: Fp.ORDER,
@@ -274,8 +243,9 @@ const bls12_381_CURVE_G2 = {
274
243
  const COMPZERO = setMask(Fp.toBytes(_0n), { infinity: true, compressed: true });
275
244
 
276
245
  function parseMask(bytes: Uint8Array) {
277
- // Copy, so we can remove mask data. It will be removed also later, when Fp.create will call modulo.
278
- bytes = bytes.slice();
246
+ // Copy, so we can remove mask data.
247
+ // It will be removed also later, when Fp.create will call modulo.
248
+ bytes = copyBytes(bytes);
279
249
  const mask = bytes[0] & 0b1110_0000;
280
250
  const compressed = !!((mask >> 7) & 1); // compression bit (0b1000_0000)
281
251
  const infinity = !!((mask >> 6) & 1); // point at infinity bit (0b0100_0000)
@@ -355,8 +325,8 @@ function pointG1FromBytes(bytes: Uint8Array): AffinePoint<Fp> {
355
325
  }
356
326
  }
357
327
 
358
- function signatureG1FromBytes(hex: Hex): WeierstrassPoint<Fp> {
359
- const { infinity, sort, value } = parseMask(ensureBytes('signatureHex', hex, 48));
328
+ function signatureG1FromBytes(bytes: Uint8Array): WeierstrassPoint<Fp> {
329
+ const { infinity, sort, value } = parseMask(abytes(bytes, 48, 'signature'));
360
330
  const P = Fp.ORDER;
361
331
  const Point = bls12_381.G1.Point;
362
332
  const compressedValue = bytesToNumberBE(value);
@@ -461,10 +431,10 @@ function pointG2FromBytes(bytes: Uint8Array): AffinePoint<Fp2> {
461
431
  }
462
432
  }
463
433
 
464
- function signatureG2FromBytes(hex: Hex) {
434
+ function signatureG2FromBytes(bytes: Uint8Array) {
465
435
  const { ORDER: P } = Fp;
466
436
  // TODO: Optimize, it's very slow because of sqrt.
467
- const { infinity, sort, value } = parseMask(ensureBytes('signatureHex', hex));
437
+ const { infinity, sort, value } = parseMask(abytes(bytes));
468
438
  const Point = bls12_381.G2.Point;
469
439
  const half = value.length / 2;
470
440
  if (half !== 48 && half !== 96)
@@ -493,6 +463,127 @@ function signatureG2FromBytes(hex: Hex) {
493
463
  return point;
494
464
  }
495
465
 
466
+ const signatureCoders = {
467
+ ShortSignature: {
468
+ fromBytes(bytes: Uint8Array) {
469
+ return signatureG1FromBytes(abytes(bytes));
470
+ },
471
+ fromHex(hex: string): WeierstrassPoint<Fp> {
472
+ return signatureG1FromBytes(hexToBytes(hex));
473
+ },
474
+ toBytes(point: WeierstrassPoint<Fp>) {
475
+ return signatureG1ToBytes(point);
476
+ },
477
+ toRawBytes(point: WeierstrassPoint<Fp>) {
478
+ return signatureG1ToBytes(point);
479
+ },
480
+ toHex(point: WeierstrassPoint<Fp>) {
481
+ return bytesToHex(signatureG1ToBytes(point));
482
+ },
483
+ },
484
+ LongSignature: {
485
+ fromBytes(bytes: Uint8Array): WeierstrassPoint<Fp2> {
486
+ return signatureG2FromBytes(abytes(bytes));
487
+ },
488
+ fromHex(hex: string): WeierstrassPoint<Fp2> {
489
+ return signatureG2FromBytes(hexToBytes(hex));
490
+ },
491
+ toBytes(point: WeierstrassPoint<Fp2>) {
492
+ return signatureG2ToBytes(point);
493
+ },
494
+ toRawBytes(point: WeierstrassPoint<Fp2>) {
495
+ return signatureG2ToBytes(point);
496
+ },
497
+ toHex(point: WeierstrassPoint<Fp2>) {
498
+ return bytesToHex(signatureG2ToBytes(point));
499
+ },
500
+ },
501
+ };
502
+
503
+ const fields = {
504
+ Fp,
505
+ Fp2,
506
+ Fp6,
507
+ Fp12,
508
+ Fr: bls12_381_Fr,
509
+ };
510
+ const G1_Point = weierstrass(bls12_381_CURVE_G1, {
511
+ allowInfinityPoint: true,
512
+ Fn: bls12_381_Fr,
513
+ fromBytes: pointG1FromBytes,
514
+ toBytes: pointG1ToBytes,
515
+ // Checks is the point resides in prime-order subgroup.
516
+ // point.isTorsionFree() should return true for valid points
517
+ // It returns false for shitty points.
518
+ // https://eprint.iacr.org/2021/1130.pdf
519
+ isTorsionFree: (c, point): boolean => {
520
+ // GLV endomorphism ψ(P)
521
+ const beta = BigInt(
522
+ '0x5f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe'
523
+ );
524
+ const phi = new c(Fp.mul(point.X, beta), point.Y, point.Z);
525
+ // TODO: unroll
526
+ const xP = point.multiplyUnsafe(BLS_X).negate(); // [x]P
527
+ const u2P = xP.multiplyUnsafe(BLS_X); // [u2]P
528
+ return u2P.equals(phi);
529
+ },
530
+ // Clear cofactor of G1
531
+ // https://eprint.iacr.org/2019/403
532
+ clearCofactor: (_c, point) => {
533
+ // return this.multiplyUnsafe(CURVE.h);
534
+ return point.multiplyUnsafe(BLS_X).add(point); // x*P + P
535
+ },
536
+ });
537
+ const G2_Point = weierstrass(bls12_381_CURVE_G2, {
538
+ Fp: Fp2,
539
+ allowInfinityPoint: true,
540
+ Fn: bls12_381_Fr,
541
+ fromBytes: pointG2FromBytes,
542
+ toBytes: pointG2ToBytes,
543
+ // https://eprint.iacr.org/2021/1130.pdf
544
+ // Older version: https://eprint.iacr.org/2019/814.pdf
545
+ isTorsionFree: (c, P): boolean => {
546
+ return P.multiplyUnsafe(BLS_X).negate().equals(G2psi(c, P)); // ψ(P) == [u](P)
547
+ },
548
+ // clear_cofactor_bls12381_g2 from RFC 9380.
549
+ // https://eprint.iacr.org/2017/419.pdf
550
+ // prettier-ignore
551
+ clearCofactor: (c, P) => {
552
+ const x = BLS_X;
553
+ let t1 = P.multiplyUnsafe(x).negate(); // [-x]P
554
+ let t2 = G2psi(c, P); // Ψ(P)
555
+ let t3 = P.double(); // 2P
556
+ t3 = G2psi2(c, t3); // Ψ²(2P)
557
+ t3 = t3.subtract(t2); // Ψ²(2P) - Ψ(P)
558
+ t2 = t1.add(t2); // [-x]P + Ψ(P)
559
+ t2 = t2.multiplyUnsafe(x).negate(); // [x²]P - [x]Ψ(P)
560
+ t3 = t3.add(t2); // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P)
561
+ t3 = t3.subtract(t1); // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P) + [x]P
562
+ const Q = t3.subtract(P); // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P) + [x]P - 1P
563
+ return Q; // [x²-x-1]P + [x-1]Ψ(P) + Ψ²(2P)
564
+ },
565
+ });
566
+
567
+ const bls12_hasher_opts = {
568
+ mapToG1: mapToG1,
569
+ mapToG2: mapToG2,
570
+ hasherOpts: hasher_opts,
571
+ hasherOptsG1: { ...hasher_opts, m: 1, DST: 'BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_' },
572
+ hasherOptsG2: { ...hasher_opts },
573
+ };
574
+
575
+ const bls12_params = {
576
+ ateLoopSize: BLS_X, // The BLS parameter x for BLS12-381
577
+ xNegative: true,
578
+ twistType: 'multiplicative' as const,
579
+ randomBytes: randomBytes,
580
+ // https://datatracker.ietf.org/doc/html/rfc9380#name-clearing-the-cofactor
581
+ // https://datatracker.ietf.org/doc/html/rfc9380#name-cofactor-clearing-for-bls12
582
+ // G2hEff: BigInt(
583
+ // '0xbc69f08f2ee75b3584c6a0ea91b352888e2a8e9145ad7689986ff031508ffe1329c2f178731db956d82bf015d1212b02ec0ec69d7477c1ae954cbc06689f6a359894c0adebbf6b4e8020005aaa95551'
584
+ // ),
585
+ };
586
+
496
587
  /**
497
588
  * bls12-381 pairing-friendly curve.
498
589
  * @example
@@ -504,133 +595,14 @@ function signatureG2FromBytes(hex: Hex) {
504
595
  * const signature = bls.sign(message, privateKey);
505
596
  * const isValid = bls.verify(signature, message, publicKey);
506
597
  */
507
- export const bls12_381: CurveFn = bls({
508
- // Fields
509
- fields: {
510
- Fp,
511
- Fp2,
512
- Fp6,
513
- Fp12,
514
- Fr: bls12_381_Fr,
515
- },
516
- // G1: y² = x³ + 4
517
- G1: {
518
- ...bls12_381_CURVE_G1,
519
- Fp,
520
- htfDefaults: { ...htfDefaults, m: 1, DST: 'BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_' },
521
- wrapPrivateKey: true,
522
- allowInfinityPoint: true,
523
- // Checks is the point resides in prime-order subgroup.
524
- // point.isTorsionFree() should return true for valid points
525
- // It returns false for shitty points.
526
- // https://eprint.iacr.org/2021/1130.pdf
527
- isTorsionFree: (c, point): boolean => {
528
- // GLV endomorphism ψ(P)
529
- const beta = BigInt(
530
- '0x5f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe'
531
- );
532
- const phi = new c(Fp.mul(point.X, beta), point.Y, point.Z);
533
- // TODO: unroll
534
- const xP = point.multiplyUnsafe(BLS_X).negate(); // [x]P
535
- const u2P = xP.multiplyUnsafe(BLS_X); // [u2]P
536
- return u2P.equals(phi);
537
- },
538
- // Clear cofactor of G1
539
- // https://eprint.iacr.org/2019/403
540
- clearCofactor: (_c, point) => {
541
- // return this.multiplyUnsafe(CURVE.h);
542
- return point.multiplyUnsafe(BLS_X).add(point); // x*P + P
543
- },
544
- mapToCurve: mapToG1,
545
- fromBytes: pointG1FromBytes,
546
- toBytes: pointG1ToBytes,
547
- ShortSignature: {
548
- fromBytes(bytes: Uint8Array) {
549
- abytes(bytes);
550
- return signatureG1FromBytes(bytes);
551
- },
552
- fromHex(hex: Hex): WeierstrassPoint<Fp> {
553
- return signatureG1FromBytes(hex);
554
- },
555
- toBytes(point: WeierstrassPoint<Fp>) {
556
- return signatureG1ToBytes(point);
557
- },
558
- toRawBytes(point: WeierstrassPoint<Fp>) {
559
- return signatureG1ToBytes(point);
560
- },
561
- toHex(point: WeierstrassPoint<Fp>) {
562
- return bytesToHex(signatureG1ToBytes(point));
563
- },
564
- },
565
- },
566
- G2: {
567
- ...bls12_381_CURVE_G2,
568
- Fp: Fp2,
569
- // https://datatracker.ietf.org/doc/html/rfc9380#name-clearing-the-cofactor
570
- // https://datatracker.ietf.org/doc/html/rfc9380#name-cofactor-clearing-for-bls12
571
- hEff: BigInt(
572
- '0xbc69f08f2ee75b3584c6a0ea91b352888e2a8e9145ad7689986ff031508ffe1329c2f178731db956d82bf015d1212b02ec0ec69d7477c1ae954cbc06689f6a359894c0adebbf6b4e8020005aaa95551'
573
- ),
574
- htfDefaults: { ...htfDefaults },
575
- wrapPrivateKey: true,
576
- allowInfinityPoint: true,
577
- mapToCurve: mapToG2,
578
- // Checks is the point resides in prime-order subgroup.
579
- // point.isTorsionFree() should return true for valid points
580
- // It returns false for shitty points.
581
- // https://eprint.iacr.org/2021/1130.pdf
582
- // Older version: https://eprint.iacr.org/2019/814.pdf
583
- isTorsionFree: (c, P): boolean => {
584
- return P.multiplyUnsafe(BLS_X).negate().equals(G2psi(c, P)); // ψ(P) == [u](P)
585
- },
586
- // Maps the point into the prime-order subgroup G2.
587
- // clear_cofactor_bls12381_g2 from RFC 9380.
588
- // https://eprint.iacr.org/2017/419.pdf
589
- // prettier-ignore
590
- clearCofactor: (c, P) => {
591
- const x = BLS_X;
592
- let t1 = P.multiplyUnsafe(x).negate(); // [-x]P
593
- let t2 = G2psi(c, P); // Ψ(P)
594
- let t3 = P.double(); // 2P
595
- t3 = G2psi2(c, t3); // Ψ²(2P)
596
- t3 = t3.subtract(t2); // Ψ²(2P) - Ψ(P)
597
- t2 = t1.add(t2); // [-x]P + Ψ(P)
598
- t2 = t2.multiplyUnsafe(x).negate(); // [x²]P - [x]Ψ(P)
599
- t3 = t3.add(t2); // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P)
600
- t3 = t3.subtract(t1); // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P) + [x]P
601
- const Q = t3.subtract(P); // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P) + [x]P - 1P
602
- return Q; // [x²-x-1]P + [x-1]Ψ(P) + Ψ²(2P)
603
- },
604
- fromBytes: pointG2FromBytes,
605
- toBytes: pointG2ToBytes,
606
- Signature: {
607
- fromBytes(bytes: Uint8Array): WeierstrassPoint<Fp2> {
608
- abytes(bytes);
609
- return signatureG2FromBytes(bytes);
610
- },
611
- fromHex(hex: Hex): WeierstrassPoint<Fp2> {
612
- return signatureG2FromBytes(hex);
613
- },
614
- toBytes(point: WeierstrassPoint<Fp2>) {
615
- return signatureG2ToBytes(point);
616
- },
617
- toRawBytes(point: WeierstrassPoint<Fp2>) {
618
- return signatureG2ToBytes(point);
619
- },
620
- toHex(point: WeierstrassPoint<Fp2>) {
621
- return bytesToHex(signatureG2ToBytes(point));
622
- },
623
- },
624
- },
625
- params: {
626
- ateLoopSize: BLS_X, // The BLS parameter x for BLS12-381
627
- r: bls12_381_CURVE_G1.n, // order; z⁴ − z² + 1; CURVE.n from other curves
628
- xNegative: true,
629
- twistType: 'multiplicative',
630
- },
631
- htfDefaults,
632
- hash: sha256,
633
- });
598
+ export const bls12_381: BlsCurvePairWithSignatures = bls(
599
+ fields,
600
+ G1_Point,
601
+ G2_Point,
602
+ bls12_params,
603
+ bls12_hasher_opts,
604
+ signatureCoders
605
+ );
634
606
 
635
607
  // 3-isogeny map from E' to E https://www.rfc-editor.org/rfc/rfc9380#appendix-E.3
636
608
  const isogenyMapG2 = isogenyMap(
package/src/bn254.ts CHANGED
@@ -54,18 +54,17 @@ Ate loop size: 6x+2
54
54
  * @module
55
55
  */
56
56
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
57
- import { sha256 } from '@noble/hashes/sha2.js';
58
57
  import {
59
- bls,
60
- type CurveFn as BLSCurveFn,
58
+ blsBasic,
59
+ type BLSCurvePair,
61
60
  type PostPrecomputeFn,
62
61
  type PostPrecomputePointAddFn,
63
62
  } from './abstract/bls.ts';
64
63
  import { Field, type IField } from './abstract/modular.ts';
65
64
  import type { Fp, Fp12, Fp2, Fp6 } from './abstract/tower.ts';
66
65
  import { psiFrobenius, tower12 } from './abstract/tower.ts';
67
- import { type CurveFn, weierstrass, type WeierstrassOpts } from './abstract/weierstrass.ts';
68
- import { bitGet, bitLen, notImplemented } from './utils.ts';
66
+ import { weierstrass, type WeierstrassOpts } from './abstract/weierstrass.ts';
67
+ import { bitLen } from './utils.ts';
69
68
  // prettier-ignore
70
69
  const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3);
71
70
  const _6n = BigInt(6);
@@ -94,42 +93,11 @@ const Fp2B = {
94
93
  c1: BigInt('266929791119991161246907387137283842545076965332900288569378510910307636690'),
95
94
  };
96
95
 
97
- const { Fp, Fp2, Fp6, Fp4Square, Fp12 } = tower12({
96
+ const { Fp, Fp2, Fp6, Fp12 } = tower12({
98
97
  ORDER: bn254_G1_CURVE.p,
98
+ X_LEN: BN_X_LEN,
99
99
  FP2_NONRESIDUE: [BigInt(9), _1n],
100
100
  Fp2mulByB: (num) => Fp2.mul(num, Fp2B),
101
- // The result of any pairing is in a cyclotomic subgroup
102
- // https://eprint.iacr.org/2009/565.pdf
103
- Fp12cyclotomicSquare: ({ c0, c1 }): Fp12 => {
104
- const { c0: c0c0, c1: c0c1, c2: c0c2 } = c0;
105
- const { c0: c1c0, c1: c1c1, c2: c1c2 } = c1;
106
- const { first: t3, second: t4 } = Fp4Square(c0c0, c1c1);
107
- const { first: t5, second: t6 } = Fp4Square(c1c0, c0c2);
108
- const { first: t7, second: t8 } = Fp4Square(c0c1, c1c2);
109
- let t9 = Fp2.mulByNonresidue(t8); // T8 * (u + 1)
110
- return {
111
- c0: Fp6.create({
112
- c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), _2n), t3), // 2 * (T3 - c0c0) + T3
113
- c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1), _2n), t5), // 2 * (T5 - c0c1) + T5
114
- c2: Fp2.add(Fp2.mul(Fp2.sub(t7, c0c2), _2n), t7),
115
- }), // 2 * (T7 - c0c2) + T7
116
- c1: Fp6.create({
117
- c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0), _2n), t9), // 2 * (T9 + c1c0) + T9
118
- c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1), _2n), t4), // 2 * (T4 + c1c1) + T4
119
- c2: Fp2.add(Fp2.mul(Fp2.add(t6, c1c2), _2n), t6),
120
- }),
121
- }; // 2 * (T6 + c1c2) + T6
122
- },
123
- Fp12cyclotomicExp(num, n) {
124
- let z = Fp12.ONE;
125
- for (let i = BN_X_LEN - 1; i >= 0; i--) {
126
- z = Fp12._cyclotomicSquare(z);
127
- if (bitGet(n, i)) z = Fp12.mul(z, num);
128
- }
129
- return z;
130
- },
131
- // https://eprint.iacr.org/2010/354.pdf
132
- // https://eprint.iacr.org/2009/565.pdf
133
101
  Fp12finalExponentiate: (num) => {
134
102
  const powMinusX = (num: Fp12) => Fp12.conjugate(Fp12._cyclotomicExp(num, BN_X));
135
103
  const r0 = Fp12.mul(Fp12.conjugate(num), Fp12.inv(num));
@@ -153,24 +121,6 @@ const { Fp, Fp2, Fp6, Fp4Square, Fp12 } = tower12({
153
121
  // END OF CURVE FIELDS
154
122
  const { G2psi, psi } = psiFrobenius(Fp, Fp2, Fp2.NONRESIDUE);
155
123
 
156
- /*
157
- No hashToCurve for now (and signatures):
158
-
159
- - RFC 9380 doesn't mention bn254 and doesn't provide test vectors
160
- - Overall seems like nobody is using BLS signatures on top of bn254
161
- - Seems like it can utilize SVDW, which is not implemented yet
162
- */
163
- const htfDefaults = Object.freeze({
164
- // DST: a domain separation tag defined in section 2.2.5
165
- DST: 'BN254G2_XMD:SHA-256_SVDW_RO_',
166
- encodeDST: 'BN254G2_XMD:SHA-256_SVDW_RO_',
167
- p: Fp.ORDER,
168
- m: 2,
169
- k: 128,
170
- expand: 'xmd',
171
- hash: sha256,
172
- });
173
-
174
124
  export const _postPrecompute: PostPrecomputeFn = (
175
125
  Rx: Fp2,
176
126
  Ry: Fp2,
@@ -202,73 +152,68 @@ const bn254_G2_CURVE: WeierstrassOpts<Fp2> = {
202
152
  ]),
203
153
  };
204
154
 
205
- /**
206
- * bn254 (a.k.a. alt_bn128) pairing-friendly curve.
207
- * Contains G1 / G2 operations and pairings.
208
- */
209
- export const bn254: BLSCurveFn = bls({
210
- // Fields
211
- fields: { Fp, Fp2, Fp6, Fp12, Fr: bn254_Fr },
212
- G1: {
213
- ...bn254_G1_CURVE,
214
- Fp,
215
- htfDefaults: { ...htfDefaults, m: 1, DST: 'BN254G2_XMD:SHA-256_SVDW_RO_' },
216
- wrapPrivateKey: true,
217
- allowInfinityPoint: true,
218
- mapToCurve: notImplemented,
219
- fromBytes: notImplemented,
220
- toBytes: notImplemented,
221
- ShortSignature: {
222
- fromBytes: notImplemented,
223
- fromHex: notImplemented,
224
- toBytes: notImplemented,
225
- toRawBytes: notImplemented,
226
- toHex: notImplemented,
227
- },
228
- },
229
- G2: {
230
- ...bn254_G2_CURVE,
231
- Fp: Fp2,
232
- hEff: BigInt('21888242871839275222246405745257275088844257914179612981679871602714643921549'),
233
- htfDefaults: { ...htfDefaults },
234
- wrapPrivateKey: true,
235
- allowInfinityPoint: true,
236
- isTorsionFree: (c, P) => P.multiplyUnsafe(SIX_X_SQUARED).equals(G2psi(c, P)), // [p]P = [6X^2]P
237
- mapToCurve: notImplemented,
238
- fromBytes: notImplemented,
239
- toBytes: notImplemented,
240
- Signature: {
241
- fromBytes: notImplemented,
242
- fromHex: notImplemented,
243
- toBytes: notImplemented,
244
- toRawBytes: notImplemented,
245
- toHex: notImplemented,
246
- },
247
- },
248
- params: {
249
- ateLoopSize: BN_X * _6n + _2n,
250
- r: bn254_Fr.ORDER,
251
- xNegative: false,
252
- twistType: 'divisive',
253
- },
254
- htfDefaults,
255
- hash: sha256,
256
- postPrecompute: _postPrecompute,
155
+ const fields = { Fp, Fp2, Fp6, Fp12, Fr: bn254_Fr };
156
+ const bn254_G1 = weierstrass(bn254_G1_CURVE, {
157
+ Fp,
158
+ Fn: bn254_Fr,
159
+ allowInfinityPoint: true,
160
+ });
161
+ const bn254_G2 = weierstrass(bn254_G2_CURVE, {
162
+ Fp: Fp2,
163
+ Fn: bn254_Fr,
164
+ allowInfinityPoint: true,
165
+ isTorsionFree: (c, P) => P.multiplyUnsafe(SIX_X_SQUARED).equals(G2psi(c, P)), // [p]P = [6X^2]P
257
166
  });
167
+ /*
168
+ No hashToCurve for now (and signatures):
169
+
170
+ - RFC 9380 doesn't mention bn254 and doesn't provide test vectors
171
+ - Overall seems like nobody is using BLS signatures on top of bn254
172
+ - Seems like it can utilize SVDW, which is not implemented yet
173
+ */
174
+ // const htfDefaults = Object.freeze({
175
+ // // DST: a domain separation tag defined in section 2.2.5
176
+ // DST: 'BN254G2_XMD:SHA-256_SVDW_RO_',
177
+ // encodeDST: 'BN254G2_XMD:SHA-256_SVDW_RO_',
178
+ // p: Fp.ORDER,
179
+ // m: 2,
180
+ // k: 128,
181
+ // expand: 'xmd',
182
+ // hash: sha256,
183
+ // });
184
+ // const hasherOpts = {
185
+ // { ...htfDefaults, m: 1, DST: 'BN254G2_XMD:SHA-256_SVDW_RO_' }
186
+ // };
187
+ const bn254_params = {
188
+ ateLoopSize: BN_X * _6n + _2n,
189
+ r: bn254_Fr.ORDER,
190
+ xNegative: false,
191
+ twistType: 'divisive' as const,
192
+ postPrecompute: _postPrecompute,
193
+ };
194
+ // const bn254_hasher = {
195
+ // hasherOpts: htfDefaults,
196
+ // hasherOptsG1: { m: 1, DST: 'BN254G2_XMD:SHA-256_SVDW_RO_' },
197
+ // hasherOptsG2: htfDefaults
198
+ // };
199
+ // G2_heff hEff: BigInt('21888242871839275222246405745257275088844257914179612981679871602714643921549'),
200
+ // fromBytes: notImplemented,
201
+ // toBytes: notImplemented,
202
+
203
+ // mapToCurve: notImplemented,
204
+ // fromBytes: notImplemented,
205
+ // toBytes: notImplemented,
206
+ // ShortSignature: {
207
+ // fromBytes: notImplemented,
208
+ // fromHex: notImplemented,
209
+ // toBytes: notImplemented,
210
+ // toRawBytes: notImplemented,
211
+ // toHex: notImplemented,
212
+ // },
258
213
 
259
214
  /**
260
- * bn254 weierstrass curve with ECDSA.
261
- * This is very rare and probably not used anywhere.
262
- * Instead, you should use G1 / G2, defined above.
263
- * @deprecated
215
+ * bn254 (a.k.a. alt_bn128) pairing-friendly curve.
216
+ * Contains G1 / G2 operations and pairings.
264
217
  */
265
- export const bn254_weierstrass: CurveFn = weierstrass({
266
- a: BigInt(0),
267
- b: BigInt(3),
268
- Fp,
269
- n: BigInt('21888242871839275222246405745257275088548364400416034343698204186575808495617'),
270
- Gx: BigInt(1),
271
- Gy: BigInt(2),
272
- h: BigInt(1),
273
- hash: sha256,
274
- });
218
+ // bn254_hasher
219
+ export const bn254: BLSCurvePair = blsBasic(fields, bn254_G1, bn254_G2, bn254_params);