@noble/curves 1.9.1 → 1.9.3

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 (223) hide show
  1. package/README.md +238 -227
  2. package/_shortw_utils.d.ts +8 -5
  3. package/_shortw_utils.d.ts.map +1 -1
  4. package/_shortw_utils.js +3 -8
  5. package/_shortw_utils.js.map +1 -1
  6. package/abstract/bls.d.ts +123 -62
  7. package/abstract/bls.d.ts.map +1 -1
  8. package/abstract/bls.js +219 -163
  9. package/abstract/bls.js.map +1 -1
  10. package/abstract/curve.d.ts +142 -21
  11. package/abstract/curve.d.ts.map +1 -1
  12. package/abstract/curve.js +224 -143
  13. package/abstract/curve.js.map +1 -1
  14. package/abstract/edwards.d.ts +190 -49
  15. package/abstract/edwards.d.ts.map +1 -1
  16. package/abstract/edwards.js +322 -136
  17. package/abstract/edwards.js.map +1 -1
  18. package/abstract/fft.d.ts +12 -10
  19. package/abstract/fft.d.ts.map +1 -1
  20. package/abstract/fft.js +12 -13
  21. package/abstract/fft.js.map +1 -1
  22. package/abstract/hash-to-curve.d.ts +31 -13
  23. package/abstract/hash-to-curve.d.ts.map +1 -1
  24. package/abstract/hash-to-curve.js +34 -19
  25. package/abstract/hash-to-curve.js.map +1 -1
  26. package/abstract/modular.d.ts +31 -13
  27. package/abstract/modular.d.ts.map +1 -1
  28. package/abstract/modular.js +125 -52
  29. package/abstract/modular.js.map +1 -1
  30. package/abstract/montgomery.d.ts +18 -5
  31. package/abstract/montgomery.d.ts.map +1 -1
  32. package/abstract/montgomery.js +23 -6
  33. package/abstract/montgomery.js.map +1 -1
  34. package/abstract/poseidon.d.ts +5 -13
  35. package/abstract/poseidon.d.ts.map +1 -1
  36. package/abstract/poseidon.js +12 -7
  37. package/abstract/poseidon.js.map +1 -1
  38. package/abstract/tower.d.ts +23 -49
  39. package/abstract/tower.d.ts.map +1 -1
  40. package/abstract/tower.js +9 -3
  41. package/abstract/tower.js.map +1 -1
  42. package/abstract/utils.d.ts +1 -115
  43. package/abstract/utils.d.ts.map +1 -1
  44. package/abstract/utils.js +17 -371
  45. package/abstract/utils.js.map +1 -1
  46. package/abstract/weierstrass.d.ts +206 -124
  47. package/abstract/weierstrass.d.ts.map +1 -1
  48. package/abstract/weierstrass.js +747 -604
  49. package/abstract/weierstrass.js.map +1 -1
  50. package/bls12-381.d.ts +2 -0
  51. package/bls12-381.d.ts.map +1 -1
  52. package/bls12-381.js +504 -466
  53. package/bls12-381.js.map +1 -1
  54. package/bn254.d.ts +2 -0
  55. package/bn254.d.ts.map +1 -1
  56. package/bn254.js +44 -32
  57. package/bn254.js.map +1 -1
  58. package/ed25519.d.ts +55 -66
  59. package/ed25519.d.ts.map +1 -1
  60. package/ed25519.js +172 -186
  61. package/ed25519.js.map +1 -1
  62. package/ed448.d.ts +60 -57
  63. package/ed448.d.ts.map +1 -1
  64. package/ed448.js +172 -166
  65. package/ed448.js.map +1 -1
  66. package/esm/_shortw_utils.d.ts +8 -5
  67. package/esm/_shortw_utils.d.ts.map +1 -1
  68. package/esm/_shortw_utils.js +3 -8
  69. package/esm/_shortw_utils.js.map +1 -1
  70. package/esm/abstract/bls.d.ts +123 -62
  71. package/esm/abstract/bls.d.ts.map +1 -1
  72. package/esm/abstract/bls.js +220 -164
  73. package/esm/abstract/bls.js.map +1 -1
  74. package/esm/abstract/curve.d.ts +142 -21
  75. package/esm/abstract/curve.d.ts.map +1 -1
  76. package/esm/abstract/curve.js +219 -143
  77. package/esm/abstract/curve.js.map +1 -1
  78. package/esm/abstract/edwards.d.ts +190 -49
  79. package/esm/abstract/edwards.d.ts.map +1 -1
  80. package/esm/abstract/edwards.js +320 -138
  81. package/esm/abstract/edwards.js.map +1 -1
  82. package/esm/abstract/fft.d.ts +12 -10
  83. package/esm/abstract/fft.d.ts.map +1 -1
  84. package/esm/abstract/fft.js +10 -11
  85. package/esm/abstract/fft.js.map +1 -1
  86. package/esm/abstract/hash-to-curve.d.ts +31 -13
  87. package/esm/abstract/hash-to-curve.d.ts.map +1 -1
  88. package/esm/abstract/hash-to-curve.js +33 -19
  89. package/esm/abstract/hash-to-curve.js.map +1 -1
  90. package/esm/abstract/modular.d.ts +31 -13
  91. package/esm/abstract/modular.d.ts.map +1 -1
  92. package/esm/abstract/modular.js +124 -51
  93. package/esm/abstract/modular.js.map +1 -1
  94. package/esm/abstract/montgomery.d.ts +18 -5
  95. package/esm/abstract/montgomery.d.ts.map +1 -1
  96. package/esm/abstract/montgomery.js +23 -6
  97. package/esm/abstract/montgomery.js.map +1 -1
  98. package/esm/abstract/poseidon.d.ts +5 -13
  99. package/esm/abstract/poseidon.d.ts.map +1 -1
  100. package/esm/abstract/poseidon.js +12 -7
  101. package/esm/abstract/poseidon.js.map +1 -1
  102. package/esm/abstract/tower.d.ts +23 -49
  103. package/esm/abstract/tower.d.ts.map +1 -1
  104. package/esm/abstract/tower.js +9 -3
  105. package/esm/abstract/tower.js.map +1 -1
  106. package/esm/abstract/utils.d.ts +1 -115
  107. package/esm/abstract/utils.d.ts.map +1 -1
  108. package/esm/abstract/utils.js +3 -344
  109. package/esm/abstract/utils.js.map +1 -1
  110. package/esm/abstract/weierstrass.d.ts +206 -124
  111. package/esm/abstract/weierstrass.d.ts.map +1 -1
  112. package/esm/abstract/weierstrass.js +743 -605
  113. package/esm/abstract/weierstrass.js.map +1 -1
  114. package/esm/bls12-381.d.ts +2 -0
  115. package/esm/bls12-381.d.ts.map +1 -1
  116. package/esm/bls12-381.js +503 -465
  117. package/esm/bls12-381.js.map +1 -1
  118. package/esm/bn254.d.ts +2 -0
  119. package/esm/bn254.d.ts.map +1 -1
  120. package/esm/bn254.js +41 -29
  121. package/esm/bn254.js.map +1 -1
  122. package/esm/ed25519.d.ts +55 -66
  123. package/esm/ed25519.d.ts.map +1 -1
  124. package/esm/ed25519.js +170 -183
  125. package/esm/ed25519.js.map +1 -1
  126. package/esm/ed448.d.ts +60 -57
  127. package/esm/ed448.d.ts.map +1 -1
  128. package/esm/ed448.js +169 -162
  129. package/esm/ed448.js.map +1 -1
  130. package/esm/index.js +7 -9
  131. package/esm/index.js.map +1 -1
  132. package/esm/jubjub.d.ts +3 -3
  133. package/esm/jubjub.d.ts.map +1 -1
  134. package/esm/jubjub.js +3 -3
  135. package/esm/jubjub.js.map +1 -1
  136. package/esm/misc.d.ts +3 -5
  137. package/esm/misc.d.ts.map +1 -1
  138. package/esm/misc.js +31 -29
  139. package/esm/misc.js.map +1 -1
  140. package/esm/nist.d.ts +7 -22
  141. package/esm/nist.d.ts.map +1 -1
  142. package/esm/nist.js +106 -101
  143. package/esm/nist.js.map +1 -1
  144. package/esm/p256.d.ts +7 -3
  145. package/esm/p256.d.ts.map +1 -1
  146. package/esm/p256.js +4 -0
  147. package/esm/p256.js.map +1 -1
  148. package/esm/p384.d.ts +7 -4
  149. package/esm/p384.d.ts.map +1 -1
  150. package/esm/p384.js +4 -1
  151. package/esm/p384.js.map +1 -1
  152. package/esm/p521.d.ts +7 -3
  153. package/esm/p521.d.ts.map +1 -1
  154. package/esm/p521.js +4 -0
  155. package/esm/p521.js.map +1 -1
  156. package/esm/secp256k1.d.ts +38 -21
  157. package/esm/secp256k1.d.ts.map +1 -1
  158. package/esm/secp256k1.js +112 -104
  159. package/esm/secp256k1.js.map +1 -1
  160. package/esm/utils.d.ts +96 -0
  161. package/esm/utils.d.ts.map +1 -0
  162. package/esm/utils.js +279 -0
  163. package/esm/utils.js.map +1 -0
  164. package/index.js +7 -9
  165. package/index.js.map +1 -1
  166. package/jubjub.d.ts +3 -3
  167. package/jubjub.d.ts.map +1 -1
  168. package/jubjub.js +3 -3
  169. package/jubjub.js.map +1 -1
  170. package/misc.d.ts +3 -5
  171. package/misc.d.ts.map +1 -1
  172. package/misc.js +35 -33
  173. package/misc.js.map +1 -1
  174. package/nist.d.ts +7 -22
  175. package/nist.d.ts.map +1 -1
  176. package/nist.js +106 -101
  177. package/nist.js.map +1 -1
  178. package/p256.d.ts +7 -3
  179. package/p256.d.ts.map +1 -1
  180. package/p256.js +4 -0
  181. package/p256.js.map +1 -1
  182. package/p384.d.ts +7 -4
  183. package/p384.d.ts.map +1 -1
  184. package/p384.js +4 -1
  185. package/p384.js.map +1 -1
  186. package/p521.d.ts +7 -3
  187. package/p521.d.ts.map +1 -1
  188. package/p521.js +4 -0
  189. package/p521.js.map +1 -1
  190. package/package.json +17 -6
  191. package/secp256k1.d.ts +38 -21
  192. package/secp256k1.d.ts.map +1 -1
  193. package/secp256k1.js +112 -104
  194. package/secp256k1.js.map +1 -1
  195. package/src/_shortw_utils.ts +6 -15
  196. package/src/abstract/bls.ts +428 -251
  197. package/src/abstract/curve.ts +307 -149
  198. package/src/abstract/edwards.ts +555 -203
  199. package/src/abstract/fft.ts +30 -19
  200. package/src/abstract/hash-to-curve.ts +75 -34
  201. package/src/abstract/modular.ts +131 -59
  202. package/src/abstract/montgomery.ts +44 -15
  203. package/src/abstract/poseidon.ts +22 -18
  204. package/src/abstract/tower.ts +40 -71
  205. package/src/abstract/utils.ts +3 -378
  206. package/src/abstract/weierstrass.ts +1086 -746
  207. package/src/bls12-381.ts +549 -490
  208. package/src/bn254.ts +47 -35
  209. package/src/ed25519.ts +214 -216
  210. package/src/ed448.ts +251 -220
  211. package/src/index.ts +7 -9
  212. package/src/jubjub.ts +3 -3
  213. package/src/misc.ts +41 -40
  214. package/src/nist.ts +161 -126
  215. package/src/p256.ts +7 -3
  216. package/src/p384.ts +7 -5
  217. package/src/p521.ts +7 -3
  218. package/src/secp256k1.ts +145 -115
  219. package/src/utils.ts +328 -0
  220. package/utils.d.ts +96 -0
  221. package/utils.d.ts.map +1 -0
  222. package/utils.js +313 -0
  223. package/utils.js.map +1 -0
