147 lines
3.5 KiB
Python
147 lines
3.5 KiB
Python
from py_ecc.bls import G2ProofOfPossession as py_ecc_bls
|
|
from py_ecc.bls.g2_primatives import signature_to_G2 as _signature_to_G2
|
|
from py_ecc.optimized_bls12_381 import ( # noqa: F401
|
|
G1,
|
|
G2,
|
|
Z1,
|
|
Z2,
|
|
FQ,
|
|
add,
|
|
multiply,
|
|
neg,
|
|
pairing,
|
|
final_exponentiate,
|
|
FQ12
|
|
)
|
|
from py_ecc.bls.g2_primitives import ( # noqa: F401
|
|
G1_to_pubkey as G1_to_bytes48,
|
|
pubkey_to_G1 as bytes48_to_G1,
|
|
G2_to_signature as G2_to_bytes96,
|
|
signature_to_G2 as bytes96_to_G2,
|
|
)
|
|
|
|
|
|
import milagro_bls_binding as milagro_bls # noqa: F401 for BLS switching option
|
|
|
|
# Flag to make BLS active or not. Used for testing, do not ignore BLS in production unless you know what you are doing.
|
|
bls_active = True
|
|
|
|
# To change bls implementation, default to PyECC for correctness. Milagro is a good faster alternative.
|
|
bls = py_ecc_bls
|
|
|
|
STUB_SIGNATURE = b'\x11' * 96
|
|
STUB_PUBKEY = b'\x22' * 48
|
|
G2_POINT_AT_INFINITY = b'\xc0' + b'\x00' * 95
|
|
STUB_COORDINATES = _signature_to_G2(G2_POINT_AT_INFINITY)
|
|
|
|
|
|
def use_milagro():
|
|
"""
|
|
Shortcut to use Milagro as BLS library
|
|
"""
|
|
global bls
|
|
bls = milagro_bls
|
|
|
|
|
|
def use_py_ecc():
|
|
"""
|
|
Shortcut to use Py-ecc as BLS library
|
|
"""
|
|
global bls
|
|
bls = py_ecc_bls
|
|
|
|
|
|
def only_with_bls(alt_return=None):
|
|
"""
|
|
Decorator factory to make a function only run when BLS is active. Otherwise return the default.
|
|
"""
|
|
def runner(fn):
|
|
def entry(*args, **kw):
|
|
if bls_active:
|
|
return fn(*args, **kw)
|
|
else:
|
|
return alt_return
|
|
return entry
|
|
return runner
|
|
|
|
|
|
@only_with_bls(alt_return=True)
|
|
def Verify(PK, message, signature):
|
|
try:
|
|
result = bls.Verify(PK, message, signature)
|
|
except Exception:
|
|
result = False
|
|
finally:
|
|
return result
|
|
|
|
|
|
@only_with_bls(alt_return=True)
|
|
def AggregateVerify(pubkeys, messages, signature):
|
|
try:
|
|
result = bls.AggregateVerify(list(pubkeys), list(messages), signature)
|
|
except Exception:
|
|
result = False
|
|
finally:
|
|
return result
|
|
|
|
|
|
@only_with_bls(alt_return=True)
|
|
def FastAggregateVerify(pubkeys, message, signature):
|
|
try:
|
|
result = bls.FastAggregateVerify(list(pubkeys), message, signature)
|
|
except Exception:
|
|
result = False
|
|
finally:
|
|
return result
|
|
|
|
|
|
@only_with_bls(alt_return=STUB_SIGNATURE)
|
|
def Aggregate(signatures):
|
|
return bls.Aggregate(signatures)
|
|
|
|
|
|
@only_with_bls(alt_return=STUB_SIGNATURE)
|
|
def Sign(SK, message):
|
|
if bls == py_ecc_bls:
|
|
return bls.Sign(SK, message)
|
|
else:
|
|
return bls.Sign(SK.to_bytes(32, 'big'), message)
|
|
|
|
|
|
@only_with_bls(alt_return=STUB_COORDINATES)
|
|
def signature_to_G2(signature):
|
|
return _signature_to_G2(signature)
|
|
|
|
|
|
@only_with_bls(alt_return=STUB_PUBKEY)
|
|
def AggregatePKs(pubkeys):
|
|
if bls == py_ecc_bls:
|
|
assert all(bls.KeyValidate(pubkey) for pubkey in pubkeys)
|
|
elif bls == milagro_bls:
|
|
# milagro_bls._AggregatePKs checks KeyValidate internally
|
|
pass
|
|
|
|
return bls._AggregatePKs(list(pubkeys))
|
|
|
|
|
|
@only_with_bls(alt_return=STUB_SIGNATURE)
|
|
def SkToPk(SK):
|
|
if bls == py_ecc_bls:
|
|
return bls.SkToPk(SK)
|
|
else:
|
|
return bls.SkToPk(SK.to_bytes(32, 'big'))
|
|
|
|
|
|
def pairing_check(values):
|
|
p_q_1, p_q_2 = values
|
|
final_exponentiation = final_exponentiate(
|
|
pairing(p_q_1[1], p_q_1[0], final_exponentiate=False)
|
|
* pairing(p_q_2[1], p_q_2[0], final_exponentiate=False)
|
|
)
|
|
return final_exponentiation == FQ12.one()
|
|
|
|
|
|
@only_with_bls(alt_return=True)
|
|
def KeyValidate(pubkey):
|
|
return py_ecc_bls.KeyValidate(pubkey)
|