Example #1
0
    def test_msg_signing(self):
        msg1 = b'Chancellor on brink of second bailout for banks'
        msg2 = b'Electrum'

        def sign_message_with_wif_privkey(wif_privkey, msg):
            key = PrivateKey.from_WIF(wif_privkey)
            return key.sign_message(msg)

        sig1 = sign_message_with_wif_privkey(
            'L1TnU2zbNaAqMoVh65Cyvmcjzbrj41Gs9iTLcWbpJCMynXuap6UN', msg1)
        addr1 = '15hETetDmcXm1mM4sEf7U2KXC9hDHFMSzz'
        sig2 = sign_message_with_wif_privkey(
            '5Hxn5C4SQuiV6e62A1MtZmbSeQyrLFhu5uYks62pU5VBUygK2KD', msg2)
        addr2 = '1GPHVTY8UD9my6jyP4tb2TYJwUbDetyNC6'

        sig1_b64 = base64.b64encode(sig1)
        sig2_b64 = base64.b64encode(sig2)

        self.assertEqual(sig1_b64, b'H/9jMOnj4MFbH3d7t4yCQ9i7DgZU/VZ278w3+ySv2F4yIsdqjsc5ng3kmN8OZAThgyfCZOQxZCWza9V5XzlVY0Y=')
        self.assertEqual(sig2_b64, b'G84dmJ8TKIDKMT9qBRhpX2sNmR0y5t+POcYnFFJCs66lJmAs3T8A6Sbpx7KA6yTQ9djQMabwQXRrDomOkIKGn18=')

        self.assertTrue(PublicKey.verify_message_and_address(sig1, msg1, addr1))
        self.assertTrue(PublicKey.verify_message_and_address(sig2, msg2, addr2))

        self.assertFalse(PublicKey.verify_message_and_address(b'wrong', msg1, addr1))
        self.assertFalse(PublicKey.verify_message_and_address(sig2, msg1, addr1))
Example #2
0
 def from_pubkey(cls, pubkey):
     '''Returns a P2PKH address from a public key.  The public key can
     be bytes or a hex string.'''
     if isinstance(pubkey, str):
         pubkey = PublicKey.from_hex(pubkey)
     else:
         pubkey = PublicKey.from_bytes(pubkey)
     return cls(hash_160(pubkey.to_bytes()), cls.ADDR_P2PKH)
Example #3
0
 def _is_public_key_valid(self, hex: str) -> bool:
     try:
         PublicKey.from_hex(hex)
         return True
     except (ValueError, TypeError):
         # ValueError <- PublicKey.from_hex()
         # TypeError <- PublicKey()
         return False
Example #4
0
 def multisig_script(cls, m, pubkeys):
     '''Returns the script for a pay-to-multisig transaction.'''
     n = len(pubkeys)
     if not 1 <= m <= n <= 15:
         raise ScriptError(
             '{:d} of {:d} multisig script not possible'.format(m, n))
     for pubkey in pubkeys:
         PublicKey.from_bytes(pubkey)  # Can be compressed or not
     # See https://bitcoin.org/en/developer-guide
     # 2 of 3 is: OP_2 pubkey1 pubkey2 pubkey3 OP_3 OP_CHECKMULTISIG
     return (bytes([Ops.OP_1 + m - 1]) +
             b''.join(cls.push_data(pubkey) for pubkey in pubkeys) +
             bytes([Ops.OP_1 + n - 1, Ops.OP_CHECKMULTISIG]))
