|
@ -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) |
|
|