Exemplo n.º 1
0
    def _ValidateAndCkdPub(self, index: Bip32KeyIndex) -> Bip32Base:
        """
        Check the key index validity and create a child key of the specified index using public derivation.

        Args:
            index (Bip32KeyIndex object): Key index

        Returns:
            Bip32Base object: Bip32 object constructed with the child parameters

        Raises:
            Bip32KeyError: If the index results in an invalid key
        """

        # Check if supported
        if not self.IsPublicDerivationSupported():
            raise Bip32KeyError("Public child derivation is not supported")

        # Hardened index is not supported for public derivation
        if index.IsHardened():
            raise Bip32KeyError(
                "Public child derivation cannot be used to create a hardened child key"
            )

        return self._CkdPub(index)
Exemplo n.º 2
0
    def __GetPartsFromBytes(ser_key_bytes: bytes,
                            is_public: bool) -> Tuple[bytes, Bip32KeyData]:
        """
        Get back key parts from serialized key bytes.

        Args:
            ser_key_bytes (bytes): Serialized key bytes
            is_public (bool)     : True if the key is public, false otherwise

        Returns:
            tuple[bytes, Bip32KeyData]: key bytes (index 0) and key data (index 1)

        Raises:
            Bip32KeyError: If the private key first byte is not zero
        """

        # Compute indexes
        depth_idx = Bip32KeyNetVersions.Length()
        fprint_idx = depth_idx + Bip32Depth.Length()
        key_index_idx = fprint_idx + Bip32FingerPrint.Length()
        chain_code_idx = key_index_idx + Bip32KeyIndex.Length()
        key_idx = chain_code_idx + Bip32ChainCode.Length()

        # Get parts
        depth = ser_key_bytes[depth_idx]
        fprint_bytes = ser_key_bytes[fprint_idx:key_index_idx]
        key_index_bytes = ser_key_bytes[key_index_idx:chain_code_idx]
        chain_code_bytes = ser_key_bytes[chain_code_idx:key_idx]
        key_bytes = ser_key_bytes[key_idx:]
        key_data = Bip32KeyData(Bip32Depth(depth),
                                Bip32KeyIndex.FromBytes(key_index_bytes),
                                Bip32ChainCode(chain_code_bytes),
                                Bip32FingerPrint(fprint_bytes))

        # If private key, the first byte shall be zero and shall be removed
        if not is_public:
            if key_bytes[0] != 0:
                raise Bip32KeyError(
                    f"Invalid extended private key (wrong secret: {key_bytes[0]})"
                )
            key_bytes = key_bytes[1:]

        return key_bytes, key_data
Exemplo n.º 3
0
    def __GetIndex(index: Union[int, Bip32KeyIndex]) -> Bip32KeyIndex:
        """
        Get index object.

        Args:
            index (int or Bip32KeyIndex): Index

        Returns:
            Bip32KeyIndex object: Bip32KeyIndex object
        """
        return Bip32KeyIndex(index) if isinstance(index, int) else index
Exemplo n.º 4
0
    def _CkdPub(self, index: Bip32KeyIndex) -> Bip32Base:
        """
        Create a child key of the specified index using public derivation.

        Args:
            index (Bip32KeyIndex object): Key index

        Returns:
            Bip32Base object: Bip32Base object

        Raises:
            Bip32KeyError: If the index results in an invalid key
        """

        # Get elliptic curve
        curve = EllipticCurveGetter.FromType(self.CurveType())

        # Get index bytes
        index_bytes = index.ToBytes(endianness="little")

        # Compute Z and chain code
        z_bytes = CryptoUtils.HmacSha512(
            self.ChainCode().ToBytes(), b"\x02" +
            self.m_pub_key.RawCompressed().ToBytes()[1:] + index_bytes)
        chain_code_bytes = Bip32BaseUtils.HmacSha512Halves(
            self.ChainCode().ToBytes(), b"\x03" +
            self.m_pub_key.RawCompressed().ToBytes()[1:] + index_bytes)[1]

        # ZL is the left 28-byte part of Z
        zl_int = BytesUtils.ToInteger(z_bytes[:28], endianness="little")

        # Compute the new public key point: PKEY + 8ZL * G
        pub_key_point = self.m_pub_key.Point() + (
            (zl_int * 8) * curve.Generator())
        # If the public key is the identity point (0, 1) discard the child
        if pub_key_point.X() == 0 and pub_key_point.Y() == 1:
            raise Bip32KeyError(
                "Computed public child key is not valid, very unlucky index")

        return Bip32Ed25519Kholaw(
            priv_key=None,
            pub_key=Ed25519KholawPublicKey.FromPoint(pub_key_point),
            key_data=Bip32KeyData(chain_code=chain_code_bytes,
                                  depth=self.Depth().Increase(),
                                  index=index,
                                  parent_fprint=self.m_pub_key.FingerPrint()),
            curve_type=self.CurveType(),
            key_net_ver=self.KeyNetVersions())
