URI: 
       tfix issue #1061: normalize trezor passphrases. Add passphrases to restore from seed with trezor. - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 15636282e421fb3e3fddd32638a931b65a9d4e8c
   DIR parent c56fe45ad7b93cdb63b6dbb27f72d97c9e789258
  HTML Author: ThomasV <thomasv@gitorious>
       Date:   Thu,  5 Mar 2015 17:09:39 +0100
       
       fix issue #1061: normalize trezor passphrases. Add passphrases to restore from seed with trezor.
       
       Diffstat:
         M lib/wallet.py                       |       4 ++--
         M plugins/trezor.py                   |      44 +++++++++++++++++++------------
       
       2 files changed, 29 insertions(+), 19 deletions(-)
       ---
   DIR diff --git a/lib/wallet.py b/lib/wallet.py
       t@@ -1321,9 +1321,9 @@ class BIP32_Wallet(Deterministic_Wallet):
                seed = self.get_seed(password)
                self.add_cosigner_seed(seed, self.root_name, password)
        
       -    def add_cosigner_seed(self, seed, name, password):
       +    def add_cosigner_seed(self, seed, name, password, passphrase=''):
                # we don't store the seed, only the master xpriv
       -        xprv, xpub = bip32_root(self.mnemonic_to_seed(seed,''))
       +        xprv, xpub = bip32_root(self.mnemonic_to_seed(seed, passphrase))
                xprv, xpub = bip32_private_derivation(xprv, "m/", self.root_derivation)
                self.add_master_public_key(name, xpub)
                self.add_master_private_key(name, xprv, password)
   DIR diff --git a/plugins/trezor.py b/plugins/trezor.py
       t@@ -5,6 +5,7 @@ from struct import pack
        from sys import stderr
        from time import sleep
        from base64 import b64encode, b64decode
       +import unicodedata
        
        import electrum
        from electrum.account import BIP32_Account
       t@@ -15,7 +16,6 @@ from electrum.transaction import deserialize
        from electrum.wallet import BIP32_HD_Wallet
        from electrum.util import print_error
        
       -from electrum_gui.qt.password_dialog import make_password_dialog, run_password_dialog
        from electrum_gui.qt.util import ok_cancel_buttons, EnterButton
        
        try:
       t@@ -36,6 +36,21 @@ def give_error(message):
            print_error(message)
            raise Exception(message)
        
       +
       +def trezor_passphrase_dialog(msg):
       +    from electrum_gui.qt.password_dialog import make_password_dialog, run_password_dialog
       +    d = QDialog()
       +    d.setModal(1)
       +    d.setLayout(make_password_dialog(d, None, msg, False))
       +    confirmed, p, passphrase = run_password_dialog(d, None, None)
       +    if not confirmed:
       +        return None
       +    if passphrase is None:
       +        passphrase = '' # Even blank string is valid Trezor passphrase
       +    passphrase = unicodedata.normalize('NFKD', unicode(passphrase))
       +    return passphrase
       +
       +
        class Plugin(BasePlugin):
        
            def fullname(self):
       t@@ -117,9 +132,13 @@ class Plugin(BasePlugin):
                    return
                wallet = TrezorWallet(storage)
                self.wallet = wallet
       +        passphrase = trezor_passphrase_dialog(_("Please enter your Trezor passphrase.") + '\n' + _("Press OK if you do not use one."))
       +        if passphrase is None:
       +            QMessageBox.critical(None, _('Error'), _("Password request canceled"), _('OK'))
       +            return
                password = wizard.password_dialog()
                wallet.add_seed(seed, password)
       -        wallet.add_cosigner_seed(' '.join(seed.split()), 'x/', password)
       +        wallet.add_cosigner_seed(seed, 'x/', password, passphrase)
                wallet.create_main_account(password)
                # disable trezor plugin
                self.set_enabled(False)
       t@@ -244,7 +263,8 @@ class TrezorWallet(BIP32_HD_Wallet):
                # trezor uses bip39
                import pbkdf2, hashlib, hmac
                PBKDF2_ROUNDS = 2048
       -        mnemonic = ' '.join(mnemonic.split())
       +        mnemonic = unicodedata.normalize('NFKD', ' '.join(mnemonic.split()))
       +        passphrase = unicodedata.normalize('NFKD', passphrase)
                return pbkdf2.PBKDF2(mnemonic, 'mnemonic' + passphrase, iterations = PBKDF2_ROUNDS, macmodule = hmac, digestmodule = hashlib.sha512).read(64)
        
            def derive_xkeys(self, root, derivation, password):
       t@@ -475,13 +495,12 @@ class TrezorQtGuiMixin(object):
                    return proto.Cancel()
                return proto.PinMatrixAck(pin=pin)
        
       -    def callback_PassphraseRequest(self, msg):
       -        confirmed, p, passphrase = self.password_dialog()
       -        if not confirmed:
       +    def callback_PassphraseRequest(self, req):
       +        msg = _("Please enter your Trezor passphrase.")
       +        passphrase = trezor_passphrase_dialog(msg)
       +        if passphrase is None:
                    QMessageBox.critical(None, _('Error'), _("Password request canceled"), _('OK'))
                    return proto.Cancel()
       -        if passphrase is None:
       -            passphrase='' # Even blank string is valid Trezor passphrase
                return proto.PassphraseAck(passphrase=passphrase)
        
            def callback_WordRequest(self, msg):
       t@@ -490,15 +509,6 @@ class TrezorQtGuiMixin(object):
                word = raw_input()
                return proto.WordAck(word=word)
        
       -    def password_dialog(self, msg=None):
       -        if not msg:
       -            msg = _("Please enter your Trezor password")
       -
       -        d = QDialog()
       -        d.setModal(1)
       -        d.setLayout( make_password_dialog(d, None, msg, False) )
       -        return run_password_dialog(d, None, None)
       -
            def pin_dialog(self, msg):
                d = QDialog(None)
                d.setModal(1)