Exemple #1
0
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)
Exemple #2
0
    def get_public_key(self, f="b64", public_key=None):
        if public_key == None:
            public_key = self.public_key

        #O4 = uncompressed.
        public_key_hex = "04" + binascii.hexlify(public_key).decode("utf-8")
        if self.use_compression:
            public_key = binascii.unhexlify(public_key_hex)
            public_key = self.compress_public_key(public_key)
            public_key_hex = binascii.hexlify(public_key).decode("utf-8")
        else:
            public_key = binascii.unhexlify(public_key_hex)

        cpub = CPubKey(x(public_key_hex))

        if f == "bin":
            return public_key

        elif f == "hex":
            return public_key_hex

        elif f == "cpub":
            return cpub

        elif f == "hash":
            return Hash160(cpub)

        else:
            return base64.b64encode(public_key).decode("utf-8")
Exemple #3
0
def analyze_key_pair(key_pair):
    """
    Converts a key pair to different formats which is useful
    for working with Bitcoin Script.
    """
    if "priv" not in key_pair:
        key_pair["priv"] = None
    pub = CPubKey(x(key_pair["pub"]))

    addr = None
    if "addr" in key_pair:
        addr = key_pair["addr"]
    """
    The Hash160 function in Python-bitcoin lib actually
    wraps around sha256 hash so every call to Hash160
    also sha256 hashes the input before ripemd160 hashing,
    meaning it the output is valid for address hashes.
    """
    return {
        "addr": {
            "base58": addr
        },
        "pub": {
            "hash": Hash160(pub),
            "hex": key_pair["pub"],
            "bin": pub
        },
        "priv": {
            "wif": key_pair["priv"],
            "hex": None,
            "bin": None
        }
    }
Exemple #4
0
    def test_from_valid_pubkey(self):
        """Create P2PKHBitcoinAddress's from valid pubkeys"""

        def T(pubkey, expected_str_addr):
            addr = P2PKHBitcoinAddress.from_pubkey(pubkey)
            self.assertEqual(str(addr), expected_str_addr)

        T(x('0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71'),
          '1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8')
        T(x('0478d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71a1518063243acd4dfe96b66e3f2ec8013c8e072cd09b3834a19f81f659cc3455'),
          '1JwSSubhmg6iPtRjtyqhUYYH7bZg3Lfy1T')

        T(CPubKey(x('0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71')),
          '1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8')
        T(CPubKey(x('0478d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71a1518063243acd4dfe96b66e3f2ec8013c8e072cd09b3834a19f81f659cc3455')),
          '1JwSSubhmg6iPtRjtyqhUYYH7bZg3Lfy1T')
    def test_from_invalid_pubkeys(self):
        """Create P2PKHBitcoinAddress's from invalid pubkeys"""

        # first test with accept_invalid=True
        def T(invalid_pubkey, expected_str_addr):
            addr = P2PKHBitcoinAddress.from_pubkey(invalid_pubkey,
                                                   accept_invalid=True)
            self.assertEqual(str(addr), expected_str_addr)

        T(x(''), '1HT7xU2Ngenf7D4yocz2SAcnNLW7rK8d4E')
        T(
            x('0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c72'
              ), '1L9V4NXbNtZsLjrD3nkU7gtEYLWRBWXLiZ')

        # With accept_invalid=False we should get CBitcoinAddressError's
        with self.assertRaises(CBitcoinAddressError):
            P2PKHBitcoinAddress.from_pubkey(x(''))
        with self.assertRaises(CBitcoinAddressError):
            P2PKHBitcoinAddress.from_pubkey(
                x('0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c72'
                  ))
        with self.assertRaises(CBitcoinAddressError):
            P2PKHBitcoinAddress.from_pubkey(
                CPubKey(
                    x('0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c72'
                      )))
def VerifyMessage(address, message, sig):
    sig = base64.b64decode(sig)
    hash = message.GetHash()

    pubkey = CPubKey.recover_compact(hash, sig)

    return str(P2PKHBitcoinAddress.from_pubkey(pubkey)) == str(address)
