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, 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 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 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 build_hash160_lookup(secret_exponents, generators): d = {} for secret_exponent in secret_exponents: for generator in generators: public_pair = secret_exponent * generator for compressed in (True, False): hash160 = public_pair_to_hash160_sec(public_pair, compressed=compressed) d[hash160] = (secret_exponent, public_pair, compressed, generator) return d
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 msg_verify(args, parser): network = network_for_netcode(args.network) message_signer = network.msg message_hash = get_message_hash(args, message_signer) try: pair, is_compressed = message_signer.pair_for_message_hash(args.signature, msg_hash=message_hash) except EncodingError: pass ta = network.address.for_p2pkh(public_pair_to_hash160_sec(pair, compressed=is_compressed)) if args.address: if ta == args.address: print("signature ok") return 0 else: print("bad signature, matches %s" % ta) return 1 else: print(ta)
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 msg_verify(args, parser): network = network_for_netcode(args.network) message_signer = network.msg message_hash = get_message_hash(args, message_signer) try: pair, is_compressed = message_signer.pair_for_message_hash( args.signature, msg_hash=message_hash) except EncodingError: pass ta = network.address.for_p2pkh( public_pair_to_hash160_sec(pair, compressed=is_compressed)) if args.address: if ta == args.address: print("signature ok") return 0 else: print("bad signature, matches %s" % ta) return 1 else: print(ta)
def annotate_signature(self, blob, da, vmc): lst = da[blob] try: sig_pair, sig_type = parse_signature_blob(blob) except ValueError: return lst.append("r: {0:#066x}".format(sig_pair[0])) lst.append("s: {0:#066x}".format(sig_pair[1])) sig_hash = vmc.signature_for_hash_type_f(sig_type, [blob], vmc) lst.append("z: {0:#066x}".format(sig_hash)) lst.append("signature type %s" % self.sighash_type_to_string(sig_type)) addresses = [] generator = vmc.generator_for_signature_type(sig_type) pairs = generator.possible_public_pairs_for_signature(sig_hash, sig_pair) for pair in pairs: for comp in (True, False): hash160 = public_pair_to_hash160_sec(pair, compressed=comp) address = self._address.for_p2pkh(hash160) addresses.append(address) lst.append(" sig for %s" % " ".join(addresses))
def public_pair_to_bitcoin_address(pair, compressed): return BitcoinMainnet.ui.address_for_p2pkh( public_pair_to_hash160_sec(pair, compressed=compressed))
def public_pair_to_bitcoin_address(pair, compressed): return BitcoinMainnet.ui.address_for_p2pkh(public_pair_to_hash160_sec(pair, compressed=compressed))