def test_sign(self): if libsecp256k1 is None: raise unittest.SkipTest("no libsecp256k1") ctx = libsecp256k1.ctx sighash = to_bytes_32(1000) secret_key = to_bytes_32(100) public_key = create_string_buffer(64) r = libsecp256k1.secp256k1_ec_pubkey_create(ctx, public_key, secret_key) self.assertEqual(r, 1) self.assertEqual( b2h(public_key), '880f50f7ceb4210289266a40b306e33ef52bb75f834c172e65175e3ce2ac3bed' '6e2835e3d57ae1fcd0954808be17bd97bf871f7a8a5edadcffcc8812576f7ae5' ) signature = create_string_buffer(64) r = libsecp256k1.secp256k1_ecdsa_sign(ctx, signature, sighash, secret_key, None, None) self.assertEqual(r, 1) compact_signature = create_string_buffer(64) libsecp256k1.secp256k1_ecdsa_signature_serialize_compact(ctx, compact_signature, signature) r = from_bytes_32(compact_signature[:32]) s = from_bytes_32(compact_signature[32:]) signature = (r, s) pubkey_size = c_size_t(65) pubkey_serialized = create_string_buffer(65) libsecp256k1.secp256k1_ec_pubkey_serialize( ctx, pubkey_serialized, byref(pubkey_size), public_key, SECP256K1_EC_UNCOMPRESSED) x = from_bytes_32(pubkey_serialized[1:33]) y = from_bytes_32(pubkey_serialized[33:]) legacy_secp256k1_group.verify((x, y), 1000, signature)
def sign(self, secret_exponent, val, gen_k=None): nonce_function = None if gen_k is not None: k_as_bytes = to_bytes_32(gen_k(self.order(), secret_exponent, val)) def adaptor(nonce32_p, msg32_p, key32_p, algo16_p, data, attempt): nonce32_p.contents[:] = list(iterbytes(k_as_bytes)) return 1 p_b32 = POINTER(c_byte * 32) nonce_function = CFUNCTYPE(c_int, p_b32, p_b32, p_b32, POINTER(c_byte * 16), c_void_p, c_uint)(adaptor) sig = create_string_buffer(64) sig_hash_bytes = to_bytes_32(val) libsecp256k1.secp256k1_ecdsa_sign(libsecp256k1.ctx, sig, sig_hash_bytes, to_bytes_32(secret_exponent), nonce_function, None) compact_signature = create_string_buffer(64) libsecp256k1.secp256k1_ecdsa_signature_serialize_compact( libsecp256k1.ctx, compact_signature, sig) r = from_bytes_32(compact_signature[:32]) s = from_bytes_32(compact_signature[32:]) return (r, s)
def multiply(self, p, e): """Multiply a point by an integer.""" e %= self.order() if p == self._infinity or e == 0: return self._infinity pubkey = create_string_buffer(64) public_pair_bytes = b'\4' + to_bytes_32(p[0]) + to_bytes_32(p[1]) r = libsecp256k1.secp256k1_ec_pubkey_parse(libsecp256k1.ctx, pubkey, public_pair_bytes, len(public_pair_bytes)) if not r: return False r = libsecp256k1.secp256k1_ec_pubkey_tweak_mul(libsecp256k1.ctx, pubkey, to_bytes_32(e)) if not r: return self._infinity pubkey_serialized = create_string_buffer(65) pubkey_size = c_size_t(65) libsecp256k1.secp256k1_ec_pubkey_serialize(libsecp256k1.ctx, pubkey_serialized, byref(pubkey_size), pubkey, SECP256K1_EC_UNCOMPRESSED) x = from_bytes_32(pubkey_serialized[1:33]) y = from_bytes_32(pubkey_serialized[33:]) return self.Point(x, y)
def __mul__(self, e): e %= self.order() if e == 0: return self._infinity pubkey = create_string_buffer(65) libsecp256k1.secp256k1_ec_pubkey_create(libsecp256k1.ctx, pubkey, c_char_p(to_bytes_32(e))) pubkey_size = c_size_t(65) pubkey_serialized = create_string_buffer(65) libsecp256k1.secp256k1_ec_pubkey_serialize( libsecp256k1.ctx, pubkey_serialized, byref(pubkey_size), pubkey, SECP256K1_EC_UNCOMPRESSED) x = from_bytes_32(pubkey_serialized[1:33]) y = from_bytes_32(pubkey_serialized[33:]) return self.Point(x, y)
def subkey(self, path): """ path: of the form "K" where K is an integer index, or "K/N" where N is usually a 0 (deposit address) or 1 (change address) """ t = path.split("/") if len(t) == 2: n, for_change = t else: n, = t for_change = 0 b = (str(n) + ':' + str(for_change) + ':').encode("utf8") + self.master_public_key() offset = from_bytes_32(double_sha256(b)) if self.secret_exponent(): return self.__class__( generator=self._generator, master_private_key=((self.master_private_key() + offset) % self._generator.order())) p1 = offset * self._generator x, y = self.public_pair() p2 = self._generator.Point(x, y) p = p1 + p2 return self.__class__(public_pair=p, generator=self._generator)
def verify(self, h, sig, generator=None): """ Return whether a signature is valid for hash h using this key. """ generator = generator or self._generator if not generator: raise ValueError("generator must be specified") val = from_bytes_32(h) pubkey = self.public_pair() rs = sigdecode_der(sig) if self.public_pair() is None: # find the pubkey from the signature and see if it matches # our key possible_pubkeys = generator.possible_public_pairs_for_signature(val, rs) hash160 = self.hash160() for candidate in possible_pubkeys: if hash160 == public_pair_to_hash160_sec(candidate, True): pubkey = candidate break if hash160 == public_pair_to_hash160_sec(candidate, False): pubkey = candidate break else: # signature is using a pubkey that's not this key return False return generator.verify(pubkey, val, rs)
def verify(self, h, sig): """ Return whether a signature is valid for hash h using this key. """ val = from_bytes_32(h) pubkey = self.public_pair() return self._generator.verify(pubkey, val, sigdecode_der(sig))
def __init__(self, generator, initial_key=None, master_private_key=None, public_pair=None, master_public_key=None): if [initial_key, public_pair, master_private_key, master_public_key ].count(None) != 3: raise ValueError( "exactly one of initial_key, master_private_key, master_public_key must be non-None" ) self._initial_key = initial_key self._generator = generator if initial_key is not None: master_private_key = initial_key_to_master_key(initial_key) if master_public_key: public_pair = tuple( from_bytes_32(master_public_key[idx:idx + 32]) for idx in (0, 32)) super(ElectrumWallet, self).__init__(generator=generator, secret_exponent=master_private_key, public_pair=public_pair, prefer_uncompressed=True)
def verify(self, h, sig, generator=None): """ Return whether a signature is valid for hash h using this key. """ generator = generator or self._generator if not generator: raise ValueError("generator must be specified") val = from_bytes_32(h) pubkey = self.public_pair() rs = sigdecode_der(sig) if self.public_pair() is None: # find the pubkey from the signature and see if it matches # our key possible_pubkeys = generator.possible_public_pairs_for_signature( val, rs) hash160 = self.hash160() for candidate in possible_pubkeys: if hash160 == public_pair_to_hash160_sec(candidate, True): pubkey = candidate break if hash160 == public_pair_to_hash160_sec(candidate, False): pubkey = candidate break else: # signature is using a pubkey that's not this key return False return generator.verify(pubkey, val, rs)
def __mul__(self, e): e %= self.order() if e == 0: return self._infinity pubkey = create_string_buffer(65) libsecp256k1.secp256k1_ec_pubkey_create(libsecp256k1.ctx, pubkey, c_char_p(to_bytes_32(e))) pubkey_size = c_size_t(65) pubkey_serialized = create_string_buffer(65) libsecp256k1.secp256k1_ec_pubkey_serialize(libsecp256k1.ctx, pubkey_serialized, byref(pubkey_size), pubkey, SECP256K1_EC_UNCOMPRESSED) x = from_bytes_32(pubkey_serialized[1:33]) y = from_bytes_32(pubkey_serialized[33:]) return self.Point(x, y)
def info_for_E(self, prefix, data): bin_data = h2b(data) size = len(bin_data) if size not in (16, 32, 64): return is_private = (size != 64) if size == 16: kwargs = dict(initial_key=data, generator=self._generator) electrum_type = "seed" if size == 32: kwargs = dict(master_private_key=from_bytes_32(bin_data), generator=self._generator) electrum_type = "private" if size == 64: kwargs = dict(master_public_key=bin_data, generator=self._generator) electrum_type = "public" return dict(type="key", key_type="electrum", electrum_type=electrum_type, is_private=is_private, key_class=self._electrum_class, kwargs=kwargs, create_f=lambda: self._electrum_class(**kwargs))
def electrum_prv(self, s): """ Parse an electrum private key from a text string in seed form ("E:xxx" where xxx is a 64-character hex string). Return a :class:`ElectrumWallet <pycoin.key.electrum.ElectrumWallet>` or None. """ blob = self._electrum_to_blob(s) if blob and len(blob) == 32: mpk = from_bytes_32(blob) return self._network.keys.electrum_private(master_private_key=mpk)
def sign(self, h): """ Return a der-encoded signature for a hash h. Will throw a RuntimeError if this key is not a private key """ if not self.is_private(): raise RuntimeError("Key must be private to be able to sign") val = from_bytes_32(h) r, s = self._generator.sign(self.secret_exponent(), val) return sigencode_der(r, s)
def initial_key_to_master_key(initial_key): """ initial_key: a hex string of length 32 """ b = initial_key.encode("utf8") orig_input = b for i in range(100000): b = hashlib.sha256(b + orig_input).digest() return from_bytes_32(b)
def sign(self, secret_exponent, val, gen_k=None): nonce_function = None if gen_k is not None: k_as_bytes = to_bytes_32(gen_k(self.order(), secret_exponent, val)) def adaptor(nonce32_p, msg32_p, key32_p, algo16_p, data, attempt): nonce32_p.contents[:] = list(iterbytes(k_as_bytes)) return 1 p_b32 = POINTER(c_byte*32) nonce_function = CFUNCTYPE(c_int, p_b32, p_b32, p_b32, POINTER(c_byte*16), c_void_p, c_uint)(adaptor) sig = create_string_buffer(64) sig_hash_bytes = to_bytes_32(val) libsecp256k1.secp256k1_ecdsa_sign( libsecp256k1.ctx, sig, sig_hash_bytes, to_bytes_32(secret_exponent), nonce_function, None) compact_signature = create_string_buffer(64) libsecp256k1.secp256k1_ecdsa_signature_serialize_compact(libsecp256k1.ctx, compact_signature, sig) r = from_bytes_32(compact_signature[:32]) s = from_bytes_32(compact_signature[32:]) return (r, s)
def ascend_bip32(bip32_pub_node, secret_exponent, child): """ Given a BIP32Node with public derivation child "child" with a known private key, return the secret exponent for the bip32_pub_node. """ i_as_bytes = struct.pack(">l", child) sec = public_pair_to_sec(bip32_pub_node.public_pair(), compressed=True) data = sec + i_as_bytes I64 = hmac.HMAC(key=bip32_pub_node._chain_code, msg=data, digestmod=hashlib.sha512).digest() I_left_as_exponent = from_bytes_32(I64[:32]) return (secret_exponent - I_left_as_exponent) % bip32_pub_node._generator.order()
def info_for_wif(self, data): data = data[1:] is_compressed = (len(data) > 32) if is_compressed: data = data[:-1] se = from_bytes_32(data) kwargs = dict(secret_exponent=se, generator=self._generator, prefer_uncompressed=not is_compressed) return dict(type="key", key_type="wif", is_private=True, kwargs=kwargs, key_class=self._key_class, create_f=lambda: self._key_class(**kwargs))
def __init__(self, initial_key=None, master_private_key=None, public_pair=None, master_public_key=None): if [initial_key, public_pair, master_private_key, master_public_key].count(None) != 3: raise ValueError( "exactly one of initial_key, master_private_key, master_public_key must be non-None") self._initial_key = initial_key if initial_key is not None: master_private_key = initial_key_to_master_key(initial_key) if master_public_key: public_pair = tuple(from_bytes_32(master_public_key[idx:idx+32]) for idx in (0, 32)) super(ElectrumWallet, self).__init__( secret_exponent=master_private_key, public_pair=public_pair, is_compressed=False)
def multiply(self, p, e): """Multiply a point by an integer.""" e %= self.order() if p == self._infinity or e == 0: return self._infinity pubkey = create_string_buffer(64) public_pair_bytes = b'\4' + to_bytes_32(p[0]) + to_bytes_32(p[1]) r = libsecp256k1.secp256k1_ec_pubkey_parse( libsecp256k1.ctx, pubkey, public_pair_bytes, len(public_pair_bytes)) if not r: return False r = libsecp256k1.secp256k1_ec_pubkey_tweak_mul(libsecp256k1.ctx, pubkey, to_bytes_32(e)) if not r: return self._infinity pubkey_serialized = create_string_buffer(65) pubkey_size = c_size_t(65) libsecp256k1.secp256k1_ec_pubkey_serialize( libsecp256k1.ctx, pubkey_serialized, byref(pubkey_size), pubkey, SECP256K1_EC_UNCOMPRESSED) x = from_bytes_32(pubkey_serialized[1:33]) y = from_bytes_32(pubkey_serialized[33:]) return self.Point(x, y)
def ascend_bip32(bip32_pub_node, secret_exponent, child): """ Given a BIP32Node with public derivation child "child" with a known private key, return the secret exponent for the bip32_pub_node. """ i_as_bytes = struct.pack(">l", child) sec = public_pair_to_sec(bip32_pub_node.public_pair(), compressed=True) data = sec + i_as_bytes I64 = hmac.HMAC(key=bip32_pub_node._chain_code, msg=data, digestmod=hashlib.sha512).digest() I_left_as_exponent = from_bytes_32(I64[:32]) return (secret_exponent - I_left_as_exponent) % ORDER
def test_sign(self): if libsecp256k1 is None: raise unittest.SkipTest("no libsecp256k1") ctx = libsecp256k1.ctx sighash = to_bytes_32(1000) secret_key = to_bytes_32(100) public_key = create_string_buffer(64) r = libsecp256k1.secp256k1_ec_pubkey_create(ctx, public_key, secret_key) self.assertEqual(r, 1) self.assertEqual( b2h(public_key), '880f50f7ceb4210289266a40b306e33ef52bb75f834c172e65175e3ce2ac3bed' '6e2835e3d57ae1fcd0954808be17bd97bf871f7a8a5edadcffcc8812576f7ae5') signature = create_string_buffer(64) r = libsecp256k1.secp256k1_ecdsa_sign(ctx, signature, sighash, secret_key, None, None) self.assertEqual(r, 1) compact_signature = create_string_buffer(64) libsecp256k1.secp256k1_ecdsa_signature_serialize_compact( ctx, compact_signature, signature) r = from_bytes_32(compact_signature[:32]) s = from_bytes_32(compact_signature[32:]) signature = (r, s) pubkey_size = c_size_t(65) pubkey_serialized = create_string_buffer(65) libsecp256k1.secp256k1_ec_pubkey_serialize(ctx, pubkey_serialized, byref(pubkey_size), public_key, SECP256K1_EC_UNCOMPRESSED) x = from_bytes_32(pubkey_serialized[1:33]) y = from_bytes_32(pubkey_serialized[33:]) legacy_secp256k1_group.verify((x, y), 1000, signature)
def info_for_data(self, data, is_private): parent_fingerprint, child_index = struct.unpack(">4sL", data[5:13]) d = dict(generator=self._generator, chain_code=data[13:45], depth=ord(data[4:5]), parent_fingerprint=parent_fingerprint, child_index=child_index) if is_private: if data[45:46] != b'\0': return None d["secret_exponent"] = from_bytes_32(data[46:]) else: d["public_pair"] = sec_to_public_pair(data[45:], self._generator) return dict(type="key", key_type="bip32", bip32_type="plain", is_private=is_private, kwargs=d, key_class=self._bip32node_class, create_f=lambda: self._bip32node_class(**d))
def wif(self, s): """ Parse a WIF. Return a :class:`Key <pycoin.key.Key>` or None. """ data = self.parse_b58_hashed(s) if data is None or not data.startswith(self._wif_prefix): return None data = data[len(self._wif_prefix):] is_compressed = (len(data) > 32) if is_compressed: data = data[:-1] se = from_bytes_32(data) return self._network.keys.private(se, is_compressed=is_compressed)
def subkey(self, path): """ path: of the form "K" where K is an integer index, or "K/N" where N is usually a 0 (deposit address) or 1 (change address) """ t = path.split("/") if len(t) == 2: n, for_change = t else: n, = t for_change = 0 b = (str(n) + ':' + str(for_change) + ':').encode("utf8") + self.master_public_key() offset = from_bytes_32(double_sha256(b)) if self.secret_exponent(): return self.__class__( master_private_key=((self.master_private_key() + offset) % self._generator.order()) ) p1 = offset * self._generator x, y = self.public_pair() p2 = self._generator.Point(x, y) p = p1 + p2 return self.__class__(public_pair=p)
def deserialize(class_, blob): if len(blob) == 32: return class_(master_private_key=from_bytes_32(blob)) if len(blob) == 64: return class_(master_public_key=blob)
def _signature_for_hash_type_segwit(self, script, tx_in_idx, hash_type): return from_bytes_32(sha256(self._segwit_signature_preimage(script, tx_in_idx, hash_type)))
def _signature_for_hash_type_segwit(self, script, tx_in_idx, hash_type): hash_type |= self.FORKID_BTG << 8 return from_bytes_32(double_sha256(self._segwit_signature_preimage(script, tx_in_idx, hash_type)))
def _signature_for_hash_type_segwit(self, script, tx_in_idx, hash_type): return from_bytes_32( sha256( self._segwit_signature_preimage(script, tx_in_idx, hash_type)))
from coininfo import COINS, Coin from connections import connectionmanager from keyseeder import generate_key from models import * from transaction import UnsignedTransactionBuilder, SignedTransaction, FEERATE_NETWORK, FEERATE_POOLSUBSIDY, TransactionInput as UnsignedTransactionInput, NotEnoughCoinsException from indexer import import_address from indexer.models import * MIN_CONSOLIDATION_UTXOS = 100 MAX_CONSOLIDATION_UTXOS = 650 TXIN_VSIZES = {TXOUT_TYPES.P2PKH: 149, TXOUT_TYPES.P2WPKH: 68} PrivateKey = lambda raw_key: Key.make_subclass(None, secp256k1_generator)( from_bytes_32(raw_key)) class AccountExistsException(Exception): pass class InvalidAccountName(Exception): pass class Wallet(object): def __init__(self, manager): self.manager = manager @classmethod
def _signature_for_hash_type_segwit(self, script, tx_in_idx, hash_type): hash_type |= self.FORKID_BTG << 8 return from_bytes_32( double_sha256( self._segwit_signature_preimage(script, tx_in_idx, hash_type)))
def entropy_to_wif(self, entropy): return BTC.keys.private( secret_exponent=from_bytes_32(entropy[:32])).wif()