@@ -1,5 +1,4 @@
1
1
  /**
2
- * BLS (Barreto-Lynn-Scott) family of pairing-friendly curves.
3
2
  * BLS != BLS.
4
3
  * The file implements BLS (Boneh-Lynn-Shacham) signatures.
5
4
  * Used in both BLS (Barreto-Lynn-Scott) and BN (Barreto-Naehrig)
@@ -10,28 +9,40 @@
10
9
  * - Gt, created by bilinear (ate) pairing e(G1, G2), consists of p-th roots of unity in
11
10
  * Fq^k where k is embedding degree. Only degree 12 is currently supported, 24 is not.
12
11
  * Pairing is used to aggregate and verify signatures.
13
- * There are two main ways to use it:
14
- * 1. Fp for short private keys, Fp₂ for signatures
15
- * 2. Fp for short signatures, Fp₂ for private keys
12
+ * There are two modes of operation:
13
+ * - Long signatures: X-byte keys + 2X-byte sigs (G1 keys + G2 sigs).
14
+ * - Short signatures: 2X-byte keys + X-byte sigs (G2 keys + G1 sigs).
16
15
  * @module
17
16
  **/
18
17
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
19
- // TODO: import { AffinePoint } from './curve.ts';
20
18
  import {
19
+ abytes,
20
+ ensureBytes,
21
+ memoized,
22
+ randomBytes,
23
+ type CHash,
24
+ type Hex,
25
+ type PrivKey,
26
+ } from '../utils.ts';
27
+ import { normalizeZ } from './curve.ts';
28
+ import {
29
+ createHasher,
30
+ type H2CHasher,
31
+ type H2CHashOpts,
32
+ type H2COpts,
21
33
  type H2CPointConstructor,
22
34
  type htfBasicOpts,
23
- type Opts as HTFOpts,
24
35
  type MapToCurve,
25
- createHasher,
26
36
  } from './hash-to-curve.ts';
27
- import { type IField, getMinHashLength, mapHashToField } from './modular.ts';
28
- import type { Fp12, Fp12Bls, Fp2, Fp2Bls, Fp6 } from './tower.ts';
29
- import { type CHash, type Hex, type PrivKey, ensureBytes, memoized } from './utils.ts';
37
+ import { getMinHashLength, mapHashToField, type IField } from './modular.ts';
38
+ import type { Fp12, Fp12Bls, Fp2, Fp2Bls, Fp6Bls } from './tower.ts';
30
39
  import {
40
+ _normFnElement,
41
+ weierstrassPoints,
31
42
  type CurvePointsRes,
32
43
  type CurvePointsType,
33
- type ProjPointType,
34
- weierstrassPoints,
44
+ type WeierstrassPoint,
45
+ type WeierstrassPointCons,
35
46
  } from './weierstrass.ts';
36
47
 
37
48
  type Fp = bigint; // Can be different field?
