예제 #1
0
    def test_public_derivation(self):
        # Construct from extended private key
        bip32_ctx = Bip32.FromExtendedKey(TEST_PUBLIC_DER_MAIN["ex_priv"])
        # Shall not be public
        self.assertFalse(bip32_ctx.IsPublicOnly())

        # Convert to public
        bip32_ctx.ConvertToPublic()
        # Shall be public and the public key shall be correct
        self.assertTrue(bip32_ctx.IsPublicOnly())
        self.assertEqual(TEST_PUBLIC_DER_MAIN["ex_pub"],
                         bip32_ctx.PublicKey().ToExtended())
        # Getting the private key shall raise an exception
        self.assertRaises(Bip32KeyError, bip32_ctx.PrivateKey)
        self.assertRaises(Bip32KeyError, bip32_ctx.EcdsaPrivateKey)

        # Test derivation paths
        for test in TEST_PUBLIC_DER_MAIN["der_paths"]:
            # Public derivation does not support hardened indexes
            if Bip32Utils.IsHardenedIndex(test["index"]):
                self.assertRaises(Bip32KeyError, bip32_ctx.ChildKey,
                                  test["index"])
            else:
                bip32_ctx = bip32_ctx.ChildKey(test["index"])
                self.assertEqual(test["ex_pub"],
                                 bip32_ctx.PublicKey().ToExtended())
예제 #2
0
def generate_uuid(mnemonic, passphrase=""):
    # At this point the Cobo Vault hardware is directly using the (secret)
    # BIP39 mnemonic, converting it to a BIP39 seed value.  If one is using a
    # Shamir (SLIP39) mnemonic a different path is taken to generate these
    # seed bytes.
    seed_bytes = Bip39SeedGenerator(mnemonic).Generate(passphrase)

    # From this point onwards the code is identical whether a BIP39 or SLIP39
    # mnemonic.  The following extracts the BIP32 Root Key. This is still secret
    # data that we don't want leaking from the Cobo Vault hardware.
    bip32_root = Bip32.FromSeed(seed_bytes)

    # Given the BIP32 root key, derive a BIP32 extended (public/private) keypair,
    # using Cobo's BIP32 derivation path.  Note that this path is only used for
    # generating the 'UUID' used by the Cobo Vault (and app).  For coin-specific
    # (e.g. Bitcoin etc.) keys the Cobo Vault hardware and App use more typical
    # hardened paths that are commonly used -  E.g. m/49'/0'/0' for bitcoin,
    # m/44'/60'/0' for Ethereum, etc. Still secret data here!
    cobo_extend_key = (
        bip32_root.ChildKey(Bip32Utils.HardenIndex(44))
        .ChildKey(Bip32Utils.HardenIndex(1131373167))
        .ChildKey(Bip32Utils.HardenIndex(0))
    )

    # Up until this point the Cobo Vault hardware has been dealing with secret
    # information that should never be leaked outside the device, as doing so
    # would allow stealing of one's keys and thus cryptocurrency.  The next step
    # discards the private key information and extracts the public key only.  The
    # public key can be used to find all transactions associated with a wallet, but
    # it *cannot* be used to spend (or steal) cryptocurrency.
    public_key = cobo_extend_key.PublicKey().RawCompressed().ToHex()

    # After discarding the private (secret) key, compress the public key and remove
    # a couple bytes to produce the 'uuid'.
    uuid = public_key[2:]
    return uuid
예제 #3
0
    def __test_public_derivation_ex_key(ut_class, bip32_ctx, test_vector):
        # Shall be public and the public key shall be correct
        ut_class.assertTrue(bip32_ctx.IsPublicOnly())
        ut_class.assertEqual(test_vector["ex_pub"],
                             bip32_ctx.PublicKey().ToExtended())
        # Getting the private key shall raise an exception
        ut_class.assertRaises(Bip32KeyError, bip32_ctx.PrivateKey)

        # Test derivation paths
        for test in test_vector["der_paths"]:
            # Public derivation does not support hardened indexes
            if Bip32Utils.IsHardenedIndex(test["index"]):
                ut_class.assertRaises(Bip32KeyError, bip32_ctx.ChildKey,
                                      test["index"])
            else:
                bip32_ctx = bip32_ctx.ChildKey(test["index"])
                ut_class.assertEqual(test["ex_pub"],
                                     bip32_ctx.PublicKey().ToExtended())