Exemple #7
0
 def __init__(self, data):
     if isinstance(data, str):
         data = bytearray.fromhex(data)
     if isinstance(data, bytearray):
         data = bytes(data)
     if not isinstance(data, bytes):
         raise ValueError(
             'PubKey can be constructed only from either hex string, bytearray or byte data'
         )
     object.__setattr__(self, 'cpubkey', CPubKey(data))
Exemple #8
0
def make_fully_valid(pubkey):
    assert len(pubkey) == 31    # One sign byte and one nonce byte required (for 33 bytes).

    cpubkey = CPubKey(b'')
    random_bytes = hashlib.sha256(pubkey).digest()      # Deterministically generated, for unit tests.
    sign = (random_bytes[0] & 0b1) + 2                  # 0x02 or 0x03
    nonce = initial_nonce = random_bytes[1]

    while not cpubkey.is_fullyvalid:
        # Increment nonce.
        nonce += 1
        assert nonce != initial_nonce

        # Construct a possibly fully valid public key.
        possibly_fully_valid_pubkey = bytes([sign]) + pubkey + bytes([nonce % 256])
        cpubkey = CPubKey(possibly_fully_valid_pubkey)

    fully_valid_pubkey = possibly_fully_valid_pubkey
    assert len(fully_valid_pubkey) == 33
    return fully_valid_pubkey
Exemple #9
0
def format_variable_value(value, var_type):
    """Returns a 2-tuple of (is_valid, formatted_value)."""
    if var_type == 'address':
        try:
            h160 = CBase58Data(value).to_bytes()
        except Exception:
            # Check if value is a hash160.
            if is_hex(value) and len(
                    format_hex_string(value, with_prefix=False)) == 40:
                h160 = format_hex_string(value,
                                         with_prefix=False).decode('hex')
            else:
                return False, 'Error: Could not decode address.'
        return True, '0x' + h160.encode('hex')
    elif var_type == 'pubkey':
        if not is_hex(value):
            return False, 'Error: Pubkey must be hex.'
        key_hex = format_hex_string(value, with_prefix=False)
        pub = CPubKey(key_hex.decode('hex'))
        if not pub.is_fullyvalid:
            return False, 'Error: Pubkey is invalid.'
        return True, '0x' + key_hex
    elif var_type == 'text':
        try:
            return True, '0x' + value.encode('hex')
        except Exception as e:
            return False, 'Error: ' + str(e)
    elif var_type == 'signature':
        if not is_hex(value):
            return False, 'Error: Signature must be hex.'
        # We remain algorithm-agnostic by not checking the length.
        return True, format_hex_string(value, with_prefix=True)
    elif var_type == 'script':
        if not is_hex(value):
            try:
                scr = Script.from_human(value)
                return True, format_hex_string(scr.get_hex(), with_prefix=True)
            except Exception:
                return False, 'Error: Cannot parse human-readable script.'
        try:
            scr = Script(
                format_hex_string(value, with_prefix=False).decode('hex'))
            return True, format_hex_string(value, with_prefix=True)
        except Exception:
            return False, 'Error: Cannot parse script.'

    return True, value
Exemple #10
0
    def is_valid(self):
        mb = BitcoinMessage(self.message)
        sig = base64.b64decode(self.sig)
        message_hash = mb.GetHash()

        #print("hash: %s" % message_hash.hex())
        pubkey = CPubKey.recover_compact(message_hash, sig)
        if not pubkey:
            return False
        #print("pubkey: %s" % pubkey.hex())
        if pubkey.hex() == self.address:
            return True
        for txin_type in ['p2pkh', 'p2wpkh', 'p2wpkh-p2sh']:
            addr = pubkey_to_address(txin_type, pubkey.hex())
            if addr == str(self.address):
                return True
        return False