@@ -42,15 +53,29 @@ const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3);
42
53
  export type TwistType = 'multiplicative' | 'divisive';
43
54
 
44
55
  export type ShortSignatureCoder<Fp> = {
45
- fromHex(hex: Hex): ProjPointType<Fp>;
46
- toRawBytes(point: ProjPointType<Fp>): Uint8Array;
47
- toHex(point: ProjPointType<Fp>): string;
56
+ fromBytes(bytes: Uint8Array): WeierstrassPoint<Fp>;
57
+ fromHex(hex: Hex): WeierstrassPoint<Fp>;
58
+ toBytes(point: WeierstrassPoint<Fp>): Uint8Array;
59
+ /** @deprecated use `toBytes` */
60
+ toRawBytes(point: WeierstrassPoint<Fp>): Uint8Array;
61
+ toHex(point: WeierstrassPoint<Fp>): string;
48
62
  };
49
63
 
50
64
  export type SignatureCoder<Fp> = {
51
- fromHex(hex: Hex): ProjPointType<Fp>;
52
- toRawBytes(point: ProjPointType<Fp>): Uint8Array;
53
- toHex(point: ProjPointType<Fp>): string;
65
+ fromBytes(bytes: Uint8Array): WeierstrassPoint<Fp>;
66
+ fromHex(hex: Hex): WeierstrassPoint<Fp>;
67
+ toBytes(point: WeierstrassPoint<Fp>): Uint8Array;
68
+ /** @deprecated use `toBytes` */
69
+ toRawBytes(point: WeierstrassPoint<Fp>): Uint8Array;
70
+ toHex(point: WeierstrassPoint<Fp>): string;
71
+ };
72
+
73
+ export type BlsFields = {
74
+ Fp: IField<Fp>;
75
+ Fr: IField<bigint>;
76
+ Fp2: Fp2Bls;
77
+ Fp6: Fp6Bls;
78
+ Fp12: Fp12Bls;
54
79
  };
55
80
 
