Example #1
0
def main():
    # Mnemonics can be generated using `chia keys generate_and_print`, or `chia keys generate`. The latter stored
    # the key in the OS keychain (unencrypted file if linux).
    mnemonic: str = "neither medal holiday echo link dog sleep idea turkey logic security sword save taxi chapter artwork toddler wealth local mind manual never unlock narrow"

    seed: bytes = mnemonic_to_seed(mnemonic, passphrase="")
    master_private_key: PrivateKey = AugSchemeMPL.key_gen(seed)
    intermediate_sk: PrivateKey = AugSchemeMPL.derive_child_sk(
        master_private_key, 12381)
    intermediate_sk = AugSchemeMPL.derive_child_sk(intermediate_sk, 8444)
    intermediate_sk = AugSchemeMPL.derive_child_sk(intermediate_sk, 2)
    print(
        f"Parent public key is: {intermediate_sk.get_g1()}. Please use this within `create_unsigned_tx.py`"
    )

    # If you want to use hardened keys which are more secure against quantum computers, you need to export
    # The public keys
    # create_hardened_child_public_keys(mnemonic, 1000)

    try:
        with open("tx_3.json", "r") as f:
            spend_bundle_json = f.read()
    except Exception:
        print(
            "Error: create your transaction (spend bundle) json and put it into the json file."
        )
        return

    spend_bundle_json_dict: Dict = json.loads(spend_bundle_json)
    spend_bundle: SpendBundle = SpendBundle.from_json_dict(
        spend_bundle_json_dict)

    sign_tx(intermediate_sk, spend_bundle, use_hardened_keys=False)
Example #2
0
def sign(args):
    if args.message is None:
        print("Please specify the message argument -d")
        quit()

    if args.fingerprint is None or args.hd_path is None:
        print(
            "Please specify the fingerprint argument -f and hd_path argument -t"
        )
        quit()

    message = args.message
    assert message is not None

    k = Keychain()
    private_keys = k.get_all_private_keys()

    fingerprint = args.fingerprint
    assert fingerprint is not None
    hd_path = args.hd_path
    assert hd_path is not None
    path: List[uint32] = [
        uint32(int(i)) for i in hd_path.split("/") if i != "m"
    ]
    for sk, _ in private_keys:
        if sk.get_g1().get_fingerprint() == fingerprint:
            for c in path:
                sk = AugSchemeMPL.derive_child_sk(sk, c)
            print("Public key:", sk.get_g1())
            print("Signature:", AugSchemeMPL.sign(sk, bytes(message, "utf-8")))
            return
    print(f"Fingerprint {fingerprint} not found in keychain")
Example #3
0
def sign(message: str, fingerprint: int, hd_path: str):
    k = Keychain()
    private_keys = k.get_all_private_keys()

    path: List[uint32] = [uint32(int(i)) for i in hd_path.split("/") if i != "m"]
    for sk, _ in private_keys:
        if sk.get_g1().get_fingerprint() == fingerprint:
            for c in path:
                sk = AugSchemeMPL.derive_child_sk(sk, c)
            print("Public key:", sk.get_g1())
            print("Signature:", AugSchemeMPL.sign(sk, bytes(message, "utf-8")))
            return
    print(f"Fingerprint {fingerprint} not found in keychain")
Example #4
0
def create_hardened_child_public_keys(mnemonic: str, number: int = 5000):
    """
    Creates child public keys, derived from the master private key, using hardened derivation. This method is more
    secure than public key derivation since it's following the EIP-2333 spec for quantum security.
    """

    seed: bytes = mnemonic_to_seed(mnemonic, passphrase="")
    master_private_key: PrivateKey = AugSchemeMPL.key_gen(seed)

    intermediate_sk: PrivateKey = AugSchemeMPL.derive_child_sk(
        master_private_key, 12381)
    intermediate_sk = AugSchemeMPL.derive_child_sk(intermediate_sk, 8444)
    intermediate_sk = AugSchemeMPL.derive_child_sk(intermediate_sk, 2)

    all_pks: List[G1Element] = []
    for i in range(number):
        child_sk: PrivateKey = AugSchemeMPL.derive_child_sk(intermediate_sk, i)
        child_pk: G1Element = child_sk.get_g1()
        all_pks.append(child_pk)

    with open("child_public_keys.txt", "w") as f:
        lines = [f"{bytes(pk).hex()}\n" for pk in all_pks]
        f.writelines(lines)
