Ejemplo n.º 1
0
 def get_script_sig(r: bytes, s: bytes, public_key: bytes):
     """Construct an unlocking script with a sign [r, s]"""
     # Convert r and s to DER
     sig = signature_to_der(r, s)
     # Construct a sigScript = DER(DER(r,s)+01) + <length pubkey> + <pubkey>
     return (int2bytes(len(sig) + 1, 1) + sig + b"\x01" +
             int2bytes(len(public_key), 1) + public_key)
Ejemplo n.º 2
0
 def point_to_publickey(point: ECPoint, compressed=True):
     """Convert a point to a public key"""
     if compressed:
         return (b"\x02" if point.y % 2 == 0 else b"\x03") + \
                int2bytes(point.x)
     else:
         return b"\x04" + int2bytes(point.x) + int2bytes(point.y)
Ejemplo n.º 3
0
    def serialize(self):
        """Return serialized format (str) of this key (xprv / xpub)"""
        if self.is_private():
            ser_key = (
                MAINNET_PRIVATE +
                int2bytes(self.level, 1) +
                self.fingerprint +
                int2bytes(self.index, 4) +
                self.chain_code +
                b"\x00" +
                self.key
            )
        elif self.is_public():
            ser_key = (
                MAINNET_PUBLIC +
                int2bytes(self.level, 1) +
                self.fingerprint +
                int2bytes(self.index, 4) +
                self.chain_code +
                KeysBTC.point_to_publickey(self.key)
            )
        else:
            raise ValueError("Invalid extended key")

        checksum = sha256(sha256(ser_key))[:4]

        return base58_encode(ser_key + checksum)
Ejemplo n.º 4
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())
        )
Ejemplo n.º 5
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)
Ejemplo n.º 6
0
    def get_script_p2pkh(hash: bytes):
        """Construct a locking pay-to-pubkey-hash script (p2pkh):

        OP_DUP OP_HASH160 <len of pubkey hash> <pubkey hash> OP_CHECKSIG
        """
        return (OP_DUP + OP_HASH160 + int2bytes(len(hash), 1) + hash +
                OP_EQUALVERIFY + OP_CHECKSIG)
Ejemplo 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
Ejemplo n.º 8
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)
        )
Ejemplo n.º 9
0
    def mnemonic_to_entropy(self, mnemonic: list):
        """Calculate an entropy from a mnemonic phrase.

        Parameters:
            mnemonic -- a list with mnemonic words in a multiple of
            3 words (length - 12-24 words).
        Return bytes in a multiple of 32 bits (length - 128-256 bits).
        """
        words_count = len(mnemonic)

        # Check number of words
        if words_count < 12 or words_count > 24 or words_count % 3 != 0:
            raise Exception("Invalid number of the words")

        ent_len = words_count * 11 * 32 // 33
        ent_cs = 0

        for x in mnemonic:
            try:
                ent_cs = (ent_cs << 11) | self._wordlist.index(x)
            except ValueError:
                raise ValueError("Invalid word: '{:s}'".format(x))

        return int2bytes(ent_cs >> (ent_len // 32), ent_len // 8)
Ejemplo n.º 10
0
    def get_script_p2sh(hash):
        """Construct a locking pay-to-script-hash script (p2sh):

        OP_HASH160 <len of script hash> <script hash> OP_EQUAL
        """
        return (OP_HASH160 + int2bytes(len(hash), 1) + hash + OP_EQUAL)