Example #5
0
    def get_master_public_key(self, bip32_path):
        self.checkDevice()
        # bip32_path is of the form 44'/0'/1'
        # S-L-O-W - we don't handle the fingerprint directly, so compute
        # it manually from the previous node
        # This only happens once so it's bearable
        #self.get_client() # prompt for the PIN before displaying the dialog if necessary
        #self.handler.show_message("Computing master public key")
        splitPath = bip32_path.split('/')
        if splitPath[0] == 'm':
            splitPath = splitPath[1:]
            bip32_path = bip32_path[2:]
        fingerprint = 0
        if len(splitPath) > 1:
            prevPath = "/".join(splitPath[0:len(splitPath) - 1])
            nodeData = self.dongleObject.getWalletPublicKey(prevPath)
            publicKey = compress_public_key(nodeData['publicKey'])
            h = hashlib.new('ripemd160')
            h.update(hashlib.sha256(publicKey).digest())
            fingerprint = unpack(">I", h.digest()[0:4])[0]
        nodeData = self.dongleObject.getWalletPublicKey(bip32_path)
        publicKey = bytes(compress_public_key(nodeData['publicKey']))
        depth = len(splitPath)
        lastChild = splitPath[len(splitPath) - 1].split('\'')
        childnum = int(lastChild[0]) if len(
            lastChild) == 1 else 0x80000000 | int(lastChild[0])

        derivation = BIP32Derivation(
            chain_code=nodeData['chainCode'],
            depth=depth,
            parent_fingerprint=pack_be_uint32(fingerprint),
            n=childnum)
        return BIP32PublicKey(PublicKey.from_bytes(publicKey), derivation,
                              Net.COIN)
Example #6
0
 def test_to_address_compressed(self):
     pubkey_hex = '036d6caac248af96f6afa7f904f550253a0f3ef3f5aa2fe6838a95b216691468e2'
     pubkey = PublicKey.from_hex(pubkey_hex)
     output = P2PK_Output(pubkey, Bitcoin)
     address = output.to_address()
     assert isinstance(address, P2PKH_Address)
     assert address.to_string() == '16ZbRYV2f1NNuNQ9FDYyUMC2d1cjGS2G3L'
Example #7
0
    def _write(self):
        if threading.currentThread().isDaemon():
            logger.error('daemon thread cannot write wallet')
            return
        if not self.modified:
            return
        s = json.dumps(self.data, indent=4, sort_keys=True)
        if self.pubkey:
            c = zlib.compress(s.encode())
            s = PublicKey.from_hex(self.pubkey).encrypt_message_to_base64(c)

        temp_path = "%s.tmp.%s" % (self.path, os.getpid())
        with open(temp_path, "w", encoding='utf-8') as f:
            f.write(s)
            f.flush()
            os.fsync(f.fileno())

        mode = os.stat(self.path).st_mode if self.file_exists(
        ) else stat.S_IREAD | stat.S_IWRITE
        # perform atomic write on POSIX systems
        try:
            os.rename(temp_path, self.path)
        except:
            os.remove(self.path)
            os.rename(temp_path, self.path)
        os.chmod(self.path, mode)
        self._file_exists = True
        self.raw = s
        logger.debug("saved '%s'", self.path)
        self.modified = False
Example #8
0
    def _convert_version_14(self) -> None:
        # convert imported wallets for 3.0
        if not self._is_upgrade_method_needed(13, 13):
            return

        if self.get('wallet_type') == 'imported':
            addresses = self.get('addresses')
            if type(addresses) is list:
                addresses = dict([(x, None) for x in addresses])
                self.put('addresses', addresses)
        elif self.get('wallet_type') == 'standard':
            if self.get('keystore').get('type') == 'imported':
                addresses = set(self.get('addresses').get('receiving'))
                pubkeys = self.get('keystore').get('keypairs').keys()
                assert len(addresses) == len(pubkeys)
                d = {}
                for pubkey in pubkeys:
                    addr = PublicKey.from_hex(pubkey).to_address(
                        coin=Net.COIN).to_string()
                    assert addr in addresses
                    d[addr] = {
                        'pubkey': pubkey,
                        'redeem_script': None,
                        'type': 'p2pkh'
                    }
                self.put('addresses', d)
                self.put('pubkeys', None)
                self.put('wallet_type', 'imported')
        self.put('seed_version', 14)
    def do_send(self, window: 'ElectrumWindow', account: AbstractAccount,
                tx: Transaction) -> None:
        def on_done(window, future):
            try:
                future.result()
            except Exception as exc:
                window.on_exception(exc)
            else:
                window.show_message('\n'.join((
                    _("Your transaction was sent to the cosigning pool."),
                    _("Open your cosigner wallet to retrieve it."),
                )))

        def send_message():
            server.put(item.keyhash_hex, message)

        account_id = account.get_id()
        for item in self._items:
            if self._is_theirs(window, account_id, item, tx):
                raw_tx_bytes = json.dumps(tx.to_dict()).encode()
                public_key = PublicKey.from_bytes(item.pubkey_bytes)
                message = public_key.encrypt_message_to_base64(raw_tx_bytes)
                WaitingDialog(item.window,
                              _('Sending transaction to cosigning pool...'),
                              send_message,
                              on_done=partial(on_done, item.window))