Exemplo n.º 5
0
    def AddElem(self, elem: Union[int, Bip32KeyIndex]) -> Bip32Path:
        """
        Return a new path object with the specified element added.

        Args:
            elem (str or Bip32KeyIndex): Path element

        Returns:
            Bip32Path object: Bip32Path object

        Raises:
            Bip32PathError: If the path element is not valid
        """
        if isinstance(elem, int):
            elem = Bip32KeyIndex(elem)
        return Bip32Path(self.m_elems + [elem], self.m_is_absolute)
Exemplo n.º 6
0
    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())
Exemplo n.º 7
0
    def __init__(self, elems: Sequence[Union[int, Bip32KeyIndex]],
                 is_absolute: bool) -> None:
        """
        Construct class.

        Args:
            elems (list)      : Path elements
            is_absolute (bool): True if path is an absolute one, false otherwise
        """
        try:
            self.m_elems = [
                Bip32KeyIndex(elem) if isinstance(elem, int) else elem
                for elem in elems
            ]
        except ValueError as ex:
            raise Bip32PathError(
                "The path contains some invalid key indexes") from ex

        self.m_is_absolute = is_absolute
Exemplo n.º 8
0
    def _ValidateAndCkdPriv(self, index: Bip32KeyIndex) -> Bip32Base:
        """
        Check the key index validity and create a child key of the specified index using private derivation.

        Args:
            index (Bip32KeyIndex object): Key index

        Returns:
            Bip32Base object: Bip32 object constructed with the child parameters

        Raises:
            Bip32KeyError: If the index results in an invalid key
        """

        # Check if supported
        if not index.IsHardened(
        ) and not self.IsPrivateUnhardenedDerivationSupported():
            raise Bip32KeyError(
                "Private child derivation with not-hardened index is not supported"
            )

        return self._CkdPriv(index)
Exemplo n.º 9
0
    def _CkdPriv(self, index: Bip32KeyIndex) -> Bip32Base:
        """
        Create a child key of the specified index using private derivation.

        Args:
            index (Bip32KeyIndex object): Key index

        Returns:
            Bip32Base object: Bip32Base object

        Raises:
            Bip32KeyError: If the index results in an invalid key
        """
        assert self.m_priv_key is not None

        # Get elliptic curve
        curve = EllipticCurveGetter.FromType(self.CurveType())

        # Get index bytes
        index_bytes = index.ToBytes(endianness="little")

        # Compute Z and chain code
        if index.IsHardened():
            z_bytes = CryptoUtils.HmacSha512(
                self.ChainCode().ToBytes(),
                b"\x00" + self.m_priv_key.Raw().ToBytes() + index_bytes)
            chain_code_bytes = Bip32BaseUtils.HmacSha512Halves(
                self.ChainCode().ToBytes(),
                b"\x01" + self.m_priv_key.Raw().ToBytes() + index_bytes)[1]
        else:
            z_bytes = CryptoUtils.HmacSha512(
                self.ChainCode().ToBytes(), b"\x02" +
                self.m_pub_key.RawCompressed().ToBytes()[1:] + index_bytes)
            chain_code_bytes = Bip32BaseUtils.HmacSha512Halves(
                self.ChainCode().ToBytes(), b"\x03" +
                self.m_pub_key.RawCompressed().ToBytes()[1:] + index_bytes)[1]

        # ZL is the left 28-byte part of Z
        zl_int = BytesUtils.ToInteger(z_bytes[:28], endianness="little")
        # ZR is the right 32-byte part of Z
        zr_int = BytesUtils.ToInteger(z_bytes[32:], endianness="little")

        # Compute kL
        kl_int = (zl_int * 8) + BytesUtils.ToInteger(
            self.m_priv_key.Raw().ToBytes()[:32], endianness="little")
        if kl_int % curve.Order() == 0:
            raise Bip32KeyError(
                "Computed private child key is not valid, very unlucky index")
        # Compute kR
        kr_int = (zr_int +
                  BytesUtils.ToInteger(self.m_priv_key.Raw().ToBytes()[32:],
                                       endianness="little")) % 2**256
        # Compute private key
        priv_key = Ed25519KholawPrivateKey.FromBytes(
            IntegerUtils.ToBytes(kl_int,
                                 Ed25519KholawPrivateKey.Length() // 2,
                                 endianness="little") +
            IntegerUtils.ToBytes(kr_int,
                                 Ed25519KholawPrivateKey.Length() // 2,
                                 endianness="little"))

        return Bip32Ed25519Kholaw(
            priv_key=priv_key,
            pub_key=None,
            key_data=Bip32KeyData(chain_code=chain_code_bytes,
                                  depth=self.Depth().Increase(),
                                  index=index,
                                  parent_fprint=self.m_pub_key.FingerPrint()),
            curve_type=self.CurveType(),
            key_net_ver=self.KeyNetVersions())