def do_test(as_public_pair, as_sec, is_compressed, as_hash160_sec, as_bitcoin_address): self.assertEqual(encoding.sec_to_public_pair(as_sec), as_public_pair) self.assertEqual(encoding.public_pair_to_sec(as_public_pair, compressed=is_compressed), as_sec) self.assertEqual(encoding.is_sec_compressed(as_sec), is_compressed) self.assertEqual(encoding.public_pair_to_hash160_sec(as_public_pair, compressed=is_compressed), as_hash160_sec) self.assertEqual(encoding.hash160_sec_to_bitcoin_address(as_hash160_sec), as_bitcoin_address) self.assertEqual(encoding.public_pair_to_bitcoin_address(as_public_pair, compressed=is_compressed), as_bitcoin_address) self.assertTrue(encoding.is_valid_bitcoin_address(as_bitcoin_address)) bad_address = as_bitcoin_address[:17] + chr(ord(as_bitcoin_address[17]) + 1) + as_bitcoin_address[18:] self.assertFalse(encoding.is_valid_bitcoin_address(bad_address))
def calculate(self): all_tasks = pstasks.mac_tasks(self._config).allprocs() bit_tasks = [] try: if self._config.PID: # find tasks given PIDs pidlist = [int(p) for p in self._config.PID.split(',')] bit_tasks = [t for t in all_tasks if t.p_pid in pidlist] else: # find multibit process name_re = re.compile("JavaApplicationS", re.I) bit_tasks = [ t for t in all_tasks if name_re.search(str(t.p_comm)) ] except: pass if len(bit_tasks) == 0: yield (None, None) # scan for bitcoin addresses with yara, 34 chars, https://en.bitcoin.it/wiki/Address # Most Bitcoin addresses are 34 characters. They consist of random digits and uppercase # and lowercase letters, with the exception that the uppercase letter "O", uppercase # letter "I", lowercase letter "l", and the number "0" are never used to prevent visual ambiguity. bit_addrs = [] addr_rule = yara.compile(sources={ 'n': 'rule r1 {strings: $a = /[1-9a-zA-z]{34}(?!OIl)/ condition: $a}' }) for task in bit_tasks: scanner = mac_yarascan.MapYaraScanner(task=task, rules=addr_rule) for hit, address in scanner.scan(): content = scanner.address_space.zread(address, 34) if pyenc.is_valid_bitcoin_address( content) and content not in bit_addrs: bit_addrs.append(content) # scan for bitcoin keys with yara, 52 char compressed base58, starts with L or K, https://en.bitcoin.it/wiki/Private_key addr_key = {} key_rule = yara.compile(sources={ 'n': 'rule r1 {strings: $a = /(L|K)[0-9A-Za-z]{51}/ condition: $a}' }) for task in bit_tasks: scanner = mac_yarascan.MapYaraScanner(task=task, rules=key_rule) for hit, address in scanner.scan(): content = scanner.address_space.zread(address, 52) if pyenc.is_valid_wif(content): secret_exp = pyenc.wif_to_secret_exponent(content) key = pykey.Key(secret_exponent=secret_exp, is_compressed=True) if key.address() not in addr_key.keys(): addr_key[key.address()] = content yield (content, key.address()) # addresses with no known keys for bit_addr in bit_addrs: if bit_addr not in addr_key.keys(): yield ("UNKNOWN", bit_addr)
def dumpprivkey(self, address, return_sec_exp=False): if is_valid_bitcoin_address(address)==False: return Exception("Invalid address %s" % address) try: secret_exponent = self.getsecretexponent(address) wif = secret_exponent_to_wif(secret_exponent) except: raise Exception("Unknown address: %s" % address) return wif
def getsecretexponent(self, address): if is_valid_bitcoin_address(address)==False: raise Exception("Invalid address: %s" % address) address, encrypted_secret_exponent, rounds, salt = self.db.getaddress(address) if encrypted_secret_exponent is not None: return self.decryptsecretexponent(encrypted_secret_exponent, rounds, salt) raise Exception("Unknown address: %s" % address)
def dumpprivkey(self, address, return_sec_exp=False): if is_valid_bitcoin_address(address) == False: return Exception("Invalid address %s" % address) try: secret_exponent = self.getsecretexponent(address) wif = secret_exponent_to_wif(secret_exponent) except: raise Exception("Unknown address: %s" % address) return wif
def processQRCode(code): print "The QR Code says " + code if is_valid_bitcoin_address(code): print "this is a bitcoin address" giveBTC(code) elif is_valid_wif(code): print "this is a private key" takeBTC(code) else: print "this is not a bitcoin address or private key"
def validateaddress(self, address): infos = {"isvalid": is_valid_bitcoin_address(address)} if infos["isvalid"]: infos["address"] = address infos["ismine"] = False address, encrypted_secret_exponent, rounds, salt = self.db.getaddress( address) if address is not None: infos["ismine"] = True return infos
def validateaddress(self, address): infos = { "isvalid": is_valid_bitcoin_address(address) } if infos["isvalid"]: infos["address"] = address infos["ismine"] = False address, encrypted_secret_exponent, rounds, salt = self.db.getaddress(address) if address is not None: infos["ismine"] = True return infos;
def dumppubkey(self, address): if is_valid_bitcoin_address(address)==False: return Exception("Invalid address %s" % address) try: secret_exponent = self.getsecretexponent(address) public_pair = ecdsa.public_pair_for_secret_exponent(ecdsa.generator_secp256k1, secret_exponent) pubkey = public_pair_to_sec(public_pair, compressed=True) pubkey = b2h(pubkey) except: raise Exception("Unknown address: %s" % address) return pubkey
def getsecretexponent(self, address): if is_valid_bitcoin_address(address) == False: raise Exception("Invalid address: %s" % address) address, encrypted_secret_exponent, rounds, salt = self.db.getaddress( address) if encrypted_secret_exponent is not None: return self.decryptsecretexponent(encrypted_secret_exponent, rounds, salt) raise Exception("Unknown address: %s" % address)
def dumppubkey(self, address): if is_valid_bitcoin_address(address) == False: return Exception("Invalid address %s" % address) try: secret_exponent = self.getsecretexponent(address) public_pair = ecdsa.public_pair_for_secret_exponent( ecdsa.generator_secp256k1, secret_exponent) pubkey = public_pair_to_sec(public_pair, compressed=True) pubkey = b2h(pubkey) except: raise Exception("Unknown address: %s" % address) return pubkey
def calculate(self): all_tasks = pstasks.mac_tasks(self._config).allprocs() bit_tasks = [] try: if self._config.PID: # find tasks given PIDs pidlist = [int(p) for p in self._config.PID.split(',')] bit_tasks = [t for t in all_tasks if t.p_pid in pidlist] else: # find multibit process name_re = re.compile("JavaApplicationS", re.I) bit_tasks = [t for t in all_tasks if name_re.search(str(t.p_comm))] except: pass if len(bit_tasks) == 0: yield (None, None) # scan for bitcoin addresses with yara, 34 chars, https://en.bitcoin.it/wiki/Address # Most Bitcoin addresses are 34 characters. They consist of random digits and uppercase # and lowercase letters, with the exception that the uppercase letter "O", uppercase # letter "I", lowercase letter "l", and the number "0" are never used to prevent visual ambiguity. bit_addrs = [] addr_rule = yara.compile(sources = {'n' : 'rule r1 {strings: $a = /[1-9a-zA-z]{34}(?!OIl)/ condition: $a}'}) for task in bit_tasks: scanner = mac_yarascan.MapYaraScanner(task = task, rules = addr_rule) for hit, address in scanner.scan(): content = scanner.address_space.zread(address, 34) if pyenc.is_valid_bitcoin_address(content) and content not in bit_addrs: bit_addrs.append(content) # scan for bitcoin keys with yara, 52 char compressed base58, starts with L or K, https://en.bitcoin.it/wiki/Private_key addr_key = {} key_rule = yara.compile(sources = {'n' : 'rule r1 {strings: $a = /(L|K)[0-9A-Za-z]{51}/ condition: $a}'}) for task in bit_tasks: scanner = mac_yarascan.MapYaraScanner(task = task, rules = key_rule) for hit, address in scanner.scan(): content = scanner.address_space.zread(address, 52) if pyenc.is_valid_wif(content): secret_exp = pyenc.wif_to_secret_exponent(content) key = pykey.Key(secret_exponent = secret_exp,is_compressed=True) if key.address() not in addr_key.keys(): addr_key[key.address()] = content yield(content, key.address()) # addresses with no known keys for bit_addr in bit_addrs: if bit_addr not in addr_key.keys(): yield ("UNKNOWN", bit_addr)
def processQRCode(code): print "The QR Code says " + code if is_valid_bitcoin_address(code): print "this is a bitcoin address" giveBTC(code) print "main thread: telling camera to start" to_cam.put('start') # reset for the next person elif is_valid_wif(code): print "this is a private key" takeBTC(code) print "main thread: telling camera to start" to_cam.put('start') # reset for the next person else: print "this is not a bitcoin address or private key"
print("Public key hex: ", my_key.sec_as_hex()) print(" uncompressed: ", my_key.sec_as_hex(use_uncompressed=True)) assert(my_key.sec_as_hex() == bitcoin.core.b2x(my_key.sec())) print("Public key hash160: ", b2h(my_key.hash160())) print(" uncompressed: ", b2h(my_key.hash160(use_uncompressed=True))) #print("Bitcoin Address : ", my_key.address()) addr_compressed = encoding.public_pair_to_bitcoin_address(public_key, True, my_addr_prefix) addr_uncompressed = encoding.public_pair_to_bitcoin_address(public_key, False, my_addr_prefix) print("Bitcoin Address: ", addr_compressed) print(" uncompressed: ", addr_uncompressed) assert(encoding.is_valid_bitcoin_address(addr_compressed, my_addr_prefix)) assert(encoding.is_valid_bitcoin_address(addr_uncompressed, my_addr_prefix)) assert(my_key.address() == addr_compressed) pubkey_bytes = encoding.public_pair_to_sec(public_key, True); assert(my_key.sec_as_hex() == b2h(pubkey_bytes)) pubkey_bytes = encoding.public_pair_to_sec(public_key, False); assert(my_key.sec_as_hex(use_uncompressed=True) == b2h(pubkey_bytes)) print() #CBitcoinAddress.from_bytes(bitcoin.core.serialize.Hash160(my_key.address()), 111) btc_addr = CBitcoinAddress.from_bytes(bitcoin.base58.decode(my_key.address()), bitcoin.params.BASE58_PREFIXES['PUBKEY_ADDR']) print("Bitcoin Address hex: ", hexlify(btc_addr.to_bytes())) assert(bitcoin.base58.encode(btc_addr.to_bytes()) == addr_compressed) pubkey_b58 = encoding.b2a_base58(pubkey_bytes)
def main(): parser = argparse.ArgumentParser( description="Manipulate bitcoin (or alt coin) transactions.", epilog=EPILOG) parser.add_argument('-t', "--transaction-version", type=int, help='Transaction version, either 1 (default) or 3 (not yet supported).') parser.add_argument('-l', "--lock-time", type=parse_locktime, help='Lock time; either a block' 'index, or a date/time (example: "2014-01-01T15:00:00"') parser.add_argument('-n', "--network", default="BTC", help='Define network code (M=Bitcoin mainnet, T=Bitcoin testnet).') parser.add_argument('-a', "--augment", action='store_true', help='augment tx by adding any missing spendable metadata by fetching' ' inputs from cache and/or web services') parser.add_argument("-i", "--fetch-spendables", metavar="address", action="append", help='Add all unspent spendables for the given bitcoin address. This information' ' is fetched from web services.') parser.add_argument('-f', "--private-key-file", metavar="path-to-private-keys", action="append", help='file containing WIF or BIP0032 private keys. If file name ends with .gpg, ' '"gpg -d" will be invoked automatically. File is read one line at a time, and if ' 'the file contains only one WIF per line, it will also be scanned for a bitcoin ' 'address, and any addresses found will be assumed to be public keys for the given' ' private key.', type=argparse.FileType('r')) parser.add_argument('-g', "--gpg-argument", help='argument to pass to gpg (besides -d).', default='') parser.add_argument("--remove-tx-in", metavar="tx_in_index_to_delete", action="append", type=int, help='remove a tx_in') parser.add_argument("--remove-tx-out", metavar="tx_out_index_to_delete", action="append", type=int, help='remove a tx_out') parser.add_argument('-F', "--fee", help='fee, in satoshis, to pay on transaction, or ' '"standard" to auto-calculate. This is only useful if the "split pool" ' 'is used; otherwise, the fee is automatically set to the unclaimed funds.', default="standard", metavar="transaction-fee", type=parse_fee) parser.add_argument('-C', "--cache", help='force the resultant transaction into the transaction cache.' ' Mostly for testing.', action='store_true'), parser.add_argument('-u', "--show-unspents", action='store_true', help='show TxOut items for this transaction in Spendable form.') parser.add_argument('-b', "--bitcoind-url", help='URL to bitcoind instance to validate against (http://user:pass@host:port).') parser.add_argument('-o', "--output-file", metavar="path-to-output-file", type=argparse.FileType('wb'), help='file to write transaction to. This supresses most other output.') parser.add_argument("argument", nargs="+", help='generic argument: can be a hex transaction id ' '(exactly 64 characters) to be fetched from cache or a web service;' ' a transaction as a hex string; a path name to a transaction to be loaded;' ' a spendable 4-tuple of the form tx_id/tx_out_idx/script_hex/satoshi_count ' 'to be added to TxIn list; an address/satoshi_count to be added to the TxOut ' 'list; an address to be added to the TxOut list and placed in the "split' ' pool".') args = parser.parse_args() # defaults txs = [] spendables = [] payables = [] key_iters = [] TX_ID_RE = re.compile(r"^[0-9a-fA-F]{64}$") # there are a few warnings we might optionally print out, but only if # they are relevant. We don't want to print them out multiple times, so we # collect them here and print them at the end if they ever kick in. warning_tx_cache = None warning_get_tx = None warning_spendables = None if args.private_key_file: wif_re = re.compile(r"[1-9a-km-zA-LMNP-Z]{51,111}") # address_re = re.compile(r"[1-9a-kmnp-zA-KMNP-Z]{27-31}") for f in args.private_key_file: if f.name.endswith(".gpg"): gpg_args = ["gpg", "-d"] if args.gpg_argument: gpg_args.extend(args.gpg_argument.split()) gpg_args.append(f.name) popen = subprocess.Popen(gpg_args, stdout=subprocess.PIPE) f = popen.stdout for line in f.readlines(): # decode if isinstance(line, bytes): line = line.decode("utf8") # look for WIFs possible_keys = wif_re.findall(line) def make_key(x): try: return Key.from_text(x) except Exception: return None keys = [make_key(x) for x in possible_keys] for key in keys: if key: key_iters.append((k.wif() for k in key.subkeys(""))) # if len(keys) == 1 and key.hierarchical_wallet() is None: # # we have exactly 1 WIF. Let's look for an address # potential_addresses = address_re.findall(line) # we create the tx_db lazily tx_db = None for arg in args.argument: # hex transaction id if TX_ID_RE.match(arg): if tx_db is None: warning_tx_cache = message_about_tx_cache_env() warning_get_tx = message_about_get_tx_env() tx_db = get_tx_db() tx = tx_db.get(h2b_rev(arg)) if not tx: for m in [warning_tx_cache, warning_get_tx, warning_spendables]: if m: print("warning: %s" % m, file=sys.stderr) parser.error("can't find Tx with id %s" % arg) txs.append(tx) continue # hex transaction data try: tx = Tx.tx_from_hex(arg) txs.append(tx) continue except Exception: pass try: key = Key.from_text(arg) # TODO: check network if key.wif() is None: payables.append((key.address(), 0)) continue # TODO: support paths to subkeys key_iters.append((k.wif() for k in key.subkeys(""))) continue except Exception: pass if os.path.exists(arg): try: with open(arg, "rb") as f: if f.name.endswith("hex"): f = io.BytesIO(codecs.getreader("hex_codec")(f).read()) tx = Tx.parse(f) txs.append(tx) try: tx.parse_unspents(f) except Exception as ex: pass continue except Exception: pass parts = arg.split("/") if len(parts) == 4: # spendable try: spendables.append(Spendable.from_text(arg)) continue except Exception: pass # TODO: fix allowable_prefixes allowable_prefixes = b'\0' if len(parts) == 2 and encoding.is_valid_bitcoin_address( parts[0], allowable_prefixes=allowable_prefixes): try: payables.append(parts) continue except ValueError: pass parser.error("can't parse %s" % arg) if args.fetch_spendables: warning_spendables = message_about_spendables_for_address_env() for address in args.fetch_spendables: spendables.extend(spendables_for_address(address)) for tx in txs: if tx.missing_unspents() and args.augment: if tx_db is None: warning_tx_cache = message_about_tx_cache_env() warning_get_tx = message_about_get_tx_env() tx_db = get_tx_db() tx.unspents_from_db(tx_db, ignore_missing=True) txs_in = [] txs_out = [] unspents = [] # we use a clever trick here to keep each tx_in corresponding with its tx_out for tx in txs: smaller = min(len(tx.txs_in), len(tx.txs_out)) txs_in.extend(tx.txs_in[:smaller]) txs_out.extend(tx.txs_out[:smaller]) unspents.extend(tx.unspents[:smaller]) for tx in txs: smaller = min(len(tx.txs_in), len(tx.txs_out)) txs_in.extend(tx.txs_in[smaller:]) txs_out.extend(tx.txs_out[smaller:]) unspents.extend(tx.unspents[smaller:]) for spendable in spendables: txs_in.append(spendable.tx_in()) unspents.append(spendable) for address, coin_value in payables: script = standard_tx_out_script(address) txs_out.append(TxOut(coin_value, script)) lock_time = args.lock_time version = args.transaction_version # if no lock_time is explicitly set, inherit from the first tx or use default if lock_time is None: if txs: lock_time = txs[0].lock_time else: lock_time = DEFAULT_LOCK_TIME # if no version is explicitly set, inherit from the first tx or use default if version is None: if txs: version = txs[0].version else: version = DEFAULT_VERSION if args.remove_tx_in: s = set(args.remove_tx_in) txs_in = [tx_in for idx, tx_in in enumerate(txs_in) if idx not in s] if args.remove_tx_out: s = set(args.remove_tx_out) txs_out = [tx_out for idx, tx_out in enumerate(txs_out) if idx not in s] tx = Tx(txs_in=txs_in, txs_out=txs_out, lock_time=lock_time, version=version, unspents=unspents) fee = args.fee try: distribute_from_split_pool(tx, fee) except ValueError as ex: print("warning: %s" % ex.args[0], file=sys.stderr) unsigned_before = tx.bad_signature_count() if unsigned_before > 0 and key_iters: def wif_iter(iters): while len(iters) > 0: for idx, iter in enumerate(iters): try: wif = next(iter) yield wif except StopIteration: iters = iters[:idx] + iters[idx+1:] break print("signing...", file=sys.stderr) sign_tx(tx, wif_iter(key_iters)) unsigned_after = tx.bad_signature_count() if unsigned_after > 0 and key_iters: print("warning: %d TxIn items still unsigned" % unsigned_after, file=sys.stderr) if len(tx.txs_in) == 0: print("warning: transaction has no inputs", file=sys.stderr) if len(tx.txs_out) == 0: print("warning: transaction has no outputs", file=sys.stderr) include_unspents = (unsigned_after > 0) tx_as_hex = tx.as_hex(include_unspents=include_unspents) if args.output_file: f = args.output_file if f.name.endswith(".hex"): f.write(tx_as_hex.encode("utf8")) else: tx.stream(f) if include_unspents: tx.stream_unspents(f) f.close() elif args.show_unspents: for spendable in tx.tx_outs_as_spendable(): print(spendable.as_text()) else: if not tx.missing_unspents(): check_fees(tx) dump_tx(tx, args.network) if include_unspents: print("including unspents in hex dump since transaction not fully signed") print(tx_as_hex) if args.cache: if tx_db is None: warning_tx_cache = message_about_tx_cache_env() warning_get_tx = message_about_get_tx_env() tx_db = get_tx_db() tx_db.put(tx) if args.bitcoind_url: if tx_db is None: warning_tx_cache = message_about_tx_cache_env() warning_get_tx = message_about_get_tx_env() tx_db = get_tx_db() validate_bitcoind(tx, tx_db, args.bitcoind_url) if tx.missing_unspents(): print("\n** can't validate transaction as source transactions missing", file=sys.stderr) else: try: if tx_db is None: warning_tx_cache = message_about_tx_cache_env() warning_get_tx = message_about_get_tx_env() tx_db = get_tx_db() tx.validate_unspents(tx_db) print('all incoming transaction values validated') except BadSpendableError as ex: print("\n**** ERROR: FEES INCORRECTLY STATED: %s" % ex.args[0], file=sys.stderr) except Exception as ex: print("\n*** can't validate source transactions as untampered: %s" % ex.args[0], file=sys.stderr) # print warnings for m in [warning_tx_cache, warning_get_tx, warning_spendables]: if m: print("warning: %s" % m, file=sys.stderr)
def is_pubkey_valid(pubkey): try: return encoding.is_valid_bitcoin_address(pubtoaddr(pubkey)) except: return False
# convert public key pair to public key to address pubkey_hashed = encoding.public_pair_to_hash160_sec(pubkey_pair, True) print("Public key hash160: ", bitcoin.core.b2x(pubkey_hashed)) pubkey_addr = encoding.hash160_sec_to_bitcoin_address( pubkey_hashed, address_prefix=my_pubaddr_prefix) assert (addr_compressed == pubkey_addr) pubkey_hashed = encoding.public_pair_to_hash160_sec(pubkey_pair, False) print(" uncompressed: ", bitcoin.core.b2x(pubkey_hashed)) pubkey_addr = encoding.hash160_sec_to_bitcoin_address( pubkey_hashed, address_prefix=my_pubaddr_prefix) assert (addr_uncompressed == pubkey_addr) print("Bitcoin Address: ", addr_compressed) print(" uncompressed: ", addr_uncompressed) assert (encoding.is_valid_bitcoin_address( addr_compressed, allowable_prefixes=my_pubaddr_prefix)) assert (encoding.is_valid_bitcoin_address( addr_uncompressed, allowable_prefixes=my_pubaddr_prefix)) print() ## Uncompressed public key pubkey_bytes = encoding.public_pair_to_sec(pubkey_pair, False) # uncompressed pubkey_b58 = encoding.b2a_base58(pubkey_bytes) assert (pubkey_bytes == encoding.a2b_base58(pubkey_b58)) btc_addr = CBitcoinAddress.from_bytes( pubkey_bytes, bitcoin.params.BASE58_PREFIXES['PUBKEY_ADDR']) assert (b2h(cec_key.get_pubkey()) == b2h(btc_addr.to_bytes())) assert (hexlify(cec_key.get_pubkey()) == hexlify(pubkey_bytes))