Exemplo n.º 1
0
    def deserialize(self, ser_key: str):
        """Deserialize a serialized key into self"""
        ser_key = base58_decode(ser_key, 82)

        # Checksum
        if sha256(sha256(ser_key[:78]))[:4] != ser_key[78:]:
            raise ValueError(
                "Wrong checksum of the extended key: {:s}".format(ser_key.hex())
            )

        self.level = ser_key[4]
        self.fingerprint = ser_key[5:9]
        self.index = bytes2int(ser_key[9:13])
        self.chain_code = ser_key[13:45]

        if ser_key[:4] == MAINNET_PRIVATE:
            # Miss 00 and get the private key
            self.key = ser_key[46:78]
        elif ser_key[:4] == MAINNET_PUBLIC:
            # Get x coordinate of the public point
            x = bytes2int(ser_key[46:78])
            # Calculate y coordinate of the public point
            y = ECPoint.get_secp256k1_y(x)
            # Choice even y if prefix = 02, else choice odd y
            if ser_key[45] == 2:
                y = ECPoint.get_secp256k1_p() - y if y % 2 != 0 else y
            else:
                y = ECPoint.get_secp256k1_p() - y if y % 2 == 0 else y

            self.key = ECPoint(x, y)
        else:
            raise ValueError(
                "Invalid serialized extended key: {:s}".format(ser_key.hex())
            )
Exemplo n.º 2
0
    def prv_to_child(parent_prv: ExtendedKey, index: int):
        """Return an extended child private key.

        Parameters:
            parent_prv -- a parent private key,
            index -- an index of a parent private key
        """
        cur_key = KeysBTC(parent_prv.key)
        ser32_index = int2bytes(index, 4)

        # If a hardened index the take the private key,
        # otherwise, take the public key.
        if index >= 2 ** 31:
            data = b"\x00" + cur_key.get_private_key() + ser32_index
        else:
            data = cur_key.get_public_key() + ser32_index

        child_hash = hmac_sha512(parent_prv.chain_code, data)

        child_hash_left = bytes2int(child_hash[:32])
        k_i = (child_hash_left + cur_key.get_private_key_int()) % \
              ECPoint.get_secp256k1_order()
        # Check the left part
        if child_hash_left >= ECPoint.get_secp256k1_order() or k_i == 0:
            raise ValueError("The resulting key is invalid")

        # The right part is child_hash[32:]
        return ExtendedKey(
            int2bytes(k_i),
            child_hash[32:],
            parent_prv.level + 1,    # increase level
            index,
            ExtendedKey.get_fingerprint(cur_key.get_public_key())
        )
Exemplo n.º 3
0
    def seed_to_master_key(seed):
        """Return an extended master (root) private key (BIP32) for a seed"""
        hash = hmac_sha512(b"Bitcoin seed", seed)
        key = hash[:32]
        chain_code = hash[32:]

        # Check key
        key_int = bytes2int(key)
        if key_int == 0 or key_int >= ECPoint.get_secp256k1_order():
            raise ValueError("Wrong master key")

        return ExtendedKey(key, chain_code)
Exemplo n.º 4
0
    def verify(self, hash: bytes, r: bytes, s: bytes):
        """Verify a sign r, s for a hash with the object's keys"""
        N = ECPoint.get_secp256k1_order()
        h = bytes2int(hash) % N
        h = 1 if h == 0 else h

        r1 = bytes2int(r)
        s_inv = mod_inverse(bytes2int(s), N)
        u1 = (h * s_inv) % N
        u2 = (r1 * s_inv) % N
        C = self.get_generator_point() * u1 + self.get_public_point() * u2

        return C.x == r1
Exemplo n.º 5
0
    def pub_to_child(parent_pub: ExtendedKey, index: int):
        """Return an extended child public key.

        Parameters:
            parent_pub -- a parent public key,
            index -- an index of a parent public key
        """
        # Check if index is not a hardened key
        if index >= 2 ** 31:
            raise ValueError(
                "Cannot generate a child public key because "
                "it is a hardened key"
            )

        ser32_index = int2bytes(index, 4)
        public_key = KeysBTC.point_to_publickey(parent_pub.key)

        data = public_key + ser32_index

        child_hash = hmac_sha512(parent_pub.chain_code, data)

        child_hash_left = bytes2int(child_hash[:32])
        K_i = KeysBTC.get_generator_point() * child_hash_left + parent_pub.key
        # Check the left part
        if child_hash_left >= ECPoint.get_secp256k1_order() or \
                K_i == ECPoint.infinity():
            raise ValueError(
                "The resulting key is invalid for index {:d}".format(index)
            )

        # The right part is child_hash[32:]
        return ExtendedKey(
            K_i,
            child_hash[32:],
            parent_pub.level + 1,    # increase level
            index,
            ExtendedKey.get_fingerprint(public_key)
        )
Exemplo n.º 6
0
    def sign(self, hash: bytes):
        """Sign a hash with the object's keys"""
        private_key_int = self.get_private_key_int()
        N = ECPoint.get_secp256k1_order()
        h = bytes2int(hash) % N
        h = 1 if h == 0 else h

        # get the deterministic random integer with RFC 6979
        k = random_rfc6979(hash, private_key_int, N,
                           self.get_generator_point())
        # Calculate G * k
        C = self.get_generator_point() * k
        s = ((h + C.x * private_key_int) * mod_inverse(k, N)) % N

        # Return r and s
        return int2bytes(C.x), int2bytes(s)
Exemplo n.º 7
0
    def __init__(self, private_key=None):
        """Construct an object with a private key (bytes or str)"""

        # Init private_key, if input is None then get a random BBS
        if private_key is None:
            self._private_key = int2bytes(
                random_bbs(ECPoint.get_secp256k1_order_len()))
        else:
            self._private_key = bytes.fromhex(private_key) \
                if isinstance(private_key, str) else private_key

        assert bytes2int(self._private_key) > 0, "Invalid private key"

        self._public_point = None
        self._public_key = None
        self._public_key_hash = None
        self._address = None
Exemplo n.º 8
0
 def get_generator_point():
     """Return Generator Point for SECP256k1"""
     return ECPoint(ECPoint.get_secp256k1_gx(), ECPoint.get_secp256k1_gy())
Exemplo n.º 9
0
# --- Usage and testing ---
if __name__ == "__main__":

    from btc.ecpoint import ECPoint

    # Find the nearest point with x coordinate >= start_x
    start_x = 10**33

    while True:
        try:
            p = ECPoint(start_x, ECPoint.get_secp256k1_y(start_x))
            break
        except AssertionError:
            start_x += 1
            continue

    print(p)