Example #10
0
    def sign_message(self, sequence, message, password):
        sig = None
        try:
            message = message.encode('utf8')
            inputPath = self.get_derivation() + "/%d/%d" % sequence
            msg_hash = sha256d(msg_magic(message))
            inputHash = msg_hash.hex()
            hasharray = []
            hasharray.append({'hash': inputHash, 'keypath': inputPath})
            hasharray = json.dumps(hasharray)

            msg = b'{"sign":{"meta":"sign message", "data":%s}}' % hasharray.encode(
                'utf8')

            dbb_client = self.plugin.get_client(self)

            if not dbb_client.is_paired():
                raise Exception(_("Bitbox does not appear to be connected."))

            reply = dbb_client.hid_send_encrypt(msg)
            self.handler.show_message(
                _("Signing message ...") + "\n\n" +
                _("To continue, touch the Digital Bitbox's blinking light for "
                  "3 seconds.") + "\n\n" +
                _("To cancel, briefly touch the blinking light or wait for the timeout."
                  ))
            # Send twice, first returns an echo for smart verification (not implemented)
            reply = dbb_client.hid_send_encrypt(msg)
            self.handler.finished()

            if 'error' in reply:
                raise Exception(reply['error']['message'])

            if 'sign' not in reply:
                raise Exception(_("Bitbox did not sign the message."))

            siginfo = reply['sign'][0]
            compact_sig = bytes.fromhex(siginfo['sig'])
            if 'recid' in siginfo:
                recids = [int(siginfo['recid'], 16)]
            else:
                recids = range(4)
            for recid in recids:
                # firmware > v2.1.1
                message_sig = bytes([recid + 27]) + compact_sig
                try:
                    pubkey = PublicKey.from_signed_message(
                        message_sig, message)
                except Exception:
                    logger.exception(
                        f"If Digital Bitbox signing failed, this may be why")
                    continue
                if pubkey.verify_message(message_sig, message):
                    return message_sig
            raise RuntimeError(
                _("Unable to sign as Bitbox failed to provide a valid signature"
                  ))
        except Exception as e:
            self.give_error(e)
        return sig
Example #11
0
 def test_to_script_bytes(self):
     pubkey_hex = '0363f75554e05e05a04551e59d78d78965ec6789f42199f7cbaa9fa4bd2df0a4b4'
     pubkey = PublicKey.from_hex(pubkey_hex)
     output = P2PK_Output(pubkey, Bitcoin)
     raw = output.to_script_bytes()
     assert isinstance(raw, bytes)
     assert raw == push_item(bytes.fromhex(pubkey_hex)) + pack_byte(OP_CHECKSIG)
