def __GetElemIndex(path_elem: str) -> Optional[int]: """ Get index of a path element. Args: path_elem (str): Path element Returns: int: Index of the element None: If the element is not a valid index """ # Get if hardened is_hardened = len(path_elem) > 0 and path_elem[ -1] in Bip32PathParserConst.HARDENED_CHARS # If hardened, remove the last character from the string if is_hardened: path_elem = path_elem[:-1] # The remaining string shall be numeric if not path_elem.isnumeric(): return None return int(path_elem) if not is_hardened else Bip32Utils.HardenIndex( int(path_elem))
class Bip44Const: """ Class container for BIP44 constants. """ # Specification name SPEC_NAME = "BIP-0044" # Purpose PURPOSE = Bip32Utils.HardenIndex(44) # Allowed coins ALLOWED_COINS = \ [ Bip44Coins.BITCOIN , Bip44Coins.BITCOIN_TESTNET, Bip44Coins.BITCOIN_CASH , Bip44Coins.BITCOIN_CASH_TESTNET, Bip44Coins.BITCOIN_SV , Bip44Coins.BITCOIN_SV_TESTNET, Bip44Coins.LITECOIN , Bip44Coins.LITECOIN_TESTNET, Bip44Coins.DOGECOIN , Bip44Coins.DOGECOIN_TESTNET, Bip44Coins.DASH , Bip44Coins.DASH_TESTNET, Bip44Coins.ZCASH , Bip44Coins.ZCASH_TESTNET, Bip44Coins.ETHEREUM , Bip44Coins.ETHEREUM_CLASSIC , Bip44Coins.RIPPLE , Bip44Coins.TRON , Bip44Coins.VECHAIN , Bip44Coins.COSMOS , Bip44Coins.BAND_PROTOCOL , Bip44Coins.KAVA , Bip44Coins.IRIS_NET , Bip44Coins.BINANCE_CHAIN , Bip44Coins.BINANCE_SMART_CHAIN, Bip44Coins.NINE_CHRONICLES_GOLD, ] # Map from Bip44Coins to coin classes COIN_TO_CLASS = \ { Bip44Coins.BITCOIN : Bip44BitcoinMainNet, Bip44Coins.BITCOIN_TESTNET : Bip44BitcoinTestNet, Bip44Coins.BITCOIN_CASH : Bip44BitcoinCashMainNet, Bip44Coins.BITCOIN_CASH_TESTNET : Bip44BitcoinCashTestNet, Bip44Coins.BITCOIN_SV : Bip44BitcoinSvMainNet, Bip44Coins.BITCOIN_SV_TESTNET : Bip44BitcoinSvTestNet, Bip44Coins.LITECOIN : Bip44LitecoinMainNet, Bip44Coins.LITECOIN_TESTNET : Bip44LitecoinTestNet, Bip44Coins.DOGECOIN : Bip44DogecoinMainNet, Bip44Coins.DOGECOIN_TESTNET : Bip44DogecoinTestNet, Bip44Coins.DASH : Bip44DashMainNet, Bip44Coins.DASH_TESTNET : Bip44DashTestNet, Bip44Coins.ZCASH : Bip44ZcashMainNet, Bip44Coins.ZCASH_TESTNET : Bip44ZcashTestNet, Bip44Coins.ETHEREUM : Bip44Ethereum, Bip44Coins.ETHEREUM_CLASSIC : Bip44EthereumClassic, Bip44Coins.RIPPLE : Bip44Ripple, Bip44Coins.TRON : Bip44Tron, Bip44Coins.VECHAIN : Bip44VeChain, Bip44Coins.COSMOS : Bip44Cosmos, Bip44Coins.BAND_PROTOCOL : Bip44BandProtocol, Bip44Coins.KAVA : Bip44Kava, Bip44Coins.IRIS_NET : Bip44IrisNet, Bip44Coins.BINANCE_CHAIN : Bip44BinanceChain, Bip44Coins.BINANCE_SMART_CHAIN : Bip44BinanceSmartChain, Bip44Coins.NINE_CHRONICLES_GOLD : Bip44NineChroniclesGold, }
def __CkdPub(self, index: int) -> 'Bip32': """ Create a publicly derived child key of the specified index. Args: index (int): Index Returns: Bip32 object: Bip32 object constructed with the child parameters Raises: Bip32KeyError: If the index is hardened or results in an invalid key """ # Check if index is hardened if Bip32Utils.IsHardenedIndex(index): raise Bip32KeyError( "Public child derivation cannot be used to create a hardened child key" ) # Data for HMAC, same of __CkdPriv() for public child key data = self.EcdsaPublicKey().RawCompressed().ToBytes( ) + index.to_bytes(4, "big") # Get HMAC of data i_l, i_r = self.__HmacHalves(data) # Construct curve point i_l*G+K point = ConvUtils.BytesToInteger( i_l) * generator_secp256k1 + self.m_ver_key.pubkey.point # Try to construct public key from the curve point try: k_i = ecdsa.VerifyingKey.from_public_point(point, curve=SECP256k1) except ecdsa.keys.MalformedPointError as ex: raise Bip32KeyError( "Computed public child key is not valid, very unlucky index" ) from ex # Construct and return a new Bip32 object return Bip32(secret=k_i, chain=i_r, depth=self.m_depth + 1, index=index, fprint=self.FingerPrint(), is_public=True, key_net_ver=self.m_key_net_ver)
def __CkdPriv(self, index: int) -> 'Bip32': """ Create a child key of the specified index. Args: index (int): Index Returns: Bip32 object: Bip32 object constructed with the child parameters Raises: Bip32KeyError: If the index results in an invalid key """ # Index as bytes index_bytes = index.to_bytes(4, "big") # Data for HMAC if Bip32Utils.IsHardenedIndex(index): data = b"\x00" + self.EcdsaPrivateKey().Raw().ToBytes( ) + index_bytes else: data = self.EcdsaPublicKey().RawCompressed().ToBytes( ) + index_bytes # Compute HMAC halves i_l, i_r = self.__HmacHalves(data) # Construct new key secret from i_l and current private key i_l_int = ConvUtils.BytesToInteger(i_l) key_int = ConvUtils.BytesToInteger(self.m_key.to_string()) new_key_int = (i_l_int + key_int) % Bip32Const.CURVE_ORDER # Convert to string and left pad with zeros secret = ConvUtils.IntegerToBytes(new_key_int) secret = b"\x00" * (32 - len(secret)) + secret # Construct and return a new Bip32 object return Bip32(secret=secret, chain=i_r, depth=self.m_depth + 1, index=index, fprint=self.FingerPrint(), is_public=False, key_net_ver=self.m_key_net_ver)
def _AccountGeneric(cls, bip_obj, acc_idx): """ Derive a child key from the specified account index and return a new Bip object (e.g. BIP44, BIP49, BIP84). It shall be called from a child class. Args: bip_obj (Bip44Base child object): Bip44Base child object (e.g. BIP44, BIP49, BIP84) acc_idx (int) : Account index Returns: Bip44Base child object: Bip44Base child object Raises: Bip44DepthError: If the current depth is not suitable for deriving keys Bip32KeyError: If the derivation results in an invalid key """ if not cls.IsLevel(bip_obj, Bip44Levels.COIN): raise Bip44DepthError("Current depth (%d) is not suitable for deriving account" % bip_obj.m_bip32.Depth()) return cls(bip_obj.m_bip32.ChildKey(Bip32Utils.HardenIndex(acc_idx)), bip_obj.m_coin_type)
def _CoinGeneric(cls, bip_obj): """ Derive a child key from the coin type specified at construction and return a new Bip object (e.g. BIP44, BIP49, BIP84). It shall be called from a child class. Args: bip_obj (Bip44Base child object): Bip44Base child object (e.g. BIP44, BIP49, BIP84) Returns: Bip44Base child object: Bip44Base child object Raises: Bip44DepthError: If the current depth is not suitable for deriving keys Bip32KeyError: If the derivation results in an invalid key """ if not cls.IsLevel(bip_obj, Bip44Levels.PURPOSE): raise Bip44DepthError("Current depth (%d) is not suitable for deriving coin" % bip_obj.m_bip32.Depth()) coin_idx = Bip44BaseConst.COIN_TO_IDX[bip_obj.m_coin_type] return cls(bip_obj.m_bip32.ChildKey(Bip32Utils.HardenIndex(coin_idx)), bip_obj.m_coin_type)
class Bip49Const: """ Class container for BIP44 constants. """ # Specification name SPEC_NAME: str = "BIP-0049" # Purpose PURPOSE: int = Bip32Utils.HardenIndex(49) # Allowed coins ALLOWED_COINS: List[Bip44Coins] = [ Bip44Coins.BITCOIN, Bip44Coins.BITCOIN_TESTNET, Bip44Coins.BITCOIN_CASH, Bip44Coins.BITCOIN_CASH_TESTNET, Bip44Coins.BITCOIN_SV, Bip44Coins.BITCOIN_SV_TESTNET, Bip44Coins.LITECOIN, Bip44Coins.LITECOIN_TESTNET, Bip44Coins.DOGECOIN, Bip44Coins.DOGECOIN_TESTNET, Bip44Coins.DASH, Bip44Coins.DASH_TESTNET, Bip44Coins.ZCASH, Bip44Coins.ZCASH_TESTNET, ] # Map from Bip44Coins to coin classes COIN_TO_CLASS: Dict[Bip44Coins, Type[BipCoinBase]] = { Bip44Coins.BITCOIN: Bip49BitcoinMainNet, Bip44Coins.BITCOIN_TESTNET: Bip49BitcoinTestNet, Bip44Coins.BITCOIN_CASH: Bip49BitcoinCashMainNet, Bip44Coins.BITCOIN_CASH_TESTNET: Bip49BitcoinCashTestNet, Bip44Coins.BITCOIN_SV: Bip49BitcoinSvMainNet, Bip44Coins.BITCOIN_SV_TESTNET: Bip49BitcoinSvTestNet, Bip44Coins.LITECOIN: Bip49LitecoinMainNet, Bip44Coins.LITECOIN_TESTNET: Bip49LitecoinTestNet, Bip44Coins.DOGECOIN: Bip49DogecoinMainNet, Bip44Coins.DOGECOIN_TESTNET: Bip49DogecoinTestNet, Bip44Coins.DASH: Bip49DashMainNet, Bip44Coins.DASH_TESTNET: Bip49DashTestNet, Bip44Coins.ZCASH: Bip49ZcashMainNet, Bip44Coins.ZCASH_TESTNET: Bip49ZcashTestNet, }
class Bip84Const: """ Class container for BIP44 constants. """ # Specification name SPEC_NAME: str = "BIP-0084" # Purpose PURPOSE: int = Bip32Utils.HardenIndex(84) # Allowed coins ALLOWED_COINS: List[Bip44Coins] = [ Bip44Coins.BITCOIN, Bip44Coins.BITCOIN_TESTNET, Bip44Coins.LITECOIN, Bip44Coins.LITECOIN_TESTNET, ] # Map from Bip44Coins to coin classes COIN_TO_CLASS: Dict[Bip44Coins, Type[BipCoinBase]] = { Bip44Coins.BITCOIN: Bip84BitcoinMainNet, Bip44Coins.BITCOIN_TESTNET: Bip84BitcoinTestNet, Bip44Coins.LITECOIN: Bip84LitecoinMainNet, Bip44Coins.LITECOIN_TESTNET: Bip84LitecoinTestNet, }