@noble/curves 1.9.2 → 1.9.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +186 -206
- package/_shortw_utils.d.ts +1 -0
- package/_shortw_utils.d.ts.map +1 -1
- package/_shortw_utils.js +1 -0
- package/_shortw_utils.js.map +1 -1
- package/abstract/bls.d.ts +87 -62
- package/abstract/bls.d.ts.map +1 -1
- package/abstract/bls.js +170 -163
- package/abstract/bls.js.map +1 -1
- package/abstract/curve.d.ts +109 -23
- package/abstract/curve.d.ts.map +1 -1
- package/abstract/curve.js +158 -156
- package/abstract/curve.js.map +1 -1
- package/abstract/edwards.d.ts +126 -70
- package/abstract/edwards.d.ts.map +1 -1
- package/abstract/edwards.js +212 -62
- package/abstract/edwards.js.map +1 -1
- package/abstract/hash-to-curve.d.ts +8 -4
- package/abstract/hash-to-curve.d.ts.map +1 -1
- package/abstract/hash-to-curve.js +23 -11
- package/abstract/hash-to-curve.js.map +1 -1
- package/abstract/modular.d.ts +8 -3
- package/abstract/modular.d.ts.map +1 -1
- package/abstract/modular.js +79 -35
- package/abstract/modular.js.map +1 -1
- package/abstract/montgomery.d.ts +17 -4
- package/abstract/montgomery.d.ts.map +1 -1
- package/abstract/montgomery.js +19 -3
- package/abstract/montgomery.js.map +1 -1
- package/abstract/tower.d.ts +3 -3
- package/abstract/tower.d.ts.map +1 -1
- package/abstract/tower.js.map +1 -1
- package/abstract/weierstrass.d.ts +145 -118
- package/abstract/weierstrass.d.ts.map +1 -1
- package/abstract/weierstrass.js +415 -336
- package/abstract/weierstrass.js.map +1 -1
- package/bls12-381.d.ts.map +1 -1
- package/bls12-381.js +4 -4
- package/bls12-381.js.map +1 -1
- package/ed25519.d.ts +52 -66
- package/ed25519.d.ts.map +1 -1
- package/ed25519.js +128 -155
- package/ed25519.js.map +1 -1
- package/ed448.d.ts +57 -58
- package/ed448.d.ts.map +1 -1
- package/ed448.js +114 -131
- package/ed448.js.map +1 -1
- package/esm/_shortw_utils.d.ts +1 -0
- package/esm/_shortw_utils.d.ts.map +1 -1
- package/esm/_shortw_utils.js +1 -0
- package/esm/_shortw_utils.js.map +1 -1
- package/esm/abstract/bls.d.ts +87 -62
- package/esm/abstract/bls.d.ts.map +1 -1
- package/esm/abstract/bls.js +171 -164
- package/esm/abstract/bls.js.map +1 -1
- package/esm/abstract/curve.d.ts +109 -23
- package/esm/abstract/curve.d.ts.map +1 -1
- package/esm/abstract/curve.js +156 -155
- package/esm/abstract/curve.js.map +1 -1
- package/esm/abstract/edwards.d.ts +126 -70
- package/esm/abstract/edwards.d.ts.map +1 -1
- package/esm/abstract/edwards.js +210 -62
- package/esm/abstract/edwards.js.map +1 -1
- package/esm/abstract/hash-to-curve.d.ts +8 -4
- package/esm/abstract/hash-to-curve.d.ts.map +1 -1
- package/esm/abstract/hash-to-curve.js +22 -11
- package/esm/abstract/hash-to-curve.js.map +1 -1
- package/esm/abstract/modular.d.ts +8 -3
- package/esm/abstract/modular.d.ts.map +1 -1
- package/esm/abstract/modular.js +79 -35
- package/esm/abstract/modular.js.map +1 -1
- package/esm/abstract/montgomery.d.ts +17 -4
- package/esm/abstract/montgomery.d.ts.map +1 -1
- package/esm/abstract/montgomery.js +19 -3
- package/esm/abstract/montgomery.js.map +1 -1
- package/esm/abstract/tower.d.ts +3 -3
- package/esm/abstract/tower.d.ts.map +1 -1
- package/esm/abstract/tower.js.map +1 -1
- package/esm/abstract/weierstrass.d.ts +145 -118
- package/esm/abstract/weierstrass.d.ts.map +1 -1
- package/esm/abstract/weierstrass.js +412 -334
- package/esm/abstract/weierstrass.js.map +1 -1
- package/esm/bls12-381.d.ts.map +1 -1
- package/esm/bls12-381.js +4 -4
- package/esm/bls12-381.js.map +1 -1
- package/esm/ed25519.d.ts +52 -66
- package/esm/ed25519.d.ts.map +1 -1
- package/esm/ed25519.js +131 -157
- package/esm/ed25519.js.map +1 -1
- package/esm/ed448.d.ts +57 -58
- package/esm/ed448.d.ts.map +1 -1
- package/esm/ed448.js +116 -132
- package/esm/ed448.js.map +1 -1
- package/esm/index.js +7 -9
- package/esm/index.js.map +1 -1
- package/esm/jubjub.d.ts +3 -3
- package/esm/jubjub.d.ts.map +1 -1
- package/esm/jubjub.js +3 -3
- package/esm/jubjub.js.map +1 -1
- package/esm/misc.d.ts +3 -5
- package/esm/misc.d.ts.map +1 -1
- package/esm/misc.js +0 -3
- package/esm/misc.js.map +1 -1
- package/esm/nist.d.ts +0 -6
- package/esm/nist.d.ts.map +1 -1
- package/esm/nist.js +31 -15
- package/esm/nist.js.map +1 -1
- package/esm/p256.d.ts +4 -0
- package/esm/p256.d.ts.map +1 -1
- package/esm/p256.js +4 -0
- package/esm/p256.js.map +1 -1
- package/esm/p384.d.ts +4 -1
- package/esm/p384.d.ts.map +1 -1
- package/esm/p384.js +4 -1
- package/esm/p384.js.map +1 -1
- package/esm/p521.d.ts +4 -0
- package/esm/p521.d.ts.map +1 -1
- package/esm/p521.js +4 -0
- package/esm/p521.js.map +1 -1
- package/esm/secp256k1.d.ts +32 -15
- package/esm/secp256k1.d.ts.map +1 -1
- package/esm/secp256k1.js +72 -67
- package/esm/secp256k1.js.map +1 -1
- package/esm/utils.d.ts +1 -1
- package/esm/utils.js +1 -1
- package/index.js +7 -9
- package/index.js.map +1 -1
- package/jubjub.d.ts +3 -3
- package/jubjub.d.ts.map +1 -1
- package/jubjub.js +3 -3
- package/jubjub.js.map +1 -1
- package/misc.d.ts +3 -5
- package/misc.d.ts.map +1 -1
- package/misc.js +0 -3
- package/misc.js.map +1 -1
- package/nist.d.ts +0 -6
- package/nist.d.ts.map +1 -1
- package/nist.js +31 -15
- package/nist.js.map +1 -1
- package/p256.d.ts +4 -0
- package/p256.d.ts.map +1 -1
- package/p256.js +4 -0
- package/p256.js.map +1 -1
- package/p384.d.ts +4 -1
- package/p384.d.ts.map +1 -1
- package/p384.js +4 -1
- package/p384.js.map +1 -1
- package/p521.d.ts +4 -0
- package/p521.d.ts.map +1 -1
- package/p521.js +4 -0
- package/p521.js.map +1 -1
- package/package.json +4 -2
- package/secp256k1.d.ts +32 -15
- package/secp256k1.d.ts.map +1 -1
- package/secp256k1.js +70 -65
- package/secp256k1.js.map +1 -1
- package/src/_shortw_utils.ts +1 -0
- package/src/abstract/bls.ts +319 -257
- package/src/abstract/curve.ts +226 -170
- package/src/abstract/edwards.ts +352 -139
- package/src/abstract/hash-to-curve.ts +33 -16
- package/src/abstract/modular.ts +86 -35
- package/src/abstract/montgomery.ts +36 -9
- package/src/abstract/tower.ts +4 -4
- package/src/abstract/weierstrass.ts +570 -476
- package/src/bls12-381.ts +28 -20
- package/src/ed25519.ts +161 -179
- package/src/ed448.ts +150 -156
- package/src/index.ts +7 -9
- package/src/jubjub.ts +3 -3
- package/src/misc.ts +3 -7
- package/src/nist.ts +40 -16
- package/src/p256.ts +4 -0
- package/src/p384.ts +4 -2
- package/src/p521.ts +4 -0
- package/src/secp256k1.ts +91 -73
- package/src/utils.ts +1 -1
- package/utils.d.ts +1 -1
- package/utils.js +1 -1
package/src/abstract/bls.ts
CHANGED
|
@@ -37,11 +37,12 @@ import {
|
|
|
37
37
|
import { getMinHashLength, mapHashToField, type IField } from './modular.ts';
|
|
38
38
|
import type { Fp12, Fp12Bls, Fp2, Fp2Bls, Fp6Bls } from './tower.ts';
|
|
39
39
|
import {
|
|
40
|
+
_normFnElement,
|
|
40
41
|
weierstrassPoints,
|
|
41
42
|
type CurvePointsRes,
|
|
42
43
|
type CurvePointsType,
|
|
43
|
-
type
|
|
44
|
-
type
|
|
44
|
+
type WeierstrassPoint,
|
|
45
|
+
type WeierstrassPointCons,
|
|
45
46
|
} from './weierstrass.ts';
|
|
46
47
|
|
|
47
48
|
type Fp = bigint; // Can be different field?
|
|
@@ -52,21 +53,29 @@ const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3);
|
|
|
52
53
|
export type TwistType = 'multiplicative' | 'divisive';
|
|
53
54
|
|
|
54
55
|
export type ShortSignatureCoder<Fp> = {
|
|
55
|
-
fromBytes(bytes: Uint8Array):
|
|
56
|
-
fromHex(hex: Hex):
|
|
57
|
-
toBytes(point:
|
|
56
|
+
fromBytes(bytes: Uint8Array): WeierstrassPoint<Fp>;
|
|
57
|
+
fromHex(hex: Hex): WeierstrassPoint<Fp>;
|
|
58
|
+
toBytes(point: WeierstrassPoint<Fp>): Uint8Array;
|
|
58
59
|
/** @deprecated use `toBytes` */
|
|
59
|
-
toRawBytes(point:
|
|
60
|
-
toHex(point:
|
|
60
|
+
toRawBytes(point: WeierstrassPoint<Fp>): Uint8Array;
|
|
61
|
+
toHex(point: WeierstrassPoint<Fp>): string;
|
|
61
62
|
};
|
|
62
63
|
|
|
63
64
|
export type SignatureCoder<Fp> = {
|
|
64
|
-
fromBytes(bytes: Uint8Array):
|
|
65
|
-
fromHex(hex: Hex):
|
|
66
|
-
toBytes(point:
|
|
65
|
+
fromBytes(bytes: Uint8Array): WeierstrassPoint<Fp>;
|
|
66
|
+
fromHex(hex: Hex): WeierstrassPoint<Fp>;
|
|
67
|
+
toBytes(point: WeierstrassPoint<Fp>): Uint8Array;
|
|
67
68
|
/** @deprecated use `toBytes` */
|
|
68
|
-
toRawBytes(point:
|
|
69
|
-
toHex(point:
|
|
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;
|
|
70
79
|
};
|
|
71
80
|
|
|
72
81
|
export type PostPrecomputePointAddFn = (
|
|
@@ -84,6 +93,27 @@ export type PostPrecomputeFn = (
|
|
|
84
93
|
Qy: Fp2,
|
|
85
94
|
pointAdd: PostPrecomputePointAddFn
|
|
86
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
|
+
};
|
|
87
117
|
export type CurveType = {
|
|
88
118
|
G1: CurvePointsType<Fp> & {
|
|
89
119
|
ShortSignature: SignatureCoder<Fp>;
|
|
@@ -95,21 +125,15 @@ export type CurveType = {
|
|
|
95
125
|
mapToCurve: MapToCurve<Fp2>;
|
|
96
126
|
htfDefaults: H2COpts;
|
|
97
127
|
};
|
|
98
|
-
fields:
|
|
99
|
-
Fp: IField<Fp>;
|
|
100
|
-
Fr: IField<bigint>;
|
|
101
|
-
Fp2: Fp2Bls;
|
|
102
|
-
Fp6: Fp6Bls;
|
|
103
|
-
Fp12: Fp12Bls;
|
|
104
|
-
};
|
|
128
|
+
fields: BlsFields;
|
|
105
129
|
params: {
|
|
106
130
|
// NOTE: MSB is always ignored and used as marker for length,
|
|
107
131
|
// otherwise leading zeros will be lost.
|
|
108
132
|
// Can be different from 'X' (seed) param!
|
|
109
|
-
ateLoopSize:
|
|
110
|
-
xNegative:
|
|
133
|
+
ateLoopSize: BlsPairingParams['ateLoopSize'];
|
|
134
|
+
xNegative: BlsPairingParams['xNegative'];
|
|
111
135
|
r: bigint; // TODO: remove
|
|
112
|
-
twistType:
|
|
136
|
+
twistType: BlsPairingParams['twistType']; // BLS12-381: Multiplicative, BN254: Divisive
|
|
113
137
|
};
|
|
114
138
|
htfDefaults: H2COpts;
|
|
115
139
|
hash: CHash; // Because we need outputLen for DRBG
|
|
@@ -121,67 +145,92 @@ export type CurveType = {
|
|
|
121
145
|
type PrecomputeSingle = [Fp2, Fp2, Fp2][];
|
|
122
146
|
type Precompute = PrecomputeSingle[];
|
|
123
147
|
|
|
124
|
-
|
|
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 {
|
|
125
154
|
longSignatures: BLSSigs<bigint, Fp2>;
|
|
126
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
|
+
}
|
|
127
175
|
|
|
128
|
-
|
|
129
|
-
pairing: (P: ProjPointType<Fp>, Q: ProjPointType<Fp2>, withFinalExponent?: boolean) => Fp12;
|
|
130
|
-
pairingBatch: (
|
|
131
|
-
pairs: { g1: ProjPointType<Fp>; g2: ProjPointType<Fp2> }[],
|
|
132
|
-
withFinalExponent?: boolean
|
|
133
|
-
) => Fp12;
|
|
134
|
-
|
|
176
|
+
export type CurveFn = BLSCurvePair & {
|
|
135
177
|
/** @deprecated use `longSignatures.getPublicKey` */
|
|
136
|
-
getPublicKey: (
|
|
178
|
+
getPublicKey: (secretKey: PrivKey) => Uint8Array;
|
|
137
179
|
/** @deprecated use `shortSignatures.getPublicKey` */
|
|
138
|
-
getPublicKeyForShortSignatures: (
|
|
180
|
+
getPublicKeyForShortSignatures: (secretKey: PrivKey) => Uint8Array;
|
|
139
181
|
/** @deprecated use `longSignatures.sign` */
|
|
140
182
|
sign: {
|
|
141
|
-
(message: Hex,
|
|
142
|
-
(
|
|
183
|
+
(message: Hex, secretKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array;
|
|
184
|
+
(
|
|
185
|
+
message: WeierstrassPoint<Fp2>,
|
|
186
|
+
secretKey: PrivKey,
|
|
187
|
+
htfOpts?: htfBasicOpts
|
|
188
|
+
): WeierstrassPoint<Fp2>;
|
|
143
189
|
};
|
|
144
190
|
/** @deprecated use `shortSignatures.sign` */
|
|
145
191
|
signShortSignature: {
|
|
146
|
-
(message: Hex,
|
|
147
|
-
(
|
|
192
|
+
(message: Hex, secretKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array;
|
|
193
|
+
(
|
|
194
|
+
message: WeierstrassPoint<Fp>,
|
|
195
|
+
secretKey: PrivKey,
|
|
196
|
+
htfOpts?: htfBasicOpts
|
|
197
|
+
): WeierstrassPoint<Fp>;
|
|
148
198
|
};
|
|
149
199
|
/** @deprecated use `longSignatures.verify` */
|
|
150
200
|
verify: (
|
|
151
|
-
signature: Hex |
|
|
152
|
-
message: Hex |
|
|
153
|
-
publicKey: Hex |
|
|
201
|
+
signature: Hex | WeierstrassPoint<Fp2>,
|
|
202
|
+
message: Hex | WeierstrassPoint<Fp2>,
|
|
203
|
+
publicKey: Hex | WeierstrassPoint<Fp>,
|
|
154
204
|
htfOpts?: htfBasicOpts
|
|
155
205
|
) => boolean;
|
|
156
206
|
/** @deprecated use `shortSignatures.verify` */
|
|
157
207
|
verifyShortSignature: (
|
|
158
|
-
signature: Hex |
|
|
159
|
-
message: Hex |
|
|
160
|
-
publicKey: Hex |
|
|
208
|
+
signature: Hex | WeierstrassPoint<Fp>,
|
|
209
|
+
message: Hex | WeierstrassPoint<Fp>,
|
|
210
|
+
publicKey: Hex | WeierstrassPoint<Fp2>,
|
|
161
211
|
htfOpts?: htfBasicOpts
|
|
162
212
|
) => boolean;
|
|
163
213
|
verifyBatch: (
|
|
164
|
-
signature: Hex |
|
|
165
|
-
messages: (Hex |
|
|
166
|
-
publicKeys: (Hex |
|
|
214
|
+
signature: Hex | WeierstrassPoint<Fp2>,
|
|
215
|
+
messages: (Hex | WeierstrassPoint<Fp2>)[],
|
|
216
|
+
publicKeys: (Hex | WeierstrassPoint<Fp>)[],
|
|
167
217
|
htfOpts?: htfBasicOpts
|
|
168
218
|
) => boolean;
|
|
169
219
|
/** @deprecated use `longSignatures.aggregatePublicKeys` */
|
|
170
220
|
aggregatePublicKeys: {
|
|
171
221
|
(publicKeys: Hex[]): Uint8Array;
|
|
172
|
-
(publicKeys:
|
|
222
|
+
(publicKeys: WeierstrassPoint<Fp>[]): WeierstrassPoint<Fp>;
|
|
173
223
|
};
|
|
174
224
|
/** @deprecated use `longSignatures.aggregateSignatures` */
|
|
175
225
|
aggregateSignatures: {
|
|
176
226
|
(signatures: Hex[]): Uint8Array;
|
|
177
|
-
(signatures:
|
|
227
|
+
(signatures: WeierstrassPoint<Fp2>[]): WeierstrassPoint<Fp2>;
|
|
178
228
|
};
|
|
179
229
|
/** @deprecated use `shortSignatures.aggregateSignatures` */
|
|
180
230
|
aggregateShortSignatures: {
|
|
181
231
|
(signatures: Hex[]): Uint8Array;
|
|
182
|
-
(signatures:
|
|
232
|
+
(signatures: WeierstrassPoint<Fp>[]): WeierstrassPoint<Fp>;
|
|
183
233
|
};
|
|
184
|
-
/** @deprecated use `curves.G1` and `curves.G2` */
|
|
185
234
|
G1: CurvePointsRes<Fp> & H2CHasher<Fp>;
|
|
186
235
|
G2: CurvePointsRes<Fp2> & H2CHasher<Fp2>;
|
|
187
236
|
/** @deprecated use `longSignatures.Signature` */
|
|
@@ -197,35 +246,25 @@ export type CurveFn = {
|
|
|
197
246
|
/** @deprecated */
|
|
198
247
|
G2b: Fp2;
|
|
199
248
|
};
|
|
200
|
-
curves: {
|
|
201
|
-
G1: ProjConstructor<bigint>;
|
|
202
|
-
G2: ProjConstructor<Fp2>;
|
|
203
|
-
};
|
|
204
|
-
fields: {
|
|
205
|
-
Fp: IField<Fp>;
|
|
206
|
-
Fp2: Fp2Bls;
|
|
207
|
-
Fp6: Fp6Bls;
|
|
208
|
-
Fp12: Fp12Bls;
|
|
209
|
-
Fr: IField<bigint>;
|
|
210
|
-
};
|
|
211
|
-
utils: {
|
|
212
|
-
randomPrivateKey: () => Uint8Array;
|
|
213
|
-
calcPairingPrecomputes: (p: ProjPointType<Fp2>) => Precompute;
|
|
214
|
-
};
|
|
215
249
|
};
|
|
216
250
|
|
|
217
251
|
type BLSInput = Hex | Uint8Array;
|
|
218
252
|
export interface BLSSigs<P, S> {
|
|
219
|
-
getPublicKey(
|
|
220
|
-
sign(hashedMessage:
|
|
253
|
+
getPublicKey(secretKey: PrivKey): WeierstrassPoint<P>;
|
|
254
|
+
sign(hashedMessage: WeierstrassPoint<S>, secretKey: PrivKey): WeierstrassPoint<S>;
|
|
221
255
|
verify(
|
|
222
|
-
signature:
|
|
223
|
-
message:
|
|
224
|
-
publicKey:
|
|
256
|
+
signature: WeierstrassPoint<S> | BLSInput,
|
|
257
|
+
message: WeierstrassPoint<S>,
|
|
258
|
+
publicKey: WeierstrassPoint<P> | BLSInput
|
|
225
259
|
): boolean;
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
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>;
|
|
229
268
|
Signature: SignatureCoder<S>;
|
|
230
269
|
}
|
|
231
270
|
|
|
@@ -243,39 +282,27 @@ function NAfDecomposition(a: bigint) {
|
|
|
243
282
|
return res;
|
|
244
283
|
}
|
|
245
284
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
const { Fp, Fr, Fp2, Fp6, Fp12 } = CURVE.fields;
|
|
250
|
-
const BLS_X_IS_NEGATIVE = CURVE.params.xNegative;
|
|
251
|
-
const TWIST: TwistType = CURVE.params.twistType;
|
|
252
|
-
// Point on G1 curve: (x, y)
|
|
253
|
-
const G1_ = weierstrassPoints(CURVE.G1);
|
|
254
|
-
const G1 = Object.assign(
|
|
255
|
-
G1_,
|
|
256
|
-
createHasher(G1_.Point, CURVE.G1.mapToCurve, {
|
|
257
|
-
...CURVE.htfDefaults,
|
|
258
|
-
...CURVE.G1.htfDefaults,
|
|
259
|
-
})
|
|
260
|
-
);
|
|
261
|
-
// Point on G2 curve (complex numbers): (x₁, x₂+i), (y₁, y₂+i)
|
|
262
|
-
const G2_ = weierstrassPoints(CURVE.G2);
|
|
263
|
-
const G2 = Object.assign(
|
|
264
|
-
G2_,
|
|
265
|
-
createHasher(G2_.Point as H2CPointConstructor<Fp2>, CURVE.G2.mapToCurve, {
|
|
266
|
-
...CURVE.htfDefaults,
|
|
267
|
-
...CURVE.G2.htfDefaults,
|
|
268
|
-
})
|
|
269
|
-
);
|
|
270
|
-
type G1 = typeof G1.Point.BASE;
|
|
271
|
-
type G2 = typeof G2.Point.BASE;
|
|
285
|
+
function aNonEmpty(arr: any[]) {
|
|
286
|
+
if (!Array.isArray(arr) || arr.length === 0) throw new Error('expected non-empty array');
|
|
287
|
+
}
|
|
272
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;
|
|
273
300
|
// Applies sparse multiplication as line function
|
|
274
301
|
let lineFunction: (c0: Fp2, c1: Fp2, c2: Fp2, f: Fp12, Px: Fp, Py: Fp) => Fp12;
|
|
275
|
-
if (
|
|
302
|
+
if (twistType === 'multiplicative') {
|
|
276
303
|
lineFunction = (c0: Fp2, c1: Fp2, c2: Fp2, f: Fp12, Px: Fp, Py: Fp) =>
|
|
277
304
|
Fp12.mul014(f, c0, Fp2.mul(c1, Px), Fp2.mul(c2, Py));
|
|
278
|
-
} else if (
|
|
305
|
+
} else if (twistType === 'divisive') {
|
|
279
306
|
// NOTE: it should be [c0, c1, c2], but we use different order here to reduce complexity of
|
|
280
307
|
// precompute calculations.
|
|
281
308
|
lineFunction = (c0: Fp2, c1: Fp2, c2: Fp2, f: Fp12, Px: Fp, Py: Fp) =>
|
|
@@ -324,7 +351,7 @@ export function bls(CURVE: CurveType): CurveFn {
|
|
|
324
351
|
// Point addition and point double calculations is reused for coefficients
|
|
325
352
|
// pointAdd happens only if bit set, so wNAF is reasonable. Unfortunately we cannot combine
|
|
326
353
|
// add + double in windowed precomputes here, otherwise it would be single op (since X is static)
|
|
327
|
-
const ATE_NAF = NAfDecomposition(
|
|
354
|
+
const ATE_NAF = NAfDecomposition(ateLoopSize);
|
|
328
355
|
|
|
329
356
|
const calcPairingPrecomputes = memoized((point: G2) => {
|
|
330
357
|
const p = point;
|
|
@@ -340,9 +367,9 @@ export function bls(CURVE: CurveType): CurveFn {
|
|
|
340
367
|
if (bit) ({ Rx, Ry, Rz } = pointAdd(cur, Rx, Ry, Rz, Qx, bit === -1 ? negQy : Qy));
|
|
341
368
|
ell.push(cur);
|
|
342
369
|
}
|
|
343
|
-
if (
|
|
370
|
+
if (postPrecompute) {
|
|
344
371
|
const last = ell[ell.length - 1];
|
|
345
|
-
|
|
372
|
+
postPrecompute(Rx, Ry, Rz, Qx, Qy, pointAdd.bind(null, last));
|
|
346
373
|
}
|
|
347
374
|
return ell;
|
|
348
375
|
});
|
|
@@ -362,7 +389,7 @@ export function bls(CURVE: CurveType): CurveFn {
|
|
|
362
389
|
}
|
|
363
390
|
}
|
|
364
391
|
}
|
|
365
|
-
if (
|
|
392
|
+
if (xNegative) f12 = Fp12.conjugate(f12);
|
|
366
393
|
return withFinalExponent ? Fp12.finalExponentiate(f12) : f12;
|
|
367
394
|
}
|
|
368
395
|
type PairingInput = { g1: G1; g2: G2 };
|
|
@@ -372,13 +399,11 @@ export function bls(CURVE: CurveType): CurveFn {
|
|
|
372
399
|
const res: MillerInput = [];
|
|
373
400
|
// Cache precomputed toAffine for all points
|
|
374
401
|
normalizeZ(
|
|
375
|
-
G1
|
|
376
|
-
'pz',
|
|
402
|
+
G1,
|
|
377
403
|
pairs.map(({ g1 }) => g1)
|
|
378
404
|
);
|
|
379
405
|
normalizeZ(
|
|
380
|
-
G2
|
|
381
|
-
'pz',
|
|
406
|
+
G2,
|
|
382
407
|
pairs.map(({ g2 }) => g2)
|
|
383
408
|
);
|
|
384
409
|
for (const { g1, g2 } of pairs) {
|
|
@@ -395,128 +420,201 @@ export function bls(CURVE: CurveType): CurveFn {
|
|
|
395
420
|
function pairing(Q: G1, P: G2, withFinalExponent: boolean = true): Fp12 {
|
|
396
421
|
return pairingBatch([{ g1: Q, g2: P }], withFinalExponent);
|
|
397
422
|
}
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
const length = getMinHashLength(Fr.ORDER);
|
|
404
|
-
return mapHashToField(rand(length), Fr.ORDER);
|
|
405
|
-
},
|
|
423
|
+
return {
|
|
424
|
+
Fp12, // NOTE: we re-export Fp12 here because pairing results are Fp12!
|
|
425
|
+
millerLoopBatch,
|
|
426
|
+
pairing,
|
|
427
|
+
pairingBatch,
|
|
406
428
|
calcPairingPrecomputes,
|
|
407
429
|
};
|
|
430
|
+
}
|
|
408
431
|
|
|
409
|
-
|
|
410
|
-
|
|
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);
|
|
411
444
|
}
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
type G2Hex = Hex | G2;
|
|
415
|
-
function normP1(point: G1Hex): G1 {
|
|
416
|
-
return point instanceof G1.Point ? (point as G1) : G1.Point.fromHex(point);
|
|
445
|
+
function normSig(point: SigPoint | BLSInput): SigPoint {
|
|
446
|
+
return point instanceof SigCurve.Point ? (point as SigPoint) : SigCurve.Point.fromHex(point);
|
|
417
447
|
}
|
|
418
|
-
function
|
|
419
|
-
|
|
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;
|
|
420
452
|
}
|
|
421
453
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
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
|
+
},
|
|
438
549
|
|
|
439
|
-
//
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
if (unusedArg != null) throw new Error('sign() expects 2 arguments');
|
|
449
|
-
amsg(message).assertValidity();
|
|
450
|
-
return message.multiply(PubCurve.normPrivateKeyToScalar(privateKey));
|
|
451
|
-
},
|
|
452
|
-
// Checks if pairing of public key & hash is equal to pairing of generator & signature.
|
|
453
|
-
// e(P, H(m)) == e(G, S)
|
|
454
|
-
// e(S, G) == e(H(m), P)
|
|
455
|
-
verify(
|
|
456
|
-
signature: SigPoint | BLSInput,
|
|
457
|
-
message: SigPoint,
|
|
458
|
-
publicKey: PubPoint | BLSInput,
|
|
459
|
-
unusedArg?: any
|
|
460
|
-
): boolean {
|
|
461
|
-
if (unusedArg != null) throw new Error('verify() expects 3 arguments');
|
|
462
|
-
signature = normSig(signature);
|
|
463
|
-
publicKey = normPub(publicKey);
|
|
464
|
-
const P = publicKey.negate();
|
|
465
|
-
const G = PubCurve.Point.BASE;
|
|
466
|
-
const Hm = amsg(message);
|
|
467
|
-
const S = signature;
|
|
468
|
-
// This code was changed in 1.9.x:
|
|
469
|
-
// Before it was G.negate() in G2, now it's always pubKey.negate
|
|
470
|
-
// TODO: understand if this is OK?
|
|
471
|
-
// prettier-ignore
|
|
472
|
-
const exp_ = isLongSigs ? [
|
|
473
|
-
{ g1: P, g2: Hm },
|
|
474
|
-
{ g1: G, g2: S }
|
|
475
|
-
] : [
|
|
476
|
-
{ g1: Hm, g2: P },
|
|
477
|
-
{ g1: S, g2: G }
|
|
478
|
-
];
|
|
479
|
-
// TODO
|
|
480
|
-
// @ts-ignore
|
|
481
|
-
const exp = pairingBatch(exp_);
|
|
482
|
-
return Fp12.eql(exp, Fp12.ONE);
|
|
483
|
-
},
|
|
484
|
-
|
|
485
|
-
// Adds a bunch of public key points together.
|
|
486
|
-
// pk1 + pk2 + pk3 = pkA
|
|
487
|
-
aggregatePublicKeys(publicKeys: (PubPoint | BLSInput)[]): PubPoint {
|
|
488
|
-
aNonEmpty(publicKeys);
|
|
489
|
-
publicKeys = publicKeys.map((pub) => normPub(pub));
|
|
490
|
-
const agg = publicKeys.reduce((sum, p) => sum.add(p), PubCurve.Point.ZERO);
|
|
491
|
-
agg.assertValidity();
|
|
492
|
-
return agg;
|
|
493
|
-
},
|
|
494
|
-
|
|
495
|
-
// Adds a bunch of signature points together.
|
|
496
|
-
// pk1 + pk2 + pk3 = pkA
|
|
497
|
-
aggregateSignatures(signatures: (SigPoint | BLSInput)[]): SigPoint {
|
|
498
|
-
aNonEmpty(signatures);
|
|
499
|
-
signatures = signatures.map((sig) => normSig(sig));
|
|
500
|
-
const agg = signatures.reduce((sum, s) => sum.add(s), SigCurve.Point.ZERO);
|
|
501
|
-
agg.assertValidity();
|
|
502
|
-
return agg;
|
|
503
|
-
},
|
|
504
|
-
|
|
505
|
-
hash(messageBytes: Uint8Array, DST?: string | Uint8Array): SigPoint {
|
|
506
|
-
abytes(messageBytes);
|
|
507
|
-
const opts = DST ? { DST } : undefined;
|
|
508
|
-
return SigCurve.hashToCurve(messageBytes, opts);
|
|
509
|
-
},
|
|
510
|
-
|
|
511
|
-
// @ts-ignore
|
|
512
|
-
Signature: isLongSigs ? CURVE.G2.Signature : CURVE.G1.ShortSignature,
|
|
513
|
-
};
|
|
514
|
-
}
|
|
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;
|
|
558
|
+
},
|
|
515
559
|
|
|
516
|
-
|
|
517
|
-
|
|
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,
|
|
611
|
+
calcPairingPrecomputes,
|
|
612
|
+
};
|
|
518
613
|
|
|
519
614
|
// LEGACY code
|
|
615
|
+
type G1Hex = Hex | G1;
|
|
616
|
+
type G2Hex = Hex | G2;
|
|
617
|
+
|
|
520
618
|
const { ShortSignature } = CURVE.G1;
|
|
521
619
|
const { Signature } = CURVE.G2;
|
|
522
620
|
|
|
@@ -595,45 +693,14 @@ export function bls(CURVE: CurveType): CurveFn {
|
|
|
595
693
|
const agg = shortSignatures.aggregateSignatures(signatures);
|
|
596
694
|
return signatures[0] instanceof G1.Point ? agg : ShortSignature.toBytes(agg);
|
|
597
695
|
}
|
|
598
|
-
|
|
599
|
-
// https://ethresear.ch/t/fast-verification-of-multiple-bls-signatures/5407
|
|
600
|
-
// e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si))
|
|
601
|
-
// TODO: maybe `{message: G2Hex, publicKey: G1Hex}[]` instead?
|
|
602
696
|
function verifyBatch(
|
|
603
697
|
signature: G2Hex,
|
|
604
698
|
messages: G2Hex[],
|
|
605
699
|
publicKeys: G1Hex[],
|
|
606
700
|
htfOpts?: htfBasicOpts
|
|
607
701
|
): boolean {
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
throw new Error('amount of public keys and messages should be equal');
|
|
611
|
-
const sig = normP2(signature);
|
|
612
|
-
const nMessages = messages.map((i) => normP2Hash(i, htfOpts));
|
|
613
|
-
const nPublicKeys = publicKeys.map(normP1);
|
|
614
|
-
// NOTE: this works only for exact same object
|
|
615
|
-
const messagePubKeyMap = new Map<G2, G1[]>();
|
|
616
|
-
for (let i = 0; i < nPublicKeys.length; i++) {
|
|
617
|
-
const pub = nPublicKeys[i];
|
|
618
|
-
const msg = nMessages[i];
|
|
619
|
-
let keys = messagePubKeyMap.get(msg);
|
|
620
|
-
if (keys === undefined) {
|
|
621
|
-
keys = [];
|
|
622
|
-
messagePubKeyMap.set(msg, keys);
|
|
623
|
-
}
|
|
624
|
-
keys.push(pub);
|
|
625
|
-
}
|
|
626
|
-
const paired = [];
|
|
627
|
-
try {
|
|
628
|
-
for (const [msg, keys] of messagePubKeyMap) {
|
|
629
|
-
const groupPublicKey = keys.reduce((acc, msg) => acc.add(msg));
|
|
630
|
-
paired.push({ g1: groupPublicKey, g2: msg });
|
|
631
|
-
}
|
|
632
|
-
paired.push({ g1: G1.Point.BASE.negate(), g2: sig });
|
|
633
|
-
return Fp12.eql(pairingBatch(paired), Fp12.ONE);
|
|
634
|
-
} catch {
|
|
635
|
-
return false;
|
|
636
|
-
}
|
|
702
|
+
const Hm = messages.map((m) => normP2Hash(m, htfOpts));
|
|
703
|
+
return longSignatures.verifyBatch(signature, Hm, publicKeys);
|
|
637
704
|
}
|
|
638
705
|
|
|
639
706
|
G1.Point.BASE.precompute(4);
|
|
@@ -644,12 +711,7 @@ export function bls(CURVE: CurveType): CurveFn {
|
|
|
644
711
|
millerLoopBatch,
|
|
645
712
|
pairing,
|
|
646
713
|
pairingBatch,
|
|
647
|
-
// TODO!!!
|
|
648
714
|
verifyBatch,
|
|
649
|
-
curves: {
|
|
650
|
-
G1: G1_.Point,
|
|
651
|
-
G2: G2_.Point,
|
|
652
|
-
},
|
|
653
715
|
fields: {
|
|
654
716
|
Fr,
|
|
655
717
|
Fp,
|