Example #12
0
    def get_tx_derivations(self, tx):
        keypairs = {}
        for txin_index, txin in enumerate(tx.inputs()):
            sigs = txin['signatures']
            x_pubkeys = txin['x_pubkeys']

            # Remove pubkeys that have already signed
            used = set()
            sig_idx = len(sigs) - 1
            pub_idx = len(x_pubkeys) - 1
            pre_hash = tx.preimage_hash(txin_index)
            while sig_idx >= 0:
                sig = sigs[sig_idx]
                sig_idx -= 1
                if sig is not None:
                    sig = bytes.fromhex(sig)[:-1]
                    while pub_idx >= 0:
                        x_pubkey = x_pubkeys[pub_idx]
                        public_key = PublicKey.from_hex(
                            xpubkey_to_pubkey(x_pubkey))
                        used.add(x_pubkey)
                        if public_key.verify_der_signature(
                                sig, pre_hash, None):
                            break
                        pub_idx -= 1
                pub_idx -= 1
            for x_pubkey in x_pubkeys:
                if x_pubkey in used:
                    continue
                derivation = self.get_pubkey_derivation(x_pubkey)
                if not derivation:
                    continue
                keypairs[x_pubkey] = derivation
        return keypairs
Example #13
0
 def get_pubkey_derivation(self, x_pubkey):
     if x_pubkey[0:2] in ['02', '03', '04']:
         pubkey = PublicKey.from_hex(x_pubkey)
         if pubkey in self.keypairs:
             return pubkey
     elif x_pubkey[0:2] == 'fd':
         addr = _script_to_address(x_pubkey[2:])
         return self.address_to_pubkey(addr)
Example #14
0
 def test_to_script(self):
     pubkey_hex = '0363f75554e05e05a04551e59d78d78965ec6789f42199f7cbaa9fa4bd2df0a4b4'
     pubkey = PublicKey.from_hex(pubkey_hex)
     output = P2PK_Output(pubkey, Bitcoin)
     S = output.to_script()
     assert isinstance(S, Script)
     assert S == output.to_script_bytes()
     assert isinstance(classify_output_script(S, Bitcoin), P2PK_Output)
Example #15
0
 def createmultisig(self, threshold, pubkeys):
     """Create multisig address"""
     assert isinstance(pubkeys, list), (type(threshold), type(pubkeys))
     public_keys = [PublicKey.from_hex(pubkey) for pubkey in sorted(pubkeys)]
     output = P2MultiSig_Output(public_keys, threshold)
     redeem_script = output.to_script_bytes()
     address = P2SH_Address(hash160(redeem_script)).to_string()
     return {'address':address, 'redeemScript':redeem_script.hex()}
Example #16
0
 def __init__(self, d):
     Software_KeyStore.__init__(self)
     keypairs = d.get('keypairs', {})
     self.keypairs = {
         PublicKey.from_hex(pubkey): enc_privkey
         for pubkey, enc_privkey in keypairs.items()
     }
     self._sorted = None
Example #17
0
    def load_state(self, keyinstance_rows: List[KeyInstanceRow]) -> None:
        self._keypairs.clear()
        self._public_keys.clear()

        for row in keyinstance_rows:
            data = json.loads(row.derivation_data)
            public_key = PublicKey.from_hex(data['pub'])
            self._public_keys[row.keyinstance_id] = public_key
            self._keypairs[public_key] = cast(str, data['prv'])
Example #18
0
 def test_update_password(self):
     keystore = Imported_KeyStore()
     keystore._keypairs = { PublicKey.from_hex(a): b for a, b in keypairs_dict.items() }
     keystore.update_password('new password', 'password')
     pubkey = list(keystore._keypairs.keys())[0]
     assert keystore.export_private_key(pubkey, 'new password') == (
         'KwdMAjGmerYanjeui5SHS7JkmpZvVipYvB2LJGU1ZxJwYvP98617')
     with pytest.raises(AssertionError):
         keystore.update_password('', 'new password')
 def test_raw_public_keys(self, raw_hex, coin):
     public_key = PublicKey.from_hex(raw_hex)
     x_pubkey = XPublicKey.from_hex(raw_hex)
     # assert x_pubkey.to_bytes() == bytes.fromhex(raw_hex)
     # assert x_pubkey.to_hex() == raw_hex
     assert not x_pubkey.is_bip32_key()
     assert x_pubkey.to_public_key() == public_key
     assert x_pubkey.to_address() == public_key.to_address(coin=coin)
     assert x_pubkey.to_address().coin() is coin
