# toy implementation of BLS signatures
|
|
|
|
load("bls12-381.sage")
|
|
from hashlib import sha256
|
|
|
|
def hash(m):
|
|
h_output = sha256(str(m).encode('utf-8'))
|
|
return int(h_output.hexdigest(), 16)
|
|
|
|
def hash_to_point(m):
|
|
# WARNING this hash-to-point approach should not be used!
|
|
h = hash(m)
|
|
return e.G2 * h
|
|
|
|
|
|
e = Pairing()
|
|
|
|
class Signer:
|
|
def __init__(self):
|
|
self.sk = e.F1.random_element()
|
|
self.pk = self.sk * e.G1
|
|
|
|
def sign(self, m):
|
|
H = hash_to_point(m)
|
|
return self.sk * H
|
|
|
|
def verify(pk, s, m):
|
|
H = hash_to_point(m)
|
|
return e.pair(e.G1, s) == e.pair(pk, H)
|
|
|
|
def aggr(points):
|
|
R = 0
|
|
for i in range(len(points)):
|
|
R = R + points[i]
|
|
return R
|
|
|
|
|
|
m = 1234
|
|
|
|
# single signature & verification
|
|
user0 = Signer()
|
|
s = user0.sign(m)
|
|
v = verify(user0.pk, s, m)
|
|
assert v
|
|
|
|
|
|
# BLS signature aggregation
|
|
n = 10
|
|
users = [None]*n
|
|
pks = [None]*n
|
|
sigs = [None]*n
|
|
for i in range(n):
|
|
users[i] = Signer()
|
|
pks[i] = users[i].pk
|
|
sigs[i] = users[i].sign(m)
|
|
|
|
# aggregate sigs & pks
|
|
s_aggr = aggr(sigs)
|
|
pk_aggr = aggr(pks)
|
|
|
|
# verify aggregated signature
|
|
v = verify(pk_aggr, s_aggr, m)
|
|
assert v
|