Example #1
0
def test_aggregate_verify(SKs, messages, result):
    PKs = [G2Basic.SkToPk(SK) for SK in SKs]
    messages = [bytes(msg) for msg in messages]
    signatures = [G2Basic.Sign(SK, msg) for SK, msg in zip(SKs, messages)]
    aggregate_signature = G2Basic.Aggregate(signatures)
    assert G2Basic.AggregateVerify(PKs, messages,
                                   aggregate_signature) == result
Example #2
0
def test_core_aggregate_verify(SKs, messages):
    PKs = [G2Basic.SkToPk(sk) for sk in SKs]
    messages = [bytes(msg) for msg in messages]
    signatures = [
        G2Basic._CoreSign(sk, msg, G2Basic.DST)
        for sk, msg in zip(SKs, messages)
    ]
    aggregate_signature = G2Basic.Aggregate(signatures)
    assert G2Basic._CoreAggregateVerify(PKs, messages, aggregate_signature,
                                        G2Basic.DST)
Example #3
0
def derive_private_child(master_private_key_share: bytes,
                         path: bytes,
                         master_pubkey: bytes = None) -> int:
    root_private_key_share, root_private_chaincode_share = parse_master_private_key(
        master_private_key_share)

    if master_pubkey:
        root_public_key, root_public_chaincode = parse_master_pubkey(
            master_pubkey)
        root_pubkey_address = bls_conv.G1_to_pubkey(root_public_key)
        public_chaincode_address = bls_conv.G1_to_pubkey(root_public_chaincode)
    else:
        root_pubkey_address = bls_basic.SkToPk(root_private_key_share)
        public_chaincode_address = bls_basic.SkToPk(
            root_private_chaincode_share)

    h = _hash_to_bls_field(
        _derivation_format_hash_input(root_pubkey_address,
                                      public_chaincode_address, path))
    derived_private = (root_private_key_share + root_private_chaincode_share *
                       h) % bls_curve.curve_order

    return derived_private
Example #4
0
def test_sign_verify(privkey):
    msg = str(privkey).encode('utf-8')
    pub = G2Basic.SkToPk(privkey)
    sig = G2Basic._CoreSign(privkey, msg, G2Basic.DST)
    assert G2Basic._CoreVerify(pub, msg, sig, G2Basic.DST)
Example #5
0
from py_ecc.optimized_bls12_381 import (
    G1,
    G2,
    multiply,
)
from py_ecc.bls.g2_primatives import (
    G1_to_pubkey,
    G2_to_signature,
)
from py_ecc.bls import G2Basic


@pytest.mark.parametrize(
    'pubkey,success',
    [
        (G2Basic.SkToPk(42), True),
        (b'\x11' * 48, False),
    ]
)
def test_key_validate(pubkey, success):
    assert G2Basic.KeyValidate(pubkey) == success