def createTransaction(txid, vout, value, output_address, escrow_index, state):
    """ Create an transaction from an escrow address, defined by a previous txid, to the output address """

    # This will be the return value, a little indirection to not return a Share.
    tx_deferred = Deferred()

    def _fire_response(tx):
        tx_deferred.callback(tx)
        return

    def _signatureCallback(signature, shares, hash, transaction):
        return signature

    def _computeSignatureShare(hash):
        def _get_R(R_deferred):
            R = R_deferred.x()
            return R

        def _compute_summand2(R, k_inv_d_share):
            summand2 = ConstantMultiplicationSmpcValue(state)
            summand2_deferred = summand2.initialize(R, k_inv_d_share)
            return summand2_deferred

        def _final_sum(deferreds):
            global transaction_ctr
            summand1 = WrapperSmpcValue(state)
            summand2 = WrapperSmpcValue(state)
            summand1.initialize(deferreds[0][1])
            summand2.initialize(deferreds[1][1])
            s = AdditionSmpcValue(
                state)  # add secret values of summand1, summand2 (see below)
            s_deferred = s.initialize(summand1, summand2)
            return s_deferred

        # Set parameters for creating the share of the signature
        e = int(hexlify(hash), 16)
        kG_deferred = state.smpc.getValue('k', escrow_index).getPublicValue()
        R = state.smpc.getValue('k', escrow_index).getPublicValue()
        k_inv_share = state.smpc.getValue('ki', escrow_index)
        k_inv_d_share = state.smpc.getValue('kid', escrow_index)
        """ Calculation to be performed: S_share = e * k_inv_share + R * k_inv_d_share """
        try:
            summand1 = ConstantMultiplicationSmpcValue(state)
            summand1_deferred = summand1.initialize(e, k_inv_share)
            kG_deferred.addCallback(_get_R)
            kG_deferred.addCallback(_compute_summand2,
                                    k_inv_d_share=k_inv_d_share)
            R.addCallback(_get_R)
            S_share = DeferredList([summand1_deferred, kG_deferred])
            S_share.addCallback(_final_sum)
            return (S_share, R)
        except BaseException as ex:
            log.critical('Error in signature generation! Error: ' + str(ex))
            raise RuntimeError('signing_share_failed')

    def _signatureToDER(S, R):
        S_der = der.encode_integer(int(S))
        R_der = der.encode_integer(int(R))

        signature_der = der.encode_sequence(R_der, S_der) + chr(0x01)
        return signature_der

    def _reconstruct_signature(S_share):
        try:
            global transaction_ctr
            final_sum = WrapperSmpcValue(state)
            final_sum.initialize(S_share)
            S = state.smpc.newValue('rec', state, 'S', transaction_ctr)
            return S.initialize(final_sum)
        except BaseException as e:
            log.critical('S reconstruction failed! ' + str(e))
            raise RuntimeError('signing_reconstruct_failed')

    def _computeSignature(S_share_R):
        S_share = S_share_R[0][1]
        R = S_share_R[1][1]

        def _extract_signature(_):
            global transaction_ctr
            signature = state.smpc.getValue('S',
                                            transaction_ctr).getPublicValue()
            transaction_ctr += 1
            return signature

        signature = _reconstruct_signature(S_share)
        signature.addCallback(_extract_signature)
        signature.addCallback(_signatureToDER, R=R)
        return signature

    def _computeTransaction(signature, tx, script_pubkey, pubkey):
        txin = tx.vin[0]
        txin.scriptSig = bc.core.script.CScript([signature, pubkey])

        try:
            VerifyScript(txin.scriptSig, script_pubkey, tx, 0,
                         (bc.core.scripteval.SCRIPT_VERIFY_P2SH, ))
        except BaseException as e:
            log.error(str(e))
            raise RuntimeError('signing_failed')

        transaction_serialized = bc.core.b2x(tx.serialize())
        return transaction_serialized

    cpub = CPubKey(state.input.getInputPeer('id', escrow_index)['pubkey'])
    txid = bc.core.lx(txid)

    # TXIN information
    txin = bc.core.CMutableTxIn(bc.core.COutPoint(txid, vout))
    txin_scriptPubKey = bc.core.script.CScript([
        bc.core.script.OP_DUP, bc.core.script.OP_HASH160,
        bc.core.Hash160(cpub), bc.core.script.OP_EQUALVERIFY,
        bc.core.script.OP_CHECKSIG
    ])

    # TXOUT information
    txout = bc.core.CMutableTxOut(
        int(value * bc.core.COIN),
        CBitcoinAddress(output_address).to_scriptPubKey())

    # Create unsigned transaction
    tx = bc.core.CMutableTransaction([txin], [txout])

    # Create signature hash
    sighash = bc.core.script.SignatureHash(txin_scriptPubKey, tx, 0,
                                           bc.core.script.SIGHASH_ALL)
    (S_share, R) = _computeSignatureShare(sighash)
    deferreds = DeferredList([S_share, R])
    deferreds.addCallback(_computeSignature)
    deferreds.addCallback(_computeTransaction,
                          tx=tx,
                          script_pubkey=txin_scriptPubKey,
                          pubkey=cpub)
    deferreds.addCallback(_fire_response)

    return tx_deferred
