## BIP-0032 library

The BIP-0032 library allows deriving children keys as defined by [BIP-0032](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) and [SLIP-0010](https://github.com/satoshilabs/slips/blob/master/slip-0010.md).

Since this library is wrapped inside the BIP-0044, BIP-0049 and BIP-0084 libraries, there is no need to use it alone unless you need to derive some non-standard paths.\
The library currently supports the following elliptic curves for key derivation, each one is implemented by a specific class:
- Ed25519 (based on SLIP-0010): `Bip32Slip10Ed25519` class
- Ed25519-Blake2b (based on SLIP-0010): `Bip32Slip10Ed25519Blake2b` class
- BIP32-Ed25519 (Khovratovich/Law): `Bip32KholawEd25519` class
- Nist256p1 (based on SLIP-0010): `Bip32Slip10Nist256p1` class
- Secp256k1: `Bip32Slip10Secp256k1` class

They all inherit from the generic `Bip32Base` class, which can be extended to implement new elliptic curves derivation.\
The curve depends on the specific coin and it's automatically selected if you use the `Bip44` library.

### Construction from seed

The class can be constructed from a seed. The seed can be specified manually or generated by `Bip39SeedGenerator`.\
The constructed class is the master path, so printing the private key will result in printing the master key.

**Code example**

    import binascii
    from bip_utils import Bip39SeedGenerator, Bip32Slip10Secp256k1

    # Generate from mnemonic
    mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"
    seed_bytes = Bip39SeedGenerator(mnemonic).Generate()
    # Specify seed manually
    seed_bytes = binascii.unhexlify(b"5eb00bbddcf069084889a8ab9155568165f5c453ccb85e70811aaed6f6da5fc19a5ac40b389cd370d086206dec8aa6c43daea6690f20ad3d8d48b2d2ce9e38e4")

    # Construct from seed, derivation path returned: m
    bip32_ctx = Bip32Slip10Secp256k1.FromSeed(seed_bytes)
    # Print master key in extended format
    print(bip32_ctx.PrivateKey().ToExtended())

In addition to a seed, it's also possible to specify a derivation path.

**Code example**

    import binascii
    from bip_utils import Bip32Slip10Secp256k1

    # Derivation path returned: m/0'/1'/2
    seed_bytes = binascii.unhexlify(b"5eb00bbddcf069084889a8ab9155568165f5c453ccb85e70811aaed6f6da5fc19a5ac40b389cd370d086206dec8aa6c43daea6690f20ad3d8d48b2d2ce9e38e4")
    bip32_ctx = Bip32Slip10Secp256k1.FromSeedAndPath(seed_bytes, "m/0'/1'/2")
    # Print private key for derivation path m/0'/1'/2 in extended format
    print(bip32_ctx.PrivateKey().ToExtended())

### Construction from extended key

The class can be constructed directly from an extended key.\
The returned object will be at the same depth of the specified key.

**Code example**

    from bip_utils import Bip32Slip10Secp256k1

    # Private extended key from derivation path m/0'/1 (depth 2)
    key_str = "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs"
    # Construct from key (return object has depth 2)
    bip32_ctx = Bip32Slip10Secp256k1.FromExtendedKey(key_str)
    # Return false
    print(bip32_ctx.IsPublicOnly())
    # Print keys
    print(bip32_ctx.PrivateKey().ToExtended())
    print(bip32_ctx.PublicKey().ToExtended())

    # Public extended key from derivation path m/0'/1 (depth 2)
    key_str = "xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ"
    # Construct from key (return object has depth 2)
    # The object will be public-only and support only public derivation
    bip32_ctx = Bip32Slip10Secp256k1.FromExtendedKey(key_str)
    # Return true
    print(bip32_ctx.IsPublicOnly())
    # Print public key
    print(bip32_ctx.PublicKey().ToExtended())

### Construction from private key

The class can be constructed directly from a private key, with the possibility to specify the derivation data.
If only the key bytes is specified, it will be considered a master key since there is no way to recover the key derivation data from the key bytes.\
Therefore, the returned object will have a depth and index equal to zero, a zero chain code and parent fingerprint.

**Code example**

    import binascii
    from bip_utils import Bip32KeyData, Bip32Slip10Secp256k1, Secp256k1PrivateKey
    
    # Construct from private key bytes
    priv_key_bytes = binascii.unhexlify(b"e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35")
    bip32_ctx = Bip32Slip10Secp256k1.FromPrivateKey(priv_key_bytes)
    # Or key object directly (the curve shall match the one of the Bip32 class, otherwise a Bip32KeyError will be raised)
    bip32_ctx = Bip32Slip10Secp256k1.FromPrivateKey(Secp256k1PrivateKey.FromBytes(priv_key_bytes))
    # Print keys and data
    print(bip32_ctx.PrivateKey().Raw().ToHex())
    print(bip32_ctx.PublicKey().RawCompressed().ToHex())
    print(bip32_ctx.Depth().ToInt())
    print(bip32_ctx.ChainCode().ToHex())
    print(bip32_ctx.ParentFingerPrint().ToHex())
    
    # Construct by specifying derivation data
    chain_code_bytes = binascii.unhexlify(b"873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d508")
    bip32_ctx = Bip32Slip10Secp256k1.FromPrivateKey(
        priv_key_bytes,
        Bip32KeyData(
            chain_code=chain_code_bytes,
            depth=1,
            index=2,
            parent_fprint=binascii.unhexlify(b"3442193e")
        )
    )
    # Print keys and data
    print(bip32_ctx.PrivateKey().Raw().ToHex())
    print(bip32_ctx.PublicKey().RawCompressed().ToHex())
    print(bip32_ctx.Depth().ToInt())
    print(bip32_ctx.ChainCode().ToHex())
    print(bip32_ctx.ParentFingerPrint().ToHex())

### Construction from public key

The class can be constructed directly from a public key, with the possibility to specify the derivation data.
If only the key bytes is specified, it will be considered a master key since there is no way to recover the key derivation data from the key bytes.\
Therefore, the returned object will have a depth and index equal to zero, a zero chain code and parent fingerprint.\
The constructed class will be a public-only object (see the example in the next paragraph), so it won't support hardened derivation.

**Code example**

    import binascii
    from bip_utils import Bip32KeyError, Bip32KeyData, Bip32Slip10Secp256k1, Secp256k1PublicKey
    
    # Construct from public key bytes
    pub_key_bytes = binascii.unhexlify(b"0339a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2")
    bip32_ctx = Bip32Slip10Secp256k1.FromPublicKey(pub_key_bytes)
    # Or key object directly (the curve shall match the one of the Bip32 class, otherwise a Bip32KeyError will be raised)
    bip32_ctx = Bip32Slip10Secp256k1.FromPublicKey(Secp256k1PublicKey.FromBytes(pub_key_bytes))
    # Print keys and data
    print(bip32_ctx.PublicKey().RawCompressed().ToHex())
    print(bip32_ctx.Depth().ToInt())
    print(bip32_ctx.ChainCode().ToHex())
    print(bip32_ctx.ParentFingerPrint().ToHex())
    
    # Return true
    print(bip32_ctx.IsPublicOnly())
    # Getting the private key will raise a Bip32KeyError
    try:
        print(bip32_ctx.PrivateKey().Raw().ToHex())
    except Bip32KeyError as ex:
        print(ex)
    
    # Construct by specifying derivation data
    chain_code_bytes = binascii.unhexlify(b"873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d508")
    bip32_ctx = Bip32Slip10Secp256k1.FromPublicKey(
        pub_key_bytes,
        Bip32KeyData(
            chain_code=chain_code_bytes,
            depth=2,
            index=1,
            parent_fprint=binascii.unhexlify(b"3442193e")
        )
    )
    # Print keys and data
    print(bip32_ctx.IsPublicOnly())
    print(bip32_ctx.PublicKey().RawCompressed().ToHex())
    print(bip32_ctx.Depth().ToInt())
    print(bip32_ctx.ChainCode().ToHex())
    print(bip32_ctx.ParentFingerPrint().ToHex())

### Keys derivation

Each time a key is derived, a new instance of the class is returned. This allows to chain the methods call or save a specific key pair for future derivation.\
The `Bip32KeyIndex.HardenIndex` method can be used to make an index hardened.

**Code example**

    import binascii
    from bip_utils import Bip32Slip10Secp256k1, Bip32KeyIndex

    # Seed bytes
    seed_bytes = binascii.unhexlify(b"5eb00bbddcf069084889a8ab9155568165f5c453ccb85e70811aaed6f6da5fc19a5ac40b389cd370d086206dec8aa6c43daea6690f20ad3d8d48b2d2ce9e38e4")
    # Path: m
    bip32_ctx = Bip32Slip10Secp256k1.FromSeed(seed_bytes)
    # Derivation path: m/0'/1'/2/3
    bip32_ctx = bip32_ctx.ChildKey(Bip32KeyIndex.HardenIndex(0)) \
                         .ChildKey(Bip32KeyIndex.HardenIndex(1)) \
                         .ChildKey(2)                            \
                         .ChildKey(3)
    # Print keys in extended format
    print(bip32_ctx.PrivateKey().ToExtended())
    print(bip32_ctx.PublicKey().ToExtended())

    # Print keys bytes
    print(bip32_ctx.PrivateKey().Raw().ToBytes())
    print(bytes(bip32_ctx.PrivateKey().Raw()))
    print(bip32_ctx.PublicKey().RawCompressed().ToBytes())
    print(bytes(bip32_ctx.PublicKey().RawCompressed()))
    print(bip32_ctx.PublicKey().RawUncompressed().ToBytes())
    print(bytes(bip32_ctx.PublicKey().RawUncompressed()))

    # Print keys in hex format
    print(bip32_ctx.PrivateKey().Raw().ToHex())
    print(str(bip32_ctx.PrivateKey().Raw()))
    print(bip32_ctx.PublicKey().RawCompressed().ToHex())
    print(str(bip32_ctx.PublicKey().RawCompressed()))
    print(bip32_ctx.PublicKey().RawUncompressed().ToHex())
    print(str(bip32_ctx.PublicKey().RawUncompressed()))

    # Print other BIP32 data
    print(bip32_ctx.Index().IsHardened())
    print(bip32_ctx.Index().ToInt())
    print(int(bip32_ctx.Index()))
    print(bip32_ctx.Index().ToBytes())
    print(bytes(bip32_ctx.Index()))

    print(bip32_ctx.Depth().ToInt())
    print(int(bip32_ctx.Depth()))
    print(bip32_ctx.Depth().ToBytes())
    print(bytes(bip32_ctx.Depth()))

    print(bip32_ctx.ChainCode().ToHex())
    print(str(bip32_ctx.ChainCode()))
    print(bip32_ctx.ChainCode().ToBytes())
    print(bytes(bip32_ctx.ChainCode()))

    print(bip32_ctx.FingerPrint().IsMasterKey())
    print(str(bip32_ctx.FingerPrint()))
    print(bip32_ctx.FingerPrint().ToBytes())
    print(bytes(bip32_ctx.FingerPrint()))

    print(bip32_ctx.ParentFingerPrint().IsMasterKey())
    print(bip32_ctx.ParentFingerPrint().ToBytes())
    print(bytes(bip32_ctx.ParentFingerPrint()))

    # Alternative: use DerivePath method
    bip32_ctx = Bip32Slip10Secp256k1.FromSeed(seed_bytes)
    bip32_ctx = bip32_ctx.DerivePath("0'/1'/2/3")

    # DerivePath derives from the current depth, so it can be split
    bip32_ctx = Bip32Slip10Secp256k1.FromSeed(seed_bytes)
    bip32_ctx = bip32_ctx.DerivePath("0'/1'")   # Derivation path: m/0'/1'
    bip32_ctx = bip32_ctx.DerivePath("2/3")     # Derivation path: m/0'/1'/2/3

    # Cannot derive an absolute path from a child key
    try:
        bip32_ctx = bip32_ctx.DerivePath("m/4/5")
    except ValueError:
        pass

It's also possible to use public derivation (i.e. "watch-only" addresses) by:
- Converting a private object to a public-only using `ConvertToPublic` method
- Constructing a public-only object from a public key

In case of a public-only object, only public derivation will be supported (only not-hardened indexes), otherwise a Bip32KeyError exception will be raised.

**Code example**

    from bip_utils import Bip32KeyError, Bip32KeyIndex, Bip32Slip10Secp256k1

    # Derive from a public extended key
    key_str = "xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ"
    bip32_ctx = Bip32Slip10Secp256k1.FromExtendedKey(key_str)

    # Return true
    print(bip32_ctx.IsPublicOnly())
    # Print public key
    print(bip32_ctx.PublicKey().RawCompressed().ToHex())

    # Public derivation is used to derive a child key
    bip32_ctx = bip32_ctx.ChildKey(0)
    bip32_ctx = bip32_ctx.DerivePath("1/2")
    # Print key
    print(bip32_ctx.PublicKey().RawCompressed().ToHex())

    # Getting the private key will raise a Bip32KeyError
    try:
        print(bip32_ctx.PrivateKey().Raw().ToHex())
    except Bip32KeyError as ex:
        print(ex)

    # Deriving with hardened indexes will raise a Bip32KeyError
    try:
        bip32_ctx = bip32_ctx.ChildKey(Bip32KeyIndex.HardenIndex(0))
        bip32_ctx = bip32_ctx.DerivePath("1'/2")
    except Bip32KeyError as ex:
        print(ex)

    # Derive from a private extended key
    key_str = "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs"
    bip32_ctx = Bip32Slip10Secp256k1.FromExtendedKey(key_str)
    # Convert to public object
    bip32_ctx.ConvertToPublic()
    # Same as before...

The other BIP32 classes work exactly in the same way.\
However, the `Bip32Slip10Ed25519` and `Bip32Slip10Ed25519Blake2b` classes have some differences (as written in SLIP-0010):
- Not-hardened private key derivation is not supported
- Public key derivation is not supported

For example:

    import binascii
    from bip_utils import Bip32KeyError, Bip32Slip10Ed25519, Bip32Slip10Ed25519Blake2b

    # Seed bytes
    seed_bytes = binascii.unhexlify(b"5eb00bbddcf069084889a8ab9155568165f5c453ccb85e70811aaed6f6da5fc19a5ac40b389cd370d086206dec8aa6c43daea6690f20ad3d8d48b2d2ce9e38e4")
    # Only hardened private key derivation, fine
    bip32_ctx = Bip32Slip10Ed25519.FromSeedAndPath(seed_bytes, "m/0'/1'")

    # Public derivation, Bip32KeyError is raised
    try:
        bip32_ctx = Bip32Slip10Ed25519.FromSeedAndPath(seed_bytes, "m/0'/1'")
        bip32_ctx.ConvertToPublic()
        bip32_ctx.ChildKey(0)
    except Bip32KeyError as ex:
        print(ex)

    # Same as before
    try:
        bip32_ctx = Bip32Slip10Ed25519Blake2b.FromSeedAndPath(seed_bytes, "m/0'/1'")
        bip32_ctx.ConvertToPublic()
        bip32_ctx.ChildKey(0)
    except Bip32KeyError as ex:
        print(ex)

    # Not-hardened private key derivation, Bip32KeyError is raised
    try:
        bip32_ctx = Bip32Slip10Ed25519.FromSeedAndPath(seed_bytes, "m/0/1")
        bip32_ctx = Bip32Slip10Ed25519Blake2b.FromSeedAndPath(seed_bytes, "m/0/1")
    except Bip32KeyError as ex:
        print(ex)

### Serialize/Deserialize keys

The Bip32 module allows also to serialize/deserialize public and private keys.

**Code example**

    import binascii
    from bip_utils import (
        Bip32KeyData, Bip32PublicKeySerializer, Bip32PrivateKeySerializer, Bip32KeyDeserializer,
        Secp256k1PublicKey, Secp256k1PrivateKey
    )
    
    key_data = Bip32KeyData(
        depth=1,
        index=2,
        chain_code=binascii.unhexlify(b"47fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad16282c7ae6236141"),
        parent_fprint=binascii.unhexlify(b"3442193e")
    )
    
    # Serialize public key
    pub_key_bytes = binascii.unhexlify(b"035a784662a4a20a65bf6aab9ae98a6c068a81c52e4b032c0fb5400c706cfccc56")
    pub_key_ser = Bip32PublicKeySerializer.Serialize(
        Secp256k1PublicKey.FromBytes(pub_key_bytes),
        key_data
    )
    print(pub_key_ser)
    
    # Serialize private key
    priv_key_bytes = binascii.unhexlify(b"edb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d911a0afea")
    priv_key_ser = Bip32PrivateKeySerializer.Serialize(
        Secp256k1PrivateKey.FromBytes(priv_key_bytes),
        key_data
    )
    print(priv_key_ser)
    
    # Deserialize a key
    deser_key = Bip32KeyDeserializer.DeserializeKey(priv_key_ser)
    # Print results
    print(deser_key.KeyBytes())
    print(deser_key.KeyData().Depth().ToInt())
    print(deser_key.KeyData().Index().ToInt())
    print(deser_key.KeyData().ChainCode().ToHex())
    print(deser_key.KeyData().ParentFingerPrint().ToHex())
    print(deser_key.IsPublic())

### Parse path

The Bip32 module allows also to parse derivation paths.

**Code example**

    from bip_utils import Bip32Path, Bip32PathParser, Bip32KeyIndex
    
    # Parse path, Bip32PathError is raised in case of errors
    path = Bip32PathParser.Parse("0'/1'/2")
    # 'h' or 'p' can be used as an alternative character instead of '
    path = Bip32PathParser.Parse("0h/1h/2")
    path = Bip32PathParser.Parse("0p/1p/2")
    # "m" can be added at the beginning if the path is absolute, otherwise it'll be considered relative
    path = Bip32PathParser.Parse("m/0'/1'/2")
    # If multiple slashes are present, they will be removed. The following path is the same of the previous one
    path = Bip32PathParser.Parse("m//0'///1'/2")
    # A path can also be constructed directly from a list of indexes
    # "True" specifies that the path is absolute, "False" if relative
    path = Bip32Path([0, 1, Bip32KeyIndex.HardenIndex(2)], True)
    
    # Get if absolute
    print(path.IsAbsolute())
    # Get length
    print(path.Length())
    # Get as string
    print(path.ToStr())
    print(str(path))
    # Print elements info and value
    for elem in path:
        print(elem.IsHardened())
        print(elem.ToBytes())
        print(bytes(elem))
        print(elem.ToInt())
        print(int(elem))
    # Get as list of integers
    path_list = path.ToList()
    for elem in path_list:
        print(elem)
