def from_privkey(HDKey, privkey: bytes, network: str = 'Bitcoin') -> 'HDKey': ''' Instantiates an HDKey from a raw privkey Args: privkey (bytes): the private key network (str): the network associated Returns: (HDKey): the key object ''' pubkey = simple.priv_to_pub(privkey) return HDKey(key_dict=KeyDict(path=None, network=network, depth=None, parent_fingerprint=None, index=None, parent=None, chain_code=None, fingerprint=utils.hash160(pubkey)[:4], xpriv=None, xpub=None, privkey=privkey, pubkey=pubkey), _error_on_call=False)
def from_pubkey(HDKey, pubkey: bytes, network: str = 'Bitcoin') -> 'HDKey': ''' Instantiates an HDKey from a raw pubkey Args: pubkey (bytes): the public key network (str): the network associated Returns: (HDKey): the key object ''' try: simple.compress_pubkey(pubkey) except Exception: raise ValueError('Cannot parse public key') return HDKey(key_dict=KeyDict(path=None, network=network, depth=None, parent_fingerprint=None, index=None, parent=None, chain_code=None, fingerprint=utils.hash160(pubkey)[:4], xpriv=None, xpub=None, privkey=None, pubkey=pubkey), _error_on_call=False)
def _child_from_xpriv(self, index: int, child_xpriv: str) -> 'HDKey': ''' Returns a new HDKey object based on the current object and the new child xpriv. Don't call this directly, it's for child derivation. Args: index (int): the index of the child child_xpriv (str): the child's xpriv Returns HDKey: the new child object ''' # set the path, if this key has a path path: Optional[str] if self.path is not None: if index >= utils.BIP32_HARDEN: index_str = '{}h'.format(str(index - utils.BIP32_HARDEN)) else: index_str = str(index) path = '{}/{}'.format(self.path, index_str) else: path = None # Make the pubkey xpriv_bytes = base58.decode(child_xpriv) privkey = xpriv_bytes[46:78] pubkey = simple.priv_to_pub(privkey) # What network is this for? if xpriv_bytes[0:4] == utils.VERSION_BYTES['mainnet']['private']: network = 'Bitcoin' elif xpriv_bytes[0:4] == utils.VERSION_BYTES['testnet'][ 'private']: # pragma: nocover # noqa: E501 network = 'Testnet' # pragma: nocover else: raise ValueError('unrecognized version bytes. ' 'Is this an xpriv?') # pragma: nocover return HDKey(key_dict=KeyDict(path=path, network=network, depth=xpriv_bytes[4], parent_fingerprint=xpriv_bytes[5:9], index=index, parent=self, chain_code=xpriv_bytes[13:45], fingerprint=utils.hash160(pubkey)[:4], xpriv=child_xpriv, xpub=HDKey._xpriv_to_xpub(child_xpriv), privkey=privkey, pubkey=pubkey), _error_on_call=False)
def _child_from_xpub(self, index: int, child_xpub: str) -> 'HDKey': ''' Returns a new HDKey object based on the current object and the new child xpub. Don't call this directly, it's for child derivation. Args: index (int): the index of the child child_xpub (str): the child's xpub Returns HDKey: the new child object ''' path: Optional[str] if self.path is not None: path = '{}/{}'.format(self.path, str(index)) else: path = None xpub_bytes = base58.decode(child_xpub) pubkey = xpub_bytes[45:78] if xpub_bytes[0:4] == utils.VERSION_BYTES['mainnet']['public']: network = 'Bitcoin' elif xpub_bytes[0:4] == utils.VERSION_BYTES['testnet'][ 'public']: # pragma: nocover # noqa: E501 network = 'Testnet' # pragma: nocover else: raise ValueError('unrecognized version bytes.' ' Is this an xpub?') # pragma: nocover return HDKey(key_dict=KeyDict(path=path, network=network, depth=xpub_bytes[4], parent_fingerprint=xpub_bytes[5:9], index=int.from_bytes(xpub_bytes[9:13], byteorder='big'), parent=self, chain_code=xpub_bytes[13:45], fingerprint=utils.hash160(pubkey)[:4], xpriv=None, xpub=child_xpub, privkey=None, pubkey=pubkey), _error_on_call=False)
def from_root_seed(HDKey, root_seed: bytes, network: str = 'Bitcoin') -> 'HDKey': ''' Generates a HDKey object given the root seed. Args: root_seed (bytes): 128, 256, or 512 bits network (str, Optional): Must be a selection from NETWORK_CODES, defaults to Bitcoin Returns: (HDKey) ''' # TODO: get key depending on network # data/key, msg, digest I = hmac.new( # noqa: E741 # type: ignore key=b'Bitcoin seed', msg=root_seed, digestmod='sha512').digest() # type: ignore # Private key, chain code privkey, chain_code = I[:32], I[32:] pubkey = simple.priv_to_pub(privkey) xpriv = HDKey._make_master_xpriv(privkey, chain_code, network) xpub = HDKey._xpriv_to_xpub(xpriv) root = HDKey(key_dict=KeyDict(path='m', network=network, depth=0, parent_fingerprint=b'\x00' * 4, index=0, parent=None, chain_code=chain_code, fingerprint=utils.hash160(pubkey)[:4], xpriv=xpriv, xpub=xpub, privkey=privkey, pubkey=pubkey), _error_on_call=False) return root
def from_xpub(HDKey, xpub: str, path: Optional[str] = None) -> 'HDKey': ''' Instantiate an HDKey from an xpub. Populates all possible fields Args: xpub (str): the xpub path (str): the path if it's known. useful for calling derive_path Returns: (HDKey): the key object ''' xpub_bytes = base58.decode(xpub) pubkey = xpub_bytes[45:78] try: simple.compress_pubkey(pubkey) except Exception: raise ValueError('Cannot parse public key') if xpub_bytes[0:4] == utils.VERSION_BYTES['mainnet']['public']: network = 'Bitcoin' elif xpub_bytes[0:4] == utils.VERSION_BYTES['testnet'][ 'public']: # pragma: nocover # noqa: E501 network = 'Testnet' # pragma: nocover else: raise ValueError('unrecognized version bytes. Is this an xpub?' ) # pragma: nocover # noqa: E501 return HDKey(key_dict=KeyDict(path=path, network=network, depth=xpub_bytes[4], parent_fingerprint=xpub_bytes[5:9], index=int.from_bytes(xpub_bytes[9:13], byteorder='big'), parent=None, chain_code=xpub_bytes[13:45], fingerprint=utils.hash160(pubkey)[:4], xpriv=None, xpub=xpub, privkey=None, pubkey=pubkey), _error_on_call=False)