@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.
- package/README.md +238 -227
- package/_shortw_utils.d.ts +8 -5
- package/_shortw_utils.d.ts.map +1 -1
- package/_shortw_utils.js +3 -8
- package/_shortw_utils.js.map +1 -1
- package/abstract/bls.d.ts +123 -62
- package/abstract/bls.d.ts.map +1 -1
- package/abstract/bls.js +219 -163
- package/abstract/bls.js.map +1 -1
- package/abstract/curve.d.ts +142 -21
- package/abstract/curve.d.ts.map +1 -1
- package/abstract/curve.js +224 -143
- package/abstract/curve.js.map +1 -1
- package/abstract/edwards.d.ts +190 -49
- package/abstract/edwards.d.ts.map +1 -1
- package/abstract/edwards.js +322 -136
- package/abstract/edwards.js.map +1 -1
- package/abstract/fft.d.ts +12 -10
- package/abstract/fft.d.ts.map +1 -1
- package/abstract/fft.js +12 -13
- package/abstract/fft.js.map +1 -1
- package/abstract/hash-to-curve.d.ts +31 -13
- package/abstract/hash-to-curve.d.ts.map +1 -1
- package/abstract/hash-to-curve.js +34 -19
- package/abstract/hash-to-curve.js.map +1 -1
- package/abstract/modular.d.ts +31 -13
- package/abstract/modular.d.ts.map +1 -1
- package/abstract/modular.js +125 -52
- package/abstract/modular.js.map +1 -1
- package/abstract/montgomery.d.ts +18 -5
- package/abstract/montgomery.d.ts.map +1 -1
- package/abstract/montgomery.js +23 -6
- package/abstract/montgomery.js.map +1 -1
- package/abstract/poseidon.d.ts +5 -13
- package/abstract/poseidon.d.ts.map +1 -1
- package/abstract/poseidon.js +12 -7
- package/abstract/poseidon.js.map +1 -1
- package/abstract/tower.d.ts +23 -49
- package/abstract/tower.d.ts.map +1 -1
- package/abstract/tower.js +9 -3
- package/abstract/tower.js.map +1 -1
- package/abstract/utils.d.ts +1 -115
- package/abstract/utils.d.ts.map +1 -1
- package/abstract/utils.js +17 -371
- package/abstract/utils.js.map +1 -1
- package/abstract/weierstrass.d.ts +206 -124
- package/abstract/weierstrass.d.ts.map +1 -1
- package/abstract/weierstrass.js +747 -604
- package/abstract/weierstrass.js.map +1 -1
- package/bls12-381.d.ts +2 -0
- package/bls12-381.d.ts.map +1 -1
- package/bls12-381.js +504 -466
- package/bls12-381.js.map +1 -1
- package/bn254.d.ts +2 -0
- package/bn254.d.ts.map +1 -1
- package/bn254.js +44 -32
- package/bn254.js.map +1 -1
- package/ed25519.d.ts +55 -66
- package/ed25519.d.ts.map +1 -1
- package/ed25519.js +172 -186
- package/ed25519.js.map +1 -1
- package/ed448.d.ts +60 -57
- package/ed448.d.ts.map +1 -1
- package/ed448.js +172 -166
- package/ed448.js.map +1 -1
- package/esm/_shortw_utils.d.ts +8 -5
- package/esm/_shortw_utils.d.ts.map +1 -1
- package/esm/_shortw_utils.js +3 -8
- package/esm/_shortw_utils.js.map +1 -1
- package/esm/abstract/bls.d.ts +123 -62
- package/esm/abstract/bls.d.ts.map +1 -1
- package/esm/abstract/bls.js +220 -164
- package/esm/abstract/bls.js.map +1 -1
- package/esm/abstract/curve.d.ts +142 -21
- package/esm/abstract/curve.d.ts.map +1 -1
- package/esm/abstract/curve.js +219 -143
- package/esm/abstract/curve.js.map +1 -1
- package/esm/abstract/edwards.d.ts +190 -49
- package/esm/abstract/edwards.d.ts.map +1 -1
- package/esm/abstract/edwards.js +320 -138
- package/esm/abstract/edwards.js.map +1 -1
- package/esm/abstract/fft.d.ts +12 -10
- package/esm/abstract/fft.d.ts.map +1 -1
- package/esm/abstract/fft.js +10 -11
- package/esm/abstract/fft.js.map +1 -1
- package/esm/abstract/hash-to-curve.d.ts +31 -13
- package/esm/abstract/hash-to-curve.d.ts.map +1 -1
- package/esm/abstract/hash-to-curve.js +33 -19
- package/esm/abstract/hash-to-curve.js.map +1 -1
- package/esm/abstract/modular.d.ts +31 -13
- package/esm/abstract/modular.d.ts.map +1 -1
- package/esm/abstract/modular.js +124 -51
- package/esm/abstract/modular.js.map +1 -1
- package/esm/abstract/montgomery.d.ts +18 -5
- package/esm/abstract/montgomery.d.ts.map +1 -1
- package/esm/abstract/montgomery.js +23 -6
- package/esm/abstract/montgomery.js.map +1 -1
- package/esm/abstract/poseidon.d.ts +5 -13
- package/esm/abstract/poseidon.d.ts.map +1 -1
- package/esm/abstract/poseidon.js +12 -7
- package/esm/abstract/poseidon.js.map +1 -1
- package/esm/abstract/tower.d.ts +23 -49
- package/esm/abstract/tower.d.ts.map +1 -1
- package/esm/abstract/tower.js +9 -3
- package/esm/abstract/tower.js.map +1 -1
- package/esm/abstract/utils.d.ts +1 -115
- package/esm/abstract/utils.d.ts.map +1 -1
- package/esm/abstract/utils.js +3 -344
- package/esm/abstract/utils.js.map +1 -1
- package/esm/abstract/weierstrass.d.ts +206 -124
- package/esm/abstract/weierstrass.d.ts.map +1 -1
- package/esm/abstract/weierstrass.js +743 -605
- package/esm/abstract/weierstrass.js.map +1 -1
- package/esm/bls12-381.d.ts +2 -0
- package/esm/bls12-381.d.ts.map +1 -1
- package/esm/bls12-381.js +503 -465
- package/esm/bls12-381.js.map +1 -1
- package/esm/bn254.d.ts +2 -0
- package/esm/bn254.d.ts.map +1 -1
- package/esm/bn254.js +41 -29
- package/esm/bn254.js.map +1 -1
- package/esm/ed25519.d.ts +55 -66
- package/esm/ed25519.d.ts.map +1 -1
- package/esm/ed25519.js +170 -183
- package/esm/ed25519.js.map +1 -1
- package/esm/ed448.d.ts +60 -57
- package/esm/ed448.d.ts.map +1 -1
- package/esm/ed448.js +169 -162
- 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 +31 -29
- package/esm/misc.js.map +1 -1
- package/esm/nist.d.ts +7 -22
- package/esm/nist.d.ts.map +1 -1
- package/esm/nist.js +106 -101
- package/esm/nist.js.map +1 -1
- package/esm/p256.d.ts +7 -3
- 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 +7 -4
- 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 +7 -3
- 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 +38 -21
- package/esm/secp256k1.d.ts.map +1 -1
- package/esm/secp256k1.js +112 -104
- package/esm/secp256k1.js.map +1 -1
- package/esm/utils.d.ts +96 -0
- package/esm/utils.d.ts.map +1 -0
- package/esm/utils.js +279 -0
- package/esm/utils.js.map +1 -0
- 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 +35 -33
- package/misc.js.map +1 -1
- package/nist.d.ts +7 -22
- package/nist.d.ts.map +1 -1
- package/nist.js +106 -101
- package/nist.js.map +1 -1
- package/p256.d.ts +7 -3
- package/p256.d.ts.map +1 -1
- package/p256.js +4 -0
- package/p256.js.map +1 -1
- package/p384.d.ts +7 -4
- package/p384.d.ts.map +1 -1
- package/p384.js +4 -1
- package/p384.js.map +1 -1
- package/p521.d.ts +7 -3
- package/p521.d.ts.map +1 -1
- package/p521.js +4 -0
- package/p521.js.map +1 -1
- package/package.json +17 -6
- package/secp256k1.d.ts +38 -21
- package/secp256k1.d.ts.map +1 -1
- package/secp256k1.js +112 -104
- package/secp256k1.js.map +1 -1
- package/src/_shortw_utils.ts +6 -15
- package/src/abstract/bls.ts +428 -251
- package/src/abstract/curve.ts +307 -149
- package/src/abstract/edwards.ts +555 -203
- package/src/abstract/fft.ts +30 -19
- package/src/abstract/hash-to-curve.ts +75 -34
- package/src/abstract/modular.ts +131 -59
- package/src/abstract/montgomery.ts +44 -15
- package/src/abstract/poseidon.ts +22 -18
- package/src/abstract/tower.ts +40 -71
- package/src/abstract/utils.ts +3 -378
- package/src/abstract/weierstrass.ts +1086 -746
- package/src/bls12-381.ts +549 -490
- package/src/bn254.ts +47 -35
- package/src/ed25519.ts +214 -216
- package/src/ed448.ts +251 -220
- package/src/index.ts +7 -9
- package/src/jubjub.ts +3 -3
- package/src/misc.ts +41 -40
- package/src/nist.ts +161 -126
- package/src/p256.ts +7 -3
- package/src/p384.ts +7 -5
- package/src/p521.ts +7 -3
- package/src/secp256k1.ts +145 -115
- package/src/utils.ts +328 -0
- package/utils.d.ts +96 -0
- package/utils.d.ts.map +1 -0
- package/utils.js +313 -0
- package/utils.js.map +1 -0
package/src/abstract/bls.ts
CHANGED
|
@@ -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
|
|
14
|
-
*
|
|
15
|
-
*
|
|
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 {
|
|
28
|
-
import type { Fp12, Fp12Bls, Fp2, Fp2Bls,
|
|
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
|
|
34
|
-
|
|
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
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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:
|
|
118
|
+
G1: CurvePointsType<Fp> & {
|
|
73
119
|
ShortSignature: SignatureCoder<Fp>;
|
|
74
120
|
mapToCurve: MapToCurve<Fp>;
|
|
75
|
-
htfDefaults:
|
|
121
|
+
htfDefaults: H2COpts;
|
|
76
122
|
};
|
|
77
|
-
G2:
|
|
123
|
+
G2: CurvePointsType<Fp2> & {
|
|
78
124
|
Signature: SignatureCoder<Fp2>;
|
|
79
125
|
mapToCurve: MapToCurve<Fp2>;
|
|
80
|
-
htfDefaults:
|
|
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:
|
|
94
|
-
xNegative:
|
|
95
|
-
r: bigint;
|
|
96
|
-
twistType:
|
|
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:
|
|
138
|
+
htfDefaults: H2COpts;
|
|
99
139
|
hash: CHash; // Because we need outputLen for DRBG
|
|
100
|
-
randomBytes
|
|
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
|
-
|
|
109
|
-
|
|
110
|
-
|
|
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,
|
|
113
|
-
(
|
|
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,
|
|
117
|
-
(
|
|
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 |
|
|
121
|
-
message: Hex |
|
|
122
|
-
publicKey: Hex |
|
|
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 |
|
|
127
|
-
message: Hex |
|
|
128
|
-
publicKey: Hex |
|
|
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 |
|
|
133
|
-
messages: (Hex |
|
|
134
|
-
publicKeys: (Hex |
|
|
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:
|
|
222
|
+
(publicKeys: WeierstrassPoint<Fp>[]): WeierstrassPoint<Fp>;
|
|
140
223
|
};
|
|
224
|
+
/** @deprecated use `longSignatures.aggregateSignatures` */
|
|
141
225
|
aggregateSignatures: {
|
|
142
226
|
(signatures: Hex[]): Uint8Array;
|
|
143
|
-
(signatures:
|
|
227
|
+
(signatures: WeierstrassPoint<Fp2>[]): WeierstrassPoint<Fp2>;
|
|
144
228
|
};
|
|
229
|
+
/** @deprecated use `shortSignatures.aggregateSignatures` */
|
|
145
230
|
aggregateShortSignatures: {
|
|
146
231
|
(signatures: Hex[]): Uint8Array;
|
|
147
|
-
(signatures:
|
|
232
|
+
(signatures: WeierstrassPoint<Fp>[]): WeierstrassPoint<Fp>;
|
|
148
233
|
};
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
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
|
-
|
|
193
|
-
|
|
194
|
-
|
|
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 (
|
|
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 (
|
|
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(
|
|
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 (
|
|
370
|
+
if (postPrecompute) {
|
|
289
371
|
const last = ell[ell.length - 1];
|
|
290
|
-
|
|
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 (
|
|
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
|
-
|
|
320
|
-
|
|
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.
|
|
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
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
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.
|
|
622
|
+
return point instanceof G1.Point
|
|
355
623
|
? point
|
|
356
|
-
:
|
|
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.
|
|
627
|
+
return point instanceof G2.Point
|
|
363
628
|
? point
|
|
364
|
-
:
|
|
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
|
|
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
|
|
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
|
|
385
|
-
|
|
386
|
-
|
|
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
|
|
403
|
-
|
|
404
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
457
|
-
|
|
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
|
-
|
|
472
|
-
|
|
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
|
-
|
|
486
|
-
|
|
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
|
-
|
|
505
|
-
|
|
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.
|
|
706
|
+
G1.Point.BASE.precompute(4);
|
|
536
707
|
|
|
537
708
|
return {
|
|
538
|
-
|
|
539
|
-
|
|
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
|
-
|
|
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
|
}
|