Example #5
0
    def test_bip39_eip2333_test_vector(self):
        kc: Keychain = Keychain(testing=True)
        kc.delete_all_keys()

        mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"
        passphrase = "TREZOR"
        print("entropy to seed:", mnemonic_to_seed(mnemonic, passphrase).hex())
        master_sk = kc.add_private_key(mnemonic, passphrase)
        tv_master_int = 5399117110774477986698372024995405256382522670366369834617409486544348441851
        tv_child_int = 11812940737387919040225825939013910852517748782307378293770044673328955938106
        assert master_sk == PrivateKey.from_bytes(
            tv_master_int.to_bytes(32, "big"))
        child_sk = AugSchemeMPL.derive_child_sk(master_sk, 0)
        assert child_sk == PrivateKey.from_bytes(
            tv_child_int.to_bytes(32, "big"))
Example #6
0
def test_readme():
    seed: bytes = bytes([
        0,
        50,
        6,
        244,
        24,
        199,
        1,
        25,
        52,
        88,
        192,
        19,
        18,
        12,
        89,
        6,
        220,
        18,
        102,
        58,
        209,
        82,
        12,
        62,
        89,
        110,
        182,
        9,
        44,
        20,
        254,
        22,
    ])
    sk: PrivateKey = AugSchemeMPL.key_gen(seed)
    pk: G1Element = sk.get_g1()

    message: bytes = bytes([1, 2, 3, 4, 5])
    signature: G2Element = AugSchemeMPL.sign(sk, message)

    ok: bool = AugSchemeMPL.verify(pk, message, signature)
    assert ok

    sk_bytes: bytes = bytes(sk)  # 32 bytes
    pk_bytes: bytes = bytes(pk)  # 48 bytes
    signature_bytes: bytes = bytes(signature)  # 96 bytes

    print(sk_bytes.hex(), pk_bytes.hex(), signature_bytes.hex())

    sk = PrivateKey.from_bytes(sk_bytes)
    pk = G1Element.from_bytes(pk_bytes)
    signature = G2Element.from_bytes(signature_bytes)

    seed = bytes([1]) + seed[1:]
    sk1: PrivateKey = AugSchemeMPL.key_gen(seed)
    seed = bytes([2]) + seed[1:]
    sk2: PrivateKey = AugSchemeMPL.key_gen(seed)
    message2: bytes = bytes([1, 2, 3, 4, 5, 6, 7])

    pk1: G1Element = sk1.get_g1()
    sig1: G2Element = AugSchemeMPL.sign(sk1, message)

    pk2: G1Element = sk2.get_g1()
    sig2: G2Element = AugSchemeMPL.sign(sk2, message2)

    agg_sig: G2Element = AugSchemeMPL.aggregate([sig1, sig2])

    ok = AugSchemeMPL.aggregate_verify([pk1, pk2], [message, message2],
                                       agg_sig)
    assert ok

    seed = bytes([3]) + seed[1:]
    sk3: PrivateKey = AugSchemeMPL.key_gen(seed)
    pk3: G1Element = sk3.get_g1()
    message3: bytes = bytes([100, 2, 254, 88, 90, 45, 23])
    sig3: G2Element = AugSchemeMPL.sign(sk3, message3)

    agg_sig_final: G2Element = AugSchemeMPL.aggregate([agg_sig, sig3])
    ok = AugSchemeMPL.aggregate_verify([pk1, pk2, pk3],
                                       [message, message2, message3],
                                       agg_sig_final)
    assert ok

    pop_sig1: G2Element = PopSchemeMPL.sign(sk1, message)
    pop_sig2: G2Element = PopSchemeMPL.sign(sk2, message)
    pop_sig3: G2Element = PopSchemeMPL.sign(sk3, message)
    pop1: G2Element = PopSchemeMPL.pop_prove(sk1)
    pop2: G2Element = PopSchemeMPL.pop_prove(sk2)
    pop3: G2Element = PopSchemeMPL.pop_prove(sk3)

    ok = PopSchemeMPL.pop_verify(pk1, pop1)
    assert ok
    ok = PopSchemeMPL.pop_verify(pk2, pop2)
    assert ok
    ok = PopSchemeMPL.pop_verify(pk3, pop3)
    assert ok

    pop_sig_agg: G2Element = PopSchemeMPL.aggregate(
        [pop_sig1, pop_sig2, pop_sig3])

    ok = PopSchemeMPL.fast_aggregate_verify([pk1, pk2, pk3], message,
                                            pop_sig_agg)
    assert ok

    pop_agg_pk: G1Element = pk1 + pk2 + pk3
    ok = PopSchemeMPL.verify(pop_agg_pk, message, pop_sig_agg)
    assert ok

    pop_agg_sk: PrivateKey = PrivateKey.aggregate([sk1, sk2, sk3])
    ok = PopSchemeMPL.sign(pop_agg_sk, message) == pop_sig_agg
    assert ok

    master_sk: PrivateKey = AugSchemeMPL.key_gen(seed)
    child: PrivateKey = AugSchemeMPL.derive_child_sk(master_sk, 152)
    grandchild: PrivateKey = AugSchemeMPL.derive_child_sk(child, 952)

    master_pk: G1Element = master_sk.get_g1()
    child_u: PrivateKey = AugSchemeMPL.derive_child_sk_unhardened(
        master_sk, 22)
    grandchild_u: PrivateKey = AugSchemeMPL.derive_child_sk_unhardened(
        child_u, 0)

    child_u_pk: G1Element = AugSchemeMPL.derive_child_pk_unhardened(
        master_pk, 22)
    grandchild_u_pk: G1Element = AugSchemeMPL.derive_child_pk_unhardened(
        child_u_pk, 0)

    ok = grandchild_u_pk == grandchild_u.get_g1()
    assert ok
    hd_path = input(
        "Enter the HD path in the form 'm/12381/8444/n/n', or enter Q to quit: "
    ).lower()
    if hd_path == "q":
        quit()
    verify = input(f"Is this correct path: {hd_path}? (y/n) ").lower()
    if verify == "y":
        break

