def send_ack(self, raw_tx, refund_addr): pay_det = self.details if not self.details.payment_url: return False, "no url" paymnt = pb2.Payment() paymnt.merchant_data = pay_det.merchant_data paymnt.transactions.append(bfh(raw_tx)) ref_out = paymnt.refund_to.add() ref_out.script = util.bfh(util.pay_script(TYPE_ADDRESS, refund_addr)) paymnt.memo = "Paid with the Bitcoin Payment Protocol Interface" pm = paymnt.SerializeToString() payurl = urllib.parse.urlparse(pay_det.payment_url) try: r = requests.post(payurl.geturl(), data=pm, headers=ACK_HEADERS, verify=ca_path) except requests.exceptions.SSLError: print("Payment Message/PaymentACK verify Failed") try: r = requests.post(payurl.geturl(), data=pm, headers=ACK_HEADERS, verify=False) except Exception as e: print(e) return False, "Payment Message/PaymentACK Failed" if r.status_code >= 500: return False, r.reason try: paymntack = pb2.PaymentACK() paymntack.ParseFromString(r.content) except Exception: return False, "PaymentACK could not be processed. Payment was sent; please manually verify that payment was received." return True, paymntack.memo
def point_to_ser(P, compressed=True) -> bytes: if isinstance(P, tuple): assert len(P) == 2, 'unexpected point: %s' % P x, y = P else: x, y = P.x(), P.y() if compressed: return bfh(('%02x' % (2 + (y & 1))) + ('%064x' % x)) return bfh('04' + ('%064x' % x) + ('%064x' % y))
def pubkey_to_address(txin_type, pubkey): if txin_type == 'p2pkh': return public_key_to_p2pkh(bfh(pubkey)) elif txin_type == 'p2wpkh': return public_key_to_p2wpkh(bfh(pubkey)) elif txin_type == 'p2wpkh-p2sh': scriptSig = p2wpkh_nested_script(pubkey) return hash160_to_p2sh(hash_160(bfh(scriptSig))) else: raise NotImplementedError(txin_type)
def redeem_script_to_address(txin_type, redeem_script): if txin_type == 'p2sh': return hash160_to_p2sh(hash_160(bfh(redeem_script))) elif txin_type == 'p2wsh': return script_to_p2wsh(redeem_script) elif txin_type == 'p2wsh-p2sh': scriptSig = p2wsh_nested_script(redeem_script) return hash160_to_p2sh(hash_160(bfh(scriptSig))) else: raise NotImplementedError(txin_type)
def serialize_request(req): pr = make_unsigned_request(req) signature = req.get('sig') requestor = req.get('name') if requestor and signature: pr.signature = bfh(signature) pr.pki_type = 'dnssec+btc' pr.pki_data = str(requestor) return pr
def checkPassphrase(line): passw = "" seed = util.bh2u(keystore.bip39_to_seed(line, passw)) seed = util.bfh(seed) xprv, _xpub = bitcoin.bip32_root(seed, "standard") xprv, _xpub = bitcoin.bip32_private_derivation(xprv, "", "44'") xprv, _xpub = bitcoin.bip32_private_derivation(xprv, "", "0'") xprv, _xpub = bitcoin.bip32_private_derivation(xprv, "", "0'") xprv, _xpub = bitcoin.bip32_private_derivation(xprv, "", "0") xprv2, btc_addr = bip39(seed, xprv, 0) return xprv2, btc_addr
def checkPassphrase(line): passw = "" seed = util.bh2u(keystore.bip39_to_seed(line, passw)) seed = util.bfh(seed) xprv, _xpub = bitcoin.bip32_root(seed, "standard") xprv, _xpub = bitcoin.bip32_private_derivation(xprv, "", "44'") xprv, _xpub = bitcoin.bip32_private_derivation(xprv, "", "0'") xprv, _xpub = bitcoin.bip32_private_derivation(xprv, "", "0'") xprv, _xpub = bitcoin.bip32_private_derivation(xprv, "", "0") for i in range(MAX_ADDR_IDX): deriveAddresses(line, xprv, i)
def bip32_public_derivation(xpub, branch, sequence): xtype, depth, fingerprint, child_number, c, cK = deserialize_xpub(xpub) assert sequence.startswith(branch) sequence = sequence[len(branch):] for n in sequence.split('/'): if n == '': continue i = int(n) parent_cK = cK cK, c = CKD_pub(cK, c, i) depth += 1 fingerprint = hash_160(parent_cK)[0:4] child_number = bfh("%08X"%i) return serialize_xpub(xtype, c, cK, depth, fingerprint, child_number)
def bip32_public_derivation(xpub, branch, sequence): xtype, depth, fingerprint, child_number, c, cK = deserialize_xpub(xpub) if not sequence.startswith(branch): raise ValueError('incompatible branch ({}) and sequence ({})'.format( branch, sequence)) sequence = sequence[len(branch):] for n in sequence.split('/'): if n == '': continue i = int(n) parent_cK = cK cK, c = CKD_pub(cK, c, i) depth += 1 fingerprint = hash_160(parent_cK)[0:4] child_number = bfh("%08X" % i) return serialize_xpub(xtype, c, cK, depth, fingerprint, child_number)
def i2o_ECPublicKey(pubkey, compressed=False): # public keys are 65 bytes long (520 bits) # 0x04 + 32-byte X-coordinate + 32-byte Y-coordinate # 0x00 = point at infinity, 0x02 and 0x03 = compressed, 0x04 = uncompressed # compressed keys: <sign> <x> where <sign> is 0x02 if y is even and 0x03 if y is odd if compressed: if pubkey.point.y() & 1: key = '03' + '%064x' % pubkey.point.x() else: key = '02' + '%064x' % pubkey.point.x() else: key = '04' + \ '%064x' % pubkey.point.x() + \ '%064x' % pubkey.point.y() return bfh(key)
def is_old_seed(seed): from . import old_mnemonic, mnemonic seed = mnemonic.normalize_text(seed) words = seed.split() try: # checks here are deliberately left weak for legacy reasons, see #3149 old_mnemonic.mn_decode(words) uses_electrum_words = True except Exception: uses_electrum_words = False try: seed = bfh(seed) is_hex = (len(seed) == 16 or len(seed) == 32) except Exception: is_hex = False return is_hex or (uses_electrum_words and (len(words) == 12 or len(words) == 24))
def encrypt_message(self, message, pubkey): assert_bytes(message) pk = ser_to_point(pubkey) if not ecdsa.ecdsa.point_is_valid(generator_secp256k1, pk.x(), pk.y()): raise Exception('invalid pubkey') ephemeral_exponent = number_to_string(ecdsa.util.randrange(pow(2,256)), generator_secp256k1.order()) ephemeral = EC_KEY(ephemeral_exponent) ecdh_key = point_to_ser(pk * ephemeral.privkey.secret_multiplier) key = hashlib.sha512(ecdh_key).digest() iv, key_e, key_m = key[0:16], key[16:32], key[32:] ciphertext = aes_encrypt_with_iv(key_e, iv, message) ephemeral_pubkey = bfh(ephemeral.get_public_key(compressed=True)) encrypted = b'BIE1' + ephemeral_pubkey + ciphertext mac = hmac.new(key_m, encrypted, hashlib.sha256).digest() return base64.b64encode(encrypted + mac)
def bip32_private_derivation(xprv, branch, sequence): assert sequence.startswith(branch) if branch == sequence: return xprv, xpub_from_xprv(xprv) xtype, depth, fingerprint, child_number, c, k = deserialize_xprv(xprv) sequence = sequence[len(branch):] for n in sequence.split('/'): if n == '': continue i = int(n[:-1]) + BIP32_PRIME if n[-1] == "'" else int(n) parent_k = k k, c = CKD_priv(k, c, i) depth += 1 _, parent_cK = get_pubkeys_from_secret(parent_k) fingerprint = hash_160(parent_cK)[0:4] child_number = bfh("%08X"%i) K, cK = get_pubkeys_from_secret(k) xpub = serialize_xpub(xtype, c, cK, depth, fingerprint, child_number) xprv = serialize_xprv(xtype, c, k, depth, fingerprint, child_number) return xprv, xpub
def bip32_private_derivation(xprv, branch, sequence): if not sequence.startswith(branch): raise ValueError('incompatible branch ({}) and sequence ({})'.format( branch, sequence)) if branch == sequence: return xprv, xpub_from_xprv(xprv) xtype, depth, fingerprint, child_number, c, k = deserialize_xprv(xprv) sequence = sequence[len(branch):] for n in sequence.split('/'): if n == '': continue i = int(n[:-1]) + BIP32_PRIME if n[-1] == "'" else int(n) parent_k = k k, c = CKD_priv(k, c, i) depth += 1 parent_cK = ecc.ECPrivkey(parent_k).get_public_key_bytes(compressed=True) fingerprint = hash_160(parent_cK)[0:4] child_number = bfh("%08X" % i) cK = ecc.ECPrivkey(k).get_public_key_bytes(compressed=True) xpub = serialize_xpub(xtype, c, cK, depth, fingerprint, child_number) xprv = serialize_xprv(xtype, c, k, depth, fingerprint, child_number) return xprv, xpub
def push_script(data: str) -> str: """Returns pushed data to the script, automatically choosing canonical opcodes depending on the length of the data. hex -> hex ported from https://github.com/btcsuite/btcd/blob/fdc2bc867bda6b351191b5872d2da8270df00d13/txscript/scriptbuilder.go#L128 """ data = bfh(data) from transaction import opcodes data_len = len(data) # "small integer" opcodes if data_len == 0 or data_len == 1 and data[0] == 0: return bh2u(bytes([opcodes.OP_0])) elif data_len == 1 and data[0] <= 16: return bh2u(bytes([opcodes.OP_1 - 1 + data[0]])) elif data_len == 1 and data[0] == 0x81: return bh2u(bytes([opcodes.OP_1NEGATE])) return op_push(data_len) + bh2u(data)
def make_unsigned_request(req): addr = req['address'] time = req.get('time', 0) exp = req.get('exp', 0) if time and type(time) != int: time = 0 if exp and type(exp) != int: exp = 0 amount = req['amount'] if amount is None: amount = 0 memo = req['memo'] script = bfh(util.pay_script(TYPE_ADDRESS, addr)) outputs = [(script, amount)] pd = pb2.PaymentDetails() for script, amount in outputs: pd.outputs.add(amount=amount, script=script) pd.time = time pd.expires = time + exp if exp else 0 pd.memo = memo pr = pb2.PaymentRequest() pr.serialized_payment_details = pd.SerializeToString() pr.signature = util.to_bytes('') return pr
def xprv_header(xtype): return bfh("%08x" % XPRV_HEADERS[xtype])
def xpub_header(xtype): return bfh("%08x" % XPUB_HEADERS[xtype])
def add_number_to_script(i: int) -> bytes: return bfh(push_script(script_num_to_hex(i)))
def script_to_p2wsh(script): return hash_to_segwit_addr(sha256(bfh(script)), witver=0)
if data_len == 0 or data_len == 1 and data[0] == 0: return bh2u(bytes([opcodes.OP_0])) elif data_len == 1 and data[0] <= 16: return bh2u(bytes([opcodes.OP_1 - 1 + data[0]])) elif data_len == 1 and data[0] == 0x81: return bh2u(bytes([opcodes.OP_1NEGATE])) return op_push(data_len) + bh2u(data) def add_number_to_script(i: int) -> bytes: return bfh(push_script(script_num_to_hex(i))) hash_encode = lambda x: bh2u(x[::-1]) hash_decode = lambda x: bfh(x)[::-1] hmac_sha_512 = lambda x, y: hmac.new(x, y, hashlib.sha512).digest() def is_new_seed(x, prefix=version.SEED_PREFIX): from . import mnemonic x = mnemonic.normalize_text(x) s = bh2u(hmac_sha_512(b"Seed version", x.encode('utf8'))) return s.startswith(prefix) def is_old_seed(seed): from . import old_mnemonic, mnemonic seed = mnemonic.normalize_text(seed) words = seed.split() try:
def rev_hex(s): return bh2u(bfh(s)[::-1])
def script_to_address(script, *, net=None): from .transaction import get_address_from_output_script t, addr = get_address_from_output_script(bfh(script), net=net) assert t == TYPE_ADDRESS return addr
def point_to_ser(P, comp=True ): if comp: return bfh( ('%02x'%(2+(P.y()&1)))+('%064x'%P.x()) ) return bfh( '04'+('%064x'%P.x())+('%064x'%P.y()) )
def p2wsh_nested_script(witness_script): wsh = bh2u(sha256(bfh(witness_script))) return '00' + push_script(wsh)
def p2wpkh_nested_script(pubkey): pkh = bh2u(hash_160(bfh(pubkey))) return '00' + push_script(pkh)
def msg_magic(message: bytes) -> bytes: from .bitcoin import var_int length = bfh(var_int(len(message))) return b"\x18Bitcoin Signed Message:\n" + length + message
def CKD_pub(cK, c, n): if n & BIP32_PRIME: raise Exception() return _CKD_pub(cK, c, bfh(rev_hex(int_to_hex(n, 4))))
def CKD_priv(k, c, n): is_prime = n & BIP32_PRIME return _CKD_priv(k, c, bfh(rev_hex(int_to_hex(n, 4))), is_prime)
def xpub_header(xtype, *, net=None): if net is None: net = constants.net return bfh("%08x" % net.XPUB_HEADERS[xtype])