def get_private_key(self, pubkey, password): sec = pw_decode(self.keypairs[pubkey], password) txin_type, privkey, compressed = deserialize_privkey(sec) # this checks the password if pubkey != ecc.ECPrivkey(privkey).get_public_key_hex( compressed=compressed): raise InvalidPassword() return privkey, compressed
def _CKD_pub(cK, c, s): I = hmac_oneshot(c, cK + s, hashlib.sha512) pubkey = ecc.ECPrivkey(I[0:32]) + ecc.ECPubkey(cK) if pubkey.is_at_infinity(): raise ecc.InvalidECPointException() cK_n = pubkey.get_public_key_bytes(compressed=True) c_n = I[32:] return cK_n, c_n
def bip32_root(seed, xtype): I = hmac.new(b"Bitcoin seed", seed, hashlib.sha512).digest() master_k = I[0:32] master_c = I[32:] # create xprv first, as that will check if master_k is within curve order xprv = serialize_xprv(xtype, master_c, master_k) cK = ecc.ECPrivkey(master_k).get_public_key_bytes(compressed=True) xpub = serialize_xpub(xtype, master_c, cK) return xprv, xpub
def _CKD_priv(k, c, s, is_prime): keypair = ecc.ECPrivkey(k) cK = keypair.get_public_key_bytes(compressed=True) data = bytes([0]) + k + s if is_prime else cK + s I = hmac.new(c, data, hashlib.sha512).digest() k_n = ecc.number_to_string( (ecc.string_to_number(I[0:32]) + ecc.string_to_number(k)) % ecc.CURVE_ORDER, ecc.CURVE_ORDER) c_n = I[32:] return k_n, c_n
def bip32_private_derivation(xprv, branch, sequence): if not sequence.startswith(branch): raise ValueError('incompatible branch ({}) and sequence ({})'.format( branch, sequence)) if branch == sequence: return xprv, xpub_from_xprv(xprv) xtype, depth, fingerprint, child_number, c, k = deserialize_xprv(xprv) sequence = sequence[len(branch):] for n in sequence.split('/'): if n == '': continue i = int(n[:-1]) + BIP32_PRIME if n[-1] == "'" else int(n) parent_k = k k, c = CKD_priv(k, c, i) depth += 1 parent_cK = ecc.ECPrivkey(parent_k).get_public_key_bytes(compressed=True) fingerprint = hash_160(parent_cK)[0:4] child_number = bfh("%08X" % i) cK = ecc.ECPrivkey(k).get_public_key_bytes(compressed=True) xpub = serialize_xpub(xtype, c, cK, depth, fingerprint, child_number) xprv = serialize_xprv(xtype, c, k, depth, fingerprint, child_number) return xprv, xpub
def import_privkey(self, sec, password): txin_type, privkey, compressed = deserialize_privkey(sec) pubkey = ecc.ECPrivkey(privkey).get_public_key_hex( compressed=compressed) # re-serialize the key so the internal storage format is consistent serialized_privkey = serialize_privkey(privkey, compressed, txin_type, internal_use=True) # NOTE: if the same pubkey is reused for multiple addresses (script types), # there will only be one pubkey-privkey pair for it in self.keypairs, # and the privkey will encode a txin_type but that txin_type cannot be trusted. # Removing keys complicates this further. self.keypairs[pubkey] = pw_encode(serialized_privkey, password) return txin_type, pubkey
def _CKD_priv(k, c, s, is_prime): try: keypair = ecc.ECPrivkey(k) except ecc.InvalidECPointException as e: raise BitcoinException( 'Impossible xprv (not within curve order)') from e cK = keypair.get_public_key_bytes(compressed=True) data = bytes([0]) + k + s if is_prime else cK + s I = hmac_oneshot(c, data, hashlib.sha512) I_left = ecc.string_to_number(I[0:32]) k_n = (I_left + ecc.string_to_number(k)) % ecc.CURVE_ORDER if I_left >= ecc.CURVE_ORDER or k_n == 0: raise ecc.InvalidECPointException() k_n = ecc.number_to_string(k_n, ecc.CURVE_ORDER) c_n = I[32:] return k_n, c_n
def sign(self, keypairs): for i, txin in enumerate(self.inputs()): num = txin['num_sig'] pubkeys, x_pubkeys = self.get_sorted_pubkeys(txin) for j, x_pubkey in enumerate(x_pubkeys): signatures = list(filter(None, txin['signatures'])) if len(signatures) == num: # txin is complete break if x_pubkey in keypairs.keys(): print_error("adding signature for", x_pubkey) sec, compressed = keypairs.get(x_pubkey) pubkey = ecc.ECPrivkey(sec).get_public_key_hex(compressed=compressed) # add signature sig = self.sign_txin(i, sec) self.add_signature_to_txin(txin, j, sig) #txin['x_pubkeys'][j] = pubkey txin['pubkeys'][j] = pubkey # needed for fd keys self._inputs[i] = txin print_error("is_complete", self.is_complete()) self.raw = self.serialize()
def decrypt_message(self, sequence, message, password): privkey, compressed = self.get_private_key(sequence, password) ec = ecc.ECPrivkey(privkey) decrypted = ec.decrypt_message(message) return decrypted
def sign_message(self, sequence, message, password): privkey, compressed = self.get_private_key(sequence, password) key = ecc.ECPrivkey(privkey) return key.sign_message(message, compressed)
def sign_txin(self, txin_index, privkey_bytes): pre_hash = Hash(bfh(self.serialize_preimage(txin_index))) privkey = ecc.ECPrivkey(privkey_bytes) sig = privkey.sign_transaction(pre_hash) sig = bh2u(sig) + '01' return sig
def xpub_from_xprv(xprv): xtype, depth, fingerprint, child_number, c, k = deserialize_xprv(xprv) cK = ecc.ECPrivkey(k).get_public_key_bytes(compressed=True) return serialize_xpub(xtype, c, cK, depth, fingerprint, child_number)
def _CKD_pub(cK, c, s): I = hmac.new(c, cK + s, hashlib.sha512).digest() pubkey = ecc.ECPrivkey(I[0:32]) + ecc.ECPubkey(cK) cK_n = pubkey.get_public_key_bytes(compressed=True) c_n = I[32:] return cK_n, c_n
def address_from_private_key(sec): txin_type, privkey, compressed = deserialize_privkey(sec) public_key = ecc.ECPrivkey(privkey).get_public_key_hex( compressed=compressed) return pubkey_to_address(txin_type, public_key)