k = Keychain()
private_keys = k.get_all_private_keys()
path: List[uint32] = [uint32(int(i)) for i in hd_path.split("/") if i != "m"]

# Derive HD key using path form input
for c in path:
    selected_key = AugSchemeMPL.derive_child_sk(selected_key, c)
print("Public key:", selected_key.get_g1())

# get file path
file_path = None
while True:
    file_path = input(
        "Enter the path where you want to save signed alert file, or q to quit: "
    )
    if file_path == "q" or file_path == "Q":
        quit()
    file_path = file_path.strip()
    y_n = input(f"Is this correct path (y/n)?: {file_path} ").lower()
    if y_n == "y":
        break
f_path: Path = Path(file_path)
Example #8
0
def _derive_path(sk: PrivateKey, path: List[int]) -> PrivateKey:
    for index in path:
        sk = AugSchemeMPL.derive_child_sk(sk, index)
    return sk
Example #9
0
def sign_tx(intermediate_sk: PrivateKey, spend_bundle: SpendBundle,
            use_hardened_keys: bool):
    """
    Takes in an unsigned transaction (called a spend bundle in chia), and a 24 word mnemonic (master sk)
    and generates the aggregate BLS signature for the transaction.
    """

    # This field is the ADDITIONAL_DATA found in the constants
    additional_data: bytes = bytes.fromhex(
        "ccd5bb71183532bff220ba46c268991a3ff07eb358e8255a65c30a2dce0e5fbb")
    puzzle_hash_to_sk: Dict[bytes32, PrivateKey] = {}

    if use_hardened_keys:
        # Change this loop to scan more keys if you have more
        for i in range(5000):
            child_sk: PrivateKey = AugSchemeMPL.derive_child_sk(
                intermediate_sk, i)
            child_pk: G1Element = child_sk.get_g1()
            puzzle = puzzle_for_pk(child_pk)
            puzzle_hash = puzzle.get_tree_hash()
            puzzle_hash_to_sk[puzzle_hash] = child_sk
    else:
        # Change this loop to scan more keys if you have more
        for i in range(5000):
            child_sk: PrivateKey = AugSchemeMPL.derive_child_sk_unhardened(
                intermediate_sk, i)
            child_pk: G1Element = child_sk.get_g1()
            puzzle = puzzle_for_pk(child_pk)
            puzzle_hash = puzzle.get_tree_hash()
            puzzle_hash_to_sk[puzzle_hash] = child_sk

    aggregate_signature: G2Element = G2Element()
    for coin_solution in spend_bundle.coin_solutions:
        if coin_solution.coin.puzzle_hash not in puzzle_hash_to_sk:
            print(
                f"Puzzle hash {coin_solution.coin.puzzle_hash} not found for this key."
            )
            return
        sk: PrivateKey = puzzle_hash_to_sk[coin_solution.coin.puzzle_hash]
        synthetic_secret_key: PrivateKey = calculate_synthetic_secret_key(
            sk, DEFAULT_HIDDEN_PUZZLE_HASH)

        err, conditions_dict, cost = conditions_dict_for_solution(
            coin_solution.puzzle_reveal, coin_solution.solution, 11000000000)

        if err or conditions_dict is None:
            print(
                f"Sign transaction failed, con:{conditions_dict}, error: {err}"
            )
            return

        pk_msgs = pkm_pairs_for_conditions_dict(
            conditions_dict, bytes(coin_solution.coin.name()), additional_data)
        assert len(pk_msgs) == 1
        _, msg = pk_msgs[0]
        signature = AugSchemeMPL.sign(synthetic_secret_key, msg)

        aggregate_signature = AugSchemeMPL.aggregate(
            [aggregate_signature, signature])

    new_spend_bundle = SpendBundle(spend_bundle.coin_solutions,
                                   aggregate_signature)
    print("")
    print("Signed spend bundle JSON:\n")
    print(json.dumps(new_spend_bundle.to_json_dict()))