Example #1
0
def reconstruct(signatures):
    r = b.Z2
    for i, sig in signatures.items():
        sig_point = signature_to_G2(sig)
        coef = 1
        for j in signatures:
            if j != i:
                coef = -coef * (j + 1) * prime_field_inv(
                    i - j, b.curve_order) % b.curve_order
        r = b.add(r, b.multiply(sig_point, coef))
    return G2_to_signature(r)
def test_verify_and_deposit_fails_with_incorrect_signature(
    proxy_contract,
    deposit_contract,
    bls_public_key,
    withdrawal_credentials,
    signature,
    deposit_data_root,
    public_key_witness,
    signature_witness,
    deposit_amount,
    assert_tx_failed,
    signing_root,
    bls_private_key,
):
    assert (
        int.from_bytes(
            deposit_contract.functions.get_deposit_count().call(), byteorder="little"
        )
        == 0
    )
    assert (
        deposit_contract.functions.get_deposit_root().call().hex() == EMPTY_DEPOSIT_ROOT
    )

    public_key_witness_repr = _convert_int_to_fp_repr(public_key_witness)

    another_message = hashlib.sha256(b"not the signing root").digest()
    assert signing_root != another_message
    signature = G2ProofOfPossession.Sign(bls_private_key, another_message)
    group_element = signature_to_G2(signature)
    normalized_group_element = normalize(group_element)
    signature_witness = normalized_group_element[1]
    signature_witness_repr = _convert_int_to_fp2_repr(signature_witness)

    amount_in_wei = deposit_amount * 10 ** 9
    txn = proxy_contract.functions.verifyAndDeposit(
        bls_public_key,
        withdrawal_credentials,
        signature,
        deposit_data_root,
        public_key_witness_repr,
        signature_witness_repr,
    )
    assert_tx_failed(lambda: txn.transact({"value": amount_in_wei}))

    assert (
        int.from_bytes(
            deposit_contract.functions.get_deposit_count().call(), byteorder="little"
        )
        == 0
    )
def test_bls_pairing_check(proxy_contract, signing_root, bls_public_key, signature):
    public_key_point = pubkey_to_G1(bls_public_key)
    public_key = normalize(public_key_point)
    public_key_repr = (
        _convert_int_to_fp_repr(public_key[0]),
        _convert_int_to_fp_repr(public_key[1]),
    )

    # skip some data wrangling by calling contract function for this...
    message_on_curve = proxy_contract.functions.hashToCurve(signing_root).call()

    projective_signature_point = signature_to_G2(signature)
    signature_point = normalize(projective_signature_point)
    signature_repr = (
        _convert_int_to_fp2_repr(signature_point[0]),
        _convert_int_to_fp2_repr(signature_point[1]),
    )
    assert proxy_contract.functions.blsPairingCheck(
        public_key_repr, message_on_curve, signature_repr
    ).call()
def test_bls_signature_is_valid_fails_with_invalid_signature(
    proxy_contract, bls_public_key, signing_root, public_key_witness, bls_private_key
):
    public_key_witness_repr = _convert_int_to_fp_repr(public_key_witness)

    another_message = hashlib.sha256(b"not the signing root").digest()
    assert signing_root != another_message
    signature = G2ProofOfPossession.Sign(bls_private_key, another_message)
    group_element = signature_to_G2(signature)
    normalized_group_element = normalize(group_element)
    signature_witness = normalized_group_element[1]

    signature_witness_repr = _convert_int_to_fp2_repr(signature_witness)

    assert not proxy_contract.functions.blsSignatureIsValid(
        signing_root,
        bls_public_key,
        signature,
        public_key_witness_repr,
        signature_witness_repr,
    ).call()
