electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

commit da6f292dd53d7f13a58522a9ad05dc50c92031bc
parent 1face99346b2376d095b6abd72c9301d14de958c
Author: ThomasV <thomasv@gitorious>
Date:   Mon,  3 Mar 2014 10:39:10 +0100

encrypt/decrypt messages in gui

Diffstat:
Mgui/qt/main_window.py | 107+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
Mlib/bitcoin.py | 4++++
Mlib/commands.py | 12+++++-------
Mlib/wallet.py | 18++++++++++++++++++
4 files changed, 113 insertions(+), 28 deletions(-)

diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py @@ -403,16 +403,14 @@ class ElectrumWindow(QMainWindow): #preferences_menu.setShortcut(QKeySequence.Preferences) preferences_menu.triggered.connect(self.settings_dialog) - network = tools_menu.addAction(_("&Network")) - network.triggered.connect(self.run_network_dialog) - - plugins_labels = tools_menu.addAction(_("&Plugins")) - plugins_labels.triggered.connect(self.plugins_dialog) + tools_menu.addAction(_("&Network"), self.run_network_dialog) + tools_menu.addAction(_("&Plugins"), self.plugins_dialog) tools_menu.addSeparator() + tools_menu.addAction(_("&Sign/verify message"), self.sign_verify_message) + tools_menu.addAction(_("&Encrypt/decrypt message"), self.encrypt_message) - verifymessage = tools_menu.addAction(_("&Verify message")) - verifymessage.triggered.connect(lambda: self.sign_verify_message(False)) + tools_menu.addSeparator() csv_transaction_menu = tools_menu.addMenu(_("&Create transaction")) @@ -1155,7 +1153,8 @@ class ElectrumWindow(QMainWindow): menu.addAction(_("Edit label"), lambda: self.edit_label(True)) if self.wallet.seed: menu.addAction(_("Private key"), lambda: self.show_private_key(addr)) - menu.addAction(_("Sign message"), lambda: self.sign_verify_message(True,addr)) + menu.addAction(_("Sign/verify message"), lambda: self.sign_verify_message(addr)) + menu.addAction(_("Encrypt/decrypt message"), lambda: self.encrypt_message(addr)) if addr in self.wallet.imported_keys: menu.addAction(_("Remove from wallet"), lambda: self.delete_imported_key(addr)) @@ -1731,35 +1730,39 @@ class ElectrumWindow(QMainWindow): self.show_message(_("Error: wrong signature")) - def sign_verify_message(self, sign, address=''): - if sign and not address: return + def sign_verify_message(self, address=''): d = QDialog(self) d.setModal(1) - d.setWindowTitle(_('Sign Message') if sign else _('Verify Message')) + d.setWindowTitle(_('Sign/verify Message')) d.setMinimumSize(410, 290) layout = QGridLayout(d) - address_e = QLineEdit() - address_e.setText(address) - layout.addWidget(QLabel(_('Address')), 1, 0) - layout.addWidget(address_e, 1, 1) - message_e = QTextEdit() - layout.addWidget(QLabel(_('Message')), 2, 0) - layout.addWidget(message_e, 2, 1) + layout.addWidget(QLabel(_('Message')), 1, 0) + layout.addWidget(message_e, 1, 1) layout.setRowStretch(2,3) + address_e = QLineEdit() + address_e.setText(address) + layout.addWidget(QLabel(_('Address')), 2, 0) + layout.addWidget(address_e, 2, 1) + signature_e = QTextEdit() layout.addWidget(QLabel(_('Signature')), 3, 0) layout.addWidget(signature_e, 3, 1) layout.setRowStretch(3,1) hbox = QHBoxLayout() - b = QPushButton(_("Sign") if sign else _("Verify")) + + b = QPushButton(_("Sign")) + b.clicked.connect(lambda: self.do_sign(address_e, message_e, signature_e)) + hbox.addWidget(b) + + b = QPushButton(_("Verify")) + b.clicked.connect(lambda: self.do_verify(address_e, message_e, signature_e)) hbox.addWidget(b) - f = self.do_sign if sign else self.do_verify - b.clicked.connect(lambda: f(address_e, message_e, signature_e)) + b = QPushButton(_("Close")) b.clicked.connect(d.accept) hbox.addWidget(b) @@ -1767,6 +1770,68 @@ class ElectrumWindow(QMainWindow): d.exec_() + @protected + def do_decrypt(self, message_e, pubkey_e, encrypted_e, password): + try: + decrypted = self.wallet.decrypt_message(str(pubkey_e.text()), str(encrypted_e.toPlainText()), password) + message_e.setText(decrypted) + except Exception as e: + self.show_message(str(e)) + + + def do_encrypt(self, message_e, pubkey_e, encrypted_e): + message = unicode(message_e.toPlainText()) + message = message.encode('utf-8') + try: + encrypted = bitcoin.encrypt_message(message, str(pubkey_e.text())) + encrypted_e.setText(encrypted) + except Exception as e: + self.show_message(str(e)) + + + + def encrypt_message(self, address = ''): + d = QDialog(self) + d.setModal(1) + d.setWindowTitle(_('Encrypt/decrypt Message')) + d.setMinimumSize(610, 490) + + layout = QGridLayout(d) + + message_e = QTextEdit() + layout.addWidget(QLabel(_('Message')), 1, 0) + layout.addWidget(message_e, 1, 1) + layout.setRowStretch(2,3) + + pubkey_e = QLineEdit() + if address: + pubkey = self.wallet.getpubkeys(address)[0] + pubkey_e.setText(pubkey) + layout.addWidget(QLabel(_('Public key')), 2, 0) + layout.addWidget(pubkey_e, 2, 1) + + encrypted_e = QTextEdit() + layout.addWidget(QLabel(_('Encrypted')), 3, 0) + layout.addWidget(encrypted_e, 3, 1) + layout.setRowStretch(3,1) + + hbox = QHBoxLayout() + b = QPushButton(_("Encrypt")) + b.clicked.connect(lambda: self.do_encrypt(message_e, pubkey_e, encrypted_e)) + hbox.addWidget(b) + + b = QPushButton(_("Decrypt")) + b.clicked.connect(lambda: self.do_decrypt(message_e, pubkey_e, encrypted_e)) + hbox.addWidget(b) + + b = QPushButton(_("Close")) + b.clicked.connect(d.accept) + hbox.addWidget(b) + + layout.addLayout(hbox, 4, 1) + d.exec_() + + def question(self, msg): return QMessageBox.question(self, _('Message'), msg, QMessageBox.Yes | QMessageBox.No, QMessageBox.No) == QMessageBox.Yes diff --git a/lib/bitcoin.py b/lib/bitcoin.py @@ -303,6 +303,10 @@ def verify_message(address, signature, message): return False +def encrypt_message(message, pubkey): + return EC_KEY.encrypt_message(message, pubkey.decode('hex')) + + def chunks(l, n): return [l[i:i+n] for i in xrange(0, len(l), n)] diff --git a/lib/commands.py b/lib/commands.py @@ -207,15 +207,11 @@ class Commands: return out def getpubkeys(self, addr): - assert is_valid(addr) and self.wallet.is_mine(addr) out = { 'address':addr } - account, sequence = self.wallet.get_address_index(addr) - if account != -1: - a = self.wallet.accounts[account] - out['pubkeys'] = a.get_pubkeys( sequence ) - + out['pubkeys'] = self.wallet.getpubkeys(addr) return out + def getbalance(self, account= None): if account is None: c, u = self.wallet.get_balance() @@ -400,8 +396,10 @@ class Commands: else: return "unknown transaction" + def encrypt(self, pubkey, message): - return EC_KEY.encrypt_message(message, pubkey.decode('hex')) + return bitcoin.encrypt_message(message, pubkey) + def decrypt(self, secret, message): ec = regenerate_key(secret) diff --git a/lib/wallet.py b/lib/wallet.py @@ -593,6 +593,14 @@ class NewWallet: raise Exception("Address not found", address) + def getpubkeys(self, addr): + assert is_valid(addr) and self.is_mine(addr) + account, sequence = self.get_address_index(addr) + if account != -1: + a = self.accounts[account] + return a.get_pubkeys( sequence ) + + def get_roots(self, account): roots = [] for a in account.split('&'): @@ -771,6 +779,16 @@ class NewWallet: return key.sign_message(message, compressed, address) + + def decrypt_message(self, pubkey, message, password): + address = public_key_to_bc_address(pubkey.decode('hex')) + keys = self.get_private_key(address, password) + secret = keys[0] + ec = regenerate_key(secret) + decrypted = ec.decrypt_message(message) + return decrypted[0] + + def change_gap_limit(self, value): if value >= self.gap_limit: self.gap_limit = value