Exemple #12
0
def is_fully_valid(pubkey_bin):
    """Check if the public key is valid."""
    cpubkey = CPubKey(pubkey_bin)
    return cpubkey.is_fullyvalid
    data = json.load(data_file)

pprint(data)
pprint(data['va'])
parts = data['va'].split('|')
pprint(parts)

msg = parts[0]
sig = parts[2]

pprint(sig)
sig = sig + "==="
pprint(sig)
sig = base64.b64decode(sig, '-_')

msg = BitcoinMessage(msg)
hash = msg.GetHash()

pubkey = CPubKey.recover_compact(hash, sig)
pprint(pubkey)
hex_bytes = binascii.hexlify(pubkey)
pprint(hex_bytes)

print('\n\n')
print('Address:')
print(data['ad'])

print('Pubkey:')
hex_str = hex_bytes.decode("ascii")
print(hex_str)
Exemple #14
0
def initialize(private_key=None):
    """
    Setup and initialize a new vault in the current working directory. This is
    the primary entrypoint for the prototype.
    """

    check_vaultfile_existence()
    check_private_key_is_conformant(private_key)

    #amount = random.randrange(0, 100 * COIN)
    #amount = 7084449357
    amount = 2 * COIN

    # TODO: A more sophisticated private key system is required, for any real
    # production use.
    some_private_keys = [CBitcoinSecret(private_key)] * 6

    parameter_names = [
        "user_key",
        "ephemeral_key_1",
        "ephemeral_key_2",
        "cold_key1",
        "cold_key2",
        "hot_wallet_key",
    ]

    parameters = {
        "num_shards":
        5,
        "enable_burn_transactions":
        True,
        "enable_graphviz":
        True,
        "enable_graphviz_popup":
        False,
        "amount":
        amount,
        "unspendable_key_1":
        CPubKey(
            x("0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"
              )),
    }

    for some_name in parameter_names:
        private_key = some_private_keys.pop()
        public_key = private_key.pub
        parameters[some_name] = {
            "private_key": private_key,
            "public_key": public_key
        }

    parameters["user_key_hash160"] = b2x(
        Hash160(parameters["user_key"]["public_key"]))

    # consistency check against required parameters
    required_parameters = ScriptTemplate.get_required_parameters()

    missing_parameters = False
    for required_parameter in required_parameters:
        if required_parameter not in parameters.keys():
            logger.error(f"Missing parameter: {required_parameter}")
            missing_parameters = True
    if missing_parameters:
        logger.error("Missing parameters!")
        sys.exit(1)

    # connect to bitcoind (ideally, regtest)
    connection = get_bitcoin_rpc_connection()

    # setup the user private key (for P2WPKH)
    connection._call("importprivkey",
                     str(parameters["user_key"]["private_key"]), "user")

    # Mine some coins into the "user_key" P2WPKH address
    #user_address = "bcrt1qrnwea7zc93l5wh77y832wzg3cllmcquqeal7f5"
    # parsed_address = P2WPKHBitcoinAddress(user_address)
    user_address = P2WPKHBitcoinAddress.from_scriptPubKey(
        CScript([OP_0, Hash160(parameters["user_key"]["public_key"])]))
    blocks = 110
    if connection._call("getblockchaininfo")["blocks"] < blocks:
        try:
            connection._call("sendtoaddress", user_address, 50)
        except Exception:
            pass
        connection._call("generatetoaddress", blocks, str(user_address))

    # Now find an unspent UTXO.
    unspent = connection._call("listunspent", 6, 9999, [str(user_address)],
                               True, {"minimumAmount": amount / COIN})
    if len(unspent) == 0:
        raise VaultException(
            "can't find a good UTXO for amount {}".format(amount))

    # pick the first UTXO
    utxo_details = unspent[0]
    txid = utxo_details["txid"]

    # have to consume the whole UTXO
    amount = int(utxo_details["amount"] * COIN)

    initial_tx_txid = lx(utxo_details["txid"])
    initial_tx = InitialTransaction(txid=initial_tx_txid)

    segwit_utxo = PlannedUTXO(
        name="segwit input coin",
        transaction=initial_tx,
        script_template=UserScriptTemplate,
        amount=amount,
    )
    segwit_utxo._vout_override = utxo_details["vout"]
    initial_tx.output_utxos = [segwit_utxo]  # for establishing vout

    # ===============
    # Here's where the magic happens.
    vault_initial_utxo = setup_vault(segwit_utxo, parameters)
    # ===============

    # Check that the tree is conforming to applicable rules.
    safety_check(segwit_utxo.transaction)

    # To test that the sharded UTXOs have the right amounts, do the following:
    # assert (second_utxo_amount * 99) + first_utxo_amount == amount

    # Display all UTXOs and transactions-- render the tree of possible
    # transactions. Mostly helpful for debugging purposes.
    render_planned_tree_to_text_file(segwit_utxo,
                                     filename=TEXT_RENDERING_FILENAME)

    # stats
    logger.info("*** Stats and numbers")
    logger.info(
        f"{PlannedUTXO.__counter__} UTXOs, {PlannedTransaction.__counter__} transactions"
    )

    sign_transaction_tree(segwit_utxo, parameters)

    save(segwit_utxo)

    # TODO: Delete the ephemeral keys.

    # (graph generation can wait until after key deletion)
    if parameters["enable_graphviz"] == True:
        generate_graphviz(segwit_utxo, parameters, output_filename="output.gv")

    # Create another planned transaction tree this time using
    # OP_CHECKTEMPLATEVERIFY from bip119. This can be performed after key
    # deletion because OP_CTV standard template hashes are not based on keys
    # and signatures.
    make_planned_transaction_tree_using_bip119_OP_CHECKTEMPLATEVERIFY(
        initial_tx, parameters=parameters)
    save(segwit_utxo, filename="transaction-store.ctv.json")

    # A vault has been established. Write the vaultfile.
    make_vaultfile()
