def do_test(exp_hex, wif, c_wif, public_pair_sec, c_public_pair_sec, address_b58, c_address_b58): secret_exponent = int(exp_hex, 16) sec = h2b(public_pair_sec) c_sec = h2b(c_public_pair_sec) self.assertEqual( secret_exponent_to_wif(secret_exponent, compressed=False), wif) self.assertEqual( secret_exponent_to_wif(secret_exponent, compressed=True), c_wif) key = BitcoinMainnet.ui.parse(wif) exponent = key.secret_exponent() compressed = not key._use_uncompressed() self.assertEqual(exponent, secret_exponent) self.assertFalse(compressed) key = BitcoinMainnet.ui.parse(c_wif) exponent = key.secret_exponent() compressed = not key._use_uncompressed() self.assertEqual(exponent, secret_exponent) self.assertTrue(compressed) public_pair = secret_exponent * secp256k1_generator pk_public_pair = sec_to_public_pair(sec, secp256k1_generator) compressed = is_sec_compressed(sec) self.assertEqual(pk_public_pair, public_pair) self.assertFalse(is_sec_compressed(sec)) self.assertEqual( public_pair_to_sec(pk_public_pair, compressed=False), sec) pk_public_pair = sec_to_public_pair(c_sec, secp256k1_generator) compressed = is_sec_compressed(c_sec) self.assertEqual(pk_public_pair, public_pair) self.assertTrue(compressed) self.assertEqual( public_pair_to_sec(pk_public_pair, compressed=True), c_sec) bca = public_pair_to_bitcoin_address(pk_public_pair, compressed=True) self.assertEqual(bca, c_address_b58) self.assertEqual( bitcoin_address_to_hash160_sec(c_address_b58), public_pair_to_hash160_sec(pk_public_pair, compressed=True)) bca = public_pair_to_bitcoin_address(pk_public_pair, compressed=False) self.assertEqual(bca, address_b58) self.assertEqual( bitcoin_address_to_hash160_sec(address_b58), public_pair_to_hash160_sec(pk_public_pair, compressed=False))
def test_signature_hash(self): compressed = False exponent_2 = int( "137f3276686959c82b454eea6eefc9ab1b9e45bd4636fb9320262e114e321da1", 16) address_2 = public_pair_to_bitcoin_address(exponent_2 * secp256k1_generator, compressed=compressed) key = BitcoinMainnet.ui.parse( "5JMys7YfK72cRVTrbwkq5paxU7vgkMypB55KyXEtN5uSnjV7K8Y") exponent = key.secret_exponent() public_key_sec = public_pair_to_sec(exponent * secp256k1_generator, compressed=compressed) the_coinbase_tx = Tx.coinbase_tx(public_key_sec, int(50 * 1e8), COINBASE_BYTES_FROM_80971) coins_from = [(the_coinbase_tx.hash(), 0, the_coinbase_tx.txs_out[0])] coins_to = [(int(50 * 1e8), address_2)] unsigned_coinbase_spend_tx = standard_tx(coins_from, coins_to) tx_out_script_to_check = the_coinbase_tx.txs_out[0].script idx = 0 solution_checker = BitcoinSolutionChecker(unsigned_coinbase_spend_tx) actual_hash = solution_checker._signature_hash(tx_out_script_to_check, idx, hash_type=SIGHASH_ALL) self.assertEqual( actual_hash, 29819170155392455064899446505816569230970401928540834591675173488544269166940 )
def do_test(exp_hex, wif, c_wif, public_pair_sec, c_public_pair_sec, address_b58, c_address_b58): secret_exponent = int(exp_hex, 16) sec = h2b(public_pair_sec) c_sec = h2b(c_public_pair_sec) self.assertEqual(secret_exponent_to_wif(secret_exponent, compressed=False), wif) self.assertEqual(secret_exponent_to_wif(secret_exponent, compressed=True), c_wif) key = network.parse.wif(wif) exponent = key.secret_exponent() compressed = key.is_compressed() self.assertEqual(exponent, secret_exponent) self.assertFalse(compressed) key = network.parse.wif(c_wif) exponent = key.secret_exponent() compressed = key.is_compressed() self.assertEqual(exponent, secret_exponent) self.assertTrue(compressed) public_pair = secret_exponent * key._generator pk_public_pair = sec_to_public_pair(sec, key._generator) compressed = is_sec_compressed(sec) self.assertEqual(pk_public_pair, public_pair) self.assertFalse(is_sec_compressed(sec)) self.assertEqual(public_pair_to_sec(pk_public_pair, compressed=False), sec) pk_public_pair = sec_to_public_pair(c_sec, key._generator) compressed = is_sec_compressed(c_sec) self.assertEqual(pk_public_pair, public_pair) self.assertTrue(compressed) self.assertEqual(public_pair_to_sec(pk_public_pair, compressed=True), c_sec) bca = public_pair_to_bitcoin_address(pk_public_pair, compressed=True) self.assertEqual(bca, c_address_b58) self.assertEqual(bitcoin_address_to_hash160_sec(c_address_b58), public_pair_to_hash160_sec(pk_public_pair, compressed=True)) bca = public_pair_to_bitcoin_address(pk_public_pair, compressed=False) self.assertEqual(bca, address_b58) self.assertEqual(bitcoin_address_to_hash160_sec(address_b58), public_pair_to_hash160_sec(pk_public_pair, compressed=False))
def sec(self, use_uncompressed=None): """ Return the SEC representation of this key, if available. If use_uncompressed is not set, the preferred representation is returned. """ public_pair = self.public_pair() if public_pair is None: return None return public_pair_to_sec(public_pair, compressed=not self._use_uncompressed(use_uncompressed))
def sec(self, is_compressed=None): """ Return the SEC representation of this key, if available. """ if is_compressed is None: is_compressed = self.is_compressed() public_pair = self.public_pair() if public_pair is None: return None return public_pair_to_sec(public_pair, compressed=is_compressed)
def do_test(as_public_pair, as_sec, is_compressed, as_hash160_sec, as_bitcoin_address): self.assertEqual(sec_to_public_pair(as_sec, secp256k1_generator), as_public_pair) self.assertEqual(public_pair_to_sec(as_public_pair, compressed=is_compressed), as_sec) self.assertEqual(is_sec_compressed(as_sec), is_compressed) self.assertEqual(public_pair_to_hash160_sec(as_public_pair, compressed=is_compressed), as_hash160_sec) self.assertEqual(BitcoinMainnet.ui.address_for_p2pkh(as_hash160_sec), as_bitcoin_address) self.assertTrue(is_address_valid(as_bitcoin_address)) bad_address = as_bitcoin_address[:17] + chr(ord(as_bitcoin_address[17]) + 1) + as_bitcoin_address[18:] self.assertFalse(is_address_valid(bad_address))
def sec(self, use_uncompressed=None): """ Return the SEC representation of this key, if available. If use_uncompressed is not set, the preferred representation is returned. """ public_pair = self.public_pair() if public_pair is None: return None return public_pair_to_sec( public_pair, compressed=not self._use_uncompressed(use_uncompressed))
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 f(solved_values, **kwargs): the_hash = m["the_hash"] db = kwargs.get("hash160_lookup", {}) result = db.get(the_hash) if result is None: result = kwargs.get("sec_hints", {}).get(the_hash) if result: return {m["1"]: result} if result is None: raise SolvingError("can't find public pair for %s" % b2h(the_hash)) sec = public_pair_to_sec(result[1], compressed=result[2]) return {m["1"]: sec}
def f(solved_values, **kwargs): the_hash = m["the_hash"] db = kwargs.get("hash160_lookup", {}) result = db.get(the_hash) if result is None: result = kwargs.get("sec_hints", {}).get(the_hash) if result: return {m["1"]: result} if result is None: raise SolvingError("can't find public pair for %s" % b2h(the_hash)) sec = public_pair_to_sec(result[1], compressed=result[2]) return {m["1"]: sec}
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_build_spends(self): # first, here is the tx database TX_DB = {} # create a coinbase Tx where we know the public & private key key = network.ui.parse("5JMys7YfK72cRVTrbwkq5paxU7vgkMypB55KyXEtN5uSnjV7K8Y") exponent = key.secret_exponent() compressed = False public_key_sec = public_pair_to_sec(exponent * secp256k1_generator, compressed=compressed) the_coinbase_tx = Tx.coinbase_tx(public_key_sec, int(50 * 1e8), COINBASE_BYTES_FROM_80971) TX_DB[the_coinbase_tx.hash()] = the_coinbase_tx # now create a Tx that spends the coinbase compressed = False exponent_2 = int("137f3276686959c82b454eea6eefc9ab1b9e45bd4636fb9320262e114e321da1", 16) address_2 = public_pair_to_bitcoin_address(exponent_2 * secp256k1_generator, compressed=compressed) self.assertEqual("12WivmEn8AUth6x6U8HuJuXHaJzDw3gHNZ", address_2) coins_from = [(the_coinbase_tx.hash(), 0, the_coinbase_tx.txs_out[0])] coins_to = [(int(50 * 1e8), address_2)] unsigned_coinbase_spend_tx = standard_tx(coins_from, coins_to) solver = build_hash160_lookup([exponent], [secp256k1_generator]) coinbase_spend_tx = unsigned_coinbase_spend_tx.sign(solver) TX_DB[coinbase_spend_tx.hash()] = coinbase_spend_tx # now try to respend from priv_key_2 to priv_key_3 compressed = True exponent_3 = int("f8d39b8ecd0e1b6fee5a340519f239097569d7a403a50bb14fb2f04eff8db0ff", 16) address_3 = public_pair_to_bitcoin_address(exponent_3 * secp256k1_generator, compressed=compressed) self.assertEqual("13zzEHPCH2WUZJzANymow3ZrxcZ8iFBrY5", address_3) coins_from = [(coinbase_spend_tx.hash(), 0, coinbase_spend_tx.txs_out[0])] unsigned_spend_tx = standard_tx(coins_from, [(int(50 * 1e8), address_3)]) solver.update(build_hash160_lookup([exponent_2], [secp256k1_generator])) spend_tx = unsigned_spend_tx.sign(solver) # now check that it validates self.assertEqual(spend_tx.bad_solution_count(), 0)
def do_test(as_public_pair, as_sec, is_compressed, as_hash160_sec, as_bitcoin_address): self.assertEqual(sec_to_public_pair(as_sec, secp256k1_generator), as_public_pair) self.assertEqual( public_pair_to_sec(as_public_pair, compressed=is_compressed), as_sec) self.assertEqual(is_sec_compressed(as_sec), is_compressed) self.assertEqual( public_pair_to_hash160_sec(as_public_pair, compressed=is_compressed), as_hash160_sec) self.assertEqual(network.address.for_p2pkh(as_hash160_sec), as_bitcoin_address) self.assertIsNotNone(network.parse.address(as_bitcoin_address)) bad_address = as_bitcoin_address[:17] + chr( ord(as_bitcoin_address[17]) + 1) + as_bitcoin_address[18:] self.assertIsNone(network.parse.address(bad_address))
def do_test(as_public_pair, as_sec, is_compressed, as_hash160_sec, as_bitcoin_address): self.assertEqual(sec_to_public_pair(as_sec, secp256k1_generator), as_public_pair) self.assertEqual( public_pair_to_sec(as_public_pair, compressed=is_compressed), as_sec) self.assertEqual(is_sec_compressed(as_sec), is_compressed) self.assertEqual( public_pair_to_hash160_sec(as_public_pair, compressed=is_compressed), as_hash160_sec) self.assertEqual( BitcoinMainnet.ui.address_for_p2pkh(as_hash160_sec), as_bitcoin_address) self.assertTrue(is_address_valid(as_bitcoin_address)) bad_address = as_bitcoin_address[:17] + chr( ord(as_bitcoin_address[17]) + 1) + as_bitcoin_address[18:] self.assertFalse(is_address_valid(bad_address))
def coinbase_tx(secret_exponent): public_pair = ecdsa.public_pair_for_secret_exponent( ecdsa.secp256k1.generator_secp256k1, secret_exponent) public_key_sec = public_pair_to_sec(public_pair) return Tx.coinbase_tx(public_key_sec, 2500000000)
from sys import stdin from pycoin.ecdsa import secp256r1 as p256 from pycoin.encoding import sec, hexbytes from pycoin.satoshi import der from secrets import randbelow from hashlib import sha256 generator = p256.secp256r1_generator privKey = randbelow(generator.order()) pubKey = generator * privKey sec_pub = sec.public_pair_to_sec(pubKey, compressed=False) print("pub: ", hexbytes.b2h(sec_pub)) # message = stdin.read() # message = "Hello, world!" message = "{{\n \"email\": \"[email protected]\",\n \"pubkey\": \"{}\",\n \"scheme\": \"secp256r1\",\n \"nonce\": \"d425dadb98c32e0d23ee3664d4aad64b57debbc062653102b59bd74ce4f64ad7\"\n}}".format( hexbytes.b2h(sec_pub)) digest = sha256(message.encode("utf-8")).digest() msg_hash = int.from_bytes(digest, byteorder="big") signature = generator.sign(privKey, msg_hash) print("message: ", message) # print("priv: ", privKey) der = der.sigencode_der(signature[0], signature[1]) # print("r:", signature[0]) # print("s:", signature[1]) print("sig: ", hexbytes.b2h(der)) valid = generator.verify(pubKey, msg_hash, signature) print("valid: ", valid)