예제 #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())
            )
예제 #2
0
 def __repr__(self):
     cur_tx = self.gen_transaction(to_sign=False)
     return \
         str({
             "tx_hash": sha256(sha256(cur_tx))[::-1].hex(),
             "tx": cur_tx.hex()
         })
예제 #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)
예제 #4
0
파일: keys.py 프로젝트: DagonR/simplebtclib
 def privatekey_to_wif(private_key: bytes, compressed=True):
     """Convert a private key to WIF (str)"""
     compressed_flag = b"\x01" if compressed else b""
     wif = b"\x80" + private_key + compressed_flag
     double_sha = sha256(sha256(wif))
     try:
         return base58_encode(wif + double_sha[:4])
     except Exception:
         raise ValueError("Invalid private key: {:s}".format(
             private_key.hex()))
예제 #5
0
파일: keys.py 프로젝트: DagonR/simplebtclib
    def address_to_pubkey_hash(address: str):
        """Check an address checksum.

        Return Public Key Hash if the checksum is correct
        else raise ValueError.
        """
        # calculate the public key hash
        t = base58_decode(address.lstrip("1"), 25)
        # If the checksum is correct
        if sha256(sha256(t[:21]))[:4] == t[21:]:
            return t[1:21]
        else:
            raise ValueError(
                "Incorrect checksum for address: {:s}".format(address))
예제 #6
0
파일: keys.py 프로젝트: DagonR/simplebtclib
    def get_pubkey_hash(self):
        """Return the object's public key hash"""
        if self._public_key_hash is None:
            self._public_key_hash = \
                ripemd160(sha256(self.get_public_key()))

        return self._public_key_hash
예제 #7
0
    def entropy_to_mnemonic(self, entropy: bytes):
        """Calculate a mnemonic phrase from an entropy.

        Parameters:
            entropy -- a random bytes in a multiple of 32 bits
                       (length - 128-256 bits).
        Return a list with mnemonic words.
        """
        ent_len = 8 * len(entropy)
        # Check a multiple of 32 bits
        if ent_len < 32 or ent_len % 32 != 0:
            raise Exception("Invalid entropy length")

        # cs_len -- length of checksum
        cs_len = ent_len // 32
        checksum = bytes2int(sha256(entropy)[0:2]) >> (16 - cs_len)

        ent_cs = (bytes2int(entropy) << cs_len) | checksum

        words_count = (ent_len + ent_len // 32) // 11

        mnemonic = [
            self._wordlist[(ent_cs >> 11 * x) & 0x7FF].strip()
            for x in range(words_count)
        ]
        # Reverse the list
        return mnemonic[::-1]
예제 #8
0
    def sign_all_inputs(self):
        """Sign this transaction"""
        # For each input prepare and sign a transaction
        for i in self.ins.keys():

            # Prepare the transaction to sign for the input = i
            temp_tx = self.gen_transaction(input_num=i, to_sign=True)

            # Get the hash
            hash_temp_tx = sha256(sha256(temp_tx))

            # Sign the prepared transaction
            r, s = self.ins[i]["keys"].sign(hash_temp_tx)

            # Save the final script signature and it's length
            self.ins[i]["final_script_sig"] = \
                self.get_script_sig(r, s, self.ins[i]["keys"].get_public_key())

            self.ins[i]["final_script_length"] = \
                struct.pack("<B", len(self.ins[i]["final_script_sig"]))
        return
예제 #9
0
파일: keys.py 프로젝트: DagonR/simplebtclib
    def get_address(self, version: int = None):
        """Return the object's btc-address"""
        # If None then version is a mainnet address
        version = ADDRESS_PREFIX_MAINNET if version is None else version

        if self._address is None:
            # Set an address version (mainnet or testnet)
            t = bytes([version]) + self.get_pubkey_hash()
            # Add checksum
            t += sha256(sha256(t))[0:4]
            # Count leading zeros
            leading_zeros = 0
            for _ in t:
                if _ == 0:
                    leading_zeros += 1
                else:
                    break
            # Change leading zeros by ones and encode to base58
            self._address = leading_zeros * "1" + \
                            base58_encode(t)

        return self._address
예제 #10
0
    from btc.utils import sha256
    from btc.keys import KeysBTC

    k = KeysBTC("96a69d6682a4b2eb522e896c2fa1b8ada485c472b983e27266d1d5c8c77ec374")

    # Check the right values at https://www.bitaddress.org
    # An object methods
    print("Private key (hex): ", k.get_private_key_hex())
    print("Private key (WIF-compressed): ", k.get_private_key_wif(True))
    print("Private key (WIF-uncompressed): ", k.get_private_key_wif(False))
    print("Public point: ", k.get_public_point())
    print("Public key (hex): ", k.get_public_key(compressed=True).hex(),)
    print("Is public key compressed: ", k.is_pubkey_compressed())
    print("Public key HASH160: ", k.get_pubkey_hash().hex())
    print("Address: ", k.get_address())

    # Static methods (convertions)
    print("Generator point: ", k.get_generator_point())
    print("Private key to WIF: ", k.privatekey_to_wif(k._private_key, compressed=False))
    print("WIF to private key", k.privatekey_from_wif(k.get_private_key_wif()).hex())
    print(k.address_to_pubkey_hash(k.get_address()).hex())

    # Sign and verify
    message = sha256(b"sample")
    r, s = k.sign(message)
    print(k.verify(message, r, s))



예제 #11
0
 def get_fingerprint(public_key):
     """Return first 4 bytes of HASH160 of the public_key"""
     return ripemd160(sha256(public_key))[:4]