Example #20
0
 def to_public_key(self) -> Union[BIP32PublicKey, PublicKey]:
     '''Returns a PublicKey instance or an Address instance.'''
     kind = self.kind()
     if self._pubkey_bytes is not None:
         return PublicKey.from_bytes(self._pubkey_bytes)
     elif self._bip32_xpub is not None:
         assert self._derivation_path is not None
         result = bip32_key_from_string(self._bip32_xpub)
         for n in self._derivation_path:
             result = result.child(n)
         return result
     elif self._old_mpk is not None:
         assert self._derivation_path is not None
         path = self._derivation_path
         pubkey = PublicKey.from_bytes(pack_byte(4) + self._old_mpk)
         # pylint: disable=unsubscriptable-object
         delta = double_sha256(f'{path[1]}:{path[0]}:'.encode() + self._old_mpk)
         return pubkey.add(delta)
     raise ValueError("invalid key data")
Example #21
0
 def test_to_address_uncompressed(self):
     pubkey_hex = (
         '046d6caac248af96f6afa7f904f550253a0f3ef3f5aa2fe6838a95b216691468e'
         '2487e6222a6664e079c8edf7518defd562dbeda1e7593dfd7f0be285880a24dab'
     )
     pubkey = PublicKey.from_hex(pubkey_hex)
     output = P2PK_Output(pubkey, Bitcoin)
     address = output.to_address()
     assert isinstance(address, P2PKH_Address)
     assert address.to_string() == '1G9f5Kdd5A8MeBN8jduUNfcAXUVvtFxVhP'
Example #22
0
def test_signatures(filename):
    tx, values, pk_scripts = read_json_tx(filename)

    for input_index, (value, pk_script,
                      txin) in enumerate(zip(values, pk_scripts, tx.inputs)):
        signature, pubkey = txin.script_sig.ops()
        pubkey = PublicKey.from_bytes(pubkey)
        signature_hash = tx.signature_hash(input_index, value, pk_script,
                                           SigHash(signature[-1]))
        assert pubkey.verify_der_signature(signature[:-1], signature_hash,
                                           None)
 def test_old_keystore(self, raw_hex, public_key_hex, coin):
     public_key = PublicKey.from_hex(public_key_hex)
     assert public_key.is_compressed() is False
     x_pubkey = XPublicKey.from_hex(raw_hex)
     # assert x_pubkey.to_bytes() == bytes.fromhex(raw_hex)
     # assert x_pubkey.to_hex() == raw_hex
     assert not x_pubkey.is_bip32_key()
     assert x_pubkey.to_public_key() == public_key
     assert x_pubkey.to_public_key().is_compressed() is False
     assert x_pubkey.to_address() == public_key.to_address(coin=coin)
     assert x_pubkey.to_address().coin() is coin
Example #24
0
 def get_master_public_key(self, bip32_path, creating=False):
     address_n = bip32_decompose_chain_string(bip32_path)
     with self.run_flow(creating_wallet=creating):
         node = trezorlib.btc.get_public_node(self.client, address_n).node
     self.used()
     derivation = BIP32Derivation(chain_code=node.chain_code,
                                  depth=node.depth,
                                  parent_fingerprint=pack_be_uint32(
                                      node.fingerprint),
                                  n=node.child_num)
     return BIP32PublicKey(PublicKey.from_bytes(node.public_key),
                           derivation, Net.COIN)
