예제 #1
0
def verify_signature(public_key: str, signing_data: str,
                     signature: str) -> None:
    """Verifies whether the data signature corresponds to the public key."""
    public_key = public_key.strip()
    if public_key.startswith("0x"):
        public_key = public_key[2:]

    bls_public_key = BLSPubkey(bytes.fromhex(public_key))
    if not bls_pop._is_valid_pubkey(bls_public_key):
        raise click.BadParameter("Invalid BLS public key")

    signature = signature.strip()
    if signature.startswith("0x"):
        signature = signature[2:]

    bls_signature = BLSSignature(bytes.fromhex(signature))
    if not bls_pop._is_valid_signature(bls_signature):
        raise click.BadParameter("Invalid BLS signature")

    signing_data = signing_data.strip()
    if signing_data.startswith("0x"):
        signing_data = signing_data[2:]

    if bls_pop.Verify(PK=bls_public_key,
                      message=bytes.fromhex(signing_data),
                      signature=bls_signature):
        click.secho("[+] The signature is valid", fg="green")
    else:
        click.secho("[-] The signature is invalid", fg="red")
예제 #2
0
def get_bls_secret_shares(
        total: int,
        threshold: int) -> Tuple[BLSPubkey, List[BLSPubkey], List[int]]:
    """Generates Shamir's secrets for the BLS keypair."""
    coefficients = [randint(0, PRIME - 1) for _ in range(threshold)]
    private_key_secrets = get_polynomial_points(coefficients, total)
    public_key_secrets = [
        bls_pop.SkToPk(private_key) for private_key in private_key_secrets
    ]
    return bls_pop.SkToPk(
        coefficients[0]), public_key_secrets, private_key_secrets
예제 #3
0
def sign(horcrux_file: str, horcrux_password: str) -> None:
    """Unlocks the keystore and signs the data."""
    horcrux_file = horcrux_file.strip()
    if not os.path.exists(horcrux_file):
        raise click.BadParameter("Horcrux file does not exist.")

    # read keystore from file
    with open(horcrux_file, "r") as key_file:
        keystore = HorcruxPbkdf2Keystore.create_from_json(json.load(key_file))

    signing_data = click.prompt(text="Enter hexadecimal encoded data to sign",
                                type=click.STRING).strip()
    if signing_data.startswith("0x"):
        signing_data = signing_data[2:]

    # decrypt and sign data
    private_key = int.from_bytes(keystore.decrypt(horcrux_password), "big")
    signature = bls_pop.Sign(private_key, bytes.fromhex(signing_data))

    click.echo(f"Signature: {click.style(f'0x{signature.hex()}', fg='green')}")
    click.echo(
        f"Horcrux index: {click.style(f'{keystore.index}', fg='green')}")
    click.echo(f"""Next steps:
1) Retrieve signatures of the same signing data from other horcruxes.
2) Run {click.style('./horcrux.sh reconstruct-signature', fg='blue')} to reconstruct the final signature.
   {click.style(f'NB! At least {keystore.threshold} signatures are required to reconstruct.', fg='yellow')}
""")
def reconstruct_signature(signatures: int) -> None:
    """Reconstructs BLS signatures using Shamir's secret sharing."""
    if signatures <= 0:
        raise click.BadParameter(message=INVALID_NUMBER)

    points: Dict[int, BLSSignature] = {}
    submitted = 0
    while True:
        if submitted == signatures:
            break

        index = click.prompt(
            text=("Enter the horcrux index of the submitted signature "
                  "(can be found in the owner's horcrux file)"),
            type=click.INT,
        )
        if index in points:
            click.echo("The signature for such index was already submitted")
            continue

        signature = click.prompt(
            text=("Enter the next hexadecimal encoded BLS signature "
                  f"({submitted + 1}/{signatures})"),
            type=click.STRING,
        ).strip()
        if signature.startswith("0x"):
            signature = signature[2:]

        signature = BLSSignature(bytes.fromhex(signature))
        if not bls_pop._is_valid_signature(signature):
            click.secho("The signature is invalid. Please try again.",
                        fg="red")
            continue

        points[index] = signature
        submitted += 1

    # reconstruct signature using Shamir's secret sharing

    reconstructed_signature = reconstruct_shared_bls_signature(points)
    click.echo(
        "Reconstructed signature: "
        f"{click.style(f'0x{reconstructed_signature.hex()}', fg='green')}")
    click.echo(f"Run {click.style('./horcrux.sh verify-signature', fg='blue')}"
               f" to verify whether the signature is correct.")
