def item_callback(type, d): if type == "tx": wallet_transactions.append( d ) elif print_wallet: if type == "name": print("ADDRESS "+d['hash']+" : "+d['name']) elif type == "version": print("Version: %d"%(d['version'],)) elif type == "setting": print(d['setting']+": "+str(d['value'])) elif type == "key": print("PubKey "+ short_hex(d['public_key']) + " " + public_key_to_bc_address(d['public_key']) + ": PriKey "+ short_hex(d['private_key'])) elif type == "wkey": print("WPubKey 0x"+ short_hex(d['public_key']) + " " + public_key_to_bc_address(d['public_key']) + ": WPriKey 0x"+ short_hex(d['private_key'])) print(" Created: "+time.ctime(d['created'])+" Expires: "+time.ctime(d['expires'])+" Comment: "+d['comment']) elif type == "defaultkey": print("Default Key: 0x"+ short_hex(d['key']) + " " + public_key_to_bc_address(d['key'])) elif type == "pool": print("Change Pool key %d: %s (Time: %s)"% (d['n'], public_key_to_bc_address(d['public_key']), time.ctime(d['nTime']))) elif type == "acc": print("Account %s (current key: %s)"%(d['account'], public_key_to_bc_address(d['public_key']))) elif type == "acentry": print("Move '%s' %d (other: '%s', time: %s, entry %d) %s"% (d['account'], d['nCreditDebit'], d['otherAccount'], time.ctime(d['nTime']), d['n'], d['comment'])) else: print "Unknown key type: "+type
def extract_public_key(bytes, version='\x00'): try: decoded = [ x for x in script_GetOp(bytes) ] except struct.error: return "(None)" match = [ opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4 ] if match_decoded(decoded, match): return public_key_to_bc_address(decoded[1][1], version=version) match = [ opcodes.OP_PUSHDATA4, opcodes.OP_CHECKSIG ] if match_decoded(decoded, match): return public_key_to_bc_address(decoded[0][1], version=version) match = [ opcodes.OP_DUP, opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUALVERIFY, opcodes.OP_CHECKSIG ] if match_decoded(decoded, match): return hash_160_to_bc_address(decoded[2][1], version=version) multisigs = [ [ opcodes.OP_1, opcodes.OP_PUSHDATA4, opcodes.OP_1, opcodes.OP_CHECKMULTISIG ], [ opcodes.OP_2, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_2, opcodes.OP_CHECKMULTISIG ], [ opcodes.OP_3, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_3, opcodes.OP_CHECKMULTISIG ] ] for match in multisigs: if match_decoded(decoded, match): return "["+','.join([public_key_to_bc_address(decoded[i][1]) for i in range(1,len(decoded)-1)])+"]" match = [ opcodes.OP_HASH160, 0x14, opcodes.OP_EQUAL ] if match_decoded(decoded, match): return hash_160_to_bc_address(decoded[1][1], version="\x05") return "(None)"
def extract_public_key(bytes): decoded = [x for x in script_GetOp(bytes)] # non-generated TxIn transactions push a signature # (seventy-something bytes) and then their public key # (65 bytes) onto the stack: match = [opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4] if match_decoded(decoded, match): return public_key_to_bc_address(decoded[1][1]) # The Genesis Block, self-payments, and pay-by-IP-address payments look like: # 65 BYTES:... CHECKSIG match = [opcodes.OP_PUSHDATA4, opcodes.OP_CHECKSIG] if match_decoded(decoded, match): return public_key_to_bc_address(decoded[0][1]) # Pay-by-Bitcoin-address TxOuts look like: # DUP HASH160 20 BYTES:... EQUALVERIFY CHECKSIG match = [opcodes.OP_DUP, opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUALVERIFY, opcodes.OP_CHECKSIG] if match_decoded(decoded, match): return hash_160_to_bc_address(decoded[2][1]) # OP_EVAL TxOuts look like: # DUP HASH160 20 BYTES:... EQUALVERIFY CHECKSIG match = [opcodes.OP_DUP, opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUALVERIFY, opcodes.OP_EVAL] if match_decoded(decoded, match): return hash_160_to_bc_address(decoded[2][1], version="\x01") return "(None)"
def extract_public_key(bytes): decoded = [x for x in script_GetOp(bytes)] # non-generated TxIn transactions push a signature # (seventy-something bytes) and then their public key # (65 bytes) onto the stack: match = [opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4] if match_decoded(decoded, match): return public_key_to_bc_address(decoded[1][1]) # The Genesis Block, self-payments, and pay-by-IP-address payments look like: # 65 BYTES:... CHECKSIG match = [opcodes.OP_PUSHDATA4, opcodes.OP_CHECKSIG] if match_decoded(decoded, match): return public_key_to_bc_address(decoded[0][1]) # Pay-by-Bitcoin-address TxOuts look like: # DUP HASH160 20 BYTES:... EQUALVERIFY CHECKSIG match = [ opcodes.OP_DUP, opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUALVERIFY, opcodes.OP_CHECKSIG ] if match_decoded(decoded, match): return hash_160_to_bc_address(decoded[2][1]) return "(None)"
def extract_public_key(bytes, version='\x00'): try: decoded = [x for x in script_GetOp(bytes)] except struct.error: return "(None)" # non-generated TxIn transactions push a signature # (seventy-something bytes) and then their public key # (33 or 65 bytes) onto the stack: match = [opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4] if match_decoded(decoded, match): return public_key_to_bc_address(decoded[1][1], version=version) # The Genesis Block, self-payments, and pay-by-IP-address payments look like: # 65 BYTES:... CHECKSIG match = [opcodes.OP_PUSHDATA4, opcodes.OP_CHECKSIG] if match_decoded(decoded, match): return public_key_to_bc_address(decoded[0][1], version=version) # Pay-by-Bitcoin-address TxOuts look like: # DUP HASH160 20 BYTES:... EQUALVERIFY CHECKSIG match = [ opcodes.OP_DUP, opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUALVERIFY, opcodes.OP_CHECKSIG ] if match_decoded(decoded, match): return hash_160_to_bc_address(decoded[2][1], version=version) # BIP11 TxOuts look like one of these: multisigs = [[ opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_1, opcodes.OP_CHECKMULTISIG ], [ opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_2, opcodes.OP_CHECKMULTISIG ], [ opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_3, opcodes.OP_CHECKMULTISIG ]] for match in multisigs: if match_decoded(decoded, match): return "[" + ','.join([ public_key_to_bc_address(decoded[i][1]) for i in range(1, len(decoded) - 1) ]) + "]" # BIP16 TxOuts look like: # HASH160 20 BYTES:... EQUAL match = [opcodes.OP_HASH160, 0x14, opcodes.OP_EQUAL] if match_decoded(decoded, match): return hash_160_to_bc_address(decoded[1][1], version="\x05") return "(None)"
def extract_public_key(bytes, version='\x00'): try: decoded = [ x for x in script_GetOp(bytes) ] except (struct.error, IndexError): return None # non-generated TxIn transactions push a signature # (seventy-something bytes) and then their public key # (33 or 65 bytes) onto the stack: match = [ opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4 ] if match_decoded(decoded, match): if (decoded[0][0]==0 and decoded[1][0] in [20, 32]): #Native Segwit P2PKH or P2SH output #Return the exact bytes return decoded[1][1] return public_key_to_bc_address(decoded[1][1], version=version) # The Genesis Block, self-payments, and pay-by-IP-address payments look like: # 65 BYTES:... CHECKSIG match = [ opcodes.OP_PUSHDATA4, opcodes.OP_CHECKSIG ] if match_decoded(decoded, match): return public_key_to_bc_address(decoded[0][1], version=version) # Pay-by-Bitcoin-address TxOuts look like: # DUP HASH160 20 BYTES:... EQUALVERIFY CHECKSIG match = [ opcodes.OP_DUP, opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUALVERIFY, opcodes.OP_CHECKSIG ] if match_decoded(decoded, match): return hash_160_to_bc_address(decoded[2][1], version=version) # BIP11 TxOuts look like one of these: # Note that match_decoded is dumb, so OP_1 actually matches OP_1/2/3/etc: multisigs = [ [ opcodes.OP_1, opcodes.OP_PUSHDATA4, opcodes.OP_1, opcodes.OP_CHECKMULTISIG ], [ opcodes.OP_2, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_2, opcodes.OP_CHECKMULTISIG ], [ opcodes.OP_3, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_3, opcodes.OP_CHECKMULTISIG ] ] for match in multisigs: if match_decoded(decoded, match): return [public_key_to_bc_address(decoded[i][1], version=version) for i in range(1,len(decoded)-1)] # BIP16 TxOuts look like: # HASH160 20 BYTES:... EQUAL match = [ opcodes.OP_HASH160, 0x14, opcodes.OP_EQUAL ] if match_decoded(decoded, match): script_version = '\x05' if version=='\x00' else '\xC4' return hash_160_to_bc_address(decoded[1][1], version=script_version) return None
def dump_keys(db_env, addressStart, outputFileName): db = DB(db_env) try: r = db.open("wallet.dat", "main", DB_BTREE, DB_THREAD|DB_RDONLY) except DBError: logging.error("Couldn't open addr.dat/main. Try quitting Bitcoin and running this again.") return cString = cStringIO.StringIO() kds = BCDataStream() vds = BCDataStream() for (key, value) in db.items(): kds.clear(); kds.write(key) vds.clear(); vds.write(value) type = kds.read_string() if type == "key": publicKey = kds.read_bytes(kds.read_compact_size()) privateKey = vds.read_bytes(vds.read_compact_size()) address = public_key_to_bc_address(publicKey) if address.startswith(addressStart): privateKey58 = b58encode(privateKey) cString.write('%s\n' % privateKey58) print("\nPubKey hex: "+ long_hex(publicKey) + "\nPubKey base58: "+ b58encode(publicKey) + "\nAddress: " + address + "\nPriKey hex: "+ long_hex(privateKey) + "\nPriKey base58: "+ privateKey58 + "\n") outputText = cString.getvalue() if outputText != '': writeFileText(outputFileName, outputText) db.close()
def verify_message(self, address, signature, message): sig = base64.b64decode(signature) if len(sig) != 65: raise Exception("Wrong encoding") nV = ord(sig[0]) if nV < 27 or nV >= 35: raise Exception("Bad encoding") if nV >= 31: compressed = True nV -= 4 else: compressed = False recid = nV - 27 h = Hash(msg_magic(message)) public_key = MyVerifyingKey.from_signature(sig[1:], recid, h, curve=SECP256k1) # check public key public_key.verify_digest(sig[1:], h, sigdecode=ecdsa.util.sigdecode_string) # check that we get the original signing address addr = public_key_to_bc_address( point_to_ser(public_key.pubkey.point, compressed)) if address != addr: raise Exception("Bad signature")
def extract_public_key(bytes, version='\x00'): try: decoded = [x for x in script_GetOp(bytes)] except struct.error: return "(None)" # non-generated TxIn transactions push a signature # (seventy-something bytes) and then their public key # (33 or 65 bytes) onto the stack: match = [opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4] if match_decoded(decoded, match): return public_key_to_bc_address(decoded[1][1], version=version) # The Genesis Block, self-payments, and pay-by-IP-address payments look like: # 65 BYTES:... CHECKSIG match = [opcodes.OP_PUSHDATA4, opcodes.OP_CHECKSIG] if match_decoded(decoded, match): return public_key_to_bc_address(decoded[0][1], version=version) # Pay-by-Bitcoin-address TxOuts look like: # DUP HASH160 20 BYTES:... EQUALVERIFY CHECKSIG match = [opcodes.OP_DUP, opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUALVERIFY, opcodes.OP_CHECKSIG] if match_decoded(decoded, match): return hash_160_to_bc_address(decoded[2][1], version=version) # BIP11 TxOuts look like one of these: multisigs = [ [opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_1, opcodes.OP_CHECKMULTISIG], [ opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_2, opcodes.OP_CHECKMULTISIG ], [opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_3, opcodes.OP_CHECKMULTISIG] ] for match in multisigs: if match_decoded(decoded, match): return "[" + ','.join([public_key_to_bc_address(decoded[i][1]) for i in range(1, len(decoded) - 1)]) + "]" # BIP16 TxOuts look like: # HASH160 20 BYTES:... EQUAL match = [opcodes.OP_HASH160, 0x14, opcodes.OP_EQUAL] if match_decoded(decoded, match): return hash_160_to_bc_address(decoded[1][1], version="\x05") return "(None)"
def item_callback(type, d): if type == "tx": wallet_transactions.append( d ) transaction_index[d['tx_id']] = d elif type == "key": owner_keys[public_key_to_bc_address(d['public_key'])] = d['private_key'] elif type == "ckey": owner_keys[public_key_to_bc_address(d['public_key'])] = d['crypted_key'] if not print_wallet: return if type == "tx": return elif type == "name": print("ADDRESS "+d['hash']+" : "+d['name']) elif type == "version": print("Version: %d"%(d['version'],)) elif type == "setting": print(d['setting']+": "+str(d['value'])) elif type == "key": print("PubKey "+ short_hex(d['public_key']) + " " + public_key_to_bc_address(d['public_key']) + ": PriKey "+ short_hex(d['private_key'])) elif type == "wkey": print("WPubKey 0x"+ short_hex(d['public_key']) + " " + public_key_to_bc_address(d['public_key']) + ": WPriKey 0x"+ short_hex(d['crypted_key'])) print(" Created: "+time.ctime(d['created'])+" Expires: "+time.ctime(d['expires'])+" Comment: "+d['comment']) elif type == "ckey": print("PubKey "+ short_hex(d['public_key']) + " " + public_key_to_bc_address(d['public_key']) + ": Encrypted PriKey "+ short_hex(d['crypted_key'])) elif type == "mkey": print("Master Key %d"%(d['nID']) + ": 0x"+ short_hex(d['crypted_key']) + ", Salt: 0x"+ short_hex(d['salt']) + ". Passphrase hashed %d times with method %d with other parameters 0x"%(d['nDeriveIterations'], d['nDerivationMethod']) + long_hex(d['vchOtherDerivationParameters'])) elif type == "defaultkey": print("Default Key: 0x"+ short_hex(d['key']) + " " + public_key_to_bc_address(d['key'])) elif type == "pool": print("Change Pool key %d: %s (Time: %s)"% (d['n'], public_key_to_bc_address(d['public_key']), time.ctime(d['nTime']))) elif type == "acc": print("Account %s (current key: %s)"%(d['account'], public_key_to_bc_address(d['public_key']))) elif type == "acentry": print("Move '%s' %d (other: '%s', time: %s, entry %d) %s"% (d['account'], d['nCreditDebit'], d['otherAccount'], time.ctime(d['nTime']), d['n'], d['comment'])) elif type == "bestblock": print deserialize_BlockLocator(d) elif type == "cscript": print("CScript: %s : %s"%(public_key_to_bc_address(d['scriptHash'], "\x01"), long_hex(d['script']))) else: print "Unknown key type: "+type
def item_callback(type, d): if type == "tx": wallet_transactions.append( d ) transaction_index[d['tx_id']] = d elif type == "key": owner_keys[public_key_to_bc_address(d['public_key'])] = d['private_key'] elif type == "ckey": owner_keys[public_key_to_bc_address(d['public_key'])] = d['crypted_key'] if not print_wallet: return if type == "tx": return elif type == "name": print("ADDRESS "+d['hash']+" : "+d['name']) elif type == "version": print("Version: %d"%(d['version'],)) elif type == "setting": print(d['setting']+": "+str(d['value'])) elif type == "key": print("PubKey "+ short_hex(d['public_key']) + " " + public_key_to_bc_address(d['public_key']) + ": PriKey "+ short_hex(d['private_key'])) elif type == "wkey": print("WPubKey 0x"+ short_hex(d['public_key']) + " " + public_key_to_bc_address(d['public_key']) + ": WPriKey 0x"+ short_hex(d['crypted_key'])) print(" Created: "+time.ctime(d['created'])+" Expires: "+time.ctime(d['expires'])+" Comment: "+d['comment']) elif type == "ckey": print("PubKey "+ short_hex(d['public_key']) + " " + public_key_to_bc_address(d['public_key']) + ": Encrypted PriKey "+ long_hex(d['crypted_key'])) # short_hex() elif type == "mkey": print("Master Key %d"%(d['nID']) + ": 0x"+ short_hex(d['crypted_key']) + ", Salt: 0x"+ short_hex(d['salt']) + ". Passphrase hashed %d times with method %d with other parameters 0x"%(d['nDeriveIterations'], d['nDerivationMethod']) + long_hex(d['vchOtherDerivationParameters'])) elif type == "defaultkey": print("Default Key: 0x"+ short_hex(d['key']) + " " + public_key_to_bc_address(d['key'])) elif type == "pool": print("Change Pool key %d: %s (Time: %s)"% (d['n'], public_key_to_bc_address(d['public_key']), time.ctime(d['nTime']))) elif type == "acc": print("Account %s (current key: %s)"%(d['account'], public_key_to_bc_address(d['public_key']))) elif type == "acentry": print("Move '%s' %d (other: '%s', time: %s, entry %d) %s"% (d['account'], d['nCreditDebit'], d['otherAccount'], time.ctime(d['nTime']), d['n'], d['comment'])) elif type == "bestblock": print deserialize_BlockLocator(d) elif type == "cscript": print("CScript: %s : %s"%(public_key_to_bc_address(d['scriptHash'], "\x01"), long_hex(d['script']))) else: print "Unknown key type: "+type
def extract_public_key(bytes, version='\x00'): try: decoded = [x for x in script_GetOp(bytes)] except struct.error: return "(None)" match = [opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4] if match_decoded(decoded, match): return public_key_to_bc_address(decoded[1][1], version=version) match = [opcodes.OP_PUSHDATA4, opcodes.OP_CHECKSIG] if match_decoded(decoded, match): return public_key_to_bc_address(decoded[0][1], version=version) match = [ opcodes.OP_DUP, opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUALVERIFY, opcodes.OP_CHECKSIG ] if match_decoded(decoded, match): return hash_160_to_bc_address(decoded[2][1], version=version) multisigs = [[ opcodes.OP_1, opcodes.OP_PUSHDATA4, opcodes.OP_1, opcodes.OP_CHECKMULTISIG ], [ opcodes.OP_2, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_2, opcodes.OP_CHECKMULTISIG ], [ opcodes.OP_3, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_3, opcodes.OP_CHECKMULTISIG ]] for match in multisigs: if match_decoded(decoded, match): return "[" + ','.join([ public_key_to_bc_address(decoded[i][1]) for i in range(1, len(decoded) - 1) ]) + "]" match = [opcodes.OP_HASH160, 0x14, opcodes.OP_EQUAL] if match_decoded(decoded, match): return hash_160_to_bc_address(decoded[1][1], version="\x05") return "(None)"
def import_key(keyLine, db_dir, input_mode="b58", dryrun=False, verbose=False): if len(keyLine.strip()) == 0: return if input_mode == "b58": priv_bin = privkey_b58_bin(keyLine) elif input_mode == "b64": priv_bin = privkey_b64_bin(keyLine) elif input_mode == "bin": if len(keyLine) not in (32, 279): raise ValueError("Expected a key of 32 or 279 bytes") priv_bin = keyLine if len(priv_bin) == 32: # Get the full DER key priv_bin = priv_to_der(priv_bin) # The public key of a DER-encoded private key is just the last 65 bytes pub_bin = priv_bin[-65:] # Print out the key and address if verbose: print "Private key: %s" % util.long_hex(priv_bin) print "Public key: %s" % util.long_hex(pub_bin) else: print "Private key: %s" % util.short_hex(priv_bin) print "Public key: %s" % util.short_hex(pub_bin) addr = base58.public_key_to_bc_address(pub_bin) if addr == '': # This can happen if pycrypto is not installed, or if the RIPEMD160 # hash is not available (it has been removed in the Debian/Ubuntu # version) print "Warning: Cannot calculate address; check pycrypto library" else: print "Address: %s" % addr # Data for wallet.update_wallet data = { 'private_key': priv_bin, 'public_key': pub_bin, } try: db_env = util.create_env(db_dir) except bsddb.db.DBNoSuchFileError: logging.error("Couldn't open " + db_dir) sys.exit(1) if not dryrun: db = wallet.open_wallet(db_env, writable=True) wallet.update_wallet(db, 'key', data) db.close()
def import_key(keyLine, db_dir, input_mode="b58", dryrun=False,verbose=False): if len(keyLine.strip()) == 0: return if input_mode == "b58": priv_bin = privkey_b58_bin(keyLine) elif input_mode == "b64": priv_bin = privkey_b64_bin(keyLine) elif input_mode == "bin": if len(keyLine) not in (32, 279): raise ValueError("Expected a key of 32 or 279 bytes") priv_bin = keyLine if len(priv_bin) == 32: # Get the full DER key priv_bin = priv_to_der(priv_bin) # The public key of a DER-encoded private key is just the last 65 bytes pub_bin = priv_bin[-65:] # Print out the key and address if verbose: print "Private key: %s" % util.long_hex(priv_bin) print "Public key: %s" % util.long_hex(pub_bin) else: print "Private key: %s" % util.short_hex(priv_bin) print "Public key: %s" % util.short_hex(pub_bin) addr = base58.public_key_to_bc_address(pub_bin) if addr == '': # This can happen if pycrypto is not installed, or if the RIPEMD160 # hash is not available (it has been removed in the Debian/Ubuntu # version) print "Warning: Cannot calculate address; check pycrypto library" else: print "Address: %s" % addr # Data for wallet.update_wallet data = { 'private_key': priv_bin, 'public_key': pub_bin, } try: db_env = util.create_env(db_dir) except bsddb.db.DBNoSuchFileError: logging.error("Couldn't open " + db_dir) sys.exit(1) if not dryrun: db = wallet.open_wallet(db_env, writable=True) wallet.update_wallet(db, 'key', data) db.close()
def public_key_to_bc_address(public_key, addrtype=0): """Deprecated.""" return base58.public_key_to_bc_address(public_key, addrtype)
##now we begin with the ECDSA stuff. ## we create a private key from the provided private key data, and sign hash_scriptless with it ## we also check that the private key's corresponding public key can actually redeem the specified output k = ecdsa_ssl.KEY() k.generate(('%064x' % PRIVATE_KEY).decode('hex')) #here we retrieve the public key data generated from the supplied private key pubkey_data = k.get_pubkey() #then we create a signature over the hash of the signature-less transaction sig_data=k.sign(hash_scriptless) #a one byte "hash type" is appended to the end of the signature (https://en.bitcoin.it/wiki/OP_CHECKSIG) sig_data = sig_data + chr(SIGHASH_ALL) #let's check that the provided privat key can actually redeem the output in question if (bc_address_to_hash_160(public_key_to_bc_address(pubkey_data)) != tx_info['txOut'][OUTPUT_INDEX]['scriptPubKey'][3:-2]): bytes = b58decode(SEND_TO_ADDRESS, 25) raise RuntimeError, "The supplied private key cannot be used to redeem output index %d\nYou need to supply the private key for address %s" % \ (OUTPUT_INDEX, hash_160_to_bc_address(tx_info['txOut'][OUTPUT_INDEX]['scriptPubKey'][3:-2], bytes[0])) ##now we begin creating the final transaction. this is a duplicate of the signature-less transaction, ## with the scriptSig filled out with a script that pushes the signature plus one-byte hash code type, and public key from above, to the stack final_tx = BCDataStream() final_tx.write_int32(tx_fields['version']) final_tx.write_compact_size(tx_fields['num_txin']) final_tx.write(tx_fields['prevout_hash']) final_tx.write_uint32(tx_fields['output_index']) ##now we need to write the actual scriptSig. ## this consists of the DER-encoded values r and s from the signature, a one-byte hash code type, and the public key in uncompressed format
def address(self, versionByte=None): if versionByte == None: versionByte = '\x00' if not self.__testnet else '\x6F' return base58.public_key_to_bc_address(point_compress(self.point()), versionByte)
def extract_public_key(bytes, version='\x00'): try: decoded = [x for x in script_GetOp(bytes)] except (struct.error, IndexError): return None # non-generated TxIn transactions push a signature # (seventy-something bytes) and then their public key # (33 or 65 bytes) onto the stack: match = [opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4] if match_decoded(decoded, match): if (decoded[0][0] == 0 and decoded[1][0] in [20, 32]): #Native Segwit P2PKH or P2SH output #Return the exact bytes return decoded[1][1] return public_key_to_bc_address(decoded[1][1], version=version) # The Genesis Block, self-payments, and pay-by-IP-address payments look like: # 65 BYTES:... CHECKSIG match = [opcodes.OP_PUSHDATA4, opcodes.OP_CHECKSIG] if match_decoded(decoded, match): return public_key_to_bc_address(decoded[0][1], version=version) # Pay-by-Bitcoin-address TxOuts look like: # DUP HASH160 20 BYTES:... EQUALVERIFY CHECKSIG match = [ opcodes.OP_DUP, opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUALVERIFY, opcodes.OP_CHECKSIG ] if match_decoded(decoded, match): return hash_160_to_bc_address(decoded[2][1], version=version) # BIP11 TxOuts look like one of these: # Note that match_decoded is dumb, so OP_1 actually matches OP_1/2/3/etc: multisigs = [[ opcodes.OP_1, opcodes.OP_PUSHDATA4, opcodes.OP_1, opcodes.OP_CHECKMULTISIG ], [ opcodes.OP_2, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_2, opcodes.OP_CHECKMULTISIG ], [ opcodes.OP_3, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_3, opcodes.OP_CHECKMULTISIG ]] for match in multisigs: if match_decoded(decoded, match): return [ public_key_to_bc_address(decoded[i][1], version=version) for i in range(1, len(decoded) - 1) ] # BIP16 TxOuts look like: # HASH160 20 BYTES:... EQUAL match = [opcodes.OP_HASH160, 0x14, opcodes.OP_EQUAL] if match_decoded(decoded, match): script_version = '\x05' if version == '\x00' else '\xC4' return hash_160_to_bc_address(decoded[1][1], version=script_version) return None
def __repr__(self): ret = "version: {}\n".format(self.version) ret += "minimum_version: {}\n".format(self.minimum_version) ret += "orderposnext: {}\n".format(self.orderposnext) if self.best_block: ret += "best_block: {}".format(self.best_block.__repr__()) if self.best_block_no_merkle: ret += "best_block_no_merkle: {}".format( self.best_block_no_merkle.__repr__()) if self.default_key != b'': ret += "default_key: {}\n".format(self.default_key) if self.hd_chain: ret += "hd_chain:\n {}\n".format(self.hd_chain) if self.keys: ret += "keys:\n" ret += "\n".join([ " pub_key: {}, address: {}, priv_key: {}".format( pub_key.hex(), public_key_to_bc_address(pub_key), priv_key.__repr__()) for pub_key, priv_key in self.keys.items() ]) ret += "\n" if self.wkeys: ret += "wkeys:\n" ret += "\n".join([" {}".format(wkey) for wkey in self.wkeys]) ret += "\n" if self.names: ret += "names:\n" ret += "\n".join([ " address: {}, name: {}".format(address, name) for name, address in self.names.items() ]) ret += "\n" if self.purposes: ret += "purposes:\n" ret += "\n".join([ " address: {}, purpose: {}".format(purpose, address) for purpose, address in self.purposes.items() ]) ret += "\n" if self.pool: ret += "key_pool:\n" ret += "\n".join([ " {}. {}".format(n, key_pool) for n, key_pool in self.pool.items() ]) ret += "\n" if self.accounts: ret += "accounts:\n" ret += "\n".join([ " {}: {}".format(account_name, account) for account_name, account in self.accounts.items() ]) ret += "\n" if self.accounting_entries: ret += "accounting entries:\n" ret += "\n".join([ " {}".format(account_entry) for account_entry in self.accounting_entries ]) ret += "\n" if self.key_meta: ret += "key metadata:\n" ret += "\n".join( [" {}".format(key_meta) for key_meta in self.key_meta]) ret += "\n" return ret
##now we begin with the ECDSA stuff. ## we create a private key from the provided private key data, and sign hash_scriptless with it ## we also check that the private key's corresponding public key can actually redeem the specified output k = ecdsa_ssl.KEY() k.generate(('%064x' % PRIVATE_KEY).decode('hex')) #here we retrieve the public key data generated from the supplied private key pubkey_data = k.get_pubkey() #then we create a signature over the hash of the signature-less transaction sig_data = k.sign(hash_scriptless) #a one byte "hash type" is appended to the end of the signature (https://en.bitcoin.it/wiki/OP_CHECKSIG) sig_data = sig_data + chr(SIGHASH_ALL) #let's check that the provided privat key can actually redeem the output in question if (bc_address_to_hash_160(public_key_to_bc_address(pubkey_data)) != tx_info['txOut'][OUTPUT_INDEX]['scriptPubKey'][3:-2]): bytes = b58decode(SEND_TO_ADDRESS, 25) raise RuntimeError, "The supplied private key cannot be used to redeem output index %d\nYou need to supply the private key for address %s" % \ (OUTPUT_INDEX, hash_160_to_bc_address(tx_info['txOut'][OUTPUT_INDEX]['scriptPubKey'][3:-2], bytes[0])) ##now we begin creating the final transaction. this is a duplicate of the signature-less transaction, ## with the scriptSig filled out with a script that pushes the signature plus one-byte hash code type, and public key from above, to the stack final_tx = BCDataStream() final_tx.write_int32(tx_fields['version']) final_tx.write_compact_size(tx_fields['num_txin']) final_tx.write(tx_fields['prevout_hash']) final_tx.write_uint32(tx_fields['output_index']) ##now we need to write the actual scriptSig.
def parse_wallet(self): """Parse a berkeley db .dat wallet file. A bekeley db .dat wallet file is a key-value store, with the following possible keys: - acc: account information. key is "acc"+string account name. Value is an Account object. acc entries are not read on startup, only when the deprecated `setaccount` and `getaccountaddress` RPCs are called. - acentry: TODO - bestblock: TODO - bestblock_nomerkle: TODO - ckey: TODO - cscript: TODO - defaultkey: TODO - destdata: TODO - hdchain: TODO - key: TODO - keymeta: TODO - minversion: TODO - mkey: TODO - name: TODO - orderposnext: TODO - pool: TODO - purpose: TODO - tx: TODO - version: TODO - watchmeta: TODO - watchs: TODO - wkey: TODO""" for (key, value) in self.db.items(): d = {} kds = BCBytesStream(key) vds = BCBytesStream(value) t = kds.deser_string() d["__key__"] = key d["__value__"] = value d["__type__"] = t try: if t == "acc": account = Account() account.deserialize(vds) self.accounts[kds.deser_string()] = account elif t == "acentry": account_entry = AccountingEntry() account_entry.deserialize(vds) account_entry.account = kds.deser_string() account_entry.index = kds.deser_uint64() self.accounting_entries.append(account_entry) elif t == "bestblock": best_block = BlockLocator() best_block.deserialize(vds) self.best_block = best_block elif t == "bestblock_nomerkle": best_block_no_merkle = BlockLocator() best_block_no_merkle.deserialize(vds) self.best_block_no_merkle = best_block_no_merkle elif t == "ckey": pass # TODO: parse ckey entries elif t == "cscript": pass # TODO: parse cscript entries elif t == "defaultkey": self.default_key = vds.read(vds.deser_compact_size()) elif t == "hdchain": hd_chain = HDChain() hd_chain.deserialize(vds) self.hd_chain = hd_chain elif t == "key": public_key = kds.read(kds.deser_compact_size()) private_key = PrivateKey() private_key.deserialize(vds) self.keys[public_key] = private_key self.owner_keys[public_key_to_bc_address( public_key)] = private_key elif t == "keymeta": key_metadata = KeyMeta() key_metadata.deserialize(vds) self.key_meta.append(key_metadata) elif t == "minversion": self.minimum_version = vds.deser_uint32() elif t == "mkey": pass # TODO: parse mkey entries elif t == "name": self.names[vds.deser_string()] = kds.deser_string() elif t == "orderposnext": self.orderposnext = vds.deser_int64() elif t == "pool": keypool = KeyPool() keypool.deserialize(vds) self.pool[kds.deser_int64()] = keypool elif t == "purpose": self.purposes[kds.deser_string()] = vds.deser_string() elif t == "tx": tx_id = kds.read(32) tx = WalletTransaction() tx.deserialize(vds) tx.tx_id = tx_id self.wallet_transactions.append(tx) elif t == "version": self.version = vds.deser_uint32() elif t == "watchmeta": pass # TODO: parse watchmeta entries elif t == "watchs": pass # TODO: parse watchs entries elif t == "wkey": public_key = kds.read(kds.deser_compact_size()) private_key = vds.read(vds.deser_compact_size()) created = vds.deser_int64() expires = vds.deser_int64() comment = vds.deser_string() self.wkeys.append({ 'pubkey': public_key, 'priv_key': private_key, 'created': created, 'expiers': expires, 'comment': comment }) else: print("ERROR parsing wallet.dat, type %s" % t) self.records.append(d) except Exception as e: print("ERROR parsing wallet.dat, type %s" % t) print("key data in hex: {}".format(key.hex())) print("value data in hex: {}".format(value.hex())) raise self.wallet_transactions.sort(key=lambda i: i.time_received) self.key_meta.sort(key=lambda i: i.hd_key_path)
def sign(self, data): size = c_int() sig = create_string_buffer(10000) result = EC.ECDSA_sign(0, data, len(data), sig, byref(size), self.pkey) if result != 1: return None return sig.raw[:size.value] def verify(self, data, sig): result = EC.ECDSA_verify(0, data, len(data), sig, len(sig), self.pkey) return result == 1 import time d = c_int(int(time.time() * 10000000)) EC.RAND_add(byref(d), sizeof(d), c_float(1.5)) k = Key() k.make_new_key() pub = k.get_public_key() prv = k.get_private_key() sig = k.sign("hello world" * 100) print k.verify("hello world" * 100, sig) print pub.encode("hex_codec") #print prv.encode("hex_codec") print base58.public_key_to_bc_address(pub)
def sign(self, data): size = c_int() sig = create_string_buffer(10000) result = EC.ECDSA_sign(0, data, len(data), sig, byref(size), self.pkey) if result != 1: return None return sig.raw[:size.value] def verify(self, data, sig): result = EC.ECDSA_verify(0, data, len(data), sig, len(sig), self.pkey) return result == 1 import time d = c_int(int(time.time() * 10000000)) EC.RAND_add(byref(d), sizeof(d), c_float(1.5)) k = Key() k.make_new_key() pub = k.get_public_key() prv = k.get_private_key() sig = k.sign("hello world"*100) print k.verify("hello world"*100, sig) print pub.encode("hex_codec") #print prv.encode("hex_codec") print base58.public_key_to_bc_address(pub)