Example #25
0
 def get_master_public_key(self, bip32_path):
     address_n = bip32_decompose_chain_string(bip32_path)
     creating = False
     node = self.get_public_node(address_n, creating).node
     self.used()
     derivation = BIP32Derivation(chain_code=node.chain_code,
                                  depth=node.depth,
                                  parent_fingerprint=pack_be_uint32(
                                      node.fingerprint),
                                  n=node.child_num)
     return BIP32PublicKey(PublicKey.from_bytes(node.public_key),
                           derivation, Net.COIN)
Example #26
0
 def to_public_key(self):
     '''Returns a PublicKey instance or an Address instance.'''
     kind = self.kind()
     if kind in {0x02, 0x03, 0x04}:
         return PublicKey.from_bytes(self.raw)
     if kind == 0xff:
         return self._bip32_public_key()
     if kind == 0xfe:
         return self._old_keystore_public_key()
     assert kind == 0xfd
     result = classify_output_script(Script(self.raw[1:]), Net.COIN)
     assert isinstance(result, Address)
     return result
Example #27
0
 def get_master_public_key(self,
                           bip32_path: str,
                           creating: bool = False) -> BIP32PublicKey:
     address_n = bip32_decompose_chain_string(bip32_path)
     # This will be cleared by the wrapper around `get_public_node`.
     self.creating_wallet = creating
     node = self.get_public_node(address_n).node
     self.used()
     derivation = BIP32Derivation(chain_code=node.chain_code,
                                  depth=node.depth,
                                  parent_fingerprint=pack_be_uint32(
                                      node.fingerprint),
                                  n=node.child_num)
     return BIP32PublicKey(PublicKey.from_bytes(node.public_key),
                           derivation, Net.COIN)
Example #28
0
    def _write(self) -> bytes:
        # We pack as JSON before encrypting, so can't just put in the generic key value store,
        # as that is unencrypted and would just be JSON values in the DB.

        s = json.dumps(self._data, indent=4, sort_keys=True)
        if self._pubkey:
            c = zlib.compress(s.encode())
            raw = PublicKey.from_hex(self._pubkey).encrypt_message(c)
        else:
            raw = s.encode()

        self._db_values.set("jsondata", raw)
        self._primed = True

        return raw
Example #29
0
 def get_preimage_script(self, txin):
     _type = txin['type']
     if _type == 'p2pkh':
         return txin['address'].to_script_bytes().hex()
     elif _type == 'p2sh':
         pubkeys, x_pubkeys = self.get_sorted_pubkeys(txin)
         return multisig_script(pubkeys, txin['num_sig'])
     elif _type == 'p2pk':
         output = P2PK_Output(PublicKey.from_hex(txin['pubkeys'][0]))
         return output.to_script_bytes().hex()
     elif _type == 'unknown':
         # this approach enables most P2SH smart contracts
         # (but take care if using OP_CODESEPARATOR)
         return txin['scriptCode']
     else:
         raise RuntimeError('Unknown txin type', _type)
Example #30
0
def xpubkey_to_address(x_pubkey):
    if x_pubkey[0:2] == 'fd':
        address = _script_to_address(x_pubkey[2:])
        return x_pubkey, address
    if x_pubkey[0:2] in ['02', '03', '04']:
        pubkey = x_pubkey
    elif x_pubkey[0:2] == 'ff':
        xpub, s = BIP32_KeyStore.parse_xpubkey(x_pubkey)
        pubkey = BIP32_KeyStore.get_pubkey_from_xpub(xpub, s)
    elif x_pubkey[0:2] == 'fe':
        mpk, s = Old_KeyStore.parse_xpubkey(x_pubkey)
        pubkey = Old_KeyStore.get_pubkey_from_mpk(mpk, s[0], s[1])
    else:
        raise Exception("Cannot parse pubkey")
    if pubkey:
        address = PublicKey.from_hex(pubkey).to_address(coin=Net.COIN)
    return pubkey, address