예제 #5
0
)
from py_ecc.optimized_bls12_381 import (
    add,
    curve_order,
    final_exponentiate,
    G1,
    multiply,
    neg,
    pairing,
    Z1,
    Z2,
)

from py_ecc.bls.ciphersuites import G2ProofOfPossession as bls

priv = 100
pub = bls.SkToPk(priv)
print(pub.hex())

x = pubkey_to_G1(pub)
print(x)

x2 = add(x, x)
print(x2)

agg = G1_to_pubkey(x2)
print(agg.hex())

v = pubkey_to_G1(agg)
print(v)
예제 #6
0
def process_dispatcher_output(
    dispatcher_output: List[Dict[str, Any]],
    my_bls_public_key: BLSPubkey,
    my_bls_public_key_shares: List[BLSPubkey],
    my_bls_private_key_shares: List[int],
    my_rsa_key: RsaKey,
    my_index: int,
) -> Tuple[BLSPubkey, bytes, int]:
    """
    Processes output from the dispatcher to generate final
    horcrux BLS private key and shared BLS public key.
    """
    final_public_key_shares = [my_bls_public_key]
    horcrux_private_key_shares = [my_bls_private_key_shares[my_index]]
    horcrux_public_key_shares = [my_bls_public_key_shares[my_index]]
    for encrypted_data in dispatcher_output:
        # verify the RSA signature
        ciphertext = bytes.fromhex(encrypted_data["ciphertext"])
        signature = bytes.fromhex(encrypted_data["signature"])
        if not rsa_verify(
                RSA.import_key(encrypted_data["sender_rsa_public_key"]),
                ciphertext,
                signature,
        ):
            raise ValueError("Failed to verify the RSA signature.")

        data = json.loads(
            rsa_decrypt(
                private_key=my_rsa_key,
                enc_session_key=bytes.fromhex(
                    encrypted_data["enc_session_key"]),
                nonce=bytes.fromhex(encrypted_data["nonce"]),
                tag=bytes.fromhex(encrypted_data["tag"]),
                ciphertext=ciphertext,
            ))
        recipient_bls_public_keys = [
            bytes.fromhex(pub_key) for pub_key in data["public_key_shares"]
        ]
        horcrux_private_key_share = int(data["private_key_share"])

        if (bls_pop.SkToPk(horcrux_private_key_share) !=
                recipient_bls_public_keys[my_index]):
            raise ValueError("Received invalid BLS private key share.")

        final_public_key_shares.append(
            BLSPubkey(bytes.fromhex(data["public_key"])))
        horcrux_public_key_shares.append(
            BLSPubkey(recipient_bls_public_keys[my_index]))
        horcrux_private_key_shares.append(horcrux_private_key_share)

    final_public_key = bls_pop._AggregatePKs(final_public_key_shares)
    click.echo("Shared BLS Public Key: "
               f"{click.style(f'0x{final_public_key.hex()}', fg='green')}")

    withdrawal_credentials = BLS_WITHDRAWAL_PREFIX
    withdrawal_credentials += SHA256(final_public_key)[1:]
    click.echo(
        "Withdrawal Credentials: "
        f"{click.style(f'0x{withdrawal_credentials.hex()}', fg='green')}")

    horcrux_private_key = 0
    for private_key_share in horcrux_private_key_shares:
        horcrux_private_key += private_key_share
        horcrux_private_key %= PRIME

    if bls_pop.SkToPk(horcrux_private_key) != bls_pop._AggregatePKs(
            horcrux_public_key_shares):
        raise ValueError("Invalid calculated horcrux private key")

    return final_public_key, withdrawal_credentials, horcrux_private_key
예제 #7
0
def signature(bls_private_key, signing_root):
    return G2ProofOfPossession.Sign(bls_private_key, signing_root)
예제 #8
0
def bls_public_key(bls_private_key):
    return G2ProofOfPossession.SkToPk(bls_private_key)
예제 #9
0
def bls_private_key(seed):
    return G2ProofOfPossession.KeyGen(seed)