0
# BLS Signatures
1
2
BLS (Boneh-Lynn-Shacham) signature schemes according to IETF standards, providing digital signatures with aggregation capabilities. These schemes are particularly important for blockchain applications where signature aggregation can significantly reduce data size and verification costs.
3
4
## Capabilities
5
6
### G2Basic Signature Scheme
7
8
The basic BLS signature scheme using G2 elements for signatures. This is the most commonly used BLS signature variant.
9
10
```python { .api }
11
class G2Basic:
12
DST: bytes # Domain separation tag
13
14
@classmethod
15
def SkToPk(cls, sk: int) -> bytes:
16
"""
17
Convert a secret key to a public key.
18
19
Args:
20
sk (int): Secret key as integer
21
22
Returns:
23
bytes: 48-byte compressed public key
24
"""
25
26
@staticmethod
27
def KeyValidate(pk: bytes) -> bool:
28
"""
29
Validate a public key.
30
31
Args:
32
pk (bytes): 48-byte public key to validate
33
34
Returns:
35
bool: True if key is valid, False otherwise
36
"""
37
38
@classmethod
39
def Sign(cls, sk: int, message: bytes) -> bytes:
40
"""
41
Sign a message with a secret key.
42
43
Args:
44
sk (int): Secret key as integer
45
message (bytes): Message to sign
46
47
Returns:
48
bytes: 96-byte signature
49
"""
50
51
@classmethod
52
def Verify(cls, pk: bytes, message: bytes, signature: bytes) -> bool:
53
"""
54
Verify a signature.
55
56
Args:
57
pk (bytes): 48-byte public key
58
message (bytes): Original message
59
signature (bytes): 96-byte signature to verify
60
61
Returns:
62
bool: True if signature is valid, False otherwise
63
"""
64
65
@classmethod
66
def Aggregate(cls, signatures: Sequence[bytes]) -> bytes:
67
"""
68
Aggregate multiple signatures into one.
69
70
Args:
71
signatures (Sequence[bytes]): List of 96-byte signatures
72
73
Returns:
74
bytes: 96-byte aggregated signature
75
"""
76
77
@classmethod
78
def AggregateVerify(cls, pks: Sequence[bytes], messages: Sequence[bytes], signature: bytes) -> bool:
79
"""
80
Verify an aggregated signature against multiple public keys and messages.
81
82
Args:
83
pks (Sequence[bytes]): List of 48-byte public keys
84
messages (Sequence[bytes]): List of messages (one per public key)
85
signature (bytes): 96-byte aggregated signature
86
87
Returns:
88
bool: True if aggregated signature is valid, False otherwise
89
"""
90
91
@classmethod
92
def FastAggregateVerify(cls, pks: Sequence[bytes], message: bytes, signature: bytes) -> bool:
93
"""
94
Fast verification of aggregated signature when all messages are identical.
95
96
Args:
97
pks (Sequence[bytes]): List of 48-byte public keys
98
message (bytes): Single message signed by all keys
99
signature (bytes): 96-byte aggregated signature
100
101
Returns:
102
bool: True if aggregated signature is valid, False otherwise
103
"""
104
```
105
106
### G2MessageAugmentation Signature Scheme
107
108
BLS signature scheme with message augmentation to prevent rogue key attacks without requiring proof of possession.
109
110
```python { .api }
111
class G2MessageAugmentation:
112
DST: bytes # Domain separation tag
113
114
@classmethod
115
def SkToPk(cls, sk: int) -> bytes:
116
"""Convert secret key to public key."""
117
118
@staticmethod
119
def KeyValidate(pk: bytes) -> bool:
120
"""Validate a public key."""
121
122
@classmethod
123
def Sign(cls, sk: int, message: bytes) -> bytes:
124
"""Sign a message with message augmentation."""
125
126
@classmethod
127
def Verify(cls, pk: bytes, message: bytes, signature: bytes) -> bool:
128
"""Verify a signature with message augmentation."""
129
130
@classmethod
131
def Aggregate(cls, signatures: Sequence[bytes]) -> bytes:
132
"""Aggregate multiple signatures."""
133
134
@classmethod
135
def AggregateVerify(cls, pks: Sequence[bytes], messages: Sequence[bytes], signature: bytes) -> bool:
136
"""Verify aggregated signature with message augmentation."""
137
```
138
139
### G2ProofOfPossession Signature Scheme
140
141
BLS signature scheme with proof of possession, providing the most secure aggregation capabilities.
142
143
```python { .api }
144
class G2ProofOfPossession:
145
DST: bytes # Domain separation tag
146
POP_DST: bytes # Proof of possession domain separation tag
147
148
@staticmethod
149
def SkToPk(sk: int) -> bytes:
150
"""Convert secret key to public key."""
151
152
@staticmethod
153
def KeyValidate(pk: bytes) -> bool:
154
"""Validate a public key."""
155
156
@classmethod
157
def Sign(cls, sk: int, message: bytes) -> bytes:
158
"""Sign a message."""
159
160
@classmethod
161
def Verify(cls, pk: bytes, message: bytes, signature: bytes) -> bool:
162
"""Verify a signature."""
163
164
@classmethod
165
def Aggregate(cls, signatures: Sequence[bytes]) -> bytes:
166
"""Aggregate multiple signatures."""
167
168
@classmethod
169
def AggregateVerify(cls, pks: Sequence[bytes], messages: Sequence[bytes], signature: bytes) -> bool:
170
"""Verify aggregated signature."""
171
172
@staticmethod
173
def FastAggregateVerify(pks: Sequence[bytes], message: bytes, signature: bytes) -> bool:
174
"""Fast verification when all messages are identical."""
175
176
@staticmethod
177
def PopProve(sk: int) -> bytes:
178
"""
179
Generate proof of possession for a secret key.
180
181
Args:
182
sk (int): Secret key
183
184
Returns:
185
bytes: 96-byte proof of possession
186
"""
187
188
@staticmethod
189
def PopVerify(pk: bytes, proof: bytes) -> bool:
190
"""
191
Verify proof of possession for a public key.
192
193
Args:
194
pk (bytes): 48-byte public key
195
proof (bytes): 96-byte proof of possession
196
197
Returns:
198
bool: True if proof is valid, False otherwise
199
"""
200
```
201
202
## Usage Examples
203
204
### Basic Signing and Verification
205
206
```python
207
from py_ecc.bls import G2Basic
208
209
# Generate key pair
210
private_key = 12345
211
public_key = G2Basic.SkToPk(private_key)
212
213
# Sign message
214
message = b"Hello, BLS signatures!"
215
signature = G2Basic.Sign(private_key, message)
216
217
# Verify signature
218
is_valid = G2Basic.Verify(public_key, message, signature)
219
assert is_valid
220
```
221
222
### Signature Aggregation
223
224
```python
225
from py_ecc.bls import G2Basic
226
227
# Multiple signers
228
private_keys = [123, 456, 789]
229
public_keys = [G2Basic.SkToPk(sk) for sk in private_keys]
230
messages = [b"Message 1", b"Message 2", b"Message 3"]
231
232
# Each signer signs their message
233
signatures = [G2Basic.Sign(sk, msg) for sk, msg in zip(private_keys, messages)]
234
235
# Aggregate signatures
236
aggregated_sig = G2Basic.Aggregate(signatures)
237
238
# Verify aggregated signature
239
is_valid = G2Basic.AggregateVerify(public_keys, messages, aggregated_sig)
240
assert is_valid
241
```
242
243
### Fast Aggregate Verification
244
245
```python
246
from py_ecc.bls import G2Basic
247
248
# Multiple signers signing the same message
249
private_keys = [111, 222, 333]
250
public_keys = [G2Basic.SkToPk(sk) for sk in private_keys]
251
message = b"Same message for all"
252
253
# Each signer signs the same message
254
signatures = [G2Basic.Sign(sk, message) for sk in private_keys]
255
256
# Aggregate signatures
257
aggregated_sig = G2Basic.Aggregate(signatures)
258
259
# Fast verification (more efficient when all messages are identical)
260
is_valid = G2Basic.FastAggregateVerify(public_keys, message, aggregated_sig)
261
assert is_valid
262
```
263
264
### Proof of Possession
265
266
```python
267
from py_ecc.bls import G2ProofOfPossession
268
269
# Generate key pair
270
private_key = 54321
271
public_key = G2ProofOfPossession.SkToPk(private_key)
272
273
# Generate proof of possession
274
pop_proof = G2ProofOfPossession.PopProve(private_key)
275
276
# Verify proof of possession
277
is_valid_pop = G2ProofOfPossession.PopVerify(public_key, pop_proof)
278
assert is_valid_pop
279
280
# Now the public key can be safely used in aggregation
281
message = b"Secure aggregation message"
282
signature = G2ProofOfPossession.Sign(private_key, message)
283
is_valid = G2ProofOfPossession.Verify(public_key, message, signature)
284
assert is_valid
285
```
286
287
## Error Handling
288
289
All BLS signature functions may raise `ValidationError` from `eth_utils` for invalid inputs:
290
291
- Invalid key formats or lengths
292
- Invalid signature formats or lengths
293
- Points not in the correct subgroups
294
- Invalid curve points
295
296
Always validate inputs when working with untrusted data:
297
298
```python
299
from py_ecc.bls import G2Basic
300
from eth_utils import ValidationError
301
302
try:
303
is_valid_key = G2Basic.KeyValidate(untrusted_public_key)
304
if is_valid_key:
305
result = G2Basic.Verify(untrusted_public_key, message, signature)
306
else:
307
print("Invalid public key")
308
except ValidationError as e:
309
print(f"Validation error: {e}")
310
```