Exemple #15
0
def is_fully_valid(pubkey_bin):
    cpubkey = CPubKey(pubkey_bin)
    return cpubkey.is_fullyvalid
    {'buyerurlhash': "906618b107da70ed301d701ce8dbff533f35812d"})

phrase = "sample core fitness wrong unusual inch hurry chaos myself credit welcome margin"
seed = mnemonic.Mnemonic.to_seed(phrase)
wallet = BIP32Node.from_master_secret(seed, 'XTN')
toddkeys = []
keys = []
for k in escrow['keys']:
    print k['subkey']
    hdkey = wallet.subkey_for_path(k['subkey'])
    print b2x(CKey(hdkey.sec()).pub)
    print hdkey.sec_as_hex()
    print k['publickey']
    print ""
    toddkeys.append(CKey(hdkey.sec()))
    keys.append(CPubKey(hdkey.address()))
"""
keys = []
for pubkey in escrow['keys']:
    print "PUBLIC KEY", pubkey['publickey']
    keys.append(CPubKey(pubkey['publickey']))
"""

# Create a redeemScript. Similar to a scriptPubKey the redeemScript must be
# satisfied for the funds to be spent.
redeemScript = CScript(keys)
print(b2x(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:
Exemple #17
0
def hodl_redeemScript(pubkey, nLockTime):
    publicKey = CPubKey(x(pubkey))
    return CScript([nLockTime, OP_NOP2, OP_DROP, publicKey, OP_CHECKSIG])
    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))

#print("Uncompressed public key")
c_pubkey = CPubKey(pubkey_bytes)
#print("Is public key valid? ", c_pubkey.is_valid, ", compressed? ", c_pubkey.is_compressed)
assert (c_pubkey.is_compressed == False)
assert (c_pubkey.is_valid == True)

#print("Public Key base58:", pubkey_b58)
#print("           hashed:", encoding.b2a_hashed_base58(pubkey_bytes))

## Compressed public key
pubkey_bytes = encoding.public_pair_to_sec(pubkey_pair, True)
# compressed
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'])