URI: 
       tx509 fixes and plugins - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 362ca96f382afd8f8cdb31c123df930eca461f49
   DIR parent 0693403358656f1e7d5453679f125ab48d7fb644
  HTML Author: Dmitry Sorokin <asfins@gmail.com>
       Date:   Sun,  5 Feb 2017 13:38:44 +0300
       
       x509 fixes and plugins
       
       Diffstat:
         M lib/base_wizard.py                  |      11 ++++++-----
         M lib/bitcoin.py                      |       8 ++++----
         M lib/daemon.py                       |      66 ++++++++++++++++----------------
         M lib/keystore.py                     |      12 ++++++------
         M lib/mnemonic.py                     |       2 +-
         M lib/paymentrequest.py               |       1 -
         M lib/pem.py                          |      14 +++++++-------
         M lib/plugins.py                      |       8 +-------
         M lib/storage.py                      |       6 ------
         M lib/util.py                         |       4 ++--
         M lib/wallet.py                       |       2 --
         M lib/x509.py                         |      53 ++++++++++++++++++++-----------
         M plugins/cosigner_pool/qt.py         |       4 ++--
         M plugins/email_requests/qt.py        |      11 ++++-------
         M plugins/hw_wallet/__init__.py       |       2 +-
         M plugins/labels/labels.py            |      10 ++++------
         M plugins/labels/qt.py                |       2 +-
         M plugins/virtualkeyboard/qt.py       |      10 +++++-----
       
       18 files changed, 111 insertions(+), 115 deletions(-)
       ---
   DIR diff --git a/lib/base_wizard.py b/lib/base_wizard.py
       t@@ -189,7 +189,7 @@ class BaseWizard(object):
                    except:
                        devmgr.print_error("error", name)
                        continue
       -            devices += map(lambda x: (name, x), u)
       +            devices += list(map(lambda x: (name, x), u))
                if not devices:
                    msg = ''.join([
                        _('No hardware device detected.') + '\n',
       t@@ -235,7 +235,7 @@ class BaseWizard(object):
                self.line_dialog(run_next=f, title=_('Derivation'), message=message, default=default, test=bitcoin.is_bip32_derivation)
        
            def on_hw_derivation(self, name, device_info, derivation):
       -        from keystore import hardware_keystore
       +        from .keystore import hardware_keystore
                xpub = self.plugin.get_xpub(device_info.device.id_, derivation, self)
                if xpub is None:
                    self.show_error('Cannot read xpub from device')
       t@@ -286,7 +286,7 @@ class BaseWizard(object):
                        self.load_2fa()
                        self.run('on_restore_seed', seed, is_ext)
                else:
       -            raise BaseException('Unknown seed type', seed_type)
       +            raise BaseException('Unknown seed type', self.seed_type)
        
            def on_restore_bip39(self, seed, passphrase):
                f = lambda x: self.run('on_bip44', seed, passphrase, str(x))
       t@@ -334,7 +334,8 @@ class BaseWizard(object):
                        k.update_password(None, password)
                if self.wallet_type == 'standard':
                    self.storage.put('seed_type', self.seed_type)
       -            self.storage.put('keystore', k.dump())
       +            keys = self.keystores[0].dump()
       +            self.storage.put('keystore', keys)
                    self.wallet = Standard_Wallet(self.storage)
                    self.run('create_addresses')
                elif self.wallet_type == 'multisig':
       t@@ -355,7 +356,7 @@ class BaseWizard(object):
                self.on_keystore(k)
        
            def create_seed(self):
       -        import mnemonic
       +        from . import mnemonic
                self.seed_type = 'segwit' if bitcoin.TESTNET and self.config.get('segwit') else 'standard'
                seed = mnemonic.Mnemonic('en').make_seed(self.seed_type)
                self.opt_bip39 = False
   DIR diff --git a/lib/bitcoin.py b/lib/bitcoin.py
       t@@ -29,7 +29,7 @@ import re
        import hmac
        import os
        
       -from lib.util import bfh, bh2u
       +from lib.util import bfh, bh2u, to_string
        from . import version
        from .util import print_error, InvalidPassword, assert_bytes, to_bytes
        
       t@@ -150,7 +150,7 @@ def DecodeAES(secret, e):
        def pw_encode(s, password):
            if password:
                secret = Hash(password)
       -        return EncodeAES(secret, s.encode("utf8"))
       +        return EncodeAES(secret, to_bytes(s, "utf8"))
            else:
                return s
        
       t@@ -158,7 +158,7 @@ def pw_decode(s, password):
            if password is not None:
                secret = Hash(password)
                try:
       -            d = DecodeAES(secret, s).decode("utf8")
       +            d = to_string(DecodeAES(secret, s), "utf8")
                except Exception:
                    raise InvalidPassword()
                return d
       t@@ -213,7 +213,7 @@ def Hash(x):
        
        hash_encode = lambda x: bh2u(x[::-1])
        hash_decode = lambda x: bfh(x)[::-1]
       -hmac_sha_512 = lambda x, y: _bytes(hmac.new(x, y, hashlib.sha512).digest())
       +hmac_sha_512 = lambda x, y: hmac.new(x, y, hashlib.sha512).digest()
        
        
        def is_new_seed(x, prefix=version.SEED_PREFIX):
   DIR diff --git a/lib/daemon.py b/lib/daemon.py
       t@@ -34,8 +34,8 @@ import sys
        import time
        
        # from jsonrpc import JSONRPCResponseManager
       -import jsonrpclib
       -from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer, SimpleJSONRPCRequestHandler
       +# import jsonrpclib
       +# from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer, SimpleJSONRPCRequestHandler
        
        from .version import ELECTRUM_VERSION
        from .network import Network
       t@@ -96,17 +96,17 @@ def get_server(config):
                time.sleep(1.0)
        
        
       -class RequestHandler(SimpleJSONRPCRequestHandler):
       -
       -    def do_OPTIONS(self):
       -        self.send_response(200)
       -        self.end_headers()
       -
       -    def end_headers(self):
       -        self.send_header("Access-Control-Allow-Headers",
       -                         "Origin, X-Requested-With, Content-Type, Accept")
       -        self.send_header("Access-Control-Allow-Origin", "*")
       -        SimpleJSONRPCRequestHandler.end_headers(self)
       +# class RequestHandler(SimpleJSONRPCRequestHandler):
       +#
       +#     def do_OPTIONS(self):
       +#         self.send_response(200)
       +#         self.end_headers()
       +#
       +#     def end_headers(self):
       +#         self.send_header("Access-Control-Allow-Headers",
       +#                          "Origin, X-Requested-With, Content-Type, Accept")
       +#         self.send_header("Access-Control-Allow-Origin", "*")
       +#         SimpleJSONRPCRequestHandler.end_headers(self)
        
        
        class Daemon(DaemonThread):
       t@@ -132,24 +132,24 @@ class Daemon(DaemonThread):
            def init_server(self, config, fd):
                host = config.get('rpchost', '127.0.0.1')
                port = config.get('rpcport', 0)
       -        try:
       -            server = SimpleJSONRPCServer((host, port), logRequests=False,
       -                                         requestHandler=RequestHandler)
       -        except Exception as e:
       -            self.print_error('Warning: cannot initialize RPC server on host', host, e)
       -            self.server = None
       -            os.close(fd)
       -            return
       -        os.write(fd, bytes(repr((server.socket.getsockname(), time.time())), 'utf8'))
       -        os.close(fd)
       -        server.timeout = 0.1
       -        for cmdname in known_commands:
       -            server.register_function(getattr(self.cmd_runner, cmdname), cmdname)
       -        server.register_function(self.run_cmdline, 'run_cmdline')
       -        server.register_function(self.ping, 'ping')
       -        server.register_function(self.run_daemon, 'daemon')
       -        server.register_function(self.run_gui, 'gui')
       -        self.server = server
       +        # try:
       +        #     server = SimpleJSONRPCServer((host, port), logRequests=False, requestHandler=RequestHandler)
       +        # except Exception as e:
       +        #     self.print_error('Warning: cannot initialize RPC server on host', host, e)
       +        #     self.server = None
       +        #     os.close(fd)
       +        #     return
       +        # os.write(fd, bytes(repr((server.socket.getsockname(), time.time())), 'utf8'))
       +        # os.close(fd)
       +        # server.timeout = 0.1
       +        # for cmdname in known_commands:
       +        #     server.register_function(getattr(self.cmd_runner, cmdname), cmdname)
       +        # server.register_function(self.run_cmdline, 'run_cmdline')
       +        # server.register_function(self.ping, 'ping')
       +        # server.register_function(self.run_daemon, 'daemon')
       +        # server.register_function(self.run_gui, 'gui')
       +        # self.server = server
       +        self.server = None
        
            def ping(self):
                return True
       t@@ -260,9 +260,9 @@ class Daemon(DaemonThread):
                # arguments passed to function
                args = map(lambda x: config.get(x), cmd.params)
                # decode json arguments
       -        args = map(json_decode, args)
       +        args = [json_decode(i) for i in args]
                # options
       -        args += map(lambda x: (config_options.get(x) if x in ['password', 'new_password'] else config.get(x)), cmd.options)
       +        args += list(map(lambda x: (config_options.get(x) if x in ['password', 'new_password'] else config.get(x)), cmd.options))
                cmd_runner = Commands(config, wallet, self.network)
                func = getattr(cmd_runner, cmd.name)
                result = func(*args)
   DIR diff --git a/lib/keystore.py b/lib/keystore.py
       t@@ -149,7 +149,7 @@ class Imported_KeyStore(Software_KeyStore):
                except Exception:
                    raise BaseException('Invalid private key')
                # allow overwrite
       -        self.keypairs[pubkey] = pw_encode(sec, password)
       +        self.keypairs[pubkey] = pw_encode(sec, password).decode('ascii')
                return pubkey
        
            def delete_imported_key(self, key):
       t@@ -179,7 +179,7 @@ class Imported_KeyStore(Software_KeyStore):
                    new_password = None
                for k, v in self.keypairs.items():
                    b = pw_decode(v, old_password)
       -            c = pw_encode(b, new_password)
       +            c = pw_encode(b, new_password).decode('ascii')
                    self.keypairs[k] = c
        
        
       t@@ -309,13 +309,13 @@ class BIP32_KeyStore(Deterministic_KeyStore, Xpub):
                    new_password = None
                if self.has_seed():
                    decoded = self.get_seed(old_password)
       -            self.seed = pw_encode(decoded, new_password)
       +            self.seed = pw_encode(decoded, new_password).decode('ascii')
                if self.passphrase:
                    decoded = self.get_passphrase(old_password)
       -            self.passphrase = pw_encode(decoded, new_password)
       +            self.passphrase = pw_encode(decoded, new_password).decode('ascii')
                if self.xprv is not None:
                    b = pw_decode(self.xprv, old_password)
       -            self.xprv = pw_encode(b, new_password)
       +            self.xprv = pw_encode(b, new_password).decode('ascii')
        
            def is_watching_only(self):
                return self.xprv is None
       t@@ -478,7 +478,7 @@ class Old_KeyStore(Deterministic_KeyStore):
                    new_password = None
                if self.has_seed():
                    decoded = self.get_hex_seed(old_password)
       -            self.seed = pw_encode(decoded, new_password)
       +            self.seed = pw_encode(decoded, new_password).decode('ascii')
        
        
        class Hardware_KeyStore(KeyStore, Xpub):
   DIR diff --git a/lib/mnemonic.py b/lib/mnemonic.py
       t@@ -173,7 +173,7 @@ class Mnemonic(object):
                return i % custom_entropy == 0
        
            def make_seed(self, seed_type='standard', num_bits=132, custom_entropy=1):
       -        import version
       +        from . import version
                prefix = version.seed_prefix(seed_type)
                # increase num_bits in order to obtain a uniform distibution for the last word
                bpw = math.log(len(self.wordlist), 2)
   DIR diff --git a/lib/paymentrequest.py b/lib/paymentrequest.py
       t@@ -345,7 +345,6 @@ def sign_request_with_alias(pr, alias, alias_privkey):
            pr.signature = ec_key.sign_message(message, compressed, address)
        
        
       -
        def verify_cert_chain(chain):
            """ Verify a chain of certificates. The last certificate is the CA"""
            load_ca_list()
   DIR diff --git a/lib/pem.py b/lib/pem.py
       t@@ -127,12 +127,12 @@ def pem(b, name):
            -----END CERTIFICATE-----    
            """
            s1 = b2a_base64(b)[:-1] # remove terminating \n
       -    s2 = ""
       +    s2 = b""
            while s1:
       -        s2 += s1[:64] + "\n"
       +        s2 += s1[:64] + b"\n"
                s1 = s1[64:]
       -    s = ("-----BEGIN %s-----\n" % name) + s2 + \
       -        ("-----END %s-----\n" % name)     
       +    s = ("-----BEGIN %s-----\n" % name).encode('ascii') + s2 + \
       +        ("-----END %s-----\n" % name).encode('ascii')
            return s
        
        def pemSniff(inStr, name):
       t@@ -152,8 +152,8 @@ def parse_private_key(s):
                raise SyntaxError("Not a PEM private key file")
        
        
       -def _parsePKCS8(bytes):
       -    s = ASN1_Node(str(bytes))
       +def _parsePKCS8(_bytes):
       +    s = ASN1_Node(_bytes)
            root = s.root()
            version_node = s.first_child(root)
            version = bytestr_to_int(s.get_value_of_type(version_node, 'INTEGER'))
       t@@ -192,5 +192,5 @@ def _parseASN1PrivateKey(s):
            dP = s.next_node(q)
            dQ = s.next_node(dP)
            qInv = s.next_node(dQ)
       -    return map(lambda x: bytesToNumber(s.get_value_of_type(x, 'INTEGER')), [n, e, d, p, q, dP, dQ, qInv])
       +    return list(map(lambda x: bytesToNumber(s.get_value_of_type(x, 'INTEGER')), [n, e, d, p, q, dP, dQ, qInv]))
        
   DIR diff --git a/lib/plugins.py b/lib/plugins.py
       t@@ -22,12 +22,6 @@
        # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
        # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        # SOFTWARE.
       -from __future__ import absolute_import
       -from __future__ import division
       -from __future__ import print_function
       -from __future__ import unicode_literals
       -
       -import six
        from collections import namedtuple
        import traceback
        import sys
       t@@ -192,7 +186,7 @@ class Plugins(DaemonThread):
        
        
        def hook(func):
       -    hook_names.add(func.func_name)
       +    hook_names.add(func.__name__)
            return func
        
        def run_hook(name, *args):
   DIR diff --git a/lib/storage.py b/lib/storage.py
       t@@ -22,12 +22,6 @@
        # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
        # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        # SOFTWARE.
       -from __future__ import absolute_import
       -from __future__ import division
       -from __future__ import print_function
       -from __future__ import unicode_literals
       -
       -import six
        import os
        import ast
        import threading
   DIR diff --git a/lib/util.py b/lib/util.py
       t@@ -586,7 +586,8 @@ def parse_URI(uri, on_pr=None):
                        request = pr.PaymentRequest(s)
                    else:
                        request = pr.get_payment_request(r)
       -            on_pr(request)
       +            if on_pr:
       +                on_pr(request)
                t = threading.Thread(target=get_payment_request_thread)
                t.setDaemon(True)
                t.start()
       t@@ -698,7 +699,6 @@ class SocketPipe:
                self._send(out)
        
            def send_all(self, requests):
       -        print(requests)
                out = b''.join(map(lambda x: (json.dumps(x) + '\n').encode('utf8'), requests))
                self._send(out)
        
   DIR diff --git a/lib/wallet.py b/lib/wallet.py
       t@@ -1537,8 +1537,6 @@ class Deterministic_Wallet(Abstract_Wallet):
                return self.get_master_public_key()
        
        
       -
       -
        class Simple_Wallet(Abstract_Wallet):
        
            """ Wallet with a single pubkey per address """
   DIR diff --git a/lib/x509.py b/lib/x509.py
       t@@ -63,6 +63,7 @@ ASN1_TYPES = {
            'PrintableString'  : 0x13,
            'IA5String'        : 0x16,
            'UTCTime'          : 0x17,
       +    'GeneralizedTime'  : 0x18,
            'ENUMERATED'       : 0x0A,
            'UTF8String'       : 0x0C,
        }
       t@@ -75,7 +76,7 @@ class CertificateError(Exception):
        # helper functions
        def bitstr_to_bytestr(s):
            if s[0] != 0x00:
       -        raise BaseException('no padding')
       +        raise TypeError('no padding')
            return s[1:]
        
        
       t@@ -117,7 +118,7 @@ class ASN1_Node(bytes):
            def get_node(self, ix):
                # return index of first byte, first content byte and last byte.
                first = self[ix + 1]
       -        if (self[ix + 1] & 0x80) == 0:
       +        if (first & 0x80) == 0:
                    length = first
                    ixf = ix + 2
                    ixl = ixf + length - 1
       t@@ -138,7 +139,7 @@ class ASN1_Node(bytes):
            def first_child(self, node):
                ixs, ixf, ixl = node
                if self[ixs] & 0x20 != 0x20:
       -            raise BaseException('Can only open constructed types.', hex(self[ixs]))
       +            raise TypeError('Can only open constructed types.', hex(self[ixs]))
                return self.get_node(ixf)
        
            def is_child_of(node1, node2):
       t@@ -155,7 +156,7 @@ class ASN1_Node(bytes):
                # verify type byte and return content
                ixs, ixf, ixl = node
                if ASN1_TYPES[asn1_type] != self[ixs]:
       -            raise BaseException('Wrong type:', hex(self[ixs]), hex(ASN1_TYPES[asn1_type]))
       +            raise TypeError('Wrong type:', hex(self[ixs]), hex(ASN1_TYPES[asn1_type]))
                return self[ixf:ixl + 1]
        
            def get_value(self, node):
       t@@ -217,9 +218,15 @@ class X509(object):
                # validity
                validity = der.next_node(issuer)
                ii = der.first_child(validity)
       -        self.notBefore = der.get_value_of_type(ii, 'UTCTime')
       +        try:
       +            self.notBefore = der.get_value_of_type(ii, 'UTCTime')
       +        except TypeError:
       +            self.notBefore = der.get_value_of_type(ii, 'GeneralizedTime')[2:]  # strip year
                ii = der.next_node(ii)
       -        self.notAfter = der.get_value_of_type(ii, 'UTCTime')
       +        try:
       +            self.notAfter = der.get_value_of_type(ii, 'UTCTime')
       +        except TypeError:
       +            self.notAfter = der.get_value_of_type(ii, 'GeneralizedTime')[2:]  # strip year
        
                # subject
                subject = der.next_node(validity)
       t@@ -229,17 +236,22 @@ class X509(object):
                ii = der.first_child(public_key_algo)
                self.public_key_algo = decode_OID(der.get_value_of_type(ii, 'OBJECT IDENTIFIER'))
        
       -        # pubkey modulus and exponent
       -        subject_public_key = der.next_node(public_key_algo)
       -        spk = der.get_value_of_type(subject_public_key, 'BIT STRING')
       -        spk = ASN1_Node(bitstr_to_bytestr(spk))
       -        r = spk.root()
       -        modulus = spk.first_child(r)
       -        exponent = spk.next_node(modulus)
       -        rsa_n = spk.get_value_of_type(modulus, 'INTEGER')
       -        rsa_e = spk.get_value_of_type(exponent, 'INTEGER')
       -        self.modulus = ecdsa.util.string_to_number(rsa_n)
       -        self.exponent = ecdsa.util.string_to_number(rsa_e)
       +        if self.public_key_algo != '1.2.840.10045.2.1':  # for non EC public key
       +            # pubkey modulus and exponent
       +            subject_public_key = der.next_node(public_key_algo)
       +            spk = der.get_value_of_type(subject_public_key, 'BIT STRING')
       +            spk = ASN1_Node(bitstr_to_bytestr(spk))
       +            r = spk.root()
       +            modulus = spk.first_child(r)
       +            exponent = spk.next_node(modulus)
       +            rsa_n = spk.get_value_of_type(modulus, 'INTEGER')
       +            rsa_e = spk.get_value_of_type(exponent, 'INTEGER')
       +            self.modulus = ecdsa.util.string_to_number(rsa_n)
       +            self.exponent = ecdsa.util.string_to_number(rsa_e)
       +        else:
       +            subject_public_key = der.next_node(public_key_algo)
       +            spk = der.get_value_of_type(subject_public_key, 'BIT STRING')
       +            self.ec_public_key = spk
        
                # extensions
                self.CA = False
       t@@ -308,14 +320,17 @@ def load_certificates(ca_path):
            from . import pem
            ca_list = {}
            ca_keyID = {}
       -    with open(ca_path, 'rb') as f:
       -        s = f.read().decode('ascii')
       +    # ca_path = '/tmp/tmp.txt'
       +    with open(ca_path, 'r') as f:
       +        s = f.read()
            bList = pem.dePemList(s, "CERTIFICATE")
            for b in bList:
                try:
                    x = X509(b)
                    x.check_date()
                except BaseException as e:
       +            # with open('/tmp/tmp.txt', 'w') as f:
       +            #     f.write(pem.pem(b, 'CERTIFICATE').decode('ascii'))
                    util.print_error("cert error:", e)
                    continue
        
   DIR diff --git a/plugins/cosigner_pool/qt.py b/plugins/cosigner_pool/qt.py
       t@@ -26,7 +26,7 @@
        import socket
        import threading
        import time
       -import xmlrpclib
       +from xmlrpc.client import ServerProxy
        
        from PyQt4.QtGui import *
        from PyQt4.QtCore import *
       t@@ -45,7 +45,7 @@ import traceback
        
        PORT = 12344
        HOST = 'cosigner.electrum.org'
       -server = xmlrpclib.ServerProxy('http://%s:%d'%(HOST,PORT), allow_none=True)
       +server = ServerProxy('http://%s:%d'%(HOST,PORT), allow_none=True)
        
        
        class Listener(util.DaemonThread):
   DIR diff --git a/plugins/email_requests/qt.py b/plugins/email_requests/qt.py
       t@@ -23,8 +23,6 @@
        # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        # SOFTWARE.
        
       -from __future__ import absolute_import
       -
        import time
        import threading
        import base64
       t@@ -33,9 +31,9 @@ from functools import partial
        import smtplib
        import imaplib
        import email
       -from email.MIMEMultipart import MIMEMultipart
       -from email.MIMEBase import MIMEBase
       -from email import Encoders
       +from email.mime.multipart import MIMEMultipart
       +from email.mime.base import MIMEBase
       +from email.encoders import encode_base64
        
        from PyQt4.QtGui import *
        from PyQt4.QtCore import *
       t@@ -49,7 +47,6 @@ from electrum_gui.qt.util import EnterButton, Buttons, CloseButton
        from electrum_gui.qt.util import OkButton, WindowModalDialog
        
        
       -
        class Processor(threading.Thread):
            polling_interval = 5*60
        
       t@@ -96,7 +93,7 @@ class Processor(threading.Thread):
                msg['From'] = self.username
                part = MIMEBase('application', "bitcoin-paymentrequest")
                part.set_payload(payment_request)
       -        Encoders.encode_base64(part)
       +        encode_base64(part)
                part.add_header('Content-Disposition', 'attachment; filename="payreq.btc"')
                msg.attach(part)
                s = smtplib.SMTP_SSL(self.imap_server, timeout=2)
   DIR diff --git a/plugins/hw_wallet/__init__.py b/plugins/hw_wallet/__init__.py
       t@@ -1 +1 @@
       -from plugin import HW_PluginBase
       +from .plugin import HW_PluginBase
   DIR diff --git a/plugins/labels/labels.py b/plugins/labels/labels.py
       t@@ -12,8 +12,6 @@ from electrum.plugins import BasePlugin, hook
        from electrum.i18n import _
        
        
       -
       -
        class LabelsPlugin(BasePlugin):
        
            def __init__(self, parent, config, name):
       t@@ -83,7 +81,7 @@ class LabelsPlugin(BasePlugin):
                bundle = {"labels": [],
                          "walletId": wallet_id,
                          "walletNonce": self.get_nonce(wallet)}
       -        for key, value in wallet.labels.iteritems():
       +        for key, value in wallet.labels.items():
                    try:
                        encoded_key = self.encode(wallet, key)
                        encoded_value = self.encode(wallet, value)
       t@@ -135,12 +133,12 @@ class LabelsPlugin(BasePlugin):
            def start_wallet(self, wallet):
                nonce = self.get_nonce(wallet)
                self.print_error("wallet", wallet.basename(), "nonce is", nonce)
       -        mpk = wallet.get_fingerprint()
       +        mpk = wallet.get_fingerprint().encode('ascii')
                if not mpk:
                    return
       -        password = hashlib.sha1(mpk).digest().encode('hex')[:32]
       +        password = hashlib.sha1(mpk).hexdigest()[:32].encode('ascii')
                iv = hashlib.sha256(password).digest()[:16]
       -        wallet_id = hashlib.sha256(mpk).digest().encode('hex')
       +        wallet_id = hashlib.sha256(mpk).hexdigest()
                self.wallets[wallet] = (password, iv, wallet_id)
                # If there is an auth token we can try to actually start syncing
                t = threading.Thread(target=self.pull_thread, args=(wallet, False))
   DIR diff --git a/plugins/labels/qt.py b/plugins/labels/qt.py
       t@@ -9,7 +9,7 @@ from electrum_gui.qt import EnterButton
        from electrum_gui.qt.util import ThreadedButton, Buttons
        from electrum_gui.qt.util import WindowModalDialog, OkButton
        
       -from labels import LabelsPlugin
       +from .labels import LabelsPlugin
        
        
        class Plugin(LabelsPlugin):
   DIR diff --git a/plugins/virtualkeyboard/qt.py b/plugins/virtualkeyboard/qt.py
       t@@ -3,8 +3,8 @@ from electrum.plugins import BasePlugin, hook
        from electrum.i18n import _
        import random
        
       -class Plugin(BasePlugin):
        
       +class Plugin(BasePlugin):
            vkb = None
            vkb_index = 0
        
       t@@ -25,7 +25,7 @@ class Plugin(BasePlugin):
                self.vkb_index += 1
        
            def virtual_keyboard(self, i, pw):
       -        i = i%3
       +        i = i % 3
                if i == 0:
                    chars = 'abcdefghijklmnopqrstuvwxyz '
                elif i == 1:
       t@@ -35,9 +35,9 @@ class Plugin(BasePlugin):
        
                n = len(chars)
                s = []
       -        for i in xrange(n):
       +        for i in range(n):
                    while True:
       -                k = random.randint(0,n-1)
       +                k = random.randint(0, n - 1)
                        if k not in s:
                            s.append(k)
                            break
       t@@ -53,7 +53,7 @@ class Plugin(BasePlugin):
                    l_button.setFixedWidth(25)
                    l_button.setFixedHeight(25)
                    l_button.clicked.connect(add_target(chars[s[i]]))
       -            grid.addWidget(l_button, i/6, i%6)
       +            grid.addWidget(l_button, i // 6, i % 6)
        
                vbox.addLayout(grid)