def deriveAddress(privateKey, compressed, blockChain): """ Turn a private key into an address. privateKey must be in binary format. """ privKey = CECKey() privKey.set_secretbytes(privateKey) privKey.set_compressed(compressed) publicKey = privKey.get_pubkey() hash1 = hashlib.sha256(publicKey).digest() ripemd160 = hashlib.new('ripemd160') ripemd160.update(hash1) ripe = ripemd160.digest() if blockChain == 'bitcoin': ripeWithNetworkPrefix = b'\x00' + ripe elif blockChain.startswith('testnet'): ripeWithNetworkPrefix = b'\x6F' + ripe else: raise Exception("'blockChain' parameter is not set correctly") checksum = hashlib.sha256( hashlib.sha256(ripeWithNetworkPrefix).digest()).digest()[:4] binaryBitcoinAddress = ripeWithNetworkPrefix + checksum numberOfZeroBytesOnBinaryBitcoinAddress = 0 while binaryBitcoinAddress[0:1] == b'\x00': # while the first byte is null numberOfZeroBytesOnBinaryBitcoinAddress += 1 binaryBitcoinAddress = binaryBitcoinAddress[ 1:] # take off the first byte base58encoded = encode(binaryBitcoinAddress) # encode into base58 return "1" * numberOfZeroBytesOnBinaryBitcoinAddress + base58encoded
def construct_auth_wrapper_truncated(metadata: AddressMetadata, keypair: CECKey): """Return the complete AuthWrapper object and the digest of the metadata.""" raw_metadata = metadata.SerializeToString() signature, digest = sign_metadata(raw_metadata, keypair) public_key = keypair.get_pubkey() auth_wrapper = AuthWrapper(pub_key=public_key, payload_digest=digest, scheme=1, signature=signature) return auth_wrapper, digest
def pk_scriptdecompress(pk): # https://github.com/bitcoin/bitcoin/blob/5961b23898ee7c0af2626c46d5d70e80136578d3/src/compressor.cpp#L118 xpk = bytes(bytearray([pk[0] - 2]) + pk[1:]) pk = CPubKey(xpk) cec = CECKey() cec.set_compressed(True) res = cec.set_pubkey(pk) if res is None: raise Exception(ssl_get_error()) cec.set_compressed(False) pubkey = cec.get_pubkey() return CPubKey(pubkey, _cec_key=cec)
def generate_random_keypair(): """Generate a random bitcoin address, a ECDSA keypair.""" # Generate keys secret = os.urandom(16) keypair = CECKey() keypair.set_compressed(True) keypair.set_secretbytes(secret) public_key = keypair.get_pubkey() # Generate key addr key_addr = str(P2PKHBitcoinAddress.from_pubkey(public_key)) return key_addr, keypair
def get_btc_address(): '''return new btc address and save secret used to generate address''' # Generate & Save random address and secret secret = base + '_' + str(randint(100000, 9999999999)) h = hashlib.sha256(secret).digest() # key = CBitcoinSecret.from_secret_bytes(h) key = CECKey() key.set_secretbytes(h) address = P2PKHBitcoinAddress.from_pubkey(key.get_pubkey()) cred = {"Address": address, "Secret": secret} # Save generated secret key with open("config_keys.txt", "a") as f: f.write(str(cred) + '\n') return str(address), key, secret
def sign(self, template, privateKeys): # convert all of the privateKeys to a standard binary format for us to work with privateKeysBinary = convertPrivateKeysToBinaryFormat( privateKeys, self.blockChain) """ keyCollection is a dictionary where the key of the dict is an address and the value is a tuple with (privKey, compressed) where `privKey` is the private key in binary format and `compressed` is a bool indicating whether or not the corresponding public key is compressed. """ keyCollection = generateKeyCollection(privateKeysBinary, self.blockChain) if not 'inputs' in template: raise Exception( "This template has no inputs. There is nothing to sign.") for inputIndex in range(len( template['inputs'])): # For each input in the template... for signatureIndex in range( len(template['inputs'][inputIndex] ['signatures'])): # For each signature in the input... address = template['inputs'][inputIndex]['signatures'][ signatureIndex][ 'address'] # Get the address out of the template to make this code easier to read if address in keyCollection: # if we have the private key needed for this signature.. privateKeyBinary, compressed = keyCollection[address] privKey = CECKey( ) # This CECKey object type is from the python-bitcoinlib library privKey.set_secretbytes(privateKeyBinary) privKey.set_compressed(compressed) hash_to_sign = template['inputs'][inputIndex][ 'signatures'][signatureIndex]['hash_to_sign'] signature = privKey.sign(unhexlify(hash_to_sign)) # We now have the signature. Let's put the signature and the pubkey into the template. template['inputs'][inputIndex]['signatures'][ signatureIndex]['signature'] = hexlify( signature).decode('ascii') template['inputs'][inputIndex]['signatures'][ signatureIndex]['public_key'] = hexlify( privKey.get_pubkey()).decode('ascii') return template
BASE_URL_B = "http://0.0.0.0:8081" bitcoin.SelectParams("regtest") # Init Bitcoin RPC rpc_user = "******" rpc_password = "******" rpc_connection = AuthServiceProxy("http://%s:%[email protected]:18443" % (rpc_user, rpc_password)) # Generate keys secret = os.urandom(16) keypair = CECKey() keypair.set_compressed(True) keypair.set_secretbytes(secret) private_key = keypair.get_privkey() public_key = keypair.get_pubkey() # Generate key addr key_addr = str(P2PKHBitcoinAddress.from_pubkey(public_key)) # Construct Payload header = Header(name="Something wicked", value="this way comes") entry = Entry(headers=[header], entry_data=b'This gonna be so f*****g fast') timestamp = int(time()) metadata = AddressMetadata(timestamp=timestamp, ttl=3000, entries=[entry]) # Sign raw_metadata = metadata.SerializeToString() digest = sha256(raw_metadata).digest() signature, _ = keypair.sign_compact(digest)
#my_netcode = "mainnet" bitcoin.SelectParams(my_netcode) my_params = bitcoin.params my_privkey_prefix = bytes(bytearray([my_params.BASE58_PREFIXES['SECRET_KEY']])) my_pubaddr_prefix = bytes(bytearray([my_params.BASE58_PREFIXES['PUBKEY_ADDR']])) # Create the (in)famous correct brainwallet secret key. h = hashlib.sha256(b'correct horse battery staple').digest() seckey = CBitcoinSecret.from_secret_bytes(h) cec_key = CECKey() cec_key.set_secretbytes(h) print("Secret key hex: ", seckey.hex()); btc_addr = encoding.public_pair_to_bitcoin_address(cec_key.get_pubkey(), address_prefix=my_pubaddr_prefix) print("Bitcoin address: ", btc_addr) # Create a redeemScript, with public key and checksig op code (0xac) # Similar to a scriptPubKey the redeemScript must be satisfied for the funds to be spent. txin_redeemScript = CScript([seckey.pub, OP_CHECKSIG]) print("Public key of address #", seckey.pub.hex()) # 0x21 + secret.pub + OP_CHECKSIG (0x87) print("Tx-in Redeem Script: ", b2x(txin_redeemScript)) # Create the magic P2SH scriptPubKey format from that redeemScript. You should # look at the CScript.to_p2sh_scriptPubKey() function in bitcoin.core.script to # understand what's happening, as well as read BIP16: # https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki txin_scriptPubKey = txin_redeemScript.to_p2sh_scriptPubKey() print("Redeem script hash160 #", b2x(bitcoin.core.Hash160(txin_redeemScript)))
cec_key.set_secretbytes(bitcoin.core.x(my_secret_exp)) print("Private Key dec: ", random_nbr) print("Private Key hex: ", my_secret_exp) privkey_wif = encoding.secret_exponent_to_wif(eval('0x' + my_secret_exp), wif_prefix=my_privkey_prefix) print("Private key WIF: ", privkey_wif) privkey_wif = encoding.secret_exponent_to_wif(eval('0x' + my_secret_exp), False, wif_prefix=my_privkey_prefix) print(" uncompressed: ", privkey_wif) cec_key.set_compressed(True) print() pubkey_pair = encoding.sec_to_public_pair(cec_key.get_pubkey()) print("Public key pair: ", pubkey_pair) (pub_key_x, pub_key_y) = pubkey_pair compressed_indicator = True if (pub_key_y % 2) == 0 else False print("Public key y parity? ", 'even' if compressed_indicator else 'odd') #print("Private key hexlify: ", hexlify(cec_key.get_privkey())) print("Public key hex: ", bitcoin.core.b2x(cec_key.get_pubkey())) cec_key.set_compressed(False) print(" uncompressed: ", bitcoin.core.b2x(cec_key.get_pubkey())) addr_compressed = encoding.public_pair_to_bitcoin_address( pubkey_pair, True, address_prefix=my_pubaddr_prefix) addr_uncompressed = encoding.public_pair_to_bitcoin_address( pubkey_pair, False, address_prefix=my_pubaddr_prefix)
def preimage_client(): # Setup socket context = zmq.Context() socket = context.socket(zmq.REQ) socket.connect("ipc:///tmp/TumbleBit_tx") # Setup keys data = open("./keys/EC_private_test.bin", "rb").read() alice = CECKey() alice.set_privkey(data) data = open("./keys/EC_private_test2.bin", "rb").read() bob = CECKey() bob.set_privkey(data) # Setup Images & Hashes preimages = [(sha256("test" + str(x)))[:16] for x in range(1, 16)] hashes = [ripemd160(x) for x in preimages] serial_hashes = "" for i in range(len(hashes)): serial_hashes += hashes[i] serial_preimages = "" for i in range(len(preimages)): serial_preimages += preimages[i] # Phase 1 -- Setup msg = [ b"setup_preimage", alice.get_pubkey(), bob.get_pubkey(), serial_hashes ] socket.send_multipart(msg) reply = socket.recv_multipart() redeem_script = reply[0] fund_tx = reply[1] # print "Done with PHASE1" # Phase 2 -- Get TX sighash address = "mweZnPjTeyGHVS2d3SojAGujY36sd3wQ49" msg = [b"get_tx", redeem_script, address, fund_tx] socket.send_multipart(msg) reply = socket.recv_multipart() tx = reply[0] sighash = reply[1] # print "Done with PHASE2" # Sign alice_sig = alice.sign(sighash) # Used for refund bob_sig = bob.sign(sighash) # Used for redeem # Phase 3 -- Spending tx msg = [b"spend_preimage", serial_preimages, bob_sig, tx, redeem_script] socket.send_multipart(msg) reply = socket.recv() spending_tx = reply # print "Done with PHASE3" # Phase 4 -- Refunding tx msg = [b"send_refund_tx", alice_sig, tx, redeem_script] socket.send_multipart(msg) reply = socket.recv() refund_tx = reply # print "Done with PHASE4" print "PREIMAGE: Spending tx is: %s" % binascii.hexlify(spending_tx) print "\n\n" print "PREIMAGE: Refund tx is: %s" % binascii.hexlify(refund_tx) # Clean up socket.close() context.term()
def escrow_example(): ''' P2SH Address: 2MzDcMCxcZnNnAZzFqsyuyZ4vuNCB6Qjvxd Funding tx: db1b045ea09581a51a5b5f851e7e3a64542123885e071fd6d4ff7428703a2504 Spending tx nlocktime = 30: Refund TX: 23daa9d3868255bab14d5dfe46f7fb787aaef49b17d0014902e36e4491440311 ''' SelectParams('testnet') tx = TX(test=True) print "=" * 50 print("=" * 10 + " ESCROW EXAMPLE") print "=" * 50 + "\n" # Setup keys data = open("./keys/EC_private_test.bin", "rb").read() alice = CECKey() alice.set_privkey(data) data = open("./keys/EC_private_test2.bin", "rb").read() bob = CECKey() bob.set_privkey(data) amount = 0.001 # In bitcoins redeem_script, p2sh_address = tx.setup_escrow(alice.get_pubkey(), bob.get_pubkey(), amount, 30) # Funding tx id + redeeming bitcoin address funding_tx = "db1b045ea09581a51a5b5f851e7e3a6" + \ "4542123885e071fd6d4ff7428703a2504" address = "mweZnPjTeyGHVS2d3SojAGujY36sd3wQ49" # Note: Make sure pick correct vout - default is 0 tx2, sighash = tx.get_tx(redeem_script, address, amount - 0.0001, funding_tx, 20, vout=1) # Sign alice_sig = alice.sign(sighash) bob_sig = bob.sign(sighash) print "P2SH %s" % p2sh_address print "Redeem script:\n%s\n" % binascii.hexlify(redeem_script) print "Redeem script Hash:\n%s\n" % binascii.hexlify( sha256(sha256(redeem_script))) redeem_tx = tx.spend_escrow(alice_sig, bob_sig, tx2, redeem_script) print "REDEEM TX is:\n%s\n" % binascii.hexlify(redeem_tx) refunded_tx = tx.refund_tx(alice_sig, tx2, redeem_script) print "REFUND TX is:\n%s\n" % binascii.hexlify(refunded_tx) print "=" * 50 + "\n\n"
def preimage_example(): ''' Refund test: P2SH Address: 2MscMqe6Ag5NmZKCsELKDPJRJWnPR6GGD9B Funding tx: d49038dd9141f77c230208fe1cdd24937c61a1b63f40b8a87ab50971970ac2b7 Spending tx nlocktime = 10: Refund TX: f77245db1c81b49c72464e61e3738a60f6e21c0bb744f8729def4a9877082e73 Preimage test: P2SH Address: 2NEFkj2gMZguX3QtFp31XKfnRdUpEoXTVNv Funding tx: 91e6953fdcc15687ffc54e76d55ed4b92ef60cd483e0633ef226f7509513c7d2 Spending tx nlocktime = 10: Spending TX: e006b7d1566045e136c13446114e51513f1453a7e2eb7e534d04bd7dc09532f7 Other: 1/ P2SH Address: 2N6uq4bLT6UTqqxNo7YQ5TyRrFVWSRAFyxT Funding TX: 8f717d1babd532b337cb80e743844f270129c744ebfc1ff7f6b43c1d855adc75 Spending TX: b9cfbbdef00319db95c0beae8f73de4f7639eacc9b2006a70d64b494673921eb ''' SelectParams('testnet') tx = TX(test=True) print "=" * 50 print("=" * 10 + " PREIMAGE EXAMPLE") print "=" * 50 + "\n" # Setup keys data = open("./keys/EC_private_test.bin", "rb").read() alice = CECKey() alice.set_privkey(data) data = open("./keys/EC_private_test2.bin", "rb").read() bob = CECKey() bob.set_privkey(data) preimages = [sha256("test" + str(x)) for x in range(1, 16)] hashes = [ripemd160(x) for x in preimages] # Serialize hashes serial_hashes = "" for i in range(len(hashes)): serial_hashes += hashes[i] tx.get_hashes_from_serial(serial_hashes, 15, 20) amount = 0.001 # In bitcoins redeem_script, funding_tx = tx.setup_preimage(alice.get_pubkey(), bob.get_pubkey(), hashes, amount, 10) # Funding tx id + redeeming bitcoin address funding_tx = "8f717d1babd532b337cb80e743844f270" + \ "129c744ebfc1ff7f6b43c1d855adc75" address = "mweZnPjTeyGHVS2d3SojAGujY36sd3wQ49" # Note: Make sure pick correct vout - default is 0 tx2, sighash = tx.get_tx(redeem_script, address, amount - 0.0001, funding_tx, 5) # Sign alice_sig = alice.sign(sighash) bob_sig = bob.sign(sighash) redeem_tx = tx.spend_preimage(preimages, bob_sig, tx2, redeem_script) print "REDEEM TX is:\n%s\n" % binascii.hexlify(redeem_tx) refunded_tx = tx.refund_tx(alice_sig, tx2, redeem_script) print "REFUND TX is:\n%s\n" % binascii.hexlify(refunded_tx) serial_keys = tx.get_keys_from_tx(redeem_tx) # print "SERIAL KEYS:\n%s\n" % binascii.hexlify(serial_keys) # # write to file to test in c++ # target = open("keys.bin", 'wb') # target.write(serial_keys) # target.close() print "=" * 50 + "\n\n"
def escrow_client(): # Setup socket context = zmq.Context() socket = context.socket(zmq.REQ) socket.connect("ipc:///tmp/TumbleBit_tx") # Setup keys data = open("./keys/EC_private_test.bin", "rb").read() alice = CECKey() alice.set_privkey(data) data = open("./keys/EC_private_test2.bin", "rb").read() bob = CECKey() bob.set_privkey(data) # Phase 1 -- Setup msg = [b"setup_escrow", alice.get_pubkey(), bob.get_pubkey()] socket.send_multipart(msg) reply = socket.recv_multipart() redeem_script = reply[0] fund_tx = reply[1] # print "Done with PHASE1" # Phase 2 -- Get TX sighash address = "mweZnPjTeyGHVS2d3SojAGujY36sd3wQ49" msg = [b"get_tx", redeem_script, address, fund_tx] socket.send_multipart(msg) reply = socket.recv_multipart() tx = reply[0] sighash = reply[1] # print "Done with PHASE2" # Sign alice_sig = alice.sign(sighash) bob_sig = bob.sign(sighash) # Phase 3 -- Spending tx msg = [b"spend_escrow", alice_sig, bob_sig, tx, redeem_script] socket.send_multipart(msg) reply = socket.recv() spending_tx = reply # print "Done with PHASE3" # Phase 4 -- Refunding tx msg = [b"send_refund_tx", alice_sig, tx, redeem_script] socket.send_multipart(msg) reply = socket.recv() refund_tx = reply # print "Done with PHASE4" print "ESCROW: Spending tx is: %s" % binascii.hexlify(spending_tx) print "\n\n" print "ESCROW: Refund tx is: %s" % binascii.hexlify(refund_tx) # Clean up socket.close() context.term()
class EC(object): """ Wrapper around python-bitcoinlib's CECKey class """ def __init__(self): self.key = CECKey() self.init = False self.is_private = False def load_public_key(self, key_path): with open(key_path, 'rb') as f: temp_key = f.read() self.key.set_pubkey(temp_key) self.init = True def load_private_key(self, key_path): with open(key_path, 'rb') as f: temp_key = f.read() self.key.set_privkey(temp_key) self.init = True self.is_private = True def get_pubkey(self): return self.key.get_pubkey() def sign(self, msg): if self.init: if self.is_private: sig = self.key.sign(msg) return sig else: raise ValueError('Signing requires a private key') else: raise ValueError('No key is loaded.') def verify(self, msg, sig): if self.init: return self.key.verify(msg, sig) == 1 else: raise ValueError('No key is loaded.') def serialize_sig(self, sig): """ Takes in a signature in DER format and returns a byte string of R + S that should be 64 bytes in length """ sig_struct = ECDSA_SIG_st() _ssl.d2i_ECDSA_SIG(ctypes.byref(ctypes.pointer(sig_struct)), ctypes.byref(ctypes.c_char_p(sig)), len(sig)) r = BNToBin(sig_struct.r, 32) s = BNToBin(sig_struct.s, 32) return r + s def deserialize_sig(self, serial_sig): """ Converts a serial signature (R + S) into DER format Arguments: serial_sig (bytes): A 64 byte string that represents R and S where each is 32 bytes Returns: A signature in der format Raises: Value error if serial sig is not 64 bytes """ if len(serial_sig) == 64: sig_struct = ECDSA_SIG_st() r = BinToBN(serial_sig[:32]) s = BinToBN(serial_sig[32:]) sig_struct.r = r sig_struct.s = s derlen = _ssl.i2d_ECDSA_SIG(ctypes.pointer(sig_struct), 0) if derlen == 0: _ssl.ECDSA_SIG_free(sig_struct) return None der_sig = ctypes.create_string_buffer(derlen) _ssl.i2d_ECDSA_SIG(ctypes.pointer(sig_struct), ctypes.byref(ctypes.pointer(der_sig))) return der_sig.raw else: raise ValueError('Serial sig has to be 64 bytes.')