def Encode(cls, value: Any) -> bytes: """ Encode the specified value to bytes. Args: value (any): Value to be encoded Returns: bytes: Encoded value """ # Single-byte mode if value <= SubstrateScaleCUintEncoderConst.SINGLE_BYTE_MODE_MAX_VAL: return IntegerUtils.ToBytes(value << 2, 1, endianness="little") # Two-byte mode if value <= SubstrateScaleCUintEncoderConst.TWO_BYTE_MODE_MAX_VAL: return IntegerUtils.ToBytes((value << 2) | 0b01, 2, endianness="little") # Four-byte mode if value <= SubstrateScaleCUintEncoderConst.FOUR_BYTE_MODE_MAX_VAL: return IntegerUtils.ToBytes((value << 2) | 0b10, 4, endianness="little") # Big-integer mode if value <= SubstrateScaleCUintEncoderConst.BIG_INTEGER_MODE_MAX_VAL: value_bytes = IntegerUtils.ToBytes(value, endianness="little") len_bytes = IntegerUtils.ToBytes( (len(value_bytes) - 4 << 2) | 0b11, 1, endianness="little") return len_bytes + value_bytes raise ValueError(f"Out of range integer value ({value})")
def ComputeKeys(self, minor_idx: int, major_idx: int) -> Tuple[MoneroPublicKey, MoneroPublicKey]: """ Compute the public keys of the specified subaddress. Args: minor_idx (int): Minor index (i.e. subaddress index) major_idx (int): Major index (i.e. account index) Returns: tuple[MoneroPublicKey, MoneroPublicKey]: Computed public spend key (index 0) and public view key (index 1) Raises: ValueError: If one of the indexes is not valid """ if minor_idx < 0 or minor_idx > MoneroSubaddressConst.SUBADDR_MAX_IDX: raise ValueError(f"Invalid minor index ({minor_idx})") if major_idx < 0 or major_idx > MoneroSubaddressConst.SUBADDR_MAX_IDX: raise ValueError(f"Invalid major index ({major_idx})") # Subaddress 0,0 is the primary address if minor_idx == 0 and major_idx == 0: return self.m_pub_skey, self.m_pub_vkey # Convert indexes to bytes major_idx_bytes = IntegerUtils.ToBytes(major_idx, bytes_num=MoneroSubaddressConst.SUBADDR_IDX_BYTE_LEN, endianness="little") minor_idx_bytes = IntegerUtils.ToBytes(minor_idx, bytes_num=MoneroSubaddressConst.SUBADDR_IDX_BYTE_LEN, endianness="little") # m = Kekkak256("SubAddr" + master_priv_vkey + major_idx + minor_idx) m = CryptoUtils.Kekkak256(MoneroSubaddressConst.SUBADDR_PREFIX + self.m_priv_vkey.Raw().ToBytes() + major_idx_bytes + minor_idx_bytes) m_int = BytesUtils.ToInteger(m, endianness="little") # Compute subaddress public spend key # D = master_pub_skey + m * B subaddr_pub_skey_point = self.m_pub_skey.KeyObject().Point() + (Ed25519Monero.Generator() * m_int) # Compute subaddress public view key # C = master_priv_vkey * D subaddr_pub_vkey_point = subaddr_pub_skey_point * self.m_priv_vkey.Raw().ToInt("little") return (MoneroPublicKey.FromBytes(subaddr_pub_skey_point.RawEncoded().ToBytes()), MoneroPublicKey.FromBytes(subaddr_pub_vkey_point.RawEncoded().ToBytes()))
def FromEntropy(self, entropy_bytes: bytes) -> Mnemonic: """ Generate mnemonic from the specified entropy bytes. Because of the mnemonic encoding algorithm used by Electrum, the specified entropy will only be a starting point to find a suitable one. Therefore, it's very likely that the actual entropy bytes will be different. To get the actual entropy bytes, just decode the generated mnemonic. Please note that, to successfully generate a mnemonic, the bits of the big endian integer encoded entropy shall be at least 121 (for 12 words) or 253 (for 24 words). Otherwise, a mnemonic generation is not possible and a ValueError exception will be raised. Args: entropy_bytes (bytes): Entropy bytes Returns: Mnemonic object: Generated mnemonic Raises: ValueError: If entropy byte length is not valid or a mnemonic cannot be generated """ # Do not waste time trying if the entropy bit are not enough if ElectrumV2EntropyGenerator.AreEntropyBitsEnough(entropy_bytes): # Same of Electrum: increase the entropy until a valid one is found entropy_int = BytesUtils.ToInteger(entropy_bytes) for i in range(ElectrumV2MnemonicGeneratorConst.MAX_ATTEMPTS): new_entropy_int = entropy_int + i try: return self.m_mnemonic_encoder.Encode(IntegerUtils.ToBytes(new_entropy_int)) except ValueError: continue raise ValueError("Unable to generate a valid mnemonic")
def OwnerEntropyWithLotSeq(lot_num: int, sequence_num: int) -> bytes: """ Compute the owner entropy as specified in BIP38 (with EC multiplication) with lot and sequence numbers. Args: lot_num (int) : Lot number sequence_num (int): Sequence number Returns: bytes: Owner entropy Raises: ValueError: If lot or sequence number is not valid """ # Check lot and sequence numbers if lot_num < Bip38EcConst.LOT_NUM_MIN_VAL or lot_num > Bip38EcConst.LOT_NUM_MAX_VAL: raise ValueError(f"Invalid lot number ({lot_num})") if sequence_num < Bip38EcConst.SEQ_NUM_MIN_VAL or sequence_num > Bip38EcConst.SEQ_NUM_MAX_VAL: raise ValueError(f"Invalid sequence number ({sequence_num})") # Generate random owner salt (4 bytes) owner_salt = os.urandom(Bip38EcConst.OWNER_SALT_WITH_LOT_SEQ_BYTE_LEN) # Compute lot sequence lot_sequence = IntegerUtils.ToBytes((lot_num * (Bip38EcConst.SEQ_NUM_MAX_VAL + 1)) + sequence_num, bytes_num=4) # Compute owner entropy return owner_salt + lot_sequence
def EncodeKey(pub_key: Union[bytes, IPublicKey], **kwargs: Any) -> str: """ Encode a public key to Stellar address. Args: pub_key (bytes or IPublicKey): Public key bytes or object Other Parameters: addr_type (XlmAddrTypes): Address type Returns: str: Address string Raises: ValueError: If the public key is not valid TypeError: If the public key is not ed25519 or address type is not a XlmAddrTypes enum """ # Get and check address type addr_type = kwargs["addr_type"] if not isinstance(addr_type, XlmAddrTypes): raise TypeError("Address type is not an enumerative of XlmAddrTypes") # Get public key pub_key_obj = AddrKeyValidator.ValidateAndGetEd25519Key(pub_key) payload_bytes = IntegerUtils.ToBytes(addr_type) + pub_key_obj.RawCompressed().ToBytes()[1:] # Compute checksum checksum_bytes = _XlmAddrUtils.ComputeChecksum(payload_bytes) # Encode to base32 return Base32Encoder.EncodeNoPadding(payload_bytes + checksum_bytes)
def WordsToBytesChunk(word1: str, word2: str, word3: str, words_list: MnemonicWordsList, endianness: str) -> bytes: """ Get bytes chunk from words. Args: word1 (str) : Word 1 word2 (str) : Word 2 word3 (str) : Word 3 words_list (MnemonicWordsList object): Mnemonic list endianness (str) : Bytes endianness Returns: bytes: Bytes chunk """ n = words_list.Length() # Get the word indexes word1_idx = words_list.GetWordIdx(word1) word2_idx = words_list.GetWordIdx(word2) % n word3_idx = words_list.GetWordIdx(word3) % n # Get back the bytes chunk bytes_chunk = word1_idx + (n * ((word2_idx - word1_idx) % n)) + (n * n * ( (word3_idx - word2_idx) % n)) return IntegerUtils.ToBytes(bytes_chunk, bytes_num=4, endianness=endianness)
def RawDecoded(self) -> DataBytes: """ Return the decoded point raw bytes. Returns: DataBytes object: DataBytes object """ try: return DataBytes(self.m_point.to_bytes()) # ECDSA < 0.17 doesn't have to_bytes method for PointJacobi except AttributeError: x_bytes = IntegerUtils.ToBytes(self.m_point.x(), EcdsaKeysConst.POINT_COORD_BYTE_LEN) y_bytes = IntegerUtils.ToBytes(self.m_point.y(), EcdsaKeysConst.POINT_COORD_BYTE_LEN) return DataBytes(x_bytes + y_bytes)
def ToBytes(self) -> bytes: """ Get the depth as bytes. Returns: bytes: Depth bytes """ return IntegerUtils.ToBytes(self.m_depth, bytes_num=self.Length())
def Generate(self) -> bytes: """ Generate random entropy bytes. Returns: bytes: Generated entropy bytes """ return (os.urandom(self.m_bit_len // 8) if self.m_bit_len % 8 == 0 else IntegerUtils.ToBytes(secrets.randbits(self.m_bit_len)))
def __mul__(self, scalar: int) -> IPoint: """ Multiply point by a scalar. Args: scalar (int): scalar Returns: IPoint object: IPoint object """ return Secp256k1PointCoincurve(self.m_pub_key.multiply(IntegerUtils.ToBytes(scalar)))
def ToBytes(self, endianness: str = "big") -> bytes: """ Get the key index as bytes. Args: endianness (str): Endianness Returns: bytes: Key bytes """ return IntegerUtils.ToBytes(self.m_idx, bytes_num=self.Length(), endianness=endianness)
def TweakPublicKey(pub_key: IPublicKey) -> bytes: """ Tweak a public key as defined by BIP-0086. tweaked_pub_key = lift_x(pub_key.X()) + int(HashTapTweak(bytes(pub_key.X()))) * G Args: pub_key (IPublicKey object): Public key Returns: bytes: X coordinate of the tweaked public key """ h = _P2TRUtils.HashTapTweak(pub_key) out_point = _P2TRUtils.LiftX(pub_key) + (BytesUtils.ToInteger(h) * Secp256k1.Generator()) return IntegerUtils.ToBytes(out_point.X())
def HashTapTweak(pub_key: IPublicKey) -> bytes: """ Compute the HashTapTweak of the specified public key. Args: pub_key (IPublicKey object): Public key Returns: bytes: Computed hash """ # Use the pre-computed SHA256 of "TapTweak" for speeding up return _P2TRUtils.TaggedHash(P2TRConst.TAP_TWEAK_SHA256, IntegerUtils.ToBytes(pub_key.Point().X()))
def ComputeChecksum(pub_key_hash: bytes, addr_type: FillAddrTypes) -> bytes: """ Compute checksum in EOS format. Args: pub_key_hash (bytes) : Public key hash addr_type (FillAddrTypes): Address type Returns: bytes: Computed checksum """ addr_type_byte = IntegerUtils.ToBytes(addr_type) return CryptoUtils.Blake2b(addr_type_byte + pub_key_hash, digest_size=FilAddrConst.CHECKSUM_BYTE_LEN)
def ScReduce(data_bytes: bytes) -> bytes: """ Convert the specified bytes to integer and return its lowest 32-bytes modulo ed25519-order. This ensures that the result is a valid ed25519 scalar to be used as Monero private key. Args: data_bytes (bytes): Data bytes Returns: bytes: Lowest 32-bytes modulo ed25519-order """ data_int = BytesUtils.ToInteger(data_bytes, endianness="little") return IntegerUtils.ToBytes(data_int % Ed25519Monero.Order(), bytes_num=32, endianness="little")
def __DeriveKey(self, change_idx: int, addr_idx: int) -> IPrivateKey: """ Derive the key with the specified change and address indexes. Args: change_idx (int): Change index addr_idx (int) : Address index Returns: Bip32Base object: Bip32Base object """ seq_bytes = self.__GetSequence(change_idx, addr_idx) priv_key_int = (self.MasterPrivateKey().Raw().ToInt() + BytesUtils.ToInteger(seq_bytes)) % Secp256k1.Order() return Secp256k1PrivateKey.FromBytes( IntegerUtils.ToBytes(priv_key_int, Secp256k1PrivateKey.Length()))
def __ComputePrivateKey(passfactor: bytes, factorb: bytes) -> bytes: """ Compute the private key from passfactor and factorb. Args: passfactor (bytes): Passfactor factorb (bytes) : Factorb Returns: bytes: Private key """ # Private key: (passfactor * factorb) mod N priv_key_int = (BytesUtils.ToInteger(passfactor) * BytesUtils.ToInteger(factorb)) % Secp256k1.Order() return IntegerUtils.ToBytes(priv_key_int, bytes_num=Secp256k1PrivateKey.Length())
def _CkdPrivEcdsa(cls, bip32_obj: Bip32Base, index: Bip32KeyIndex) -> Bip32Base: """ Create a child key of the specified index using private derivation. Args: bip32_obj (Bip32Base object): Bip32Base object index (Bip32KeyIndex object): Key index Returns: Bip32Base object: Bip32Base object Raises: Bip32KeyError: If the index results in an invalid key """ assert bip32_obj.m_priv_key is not None # Get elliptic curve curve = EllipticCurveGetter.FromType(bip32_obj.CurveType()) # Data for HMAC if index.IsHardened(): data_bytes = b"\x00" + bip32_obj.m_priv_key.Raw().ToBytes() + bytes(index) else: data_bytes = bip32_obj.m_pub_key.RawCompressed().ToBytes() + bytes(index) # Compute HMAC halves i_l, i_r = Bip32BaseUtils.HmacSha512Halves(bip32_obj.ChainCode().ToBytes(), data_bytes) # Construct new key secret from i_l and current private key i_l_int = BytesUtils.ToInteger(i_l) key_int = BytesUtils.ToInteger(bip32_obj.m_priv_key.Raw().ToBytes()) new_key_int = (i_l_int + key_int) % curve.Order() # Convert to string and pad with zeros new_priv_key_bytes = IntegerUtils.ToBytes(new_key_int).rjust(curve.PrivateKeyClass().Length(), b"\x00") # Construct and return a new Bip32 object return cls(priv_key=new_priv_key_bytes, pub_key=None, key_data=Bip32KeyData(chain_code=i_r, depth=bip32_obj.Depth().Increase(), index=index, parent_fprint=bip32_obj.m_pub_key.FingerPrint()), curve_type=bip32_obj.CurveType(), key_net_ver=bip32_obj.KeyNetVersions())
def _EncodeWithBytesLength(value: Any, bytes_len: int) -> bytes: """ Encode the specified value to bytes with the specified bytes length. Args: value (any) : Value to be encoded bytes_len (int): Bytes length Returns: bytes: Encoded value """ if isinstance(value, str): value = int(value) max_val = (1 << (bytes_len * 8)) - 1 if value < 0 or value > max_val: raise ValueError(f"Invalid integer value ({value})") return IntegerUtils.ToBytes(value, bytes_len, endianness="little")
def RawEncoded(self) -> DataBytes: """ Return the encoded point raw bytes. Returns: DataBytes object: DataBytes object """ try: return DataBytes(self.m_point.to_bytes("compressed")) # ECDSA < 0.17 doesn't have to_bytes method for PointJacobi except AttributeError: x_bytes = IntegerUtils.ToBytes(self.m_point.x(), EcdsaKeysConst.POINT_COORD_BYTE_LEN) if self.m_point.y() & 1: enc_bytes = b"\x03" + x_bytes else: enc_bytes = b"\x02" + x_bytes return DataBytes(enc_bytes)
def Encode(self, entropy_bytes: bytes) -> Mnemonic: """ Encode bytes to mnemonic phrase. Args: entropy_bytes (bytes): Entropy bytes (accepted lengths in bits: 128, 160, 192, 224, 256) Returns: Mnemonic object: Encoded mnemonic Raises: ValueError: If entropy is not valid """ # Check entropy length entropy_byte_len = len(entropy_bytes) if not Bip39EntropyGenerator.IsValidEntropyByteLen(entropy_byte_len): raise ValueError( f"Entropy byte length ({entropy_byte_len}) is not valid") # Convert entropy to binary string entropy_bin_str = BytesUtils.ToBinaryStr(entropy_bytes, entropy_byte_len * 8) # Get entropy hash as binary string entropy_hash_bin_str = BytesUtils.ToBinaryStr( CryptoUtils.Sha256(entropy_bytes), CryptoUtils.Sha256DigestSize() * 8) # Get mnemonic binary string by concatenating entropy and checksum mnemonic_bin_str = entropy_bin_str + entropy_hash_bin_str[:entropy_byte_len // 4] # Get mnemonic from entropy mnemonic = [] for i in range( len(mnemonic_bin_str) // Bip39MnemonicConst.WORD_BIT_LEN): # Get current word index word_bin_str = ( mnemonic_bin_str[i * Bip39MnemonicConst.WORD_BIT_LEN:(i + 1) * Bip39MnemonicConst.WORD_BIT_LEN]) word_idx = IntegerUtils.FromBinaryStr(word_bin_str) # Get word at given index mnemonic.append(self.m_words_list.GetWordAtIdx(word_idx)) return Bip39Mnemonic.FromList(mnemonic)
def __SetFlagbyteBits(magic: bytes, pub_key_mode: Bip38PubKeyModes) -> bytes: """ Set flagbyte bits and return it. Args: magic (bytes) : Magic pub_key_mode (Bip38PubKeyModes): Public key mode Returns: bytes: Flagbyte """ flagbyte_int = 0 if pub_key_mode == Bip38PubKeyModes.COMPRESSED: flagbyte_int = BitUtils.SetBit(flagbyte_int, Bip38EcConst.FLAG_BIT_COMPRESSED) if magic == Bip38EcConst.INT_PASS_MAGIC_WITH_LOT_SEQ: flagbyte_int = BitUtils.SetBit(flagbyte_int, Bip38EcConst.FLAG_BIT_LOT_SEQ) return IntegerUtils.ToBytes(flagbyte_int)
def Decode(self, mnemonic: Union[str, Mnemonic]) -> bytes: """ Decode a mnemonic phrase to bytes (no checksum). Args: mnemonic (str or Mnemonic object): Mnemonic Returns: bytes: Decoded bytes Raises: MnemonicChecksumError: If checksum is not valid ValueError: If mnemonic is not valid """ mnemonic_obj = ElectrumV2Mnemonic.FromString(mnemonic) if isinstance( mnemonic, str) else mnemonic # Check mnemonic length if mnemonic_obj.WordsCount( ) not in ElectrumV2MnemonicConst.MNEMONIC_WORD_NUM: raise ValueError( f"Mnemonic words count is not valid ({mnemonic_obj.WordsCount()})" ) # Check mnemonic validity: if not ElectrumV2MnemonicUtils.IsValidMnemonic(mnemonic_obj, self.m_mnemonic_type): raise ValueError("Invalid mnemonic") # Get words words = mnemonic_obj.ToList() # Detect language if it was not specified at construction words_list, _ = self._FindLanguage(mnemonic_obj) # Decode words n = words_list.Length() entropy_int = 0 for word in reversed(words): entropy_int = (entropy_int * n) + words_list.GetWordIdx(word) return IntegerUtils.ToBytes(entropy_int)
def Encode(data_bytes: bytes, ss58_format: int) -> str: """ Encode bytes into a SS58 string. Args: data_bytes (bytes): Data bytes (32-byte length) ss58_format (int) : SS58 format Returns: str: SS58 encoded string Raises: ValueError: If parameters are not valid """ # Check parameters if len(data_bytes) != SS58Const.DATA_BYTE_LEN: raise ValueError(f"Invalid data length ({len(data_bytes)})") if ss58_format < 0 or ss58_format > SS58Const.FORMAT_MAX_VAL: raise ValueError(f"Invalid SS58 format ({ss58_format})") if ss58_format in SS58Const.RESERVED_FORMATS: raise ValueError(f"Invalid SS58 format ({ss58_format})") # Simple account if ss58_format <= SS58Const.SIMPLE_ACCOUNT_FORMAT_MAX_VAL: ss58_format_bytes = IntegerUtils.ToBytes(ss58_format) # Full address else: # 0b00HHHHHH_MMLLLLLL -> (0b01LLLLLL, 0bHHHHHHMM) ss58_format_bytes = bytes([ ((ss58_format & 0x00FC) >> 2) | 0x0040, (ss58_format >> 8) | ((ss58_format & 0x0003) << 6) ]) # Get payload payload = ss58_format_bytes + data_bytes # Compute checksum checksum = _SS58Utils.ComputeChecksum(payload) # Encode return Base58Encoder.Encode(payload + checksum)
def __MnemonicToBinaryStr(mnemonic: Mnemonic, words_list: MnemonicWordsList) -> str: """ Get mnemonic binary string from mnemonic phrase. Args: mnemonic (Mnemonic object) : Mnemonic object words_list (MnemonicWordsList object): Words list object Returns: str: Mnemonic binary string Raises: ValueError: If the one of the mnemonic word is not valid """ # Convert each word to its index in binary format mnemonic_bin_str = map( lambda word: IntegerUtils.ToBinaryStr( words_list.GetWordIdx(word), Bip39MnemonicConst.WORD_BIT_LEN), mnemonic.ToList()) return "".join(mnemonic_bin_str)
def FindPda(cls, seeds: List[bytes], program_id: str) -> str: """ Find a valid PDA (Program Derived Address) and its corresponding bump seed. Args: seeds (list[bytes]): List of seeds bytes program_id (str) : Program ID Returns: str: Found PDA Raises: ValueError: If the PDA cannot be found or the specified seeds or program ID are not valid """ # Check if seeds are valid if len(seeds) > SplTokenConst.SEEDS_MAX_NUM: raise ValueError(f"Seeds length is not valid ({len(seeds)})") for seed in seeds: if len(seed) > Ed25519PublicKey.CompressedLength() - 1: raise ValueError(f"Seed length is not valid ({len(seeds)})") program_id_bytes = SolAddrDecoder.DecodeAddr(program_id) bump_seed = SplTokenConst.SEED_BUMP_MAX_VAL for _ in range(SplTokenConst.SEED_BUMP_MAX_VAL): # Add bump to seeds seeds_with_bump = list(seeds) seeds_with_bump.append(IntegerUtils.ToBytes(bump_seed)) # Try to create PDA try: return cls.__CreatePda(seeds_with_bump, program_id_bytes) except ValueError: # Continue with the next bump seed if PDA is not valid bump_seed -= 1 # Very unlucky case raise ValueError("Unable to find a valid PDA")
def DecodeAddr(addr: str, **kwargs: Any) -> bytes: """ Decode a Neo address to bytes. Args: addr (str): Address string Other Parameters: ver (bytes): Version Returns: bytes: Public key hash bytes Raises: ValueError: If the address encoding is not valid """ ver_bytes = kwargs["ver"] try: # Decode from base58 addr_dec_bytes = Base58Decoder.CheckDecode(addr) except Base58ChecksumError as ex: raise ValueError("Invalid base58 checksum") from ex else: # Validate length AddrDecUtils.ValidateLength( addr_dec_bytes, CryptoUtils.Hash160DigestSize() + len(ver_bytes)) # Check version ver_got = IntegerUtils.ToBytes(addr_dec_bytes[0]) if ver_bytes != ver_got: raise ValueError( f"Invalid version (expected {BytesUtils.ToHexString(ver_bytes)}, " f"got {BytesUtils.ToHexString(ver_got)})") return addr_dec_bytes[1:]
def Decrypt(priv_key_enc: str, passphrase: str) -> Tuple[bytes, Bip38PubKeyModes]: """ Decrypt the specified private key. Args: priv_key_enc (str): Encrypted private key bytes passphrase (str) : Passphrase Returns: tuple[bytes, Bip38PubKeyModes]: Decrypted private key (index 0), public key mode (index 1) Raises: Base58ChecksumError: If base58 checksum is not valid ValueError: If the encrypted key is not valid """ # Decode private key priv_key_enc_bytes = Base58Decoder.CheckDecode(priv_key_enc) # Check encrypted length if len(priv_key_enc_bytes) != Bip38EcConst.ENC_BYTE_LEN: raise ValueError(f"Invalid encrypted length ({len(priv_key_enc_bytes)})") # Get all the parts back prefix = priv_key_enc_bytes[:2] flagbyte = IntegerUtils.ToBytes(priv_key_enc_bytes[2]) address_hash = priv_key_enc_bytes[3:7] owner_entropy = priv_key_enc_bytes[7:15] encrypted_part_1_lower = priv_key_enc_bytes[15:23] encrypted_part_2 = priv_key_enc_bytes[23:] # Check prefix if prefix != Bip38EcConst.ENC_KEY_PREFIX: raise ValueError(f"Invalid prefix ({BytesUtils.ToHexString(prefix)})") # Get flagbyte options pub_key_mode, has_lot_seq = Bip38EcDecrypter.__GetFlagbyteOptions(flagbyte) # Compute passfactor passfactor = _Bip38EcUtils.PassFactor(passphrase, owner_entropy, has_lot_seq) # Derive key halves from the passpoint, address hash and owner entropy derived_half_1, derived_half_2 = _Bip38EcUtils.DeriveKeyHalves(_Bip38EcUtils.PassPoint(passfactor), address_hash, owner_entropy) # Get factorb back by decrypting factorb = Bip38EcDecrypter.__DecryptAndGetFactorb(encrypted_part_1_lower, encrypted_part_2, derived_half_1, derived_half_2) # Compute private key priv_key_bytes = Bip38EcDecrypter.__ComputePrivateKey(passfactor, factorb) # Verify the address hash address_hash_got = Bip38Addr.AddressHash(Secp256k1PrivateKey.FromBytes(priv_key_bytes).PublicKey(), pub_key_mode) if address_hash != address_hash_got: raise ValueError( f"Invalid address hash (expected: {BytesUtils.ToHexString(address_hash)}, " f"got: {BytesUtils.ToHexString(address_hash_got)})" ) return priv_key_bytes, pub_key_mode
def encode_int(int_val: int) -> bytes: return IntegerUtils.ToBytes(int_val, 32, endianness="little")
b"e9b6062841bb977ad21de71ec961900633c26f21384e015b014a637a614995", ] # Private keys with invalid lengths TEST_VECT_PRIV_KEY_INVALID_LEN = [ b"132750b8489385430d8bfa3871ade97da7f5d5ef134a5c85184f88743b526e", b"132750b8489385430d8bfa3871ade97da7f5d5ef134a5c85184f88743b526e71d0", ] # Tests for ed25519 invalid private keys TEST_VECT_ED25519_PRIV_KEY_INVALID = TEST_VECT_PRIV_KEY_INVALID_LEN # Tests for ed25519-monero invalid private keys (add key equal to curve order) TEST_VECT_ED25519_MONERO_PRIV_KEY_INVALID = TEST_VECT_PRIV_KEY_INVALID_LEN + [ binascii.hexlify( IntegerUtils.ToBytes( Ed25519Monero.Order(), bytes_num=32, endianness="little")), ] # Tests for nist256p1 invalid private keys (add zero key and key equal to curve order) TEST_VECT_NIST256P1_PRIV_KEY_INVALID = TEST_VECT_PRIV_KEY_INVALID_LEN + [ b"0000000000000000000000000000000000000000000000000000000000000000", binascii.hexlify(IntegerUtils.ToBytes(Nist256p1.Order(), bytes_num=32)), ] # Tests for secp256k1 invalid private keys (add zero key and key equal to curve order) TEST_VECT_SECP256K1_PRIV_KEY_INVALID = TEST_VECT_PRIV_KEY_INVALID_LEN + [ b"0000000000000000000000000000000000000000000000000000000000000000", binascii.hexlify(IntegerUtils.ToBytes(Secp256k1.Order(), bytes_num=32)), ] # Tests for sr25519 invalid private keys TEST_VECT_SR25519_PRIV_KEY_INVALID = [