@pytest.mark.parametrize(
    'privkey',
    [
        (1),
        (5),
        (124),
        (735),
        (127409812145),
Example #6
0
def test_sk_to_pk(privkey, success):
    if success:
        G2Basic.SkToPk(privkey)
    else:
        with pytest.raises(ValidationError):
            G2Basic.SkToPk(privkey)
Example #7
0
)
def test_aggregate(signatures, success):
    if success:
        G2Basic.Aggregate(signatures)
    else:
        with pytest.raises(ValidationError):
            G2Basic.Aggregate(signatures)


SAMPLE_MESSAGE = b'helloworld'


@pytest.mark.parametrize(
    'pubkey, message, signature, result',
    [
        (G2Basic.SkToPk(1), SAMPLE_MESSAGE, G2Basic.Sign(1, SAMPLE_MESSAGE), True),
        (G2Basic.SkToPk(2), SAMPLE_MESSAGE, G2Basic.Sign(1, SAMPLE_MESSAGE), False),
        (G2Basic.SkToPk(1), SAMPLE_MESSAGE, Z2_SIGNATURE, False),
        (Z1_PUBKEY, SAMPLE_MESSAGE, G2Basic.Sign(1, SAMPLE_MESSAGE), False),
        (Z1_PUBKEY, SAMPLE_MESSAGE, Z2_SIGNATURE, False),
        (
            b'\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',  # noqa: E501
            SAMPLE_MESSAGE,
            b'\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',  # noqa: E501
            False,
        ),
    ]
)
def test_verify(pubkey, message, signature, result):
    assert G2Basic.Verify(pubkey, message, signature) == result
def generate_bls_key_shares_with_verification(rsa_key_files:Dict[int,str], threshold:int, integrity_passphrase:str):

    parties_ids = list(rsa_key_files.keys())

    # Generate and Shamir secret share root private key with related public keys and shares
    root_private_key_shares, root_private_key = _sample_shares(parties_ids, threshold)
    root_public_key = bls_conv.pubkey_to_G1(bls_basic.SkToPk(root_private_key))
    root_public_key_shares = {id : bls_conv.pubkey_to_G1(bls_basic.SkToPk(val)) for id, val in root_private_key_shares.items()}

    # Generate and Shamir secret share private chaincode with related public chaincode
    private_chaincode_shares, private_chaincode = _sample_shares(parties_ids, threshold)
    public_chaincode = bls_conv.pubkey_to_G1(bls_basic.SkToPk(private_chaincode))

    # Set master public key and private key shares
    master_pubkey = get_master_pubkey(root_public_key, public_chaincode)
    master_private_key_shares = {id : get_master_private_key(root_private_key_shares[id], private_chaincode_shares[id]) for id in parties_ids}

    # Senity check: verify all authorized set of keys (threshold size) generate the same root public key as above
    for auth_ids in itertools.combinations(parties_ids, threshold):
        curr_public_key = _interpolate_in_group({id : root_public_key_shares[id] for id in auth_ids}, bls_curve.G1)
        if not bls_curve.eq(root_public_key, curr_public_key):
            raise GenVerErrorBasic(f'Invalid Shamir secret sharing of public key for parties {auth_ids}')
    
    # Sign test message with each private key share, derived at test path
    test_derivation_path = _get_test_path()
    derived_pubkey_address = bls_conv.G1_to_pubkey(derive_public_child(master_pubkey, _get_test_path()))
    signature_shares = {}
    for id in parties_ids:
        try:
            derived_private_key_share = derive_private_child(master_private_key_shares[id], test_derivation_path, master_pubkey)             
            test_msg, _ = _get_msg_for_address(derived_pubkey_address)
            signature_shares[id] = bls_basic.Sign(derived_private_key_share, test_msg)
        except:
            raise GenVerErrorBasic(f'Unable to sign test message for id {id}')
    
    # Scrypt checksum of public key - to avoid manipulation and brute-force
    integrity_passphrase = bytes(integrity_passphrase,'utf-8')
    scrypt_checksum = _compute_scrypt_checksum(integrity_passphrase, master_pubkey)

    # Encrypt master private key shares and (common) integrity passphrase
    encrypted_master_private_key_shares = {}
    encrypted_integrity_passphrase = {}
    for id, rsa_key_file in rsa_key_files.items():
        try:
            rsa_key = RSA.importKey(open(rsa_key_file, 'r').read())
            cipher = PKCS1_OAEP.new(rsa_key)
        except:
            raise GenVerErrorBasic(f'Reading RSA key file {rsa_key_file}')

        if rsa_key.n.bit_length() < 4096:
            GenVerErrorBasic(f'RSA key is too short: {rsa_key.n.bit_length()}, should be at least 4096 bits')

        try:
            encrypted_master_private_key_shares[id] = cipher.encrypt(master_private_key_shares[id])
            encrypted_integrity_passphrase[id] = cipher.encrypt(integrity_passphrase)
        except:
            raise GenVerErrorBasic(f'Unable to encrypt master private key share for id {id}')
        
    # Prepare data to output to file
    
    data = {}
    data['master_pubkey'] = master_pubkey.hex()

    # Ingerity check for master public key
    data['integrity_checksum'] = scrypt_checksum.hex()

    data['threshold'] = threshold
    data['parties'] = {}
    for id in parties_ids:
        party = {}
        party['test_signature_share'] = signature_shares[id].hex()
        party['encrypted_master_private_key_share'] = encrypted_master_private_key_shares[id].hex()
        party['encrypted_integrity_passphrase'] = encrypted_integrity_passphrase[id].hex()
        data['parties'][id] = party
    
    # Output file for each party id (key id)
    for id in parties_ids:
        data['key_id'] = id
        # Write to file
        key_filename = f'id_{id}_fireblocks_bls_key_{master_pubkey[:4].hex()}.json'
        try:
            ver_file = open(key_filename, 'w+')
            json.dump(data, ver_file, indent=4)
            ver_file.close()
            print("Generated file:", colored(f'{key_filename}', "green"))
        except ValueError:
            raise GenVerErrorBasic(f'Error writing key file for id {id}')

    return master_pubkey