def verify_signature_files(signature_files:Sequence[str], threshold:int=None) -> bool:
    
    # Get data from signature share file
    
    parties_ids = []
    signature_shares = {}
    master_pubkey = None
    msg = None
    derivation_index = None
    for sig_file in signature_files:
        in_data = {}
        try:
            in_file = open(sig_file, "r")
            in_data = json.load(in_file)
            in_file.close()
        except:
            raise GenVerErrorBasic(f'Reading key file {sig_file}')
            
        try:
            # Verify same master pubkey
            curr_master_pubkey = bytes.fromhex(in_data['master_pubkey'])
            if master_pubkey:
                if not master_pubkey == curr_master_pubkey:
                    raise GenVerErrorBasic(f'Different master pubkey in different files')
            else:
                master_pubkey = curr_master_pubkey

            # Verify same message
            curr_msg = in_data['message']
            if msg:
                if not msg == curr_msg:
                    raise GenVerErrorBasic(f'Different messages in different files')
            else:
                msg = curr_msg

            # Verify same derivation indx
            curr_index = in_data['derivation_index']
            if derivation_index:
                if not derivation_index == curr_index:
                    raise GenVerErrorBasic(f'Different derivation index in different files')
            else:
                derivation_index = curr_index

            curr_id = int(in_data['signer_id'])
            parties_ids.append(curr_id)
            signature_shares[curr_id] = bytes.fromhex(in_data['signature'])
        except:
            raise GenVerErrorBasic(f'Parsing key file {sig_file}')

    msg_str = msg['payload']
    if msg['hex']:
        try:
            msg_bytes = bytes.fromhex(msg['payload'])
        except:
            raise GenVerErrorBasic(f'Message string is not hex')
    else:
        msg_bytes = bytes(msg_str, 'ascii')
    
    # Convert signature shares to G2 elements to later interpolate on
    G2_signature_shares = {}
    for id, sig in signature_shares.items():
        try:
            G2_signature_shares[id] = bls_conv.signature_to_G2(sig)
        except:
            raise GenVerErrorBasic(f'Invalid encoding of signature for id {id}')
        
    if not threshold:
        threshold = len(parties_ids)

    der_path = index_to_path(derivation_index)
    derived_pubkey_address = bls_conv.G1_to_pubkey(derive_public_child(master_pubkey, der_path))
    
    print(f'Verifying signing threshold {threshold} out of {len(parties_ids)} parties')
    print("Message:", colored(msg_str, "green"))
    print("Public Key:", colored(derived_pubkey_address.hex(), "green"))
    
    # Verify joining threshold singature shares gives a valid signature
    auth_signature = b''
    for auth_ids in itertools.combinations(parties_ids, threshold):
        auth_signature = bls_conv.G2_to_signature(_interpolate_in_group({id : G2_signature_shares[id] for id in auth_ids}, bls_curve.G2))

        if not bls_basic.Verify(derived_pubkey_address, msg_bytes, auth_signature):
            raise GenVerErrorBasic(f'Failed verification of combined signature for id {auth_ids}.')
    
    print("Signature:", colored(auth_signature.hex(), "green"))
    print(colored("Success!", "green"))
    
    return True
