"""BBS+ crypto."""
from typing import List, Optional, Tuple
from ..core.error import BaseError
from ..utils.dependencies import (
assert_ursa_bbs_signatures_installed,
is_ursa_bbs_signatures_module_installed,
)
from ..wallet.util import random_seed
if is_ursa_bbs_signatures_module_installed():
from ursa_bbs_signatures import BbsException as NativeBbsException
from ursa_bbs_signatures import BlsKeyPair, SignRequest, VerifyRequest
from ursa_bbs_signatures import sign as bbs_sign
from ursa_bbs_signatures import verify as bbs_verify
from ursa_bbs_signatures._ffi.FfiException import FfiException
[docs]
class BbsException(BaseError):
"""Base BBS exception."""
[docs]
def sign_messages_bls12381g2(messages: List[bytes], secret: bytes):
"""Sign messages using a bls12381g2 private signing key.
Args:
messages (List[bytes]): The messages to sign
secret (bytes): The private signing key
Returns:
bytes: The signature
"""
assert_ursa_bbs_signatures_installed()
messages = [message.decode("utf-8") for message in messages]
try:
key_pair = BlsKeyPair.from_secret_key(secret)
sign_request = SignRequest(key_pair=key_pair, messages=messages)
except (
FfiException,
NativeBbsException,
) as error: # would be nice to be able to distinct between false and error
raise BbsException("Unable to sign messages") from error
return bbs_sign(sign_request)
[docs]
def verify_signed_messages_bls12381g2(
messages: List[bytes], signature: bytes, public_key: bytes
) -> bool:
"""Verify an ed25519 signed message according to a public verification key.
Args:
messages (List[bytes]): The signed messages to verify.
signature (bytes): The signature to verify.
public_key (bytes): The public key to use in verification.
Returns:
bool: True if the signature is verified, else False.
Raises:
BbsException: If unable to verify the BBS+ signature.
"""
assert_ursa_bbs_signatures_installed()
key_pair = BlsKeyPair(public_key=public_key)
messages = [message.decode("utf-8") for message in messages]
verify_request = VerifyRequest(
key_pair=key_pair, signature=signature, messages=messages
)
try:
return bbs_verify(verify_request)
except (
FfiException,
NativeBbsException,
) as error:
raise BbsException("Unable to verify BBS+ signature") from error
[docs]
def create_bls12381g2_keypair(seed: Optional[bytes] = None) -> Tuple[bytes, bytes]:
"""Create a public and private bls12381g2 keypair from a seed value.
Args:
seed: Seed for keypair
Returns:
A tuple of (public key, secret key)
"""
assert_ursa_bbs_signatures_installed()
if not seed:
seed = random_seed()
try:
key_pair = BlsKeyPair.generate_g2(seed)
return key_pair.public_key, key_pair.secret_key
except Exception as error:
raise BbsException("Unable to create keypair") from error