예제 #4
0
    def __test_path(self, test, path):
        # Check length
        self.assertEqual(len(test["parsed"]), path.Length())
        # Check string conversion
        self.assertEqual(test["to_str"], path.ToStr())
        self.assertEqual(test["to_str"], str(path))

        # Check by iterating
        for idx, elem in enumerate(path):
            test_elem = test["parsed"][idx]

            self.assertEqual(test_elem, int(elem))
            self.assertEqual(test_elem, int(path[idx]))
            self.assertEqual(test_elem, elem.ToInt())
            self.assertEqual(Bip32Utils.IsHardenedIndex(test_elem),
                             elem.IsHardened())

        # Check by converting to list
        for idx, elem in enumerate(path.ToList()):
            self.assertEqual(test["parsed"][idx], elem)
예제 #5
0
# Tests from BIP32 page
TEST_VECT_BIP32 = \
    [
        {
            "seed" : b"000102030405060708090a0b0c0d0e0f",
            "master" :
                {
                    "ex_pub"  : "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8",
                    "ex_priv" : "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi",
                },
            "der_paths" :
                [
                        # m/0'
                        {
                            "path"    : "m/0'",
                            "index"   : Bip32Utils.HardenIndex(0),
                            "ex_pub"  : "xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw",
                            "ex_priv" : "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7",
                        },
                        # m/0'/1
                        {
                            "path"    : "m/0'/1",
                            "index"   : 1,
                            "ex_pub"  : "xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ",
                            "ex_priv" : "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs",
                        },
                        # m/0'/1/2'
                        {
                            "path"    : "m/0'/1/2'",
                            "index"   : Bip32Utils.HardenIndex(2),
                            "ex_pub"  : "xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5",
     "xpub661MyMwAqRbcFybaNRzmKwjLEeQdU4ciWTZ1zPxvvN683xNT57Gr2k7YbdqBz5N5NdqeCEhiZLvSmZE721EUipgYL2v1QEGunyEs8JviJ6x",
     "ex_priv":
     "xprv9s21ZrQH143K3VX7GQTkxonbgca94bts9EdRC1ZKN2Z9BA3JXZxbUwo4kS28ECmXhK1NicjQ7yBwWbZXgjRVktP6Tzi4YqetK5ueSA2CaXP",
     "pub_key":
     "00835e3307bf32df124bc0bd3e3d5eb4a751ceeebe06b69fbce54fef97bc37c062",
     "priv_key":
     "2b4be7f19ee27bbf30c667b642d5f4aa69fd169872f8fc3059c08ebae2eb19e7",
     "chain_code":
     "90046a93de5380a72b5e45010748567d5ea02bbf6522f979e05c0d8d8ca9fffb",
     "parent_fprint": "00000000",
 },
 "der_paths": [
     # m/0'
     {
         "path": "m/0'",
         "index": Bip32Utils.HardenIndex(0),
         "ex_pub":
         "xpub69F72R5LsVNeZxu7hYqxueqXRsieg29CFBMAd5rr1YuAK4CCuG3wc7dT2pucqZppRkHRDGoRyvQNHLnSVPYQ8Eph974t7ok1k17Q56yv79x",
         "ex_priv":
         "xprv9vFkcuYT37pMMUpebXJxYWtnsqtAGZRLsxRZphTETDNBSFs4Mijh4KJyBcsGNuNDY4SsYz8pwQ4L9ob2Qw2gviLdtQPAwG3t4Wf8Lb4rrXX",
         "pub_key":
         "00df1f51aae49a3c17d07f603ded31c409e4c81fa8b32425a7e0de4143d3cfbeac",
         "priv_key":
         "68e0fe46dfb67e368c75379acec591dad19df3cde26e63b93a8e704f1dade7a3",
         "chain_code":
         "8b59aa11380b624e81507a27fedda59fea6d0b779a778918a2fd3590e16e9c69",
         "parent_fprint": "b8637b7e",
     },
     # m/0'/1'
     {
         "path": "m/0'/1'",
예제 #7
0
 },
 {
     "path": "m/  0/1",
     "parsed": [0, 1],
     "is_absolute": True,
     "to_str": "m/0/1",
 },
 {
     "path": "m///  0//1",
     "parsed": [0, 1],
     "is_absolute": True,
     "to_str": "m/0/1",
 },
 {
     "path": "m/0  /1'",
     "parsed": [0, Bip32Utils.HardenIndex(1)],
     "is_absolute": True,
     "to_str": "m/0/1'",
 },
 {
     "path": "m/0  /1p",
     "parsed": [0, Bip32Utils.HardenIndex(1)],
     "is_absolute": True,
     "to_str": "m/0/1'",
 },
 {
     "path": "m/0'/1'/2/",
     "parsed": [Bip32Utils.HardenIndex(0),
                Bip32Utils.HardenIndex(1), 2],
     "is_absolute": True,
     "to_str": "m/0'/1'/2",