def verify_key_file(key_file:str, passphrase:str, rsa_priv_key_file:str=None):
    try:
        in_file = open(key_file, "r")
        data = json.load(in_file)
        in_file.close()
    except:
        raise GenVerErrorBasic(f'Reading key file {key_file}')

    try:
        master_pubkey = bytes.fromhex(data['master_pubkey'])
        integrity_checksum = bytes.fromhex(data['integrity_checksum'])

        threshold = data['threshold']
        my_id = data['key_id']
        parties = data['parties']

        encrypted_private_key_share = bytes.fromhex(parties[f'{my_id}']['encrypted_master_private_key_share'])
        encrypted_integrity_passphrase = bytes.fromhex(parties[f'{my_id}']['encrypted_integrity_passphrase'])

        parties_ids = []
        test_signature_shares = {}
        for id_str, party in parties.items():
            try:
                id = int(id_str)
            except:
                raise GenVerErrorBasic(f'Invalid id {id_str}')
            parties_ids.append(id)
            test_signature_shares[id] = bytes.fromhex(party['test_signature_share'])
        
    except:
        raise GenVerErrorBasic(f'Error parsing key file')

    # If Given RSA private key, use it to get integrity passphrase (if no file, assume integrity passphrase is given)
    master_private_key_share = None
    if rsa_priv_key_file is None:
        integrity_passphrase = bytes(passphrase, 'utf-8')
    else: 
        try:
            in_file = open(rsa_priv_key_file, 'r')
            rsa_key = RSA.importKey(in_file.read(), passphrase=passphrase)
            cipher = PKCS1_OAEP.new(rsa_key)
            in_file.close()
        except:
            raise GenVerErrorBasic(f'Importing RSA key from file {rsa_priv_key_file} (perhaps wrong passphrase)')

        if not rsa_key.has_private():
            raise GenVerErrorBasic(f'Not a private RSA key file {rsa_priv_key_file}')
        
        try:
            master_private_key_share = cipher.decrypt(encrypted_private_key_share)
        except:
            raise GenVerErrorBasic(f'Invalid decryption of private key share from key file')
            
        try:
            integrity_passphrase = cipher.decrypt(encrypted_integrity_passphrase)
        except:
            raise GenVerErrorBasic(f'Invalid decryption of integrity passphrase from key file')

    # Sanity checks

    if threshold > len(parties_ids) or threshold < 1:
        raise GenVerErrorBasic(f'Invalid threhsold {threshold} for ids {parties_ids}')

    if (len(parties_ids) != len(set(parties_ids))):
        raise GenVerErrorBasic(f'Non-unique ids in verification file')
    
    test_derivation_path = _get_test_path()
    derived_public_key = derive_public_child(master_pubkey, test_derivation_path)
    derived_pubkey_address = bls_conv.G1_to_pubkey(derived_public_key)
    test_msg, _ = _get_msg_for_address(derived_pubkey_address)

    # If decrypted master_private_key Verify my own signature wasn't modified by signing again
    if master_private_key_share:
        derived_private_key_share = derive_private_child(master_private_key_share, test_derivation_path, master_pubkey)
        if not test_signature_shares[my_id] == bls_basic.Sign(derived_private_key_share, test_msg):
            raise GenVerErrorBasic(f'Modified signature share for my key id {my_id}')
    else:
        print(colored('No RSA key - not verifying private key share validity!', "cyan"))
    
    # After getting scrypt integrity passphrase validate master pubkey wasn't changed
    computed_checksum = _compute_scrypt_checksum(integrity_passphrase, master_pubkey)

    if not computed_checksum == integrity_checksum:
        raise GenVerErrorBasic(f'Failure in validating master public key integrity checksum (perhaps wrong passphrase)')

    # Convert to group elements to allow interpolation of signatures
    G2_signature_shares = {}
    for id, sig in test_signature_shares.items():
        try:
            G2_signature_shares[id] = bls_conv.signature_to_G2(sig)
        except:
            raise GenVerErrorBasic(f'Invalid encoding of signature shares for id {id}')

    # For each authorized set of the above, combine signature shares and verify

    print(f'Verifying signing threshold {threshold} out of {len(parties_ids)} parties...')
    
    for auth_ids in itertools.combinations(parties_ids, threshold):
        auth_signature = bls_conv.G2_to_signature(_interpolate_in_group({id : G2_signature_shares[id] for id in auth_ids}, bls_curve.G2))
        if not  bls_basic.Verify(derived_pubkey_address, test_msg, auth_signature):
            raise GenVerErrorBasic(f'Failed verification of combined signature for ids {auth_ids}')
    
    # Sanity check: check un-authorized set can't get valid signature (less then threhsold) 
    for auth_ids in itertools.combinations(parties_ids, threshold-1):        
        auth_signature = bls_conv.G2_to_signature(_interpolate_in_group({id : G2_signature_shares[id] for id in auth_ids}, bls_curve.G2))
        if bls_basic.Verify(derived_pubkey_address, test_msg, auth_signature):
            raise GenVerErrorBasic(f'Valid signature for unauthorized ids {auth_ids}')

    print(colored("Success!", "green"))
    return True
def sign_with_sk(sk, msg):
    return signature_to_G2(bls.Sign(sk.to_bytes(32, config.ENDIANNESS), msg))
Example #8
0
def test_G2_signature_encode_decode():
    G2_point = multiply(G2, 42)
    signature = G2_to_signature(G2_point)
    assert (normalize(signature_to_G2(signature)) == normalize(G2_point))
Example #9
0
def test_decompress_G2_with_no_modular_square_root_found():
    with pytest.raises(ValueError,
                       match="Failed to find a modular squareroot"):
        signature_to_G2(b'\xA0' + b'\x11' * 95)
Example #10
0
def signature_witness(signature):
    group_element = signature_to_G2(signature)
    normalized_group_element = normalize(group_element)
    return normalized_group_element[1]