56
81
  export type PostPrecomputePointAddFn = (
@@ -68,36 +93,51 @@ export type PostPrecomputeFn = (
68
93
  Qy: Fp2,
69
94
  pointAdd: PostPrecomputePointAddFn
70
95
  ) => void;
96
+ export type BlsPairing = {
97
+ Fp12: Fp12Bls;
98
+ calcPairingPrecomputes: (p: WeierstrassPoint<Fp2>) => Precompute;
99
+ millerLoopBatch: (pairs: [Precompute, Fp, Fp][]) => Fp12;
100
+ pairing: (P: WeierstrassPoint<Fp>, Q: WeierstrassPoint<Fp2>, withFinalExponent?: boolean) => Fp12;
101
+ pairingBatch: (
102
+ pairs: { g1: WeierstrassPoint<Fp>; g2: WeierstrassPoint<Fp2> }[],
103
+ withFinalExponent?: boolean
104
+ ) => Fp12;
105
+ };
106
+ // TODO: replace CurveType with this? It doesn't contain r however and has postPrecompute
107
+ export type BlsPairingParams = {
108
+ // NOTE: MSB is always ignored and used as marker for length,
109
+ // otherwise leading zeros will be lost.
110
+ // Can be different from 'X' (seed) param!
111
+ ateLoopSize: bigint;
112
+ xNegative: boolean;
113
+ twistType: TwistType; // BLS12-381: Multiplicative, BN254: Divisive
114
+ // This is super ugly hack for untwist point in BN254 after miller loop
115
+ postPrecompute?: PostPrecomputeFn;
116
+ };
71
117
  export type CurveType = {
72
- G1: Omit<CurvePointsType<Fp>, 'n'> & {
118
+ G1: CurvePointsType<Fp> & {
73
119
  ShortSignature: SignatureCoder<Fp>;
74
120
  mapToCurve: MapToCurve<Fp>;
75
- htfDefaults: HTFOpts;
121
+ htfDefaults: H2COpts;
76
122
  };
77
- G2: Omit<CurvePointsType<Fp2>, 'n'> & {
123
+ G2: CurvePointsType<Fp2> & {
78
124
  Signature: SignatureCoder<Fp2>;
79
125
  mapToCurve: MapToCurve<Fp2>;
80
- htfDefaults: HTFOpts;
81
- };
82
- fields: {
83
- Fp: IField<Fp>;
84
- Fr: IField<bigint>;
85
- Fp2: Fp2Bls;
86
- Fp6: IField<Fp6>;
87
- Fp12: Fp12Bls;
126
+ htfDefaults: H2COpts;
88
127
  };
128
+ fields: BlsFields;
89
129
  params: {
90
130
  // NOTE: MSB is always ignored and used as marker for length,
91
131
  // otherwise leading zeros will be lost.
92
132
  // Can be different from 'X' (seed) param!
93
- ateLoopSize: bigint;
94
- xNegative: boolean;
95
- r: bigint;
96
- twistType: TwistType; // BLS12-381: Multiplicative, BN254: Divisive
133
+ ateLoopSize: BlsPairingParams['ateLoopSize'];
134
+ xNegative: BlsPairingParams['xNegative'];
135
+ r: bigint; // TODO: remove
136
+ twistType: BlsPairingParams['twistType']; // BLS12-381: Multiplicative, BN254: Divisive
97
137
  };
98
- htfDefaults: HTFOpts;
138
+ htfDefaults: H2COpts;
99
139
  hash: CHash; // Because we need outputLen for DRBG
100
- randomBytes: (bytesLength?: number) => Uint8Array;
140
+ randomBytes?: (bytesLength?: number) => Uint8Array;
101
141
  // This is super ugly hack for untwist point in BN254 after miller loop
102
142
  postPrecompute?: PostPrecomputeFn;
103
143
  };
@@ -105,76 +145,129 @@ export type CurveType = {
105
145
  type PrecomputeSingle = [Fp2, Fp2, Fp2][];
106
146
  type Precompute = PrecomputeSingle[];
107
147
 
108
- export type CurveFn = {
109
- getPublicKey: (privateKey: PrivKey) => Uint8Array;
110
- getPublicKeyForShortSignatures: (privateKey: PrivKey) => Uint8Array;
148
+ /**
149
+ * BLS consists of two curves: G1 and G2:
150
+ * - G1 is a subgroup of (x, y) E(Fq) over y² = x³ + 4.
151
+ * - G2 is a subgroup of ((x₁, x₂+i), (y₁, y₂+i)) E(Fq²) over y² = x³ + 4(1 + i) where i is √-1
152
+ */
153
+ export interface BLSCurvePair {
154
+ longSignatures: BLSSigs<bigint, Fp2>;
155
+ shortSignatures: BLSSigs<Fp2, bigint>;
156
+ millerLoopBatch: BlsPairing['millerLoopBatch'];
157
+ pairing: BlsPairing['pairing'];
158
+ pairingBatch: BlsPairing['pairingBatch'];
159
+ G1: { Point: WeierstrassPointCons<bigint> } & H2CHasher<Fp>;
160
+ G2: { Point: WeierstrassPointCons<Fp2> } & H2CHasher<Fp2>;
161
+ fields: {
162
+ Fp: IField<Fp>;
163
+ Fp2: Fp2Bls;
164
+ Fp6: Fp6Bls;
165
+ Fp12: Fp12Bls;
166
+ Fr: IField<bigint>;
167
+ };
168
+ utils: {
169
+ randomSecretKey: () => Uint8Array;
170
+ /** @deprecated use randomSecretKey */
171
+ randomPrivateKey: () => Uint8Array;
172
+ calcPairingPrecomputes: BlsPairing['calcPairingPrecomputes'];
173
+ };
174
+ }
175
+
176
+ export type CurveFn = BLSCurvePair & {
177
+ /** @deprecated use `longSignatures.getPublicKey` */
178
+ getPublicKey: (secretKey: PrivKey) => Uint8Array;
179
+ /** @deprecated use `shortSignatures.getPublicKey` */
180
+ getPublicKeyForShortSignatures: (secretKey: PrivKey) => Uint8Array;
181
+ /** @deprecated use `longSignatures.sign` */
111
182
  sign: {
112
- (message: Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array;
113
- (message: ProjPointType<Fp2>, privateKey: PrivKey, htfOpts?: htfBasicOpts): ProjPointType<Fp2>;
183
+ (message: Hex, secretKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array;
184
+ (
185
+ message: WeierstrassPoint<Fp2>,
186
+ secretKey: PrivKey,
187
+ htfOpts?: htfBasicOpts
188
+ ): WeierstrassPoint<Fp2>;
114
189
  };
190
+ /** @deprecated use `shortSignatures.sign` */
115
191
  signShortSignature: {
116
- (message: Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array;
117
- (message: ProjPointType<Fp>, privateKey: PrivKey, htfOpts?: htfBasicOpts): ProjPointType<Fp>;
192
+ (message: Hex, secretKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array;
193
+ (
194
+ message: WeierstrassPoint<Fp>,
195
+ secretKey: PrivKey,
196
+ htfOpts?: htfBasicOpts
197
+ ): WeierstrassPoint<Fp>;
118
198
  };
199
+ /** @deprecated use `longSignatures.verify` */
119
200
  verify: (
120
- signature: Hex | ProjPointType<Fp2>,
121
- message: Hex | ProjPointType<Fp2>,
122
- publicKey: Hex | ProjPointType<Fp>,
201
+ signature: Hex | WeierstrassPoint<Fp2>,
202
+ message: Hex | WeierstrassPoint<Fp2>,
203
+ publicKey: Hex | WeierstrassPoint<Fp>,
123
204
  htfOpts?: htfBasicOpts
124
205
  ) => boolean;
206
+ /** @deprecated use `shortSignatures.verify` */
125
207
  verifyShortSignature: (
126
- signature: Hex | ProjPointType<Fp>,
127
- message: Hex | ProjPointType<Fp>,
128
- publicKey: Hex | ProjPointType<Fp2>,
208
+ signature: Hex | WeierstrassPoint<Fp>,
209
+ message: Hex | WeierstrassPoint<Fp>,
210
+ publicKey: Hex | WeierstrassPoint<Fp2>,
129
211
  htfOpts?: htfBasicOpts
130
212
  ) => boolean;
131
213
  verifyBatch: (
132
- signature: Hex | ProjPointType<Fp2>,
133
- messages: (Hex | ProjPointType<Fp2>)[],
134
- publicKeys: (Hex | ProjPointType<Fp>)[],
214
+ signature: Hex | WeierstrassPoint<Fp2>,
215
+ messages: (Hex | WeierstrassPoint<Fp2>)[],
216
+ publicKeys: (Hex | WeierstrassPoint<Fp>)[],
135
217
  htfOpts?: htfBasicOpts
136
218
  ) => boolean;
219
+ /** @deprecated use `longSignatures.aggregatePublicKeys` */
137
220
  aggregatePublicKeys: {
138
221
  (publicKeys: Hex[]): Uint8Array;
139
- (publicKeys: ProjPointType<Fp>[]): ProjPointType<Fp>;
222
+ (publicKeys: WeierstrassPoint<Fp>[]): WeierstrassPoint<Fp>;
140
223
  };
224
+ /** @deprecated use `longSignatures.aggregateSignatures` */
141
225
  aggregateSignatures: {
142
226
  (signatures: Hex[]): Uint8Array;
143
- (signatures: ProjPointType<Fp2>[]): ProjPointType<Fp2>;
227
+ (signatures: WeierstrassPoint<Fp2>[]): WeierstrassPoint<Fp2>;
144
228
  };
229
+ /** @deprecated use `shortSignatures.aggregateSignatures` */
145
230
  aggregateShortSignatures: {
146
231
  (signatures: Hex[]): Uint8Array;
147
- (signatures: ProjPointType<Fp>[]): ProjPointType<Fp>;
232
+ (signatures: WeierstrassPoint<Fp>[]): WeierstrassPoint<Fp>;
148
233
  };
149
- millerLoopBatch: (pairs: [Precompute, Fp, Fp][]) => Fp12;
150
- pairing: (P: ProjPointType<Fp>, Q: ProjPointType<Fp2>, withFinalExponent?: boolean) => Fp12;
151
- pairingBatch: (
152
- pairs: { g1: ProjPointType<Fp>; g2: ProjPointType<Fp2> }[],
153
- withFinalExponent?: boolean
154
- ) => Fp12;
155
- G1: CurvePointsRes<Fp> & ReturnType<typeof createHasher<Fp>>;
156
- G2: CurvePointsRes<Fp2> & ReturnType<typeof createHasher<Fp2>>;
234
+ G1: CurvePointsRes<Fp> & H2CHasher<Fp>;
235
+ G2: CurvePointsRes<Fp2> & H2CHasher<Fp2>;
236
+ /** @deprecated use `longSignatures.Signature` */
157
237
  Signature: SignatureCoder<Fp2>;
238
+ /** @deprecated use `shortSignatures.Signature` */
158
239
  ShortSignature: ShortSignatureCoder<Fp>;
159
240
  params: {
160
241
  ateLoopSize: bigint;
161
242
  r: bigint;
243
+ twistType: TwistType;
244
+ /** @deprecated */
162
245
  G1b: bigint;
246
+ /** @deprecated */
163
247
  G2b: Fp2;
164
248
  };
165
- fields: {
166
- Fp: IField<Fp>;
167
- Fp2: Fp2Bls;
168
- Fp6: IField<Fp6>;
169
- Fp12: Fp12Bls;
170
- Fr: IField<bigint>;
171
- };
172
- utils: {
173
- randomPrivateKey: () => Uint8Array;
174
- calcPairingPrecomputes: (p: ProjPointType<Fp2>) => Precompute;
175
- };
176
249
  };
177
250
 
251
+ type BLSInput = Hex | Uint8Array;
252
+ export interface BLSSigs<P, S> {
253
+ getPublicKey(secretKey: PrivKey): WeierstrassPoint<P>;
254
+ sign(hashedMessage: WeierstrassPoint<S>, secretKey: PrivKey): WeierstrassPoint<S>;
255
+ verify(
256
+ signature: WeierstrassPoint<S> | BLSInput,
257
+ message: WeierstrassPoint<S>,
258
+ publicKey: WeierstrassPoint<P> | BLSInput
259
+ ): boolean;
260
+ verifyBatch: (
261
+ signature: WeierstrassPoint<S> | BLSInput,
262
+ messages: WeierstrassPoint<S>[],
263
+ publicKeys: (WeierstrassPoint<P> | BLSInput)[]
264
+ ) => boolean;
265
+ aggregatePublicKeys(publicKeys: (WeierstrassPoint<P> | BLSInput)[]): WeierstrassPoint<P>;
266
+ aggregateSignatures(signatures: (WeierstrassPoint<S> | BLSInput)[]): WeierstrassPoint<S>;
267
+ hash(message: Uint8Array, DST?: string | Uint8Array, hashOpts?: H2CHashOpts): WeierstrassPoint<S>;
268
+ Signature: SignatureCoder<S>;
269
+ }
270
+
178
271
  // Not used with BLS12-381 (no sequential `11` in X). Useful for other curves.
179
272
  function NAfDecomposition(a: bigint) {
180
273
  const res = [];
@@ -189,38 +282,27 @@ function NAfDecomposition(a: bigint) {
189
282
  return res;
190
283
  }
191
284
 
192
- export function bls(CURVE: CurveType): CurveFn {
193
- // Fields are specific for curve, so for now we'll need to pass them with opts
194
- const { Fp, Fr, Fp2, Fp6, Fp12 } = CURVE.fields;
195
- const BLS_X_IS_NEGATIVE = CURVE.params.xNegative;
196
- const TWIST: TwistType = CURVE.params.twistType;
197
- // Point on G1 curve: (x, y)
198
- const G1_ = weierstrassPoints({ n: Fr.ORDER, ...CURVE.G1 });
199
- const G1 = Object.assign(
200
- G1_,
201
- createHasher(G1_.ProjectivePoint, CURVE.G1.mapToCurve, {
202
- ...CURVE.htfDefaults,
203
- ...CURVE.G1.htfDefaults,
204
- })
205
- );
206
- // Point on G2 curve (complex numbers): (x₁, x₂+i), (y₁, y₂+i)
207
- const G2_ = weierstrassPoints({ n: Fr.ORDER, ...CURVE.G2 });
208
- const G2 = Object.assign(
209
- G2_,
210
- createHasher(G2_.ProjectivePoint as H2CPointConstructor<Fp2>, CURVE.G2.mapToCurve, {
211
- ...CURVE.htfDefaults,
212
- ...CURVE.G2.htfDefaults,
213
- })
214
- );
215
- type G1 = typeof G1.ProjectivePoint.BASE;
216
- type G2 = typeof G2.ProjectivePoint.BASE;
285
+ function aNonEmpty(arr: any[]) {
286
+ if (!Array.isArray(arr) || arr.length === 0) throw new Error('expected non-empty array');
287
+ }
217
288
 
289
+ // This should be enough for bn254, no need to export full stuff?
290
+ function createBlsPairing(
291
+ fields: BlsFields,
292
+ G1: WeierstrassPointCons<Fp>,
293
+ G2: WeierstrassPointCons<Fp2>,
294
+ params: BlsPairingParams
295
+ ): BlsPairing {
296
+ const { Fp2, Fp12 } = fields;
297
+ const { twistType, ateLoopSize, xNegative, postPrecompute } = params;
298
+ type G1 = typeof G1.BASE;
299
+ type G2 = typeof G2.BASE;
218
300
  // Applies sparse multiplication as line function
219
301
  let lineFunction: (c0: Fp2, c1: Fp2, c2: Fp2, f: Fp12, Px: Fp, Py: Fp) => Fp12;
220
- if (TWIST === 'multiplicative') {
302
+ if (twistType === 'multiplicative') {
221
303
  lineFunction = (c0: Fp2, c1: Fp2, c2: Fp2, f: Fp12, Px: Fp, Py: Fp) =>
222
304
  Fp12.mul014(f, c0, Fp2.mul(c1, Px), Fp2.mul(c2, Py));
223
- } else if (TWIST === 'divisive') {
305
+ } else if (twistType === 'divisive') {
224
306
  // NOTE: it should be [c0, c1, c2], but we use different order here to reduce complexity of
225
307
  // precompute calculations.
226
308
  lineFunction = (c0: Fp2, c1: Fp2, c2: Fp2, f: Fp12, Px: Fp, Py: Fp) =>
@@ -269,7 +351,7 @@ export function bls(CURVE: CurveType): CurveFn {
269
351
  // Point addition and point double calculations is reused for coefficients
270
352
  // pointAdd happens only if bit set, so wNAF is reasonable. Unfortunately we cannot combine
271
353
  // add + double in windowed precomputes here, otherwise it would be single op (since X is static)
272
- const ATE_NAF = NAfDecomposition(CURVE.params.ateLoopSize);
354
+ const ATE_NAF = NAfDecomposition(ateLoopSize);
273
355
 
274
356
  const calcPairingPrecomputes = memoized((point: G2) => {
275
357
  const p = point;
@@ -285,9 +367,9 @@ export function bls(CURVE: CurveType): CurveFn {
285
367
  if (bit) ({ Rx, Ry, Rz } = pointAdd(cur, Rx, Ry, Rz, Qx, bit === -1 ? negQy : Qy));
286
368
  ell.push(cur);
287
369
  }
288
- if (CURVE.postPrecompute) {
370
+ if (postPrecompute) {
289
371
  const last = ell[ell.length - 1];
290
- CURVE.postPrecompute(Rx, Ry, Rz, Qx, Qy, pointAdd.bind(null, last));
372
+ postPrecompute(Rx, Ry, Rz, Qx, Qy, pointAdd.bind(null, last));
291
373
  }
292
374
  return ell;
293
375
  });
@@ -307,7 +389,7 @@ export function bls(CURVE: CurveType): CurveFn {
307
389
  }
308
390
  }
309
391
  }
310
- if (BLS_X_IS_NEGATIVE) f12 = Fp12.conjugate(f12);
392
+ if (xNegative) f12 = Fp12.conjugate(f12);
311
393
  return withFinalExponent ? Fp12.finalExponentiate(f12) : f12;
312
394
  }
313
395
  type PairingInput = { g1: G1; g2: G2 };
@@ -316,11 +398,16 @@ export function bls(CURVE: CurveType): CurveFn {
316
398
  function pairingBatch(pairs: PairingInput[], withFinalExponent: boolean = true) {
317
399
  const res: MillerInput = [];
318
400
  // Cache precomputed toAffine for all points
319
- G1.ProjectivePoint.normalizeZ(pairs.map(({ g1 }) => g1));
320
- G2.ProjectivePoint.normalizeZ(pairs.map(({ g2 }) => g2));
401
+ normalizeZ(
402
+ G1,
403
+ pairs.map(({ g1 }) => g1)
404
+ );
405
+ normalizeZ(
406
+ G2,
407
+ pairs.map(({ g2 }) => g2)
408
+ );
321
409
  for (const { g1, g2 } of pairs) {
322
- if (g1.equals(G1.ProjectivePoint.ZERO) || g2.equals(G2.ProjectivePoint.ZERO))
323
- throw new Error('pairing is not available for ZERO point');
410
+ if (g1.is0() || g2.is0()) throw new Error('pairing is not available for ZERO point');
324
411
  // This uses toAffine inside
325
412
  g1.assertValidity();
326
413
  g2.assertValidity();
@@ -333,61 +420,228 @@ export function bls(CURVE: CurveType): CurveFn {
333
420
  function pairing(Q: G1, P: G2, withFinalExponent: boolean = true): Fp12 {
334
421
  return pairingBatch([{ g1: Q, g2: P }], withFinalExponent);
335
422
  }
423
+ return {
424
+ Fp12, // NOTE: we re-export Fp12 here because pairing results are Fp12!
425
+ millerLoopBatch,
426
+ pairing,
427
+ pairingBatch,
428
+ calcPairingPrecomputes,
429
+ };
430
+ }
336
431
 
337
- const utils = {
338
- randomPrivateKey: (): Uint8Array => {
339
- const length = getMinHashLength(Fr.ORDER);
340
- return mapHashToField(CURVE.randomBytes(length), Fr.ORDER);
432
+ function createBlsSig<P, S>(
433
+ blsPairing: BlsPairing,
434
+ PubCurve: CurvePointsRes<P> & H2CHasher<P>,
435
+ SigCurve: CurvePointsRes<S> & H2CHasher<S>,
436
+ SignatureCoder: SignatureCoder<S>,
437
+ isSigG1: boolean
438
+ ): BLSSigs<P, S> {
439
+ const { Fp12, pairingBatch } = blsPairing;
440
+ type PubPoint = WeierstrassPoint<P>;
441
+ type SigPoint = WeierstrassPoint<S>;
442
+ function normPub(point: PubPoint | BLSInput): PubPoint {
443
+ return point instanceof PubCurve.Point ? (point as PubPoint) : PubCurve.Point.fromHex(point);
444
+ }
445
+ function normSig(point: SigPoint | BLSInput): SigPoint {
446
+ return point instanceof SigCurve.Point ? (point as SigPoint) : SigCurve.Point.fromHex(point);
447
+ }
448
+ function amsg(m: unknown): SigPoint {
449
+ if (!(m instanceof SigCurve.Point))
450
+ throw new Error(`expected valid message hashed to ${!isSigG1 ? 'G2' : 'G1'} curve`);
451
+ return m as SigPoint;
452
+ }
453
+
454
+ type G1 = CurvePointsRes<Fp>['Point']['BASE'];
455
+ type G2 = CurvePointsRes<Fp2>['Point']['BASE'];
456
+ type PairingInput = { g1: G1; g2: G2 };
457
+ // What matters here is what point pairing API accepts as G1 or G2, not actual size or names
458
+ const pair: (a: PubPoint, b: SigPoint) => PairingInput = !isSigG1
459
+ ? (a: PubPoint, b: SigPoint) => ({ g1: a, g2: b }) as PairingInput
460
+ : (a: PubPoint, b: SigPoint) => ({ g1: b, g2: a }) as PairingInput;
461
+ return {
462
+ // P = pk x G
463
+ getPublicKey(secretKey: PrivKey): PubPoint {
464
+ // TODO: replace with
465
+ // const sec = PubCurve.Point.Fn.fromBytes(secretKey);
466
+ const sec = _normFnElement(PubCurve.Point.Fn, secretKey);
467
+ return PubCurve.Point.BASE.multiply(sec);
468
+ },
469
+ // S = pk x H(m)
470
+ sign(message: SigPoint, secretKey: PrivKey, unusedArg?: any): SigPoint {
471
+ if (unusedArg != null) throw new Error('sign() expects 2 arguments');
472
+ // TODO: replace with
473
+ // PubCurve.Point.Fn.fromBytes(secretKey)
474
+ const sec = _normFnElement(PubCurve.Point.Fn, secretKey);
475
+ amsg(message).assertValidity();
476
+ return message.multiply(sec);
477
+ },
478
+ // Checks if pairing of public key & hash is equal to pairing of generator & signature.
479
+ // e(P, H(m)) == e(G, S)
480
+ // e(S, G) == e(H(m), P)
481
+ verify(
482
+ signature: SigPoint | BLSInput,
483
+ message: SigPoint,
484
+ publicKey: PubPoint | BLSInput,
485
+ unusedArg?: any
486
+ ): boolean {
487
+ if (unusedArg != null) throw new Error('verify() expects 3 arguments');
488
+ signature = normSig(signature);
489
+ publicKey = normPub(publicKey);
490
+ const P = publicKey.negate();
491
+ const G = PubCurve.Point.BASE;
492
+ const Hm = amsg(message);
493
+ const S = signature;
494
+ // This code was changed in 1.9.x:
495
+ // Before it was G.negate() in G2, now it's always pubKey.negate
496
+ // e(P, -Q)===e(-P, Q)==e(P, Q)^-1. Negate can be done anywhere (as long it is done once per pair).
497
+ // We just moving sign, but since pairing is multiplicative, we doing X * X^-1 = 1
498
+ const exp = pairingBatch([pair(P, Hm), pair(G, S)]);
499
+ return Fp12.eql(exp, Fp12.ONE);
500
+ },
501
+ // https://ethresear.ch/t/fast-verification-of-multiple-bls-signatures/5407
502
+ // e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si))
503
+ // TODO: maybe `{message: G2Hex, publicKey: G1Hex}[]` instead?
504
+ verifyBatch(
505
+ signature: SigPoint | BLSInput,
506
+ messages: SigPoint[],
507
+ publicKeys: (PubPoint | BLSInput)[]
508
+ ): boolean {
509
+ aNonEmpty(messages);
510
+ if (publicKeys.length !== messages.length)
511
+ throw new Error('amount of public keys and messages should be equal');
512
+ const sig = normSig(signature);
513
+ const nMessages = messages;
514
+ const nPublicKeys = publicKeys.map(normPub);
515
+ // NOTE: this works only for exact same object
516
+ const messagePubKeyMap = new Map<SigPoint, PubPoint[]>();
517
+ for (let i = 0; i < nPublicKeys.length; i++) {
518
+ const pub = nPublicKeys[i];
519
+ const msg = nMessages[i];
520
+ let keys = messagePubKeyMap.get(msg);
521
+ if (keys === undefined) {
522
+ keys = [];
523
+ messagePubKeyMap.set(msg, keys);
524
+ }
525
+ keys.push(pub);
526
+ }
527
+ const paired = [];
528
+ const G = PubCurve.Point.BASE;
529
+ try {
530
+ for (const [msg, keys] of messagePubKeyMap) {
531
+ const groupPublicKey = keys.reduce((acc, msg) => acc.add(msg));
532
+ paired.push(pair(groupPublicKey, msg));
533
+ }
534
+ paired.push(pair(G.negate(), sig));
535
+ return Fp12.eql(pairingBatch(paired), Fp12.ONE);
536
+ } catch {
537
+ return false;
538
+ }
539
+ },
540
+ // Adds a bunch of public key points together.
541
+ // pk1 + pk2 + pk3 = pkA
542
+ aggregatePublicKeys(publicKeys: (PubPoint | BLSInput)[]): PubPoint {
543
+ aNonEmpty(publicKeys);
544
+ publicKeys = publicKeys.map((pub) => normPub(pub));
545
+ const agg = (publicKeys as PubPoint[]).reduce((sum, p) => sum.add(p), PubCurve.Point.ZERO);
546
+ agg.assertValidity();
547
+ return agg;
548
+ },
549
+
550
+ // Adds a bunch of signature points together.
551
+ // pk1 + pk2 + pk3 = pkA
552
+ aggregateSignatures(signatures: (SigPoint | BLSInput)[]): SigPoint {
553
+ aNonEmpty(signatures);
554
+ signatures = signatures.map((sig) => normSig(sig));
555
+ const agg = (signatures as SigPoint[]).reduce((sum, s) => sum.add(s), SigCurve.Point.ZERO);
556
+ agg.assertValidity();
557
+ return agg;
341
558
  },
559
+
560
+ hash(messageBytes: Uint8Array, DST?: string | Uint8Array): SigPoint {
561
+ abytes(messageBytes);
562
+ const opts = DST ? { DST } : undefined;
563
+ return SigCurve.hashToCurve(messageBytes, opts) as SigPoint;
564
+ },
565
+ Signature: SignatureCoder,
566
+ };
567
+ }
568
+
569
+ // G1_Point: ProjConstructor<bigint>, G2_Point: ProjConstructor<Fp2>,
570
+ export function bls(CURVE: CurveType): CurveFn {
571
+ // Fields are specific for curve, so for now we'll need to pass them with opts
572
+ const { Fp, Fr, Fp2, Fp6, Fp12 } = CURVE.fields;
573
+ // Point on G1 curve: (x, y)
574
+ const G1_ = weierstrassPoints(CURVE.G1);
575
+ const G1 = Object.assign(
576
+ G1_,
577
+ createHasher(G1_.Point, CURVE.G1.mapToCurve, {
578
+ ...CURVE.htfDefaults,
579
+ ...CURVE.G1.htfDefaults,
580
+ })
581
+ );
582
+ // Point on G2 curve (complex numbers): (x₁, x₂+i), (y₁, y₂+i)
583
+ const G2_ = weierstrassPoints(CURVE.G2);
584
+ const G2 = Object.assign(
585
+ G2_,
586
+ createHasher(G2_.Point as H2CPointConstructor<Fp2>, CURVE.G2.mapToCurve, {
587
+ ...CURVE.htfDefaults,
588
+ ...CURVE.G2.htfDefaults,
589
+ })
590
+ );
591
+ type G1 = typeof G1.Point.BASE;
592
+ type G2 = typeof G2.Point.BASE;
593
+
594
+ const pairingRes = createBlsPairing(CURVE.fields, G1.Point, G2.Point, {
595
+ ...CURVE.params,
596
+ postPrecompute: CURVE.postPrecompute,
597
+ });
598
+
599
+ const { millerLoopBatch, pairing, pairingBatch, calcPairingPrecomputes } = pairingRes;
600
+ const longSignatures = createBlsSig(pairingRes, G1, G2, CURVE.G2.Signature, false);
601
+ const shortSignatures = createBlsSig(pairingRes, G2, G1, CURVE.G1.ShortSignature, true);
602
+
603
+ const rand = CURVE.randomBytes || randomBytes;
604
+ const randomSecretKey = (): Uint8Array => {
605
+ const length = getMinHashLength(Fr.ORDER);
606
+ return mapHashToField(rand(length), Fr.ORDER);
607
+ };
608
+ const utils = {
609
+ randomSecretKey,
610
+ randomPrivateKey: randomSecretKey,
342
611
  calcPairingPrecomputes,
343
612
  };
344
613
 
614
+ // LEGACY code
615
+ type G1Hex = Hex | G1;
616
+ type G2Hex = Hex | G2;
617
+
345
618
  const { ShortSignature } = CURVE.G1;
346
619
  const { Signature } = CURVE.G2;
347
620
 
348
- type G1Hex = Hex | G1;
349
- type G2Hex = Hex | G2;
350
- function normP1(point: G1Hex): G1 {
351
- return point instanceof G1.ProjectivePoint ? (point as G1) : G1.ProjectivePoint.fromHex(point);
352
- }
353
621
  function normP1Hash(point: G1Hex, htfOpts?: htfBasicOpts): G1 {
354
- return point instanceof G1.ProjectivePoint
622
+ return point instanceof G1.Point
355
623
  ? point
356
- : (G1.hashToCurve(ensureBytes('point', point), htfOpts) as G1);
357
- }
358
- function normP2(point: G2Hex): G2 {
359
- return point instanceof G2.ProjectivePoint ? point : Signature.fromHex(point);
624
+ : shortSignatures.hash(ensureBytes('point', point), htfOpts?.DST);
360
625
  }
361
626
  function normP2Hash(point: G2Hex, htfOpts?: htfBasicOpts): G2 {
362
- return point instanceof G2.ProjectivePoint
627
+ return point instanceof G2.Point
363
628
  ? point
364
- : (G2.hashToCurve(ensureBytes('point', point), htfOpts) as G2);
629
+ : longSignatures.hash(ensureBytes('point', point), htfOpts?.DST);
365
630
  }
366
631
 
367
- // Multiplies generator (G1) by private key.
368
- // P = pk x G
369
632
  function getPublicKey(privateKey: PrivKey): Uint8Array {
370
- return G1.ProjectivePoint.fromPrivateKey(privateKey).toRawBytes(true);
633
+ return longSignatures.getPublicKey(privateKey).toBytes(true);
371
634
  }
372
-
373
- // Multiplies generator (G2) by private key.
374
- // P = pk x G
375
635
  function getPublicKeyForShortSignatures(privateKey: PrivKey): Uint8Array {
376
- return G2.ProjectivePoint.fromPrivateKey(privateKey).toRawBytes(true);
636
+ return shortSignatures.getPublicKey(privateKey).toBytes(true);
377
637
  }
378
-
379
- // Executes `hashToCurve` on the message and then multiplies the result by private key.
380
- // S = pk x H(m)
381
638
  function sign(message: Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array;
382
639
  function sign(message: G2, privateKey: PrivKey, htfOpts?: htfBasicOpts): G2;
383
640
  function sign(message: G2Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array | G2 {
384
- const msgPoint = normP2Hash(message, htfOpts);
385
- msgPoint.assertValidity();
386
- const sigPoint = msgPoint.multiply(G1.normPrivateKeyToScalar(privateKey));
387
- if (message instanceof G2.ProjectivePoint) return sigPoint;
388
- return Signature.toRawBytes(sigPoint);
641
+ const Hm = normP2Hash(message, htfOpts);
642
+ const S = longSignatures.sign(Hm, privateKey);
643
+ return message instanceof G2.Point ? S : Signature.toBytes(S);
389
644
  }
390
-
391
645
  function signShortSignature(
392
646
  message: Hex,
393
647
  privateKey: PrivKey,
@@ -399,159 +653,65 @@ export function bls(CURVE: CurveType): CurveFn {
399
653
  privateKey: PrivKey,
400
654
  htfOpts?: htfBasicOpts
401
655
  ): Uint8Array | G1 {
402
- const msgPoint = normP1Hash(message, htfOpts);
403
- msgPoint.assertValidity();
404
- const sigPoint = msgPoint.multiply(G1.normPrivateKeyToScalar(privateKey));
405
- if (message instanceof G1.ProjectivePoint) return sigPoint;
406
- return ShortSignature.toRawBytes(sigPoint);
656
+ const Hm = normP1Hash(message, htfOpts);
657
+ const S = shortSignatures.sign(Hm, privateKey);
658
+ return message instanceof G1.Point ? S : ShortSignature.toBytes(S);
407
659
  }
408
-
409
- // Checks if pairing of public key & hash is equal to pairing of generator & signature.
410
- // e(P, H(m)) == e(G, S)
411
660
  function verify(
412
661
  signature: G2Hex,
413
662
  message: G2Hex,
414
663
  publicKey: G1Hex,
415
664
  htfOpts?: htfBasicOpts
416
665
  ): boolean {
417
- const P = normP1(publicKey);
418
666
  const Hm = normP2Hash(message, htfOpts);
419
- const G = G1.ProjectivePoint.BASE;
420
- const S = normP2(signature);
421
- const exp = pairingBatch([
422
- { g1: P.negate(), g2: Hm }, // ePHM = pairing(P.negate(), Hm, false);
423
- { g1: G, g2: S }, // eGS = pairing(G, S, false);
424
- ]);
425
- return Fp12.eql(exp, Fp12.ONE);
667
+ return longSignatures.verify(signature, Hm, publicKey);
426
668
  }
427
-
428
- // Checks if pairing of public key & hash is equal to pairing of generator & signature.
429
- // e(S, G) == e(H(m), P)
430
669
  function verifyShortSignature(
431
670
  signature: G1Hex,
432
671
  message: G1Hex,
433
672
  publicKey: G2Hex,
434
673
  htfOpts?: htfBasicOpts
435
674
  ): boolean {
436
- const P = normP2(publicKey);
437
675
  const Hm = normP1Hash(message, htfOpts);
438
- const G = G2.ProjectivePoint.BASE;
439
- const S = normP1(signature);
440
- const exp = pairingBatch([
441
- { g1: Hm, g2: P }, // eHmP = pairing(Hm, P, false);
442
- { g1: S, g2: G.negate() }, // eSG = pairing(S, G.negate(), false);
443
- ]);
444
- return Fp12.eql(exp, Fp12.ONE);
445
- }
446
-
447
- function aNonEmpty(arr: any[]) {
448
- if (!Array.isArray(arr) || arr.length === 0) throw new Error('expected non-empty array');
676
+ return shortSignatures.verify(signature, Hm, publicKey);
449
677
  }
450
-
451
- // Adds a bunch of public key points together.
452
- // pk1 + pk2 + pk3 = pkA
453
678
  function aggregatePublicKeys(publicKeys: Hex[]): Uint8Array;
454
679
  function aggregatePublicKeys(publicKeys: G1[]): G1;
455
680
  function aggregatePublicKeys(publicKeys: G1Hex[]): Uint8Array | G1 {
456
- aNonEmpty(publicKeys);
457
- const agg = publicKeys.map(normP1).reduce((sum, p) => sum.add(p), G1.ProjectivePoint.ZERO);
458
- const aggAffine = agg; //.toAffine();
459
- if (publicKeys[0] instanceof G1.ProjectivePoint) {
460
- aggAffine.assertValidity();
461
- return aggAffine;
462
- }
463
- // toRawBytes ensures point validity
464
- return aggAffine.toRawBytes(true);
681
+ const agg = longSignatures.aggregatePublicKeys(publicKeys);
682
+ return publicKeys[0] instanceof G1.Point ? agg : agg.toBytes(true);
465
683
  }
466
-
467
- // Adds a bunch of signature points together.
468
684
  function aggregateSignatures(signatures: Hex[]): Uint8Array;
469
685
  function aggregateSignatures(signatures: G2[]): G2;
470
686
  function aggregateSignatures(signatures: G2Hex[]): Uint8Array | G2 {
471
- aNonEmpty(signatures);
472
- const agg = signatures.map(normP2).reduce((sum, s) => sum.add(s), G2.ProjectivePoint.ZERO);
473
- const aggAffine = agg; //.toAffine();
474
- if (signatures[0] instanceof G2.ProjectivePoint) {
475
- aggAffine.assertValidity();
476
- return aggAffine;
477
- }
478
- return Signature.toRawBytes(aggAffine);
687
+ const agg = longSignatures.aggregateSignatures(signatures);
688
+ return signatures[0] instanceof G2.Point ? agg : Signature.toBytes(agg);
479
689
  }
480
-
481
- // Adds a bunch of signature points together.
482
690
  function aggregateShortSignatures(signatures: Hex[]): Uint8Array;
483
691
  function aggregateShortSignatures(signatures: G1[]): G1;
484
692
  function aggregateShortSignatures(signatures: G1Hex[]): Uint8Array | G1 {
485
- aNonEmpty(signatures);
486
- const agg = signatures.map(normP1).reduce((sum, s) => sum.add(s), G1.ProjectivePoint.ZERO);
487
- const aggAffine = agg; //.toAffine();
488
- if (signatures[0] instanceof G1.ProjectivePoint) {
489
- aggAffine.assertValidity();
490
- return aggAffine;
491
- }
492
- return ShortSignature.toRawBytes(aggAffine);
693
+ const agg = shortSignatures.aggregateSignatures(signatures);
694
+ return signatures[0] instanceof G1.Point ? agg : ShortSignature.toBytes(agg);
493
695
  }
494
-
495
- // https://ethresear.ch/t/fast-verification-of-multiple-bls-signatures/5407
496
- // e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si))
497
696
  function verifyBatch(
498
697
  signature: G2Hex,
499
- // TODO: maybe `{message: G2Hex, publicKey: G1Hex}[]` instead?
500
698
  messages: G2Hex[],
501
699
  publicKeys: G1Hex[],
502
700
  htfOpts?: htfBasicOpts
503
701
  ): boolean {
504
- aNonEmpty(messages);
505
- if (publicKeys.length !== messages.length)
506
- throw new Error('amount of public keys and messages should be equal');
507
- const sig = normP2(signature);
508
- const nMessages = messages.map((i) => normP2Hash(i, htfOpts));
509
- const nPublicKeys = publicKeys.map(normP1);
510
- // NOTE: this works only for exact same object
511
- const messagePubKeyMap = new Map<G2, G1[]>();
512
- for (let i = 0; i < nPublicKeys.length; i++) {
513
- const pub = nPublicKeys[i];
514
- const msg = nMessages[i];
515
- let keys = messagePubKeyMap.get(msg);
516
- if (keys === undefined) {
517
- keys = [];
518
- messagePubKeyMap.set(msg, keys);
519
- }
520
- keys.push(pub);
521
- }
522
- const paired = [];
523
- try {
524
- for (const [msg, keys] of messagePubKeyMap) {
525
- const groupPublicKey = keys.reduce((acc, msg) => acc.add(msg));
526
- paired.push({ g1: groupPublicKey, g2: msg });
527
- }
528
- paired.push({ g1: G1.ProjectivePoint.BASE.negate(), g2: sig });
529
- return Fp12.eql(pairingBatch(paired), Fp12.ONE);
530
- } catch {
531
- return false;
532
- }
702
+ const Hm = messages.map((m) => normP2Hash(m, htfOpts));
703
+ return longSignatures.verifyBatch(signature, Hm, publicKeys);
533
704
  }
534
705
 
535
- G1.ProjectivePoint.BASE._setWindowSize(4);
706
+ G1.Point.BASE.precompute(4);
536
707
 
537
708
  return {
538
- getPublicKey,
539
- getPublicKeyForShortSignatures,
540
- sign,
541
- signShortSignature,
542
- verify,
543
- verifyBatch,
544
- verifyShortSignature,
545
- aggregatePublicKeys,
546
- aggregateSignatures,
547
- aggregateShortSignatures,
709
+ longSignatures,
710
+ shortSignatures,
548
711
  millerLoopBatch,
549
712
  pairing,
550
713
  pairingBatch,
551
- G1,
552
- G2,
553
- Signature,
554
- ShortSignature,
714
+ verifyBatch,
555
715
  fields: {
556
716
  Fr,
557
717
  Fp,
@@ -561,10 +721,27 @@ export function bls(CURVE: CurveType): CurveFn {
561
721
  },
562
722
  params: {
563
723
  ateLoopSize: CURVE.params.ateLoopSize,
724
+ twistType: CURVE.params.twistType,
725
+ // deprecated
564
726
  r: CURVE.params.r,
565
727
  G1b: CURVE.G1.b,
566
728
  G2b: CURVE.G2.b,
567
729
  },
568
730
  utils,
731
+
732
+ // deprecated
733
+ getPublicKey,
734
+ getPublicKeyForShortSignatures,
735
+ sign,
736
+ signShortSignature,
737
+ verify,
738
+ verifyShortSignature,
739
+ aggregatePublicKeys,
740
+ aggregateSignatures,
741
+ aggregateShortSignatures,
742
+ G1,
743
+ G2,
744
+ Signature,
745
+ ShortSignature,
569
746
  };
570
747
  }