# 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