Browse Source

fix issue #1061: normalize trezor passphrases. Add passphrases to restore from seed with trezor.

283
ThomasV 10 years ago
parent
commit
15636282e4
  1. 4
      lib/wallet.py
  2. 44
      plugins/trezor.py

4
lib/wallet.py

@ -1321,9 +1321,9 @@ class BIP32_Wallet(Deterministic_Wallet):
seed = self.get_seed(password) seed = self.get_seed(password)
self.add_cosigner_seed(seed, self.root_name, 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 # 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) xprv, xpub = bip32_private_derivation(xprv, "m/", self.root_derivation)
self.add_master_public_key(name, xpub) self.add_master_public_key(name, xpub)
self.add_master_private_key(name, xprv, password) self.add_master_private_key(name, xprv, password)

44
plugins/trezor.py

@ -5,6 +5,7 @@ from struct import pack
from sys import stderr from sys import stderr
from time import sleep from time import sleep
from base64 import b64encode, b64decode from base64 import b64encode, b64decode
import unicodedata
import electrum import electrum
from electrum.account import BIP32_Account from electrum.account import BIP32_Account
@ -15,7 +16,6 @@ from electrum.transaction import deserialize
from electrum.wallet import BIP32_HD_Wallet from electrum.wallet import BIP32_HD_Wallet
from electrum.util import print_error 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 from electrum_gui.qt.util import ok_cancel_buttons, EnterButton
try: try:
@ -36,6 +36,21 @@ def give_error(message):
print_error(message) print_error(message)
raise Exception(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): class Plugin(BasePlugin):
def fullname(self): def fullname(self):
@ -117,9 +132,13 @@ class Plugin(BasePlugin):
return return
wallet = TrezorWallet(storage) wallet = TrezorWallet(storage)
self.wallet = wallet 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() password = wizard.password_dialog()
wallet.add_seed(seed, password) 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) wallet.create_main_account(password)
# disable trezor plugin # disable trezor plugin
self.set_enabled(False) self.set_enabled(False)
@ -244,7 +263,8 @@ class TrezorWallet(BIP32_HD_Wallet):
# trezor uses bip39 # trezor uses bip39
import pbkdf2, hashlib, hmac import pbkdf2, hashlib, hmac
PBKDF2_ROUNDS = 2048 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) return pbkdf2.PBKDF2(mnemonic, 'mnemonic' + passphrase, iterations = PBKDF2_ROUNDS, macmodule = hmac, digestmodule = hashlib.sha512).read(64)
def derive_xkeys(self, root, derivation, password): def derive_xkeys(self, root, derivation, password):
@ -475,13 +495,12 @@ class TrezorQtGuiMixin(object):
return proto.Cancel() return proto.Cancel()
return proto.PinMatrixAck(pin=pin) return proto.PinMatrixAck(pin=pin)
def callback_PassphraseRequest(self, msg): def callback_PassphraseRequest(self, req):
confirmed, p, passphrase = self.password_dialog() msg = _("Please enter your Trezor passphrase.")
if not confirmed: passphrase = trezor_passphrase_dialog(msg)
if passphrase is None:
QMessageBox.critical(None, _('Error'), _("Password request canceled"), _('OK')) QMessageBox.critical(None, _('Error'), _("Password request canceled"), _('OK'))
return proto.Cancel() return proto.Cancel()
if passphrase is None:
passphrase='' # Even blank string is valid Trezor passphrase
return proto.PassphraseAck(passphrase=passphrase) return proto.PassphraseAck(passphrase=passphrase)
def callback_WordRequest(self, msg): def callback_WordRequest(self, msg):
@ -490,15 +509,6 @@ class TrezorQtGuiMixin(object):
word = raw_input() word = raw_input()
return proto.WordAck(word=word) 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): def pin_dialog(self, msg):
d = QDialog(None) d = QDialog(None)
d.setModal(1) d.setModal(1)

Loading…
Cancel
Save