x509 fixes and plugins

This commit is contained in:
Dmitry Sorokin 2017-02-05 13:38:44 +03:00 committed by ThomasV
parent 0693403358
commit 362ca96f38
18 changed files with 111 additions and 115 deletions

View File

@ -189,7 +189,7 @@ class BaseWizard(object):
except: except:
devmgr.print_error("error", name) devmgr.print_error("error", name)
continue continue
devices += map(lambda x: (name, x), u) devices += list(map(lambda x: (name, x), u))
if not devices: if not devices:
msg = ''.join([ msg = ''.join([
_('No hardware device detected.') + '\n', _('No hardware device detected.') + '\n',
@ -235,7 +235,7 @@ class BaseWizard(object):
self.line_dialog(run_next=f, title=_('Derivation'), message=message, default=default, test=bitcoin.is_bip32_derivation) 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): 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) xpub = self.plugin.get_xpub(device_info.device.id_, derivation, self)
if xpub is None: if xpub is None:
self.show_error('Cannot read xpub from device') self.show_error('Cannot read xpub from device')
@ -286,7 +286,7 @@ class BaseWizard(object):
self.load_2fa() self.load_2fa()
self.run('on_restore_seed', seed, is_ext) self.run('on_restore_seed', seed, is_ext)
else: else:
raise BaseException('Unknown seed type', seed_type) raise BaseException('Unknown seed type', self.seed_type)
def on_restore_bip39(self, seed, passphrase): def on_restore_bip39(self, seed, passphrase):
f = lambda x: self.run('on_bip44', seed, passphrase, str(x)) f = lambda x: self.run('on_bip44', seed, passphrase, str(x))
@ -334,7 +334,8 @@ class BaseWizard(object):
k.update_password(None, password) k.update_password(None, password)
if self.wallet_type == 'standard': if self.wallet_type == 'standard':
self.storage.put('seed_type', self.seed_type) 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.wallet = Standard_Wallet(self.storage)
self.run('create_addresses') self.run('create_addresses')
elif self.wallet_type == 'multisig': elif self.wallet_type == 'multisig':
@ -355,7 +356,7 @@ class BaseWizard(object):
self.on_keystore(k) self.on_keystore(k)
def create_seed(self): def create_seed(self):
import mnemonic from . import mnemonic
self.seed_type = 'segwit' if bitcoin.TESTNET and self.config.get('segwit') else 'standard' self.seed_type = 'segwit' if bitcoin.TESTNET and self.config.get('segwit') else 'standard'
seed = mnemonic.Mnemonic('en').make_seed(self.seed_type) seed = mnemonic.Mnemonic('en').make_seed(self.seed_type)
self.opt_bip39 = False self.opt_bip39 = False

View File

@ -29,7 +29,7 @@ import re
import hmac import hmac
import os import os
from lib.util import bfh, bh2u from lib.util import bfh, bh2u, to_string
from . import version from . import version
from .util import print_error, InvalidPassword, assert_bytes, to_bytes from .util import print_error, InvalidPassword, assert_bytes, to_bytes
@ -150,7 +150,7 @@ def DecodeAES(secret, e):
def pw_encode(s, password): def pw_encode(s, password):
if password: if password:
secret = Hash(password) secret = Hash(password)
return EncodeAES(secret, s.encode("utf8")) return EncodeAES(secret, to_bytes(s, "utf8"))
else: else:
return s return s
@ -158,7 +158,7 @@ def pw_decode(s, password):
if password is not None: if password is not None:
secret = Hash(password) secret = Hash(password)
try: try:
d = DecodeAES(secret, s).decode("utf8") d = to_string(DecodeAES(secret, s), "utf8")
except Exception: except Exception:
raise InvalidPassword() raise InvalidPassword()
return d return d
@ -213,7 +213,7 @@ def Hash(x):
hash_encode = lambda x: bh2u(x[::-1]) hash_encode = lambda x: bh2u(x[::-1])
hash_decode = lambda x: bfh(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): def is_new_seed(x, prefix=version.SEED_PREFIX):

View File

@ -34,8 +34,8 @@ import sys
import time import time
# from jsonrpc import JSONRPCResponseManager # from jsonrpc import JSONRPCResponseManager
import jsonrpclib # import jsonrpclib
from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer, SimpleJSONRPCRequestHandler # from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer, SimpleJSONRPCRequestHandler
from .version import ELECTRUM_VERSION from .version import ELECTRUM_VERSION
from .network import Network from .network import Network
@ -96,17 +96,17 @@ def get_server(config):
time.sleep(1.0) time.sleep(1.0)
class RequestHandler(SimpleJSONRPCRequestHandler): # class RequestHandler(SimpleJSONRPCRequestHandler):
#
def do_OPTIONS(self): # def do_OPTIONS(self):
self.send_response(200) # self.send_response(200)
self.end_headers() # self.end_headers()
#
def end_headers(self): # def end_headers(self):
self.send_header("Access-Control-Allow-Headers", # self.send_header("Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept") # "Origin, X-Requested-With, Content-Type, Accept")
self.send_header("Access-Control-Allow-Origin", "*") # self.send_header("Access-Control-Allow-Origin", "*")
SimpleJSONRPCRequestHandler.end_headers(self) # SimpleJSONRPCRequestHandler.end_headers(self)
class Daemon(DaemonThread): class Daemon(DaemonThread):
@ -132,24 +132,24 @@ class Daemon(DaemonThread):
def init_server(self, config, fd): def init_server(self, config, fd):
host = config.get('rpchost', '127.0.0.1') host = config.get('rpchost', '127.0.0.1')
port = config.get('rpcport', 0) port = config.get('rpcport', 0)
try: # try:
server = SimpleJSONRPCServer((host, port), logRequests=False, # server = SimpleJSONRPCServer((host, port), logRequests=False, requestHandler=RequestHandler)
requestHandler=RequestHandler) # except Exception as e:
except Exception as e: # self.print_error('Warning: cannot initialize RPC server on host', host, e)
self.print_error('Warning: cannot initialize RPC server on host', host, e) # self.server = None
self.server = None # os.close(fd)
os.close(fd) # return
return # os.write(fd, bytes(repr((server.socket.getsockname(), time.time())), 'utf8'))
os.write(fd, bytes(repr((server.socket.getsockname(), time.time())), 'utf8')) # os.close(fd)
os.close(fd) # server.timeout = 0.1
server.timeout = 0.1 # for cmdname in known_commands:
for cmdname in known_commands: # server.register_function(getattr(self.cmd_runner, cmdname), cmdname)
server.register_function(getattr(self.cmd_runner, cmdname), cmdname) # server.register_function(self.run_cmdline, 'run_cmdline')
server.register_function(self.run_cmdline, 'run_cmdline') # server.register_function(self.ping, 'ping')
server.register_function(self.ping, 'ping') # server.register_function(self.run_daemon, 'daemon')
server.register_function(self.run_daemon, 'daemon') # server.register_function(self.run_gui, 'gui')
server.register_function(self.run_gui, 'gui') # self.server = server
self.server = server self.server = None
def ping(self): def ping(self):
return True return True
@ -260,9 +260,9 @@ class Daemon(DaemonThread):
# arguments passed to function # arguments passed to function
args = map(lambda x: config.get(x), cmd.params) args = map(lambda x: config.get(x), cmd.params)
# decode json arguments # decode json arguments
args = map(json_decode, args) args = [json_decode(i) for i in args]
# options # 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) cmd_runner = Commands(config, wallet, self.network)
func = getattr(cmd_runner, cmd.name) func = getattr(cmd_runner, cmd.name)
result = func(*args) result = func(*args)

View File

@ -149,7 +149,7 @@ class Imported_KeyStore(Software_KeyStore):
except Exception: except Exception:
raise BaseException('Invalid private key') raise BaseException('Invalid private key')
# allow overwrite # allow overwrite
self.keypairs[pubkey] = pw_encode(sec, password) self.keypairs[pubkey] = pw_encode(sec, password).decode('ascii')
return pubkey return pubkey
def delete_imported_key(self, key): def delete_imported_key(self, key):
@ -179,7 +179,7 @@ class Imported_KeyStore(Software_KeyStore):
new_password = None new_password = None
for k, v in self.keypairs.items(): for k, v in self.keypairs.items():
b = pw_decode(v, old_password) b = pw_decode(v, old_password)
c = pw_encode(b, new_password) c = pw_encode(b, new_password).decode('ascii')
self.keypairs[k] = c self.keypairs[k] = c
@ -309,13 +309,13 @@ class BIP32_KeyStore(Deterministic_KeyStore, Xpub):
new_password = None new_password = None
if self.has_seed(): if self.has_seed():
decoded = self.get_seed(old_password) 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: if self.passphrase:
decoded = self.get_passphrase(old_password) 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: if self.xprv is not None:
b = pw_decode(self.xprv, old_password) 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): def is_watching_only(self):
return self.xprv is None return self.xprv is None
@ -478,7 +478,7 @@ class Old_KeyStore(Deterministic_KeyStore):
new_password = None new_password = None
if self.has_seed(): if self.has_seed():
decoded = self.get_hex_seed(old_password) 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): class Hardware_KeyStore(KeyStore, Xpub):

View File

@ -173,7 +173,7 @@ class Mnemonic(object):
return i % custom_entropy == 0 return i % custom_entropy == 0
def make_seed(self, seed_type='standard', num_bits=132, custom_entropy=1): def make_seed(self, seed_type='standard', num_bits=132, custom_entropy=1):
import version from . import version
prefix = version.seed_prefix(seed_type) prefix = version.seed_prefix(seed_type)
# increase num_bits in order to obtain a uniform distibution for the last word # increase num_bits in order to obtain a uniform distibution for the last word
bpw = math.log(len(self.wordlist), 2) bpw = math.log(len(self.wordlist), 2)

View File

@ -345,7 +345,6 @@ def sign_request_with_alias(pr, alias, alias_privkey):
pr.signature = ec_key.sign_message(message, compressed, address) pr.signature = ec_key.sign_message(message, compressed, address)
def verify_cert_chain(chain): def verify_cert_chain(chain):
""" Verify a chain of certificates. The last certificate is the CA""" """ Verify a chain of certificates. The last certificate is the CA"""
load_ca_list() load_ca_list()

View File

@ -127,12 +127,12 @@ def pem(b, name):
-----END CERTIFICATE----- -----END CERTIFICATE-----
""" """
s1 = b2a_base64(b)[:-1] # remove terminating \n s1 = b2a_base64(b)[:-1] # remove terminating \n
s2 = "" s2 = b""
while s1: while s1:
s2 += s1[:64] + "\n" s2 += s1[:64] + b"\n"
s1 = s1[64:] s1 = s1[64:]
s = ("-----BEGIN %s-----\n" % name) + s2 + \ s = ("-----BEGIN %s-----\n" % name).encode('ascii') + s2 + \
("-----END %s-----\n" % name) ("-----END %s-----\n" % name).encode('ascii')
return s return s
def pemSniff(inStr, name): def pemSniff(inStr, name):
@ -152,8 +152,8 @@ def parse_private_key(s):
raise SyntaxError("Not a PEM private key file") raise SyntaxError("Not a PEM private key file")
def _parsePKCS8(bytes): def _parsePKCS8(_bytes):
s = ASN1_Node(str(bytes)) s = ASN1_Node(_bytes)
root = s.root() root = s.root()
version_node = s.first_child(root) version_node = s.first_child(root)
version = bytestr_to_int(s.get_value_of_type(version_node, 'INTEGER')) version = bytestr_to_int(s.get_value_of_type(version_node, 'INTEGER'))
@ -192,5 +192,5 @@ def _parseASN1PrivateKey(s):
dP = s.next_node(q) dP = s.next_node(q)
dQ = s.next_node(dP) dQ = s.next_node(dP)
qInv = s.next_node(dQ) 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]))

View File

@ -22,12 +22,6 @@
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # 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 from collections import namedtuple
import traceback import traceback
import sys import sys
@ -192,7 +186,7 @@ class Plugins(DaemonThread):
def hook(func): def hook(func):
hook_names.add(func.func_name) hook_names.add(func.__name__)
return func return func
def run_hook(name, *args): def run_hook(name, *args):

View File

@ -22,12 +22,6 @@
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # 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 os
import ast import ast
import threading import threading

View File

@ -586,7 +586,8 @@ def parse_URI(uri, on_pr=None):
request = pr.PaymentRequest(s) request = pr.PaymentRequest(s)
else: else:
request = pr.get_payment_request(r) request = pr.get_payment_request(r)
on_pr(request) if on_pr:
on_pr(request)
t = threading.Thread(target=get_payment_request_thread) t = threading.Thread(target=get_payment_request_thread)
t.setDaemon(True) t.setDaemon(True)
t.start() t.start()
@ -698,7 +699,6 @@ class SocketPipe:
self._send(out) self._send(out)
def send_all(self, requests): def send_all(self, requests):
print(requests)
out = b''.join(map(lambda x: (json.dumps(x) + '\n').encode('utf8'), requests)) out = b''.join(map(lambda x: (json.dumps(x) + '\n').encode('utf8'), requests))
self._send(out) self._send(out)

View File

@ -1537,8 +1537,6 @@ class Deterministic_Wallet(Abstract_Wallet):
return self.get_master_public_key() return self.get_master_public_key()
class Simple_Wallet(Abstract_Wallet): class Simple_Wallet(Abstract_Wallet):
""" Wallet with a single pubkey per address """ """ Wallet with a single pubkey per address """

View File

@ -63,6 +63,7 @@ ASN1_TYPES = {
'PrintableString' : 0x13, 'PrintableString' : 0x13,
'IA5String' : 0x16, 'IA5String' : 0x16,
'UTCTime' : 0x17, 'UTCTime' : 0x17,
'GeneralizedTime' : 0x18,
'ENUMERATED' : 0x0A, 'ENUMERATED' : 0x0A,
'UTF8String' : 0x0C, 'UTF8String' : 0x0C,
} }
@ -75,7 +76,7 @@ class CertificateError(Exception):
# helper functions # helper functions
def bitstr_to_bytestr(s): def bitstr_to_bytestr(s):
if s[0] != 0x00: if s[0] != 0x00:
raise BaseException('no padding') raise TypeError('no padding')
return s[1:] return s[1:]
@ -117,7 +118,7 @@ class ASN1_Node(bytes):
def get_node(self, ix): def get_node(self, ix):
# return index of first byte, first content byte and last byte. # return index of first byte, first content byte and last byte.
first = self[ix + 1] first = self[ix + 1]
if (self[ix + 1] & 0x80) == 0: if (first & 0x80) == 0:
length = first length = first
ixf = ix + 2 ixf = ix + 2
ixl = ixf + length - 1 ixl = ixf + length - 1
@ -138,7 +139,7 @@ class ASN1_Node(bytes):
def first_child(self, node): def first_child(self, node):
ixs, ixf, ixl = node ixs, ixf, ixl = node
if self[ixs] & 0x20 != 0x20: 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) return self.get_node(ixf)
def is_child_of(node1, node2): def is_child_of(node1, node2):
@ -155,7 +156,7 @@ class ASN1_Node(bytes):
# verify type byte and return content # verify type byte and return content
ixs, ixf, ixl = node ixs, ixf, ixl = node
if ASN1_TYPES[asn1_type] != self[ixs]: 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] return self[ixf:ixl + 1]
def get_value(self, node): def get_value(self, node):
@ -217,9 +218,15 @@ class X509(object):
# validity # validity
validity = der.next_node(issuer) validity = der.next_node(issuer)
ii = der.first_child(validity) 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) 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
subject = der.next_node(validity) subject = der.next_node(validity)
@ -229,17 +236,22 @@ class X509(object):
ii = der.first_child(public_key_algo) ii = der.first_child(public_key_algo)
self.public_key_algo = decode_OID(der.get_value_of_type(ii, 'OBJECT IDENTIFIER')) self.public_key_algo = decode_OID(der.get_value_of_type(ii, 'OBJECT IDENTIFIER'))
# pubkey modulus and exponent if self.public_key_algo != '1.2.840.10045.2.1': # for non EC public key
subject_public_key = der.next_node(public_key_algo) # pubkey modulus and exponent
spk = der.get_value_of_type(subject_public_key, 'BIT STRING') subject_public_key = der.next_node(public_key_algo)
spk = ASN1_Node(bitstr_to_bytestr(spk)) spk = der.get_value_of_type(subject_public_key, 'BIT STRING')
r = spk.root() spk = ASN1_Node(bitstr_to_bytestr(spk))
modulus = spk.first_child(r) r = spk.root()
exponent = spk.next_node(modulus) modulus = spk.first_child(r)
rsa_n = spk.get_value_of_type(modulus, 'INTEGER') exponent = spk.next_node(modulus)
rsa_e = spk.get_value_of_type(exponent, 'INTEGER') rsa_n = spk.get_value_of_type(modulus, 'INTEGER')
self.modulus = ecdsa.util.string_to_number(rsa_n) rsa_e = spk.get_value_of_type(exponent, 'INTEGER')
self.exponent = ecdsa.util.string_to_number(rsa_e) 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 # extensions
self.CA = False self.CA = False
@ -308,14 +320,17 @@ def load_certificates(ca_path):
from . import pem from . import pem
ca_list = {} ca_list = {}
ca_keyID = {} ca_keyID = {}
with open(ca_path, 'rb') as f: # ca_path = '/tmp/tmp.txt'
s = f.read().decode('ascii') with open(ca_path, 'r') as f:
s = f.read()
bList = pem.dePemList(s, "CERTIFICATE") bList = pem.dePemList(s, "CERTIFICATE")
for b in bList: for b in bList:
try: try:
x = X509(b) x = X509(b)
x.check_date() x.check_date()
except BaseException as e: 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) util.print_error("cert error:", e)
continue continue

View File

@ -26,7 +26,7 @@
import socket import socket
import threading import threading
import time import time
import xmlrpclib from xmlrpc.client import ServerProxy
from PyQt4.QtGui import * from PyQt4.QtGui import *
from PyQt4.QtCore import * from PyQt4.QtCore import *
@ -45,7 +45,7 @@ import traceback
PORT = 12344 PORT = 12344
HOST = 'cosigner.electrum.org' 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): class Listener(util.DaemonThread):

View File

@ -23,8 +23,6 @@
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
from __future__ import absolute_import
import time import time
import threading import threading
import base64 import base64
@ -33,9 +31,9 @@ from functools import partial
import smtplib import smtplib
import imaplib import imaplib
import email import email
from email.MIMEMultipart import MIMEMultipart from email.mime.multipart import MIMEMultipart
from email.MIMEBase import MIMEBase from email.mime.base import MIMEBase
from email import Encoders from email.encoders import encode_base64
from PyQt4.QtGui import * from PyQt4.QtGui import *
from PyQt4.QtCore import * from PyQt4.QtCore import *
@ -49,7 +47,6 @@ from electrum_gui.qt.util import EnterButton, Buttons, CloseButton
from electrum_gui.qt.util import OkButton, WindowModalDialog from electrum_gui.qt.util import OkButton, WindowModalDialog
class Processor(threading.Thread): class Processor(threading.Thread):
polling_interval = 5*60 polling_interval = 5*60
@ -96,7 +93,7 @@ class Processor(threading.Thread):
msg['From'] = self.username msg['From'] = self.username
part = MIMEBase('application', "bitcoin-paymentrequest") part = MIMEBase('application', "bitcoin-paymentrequest")
part.set_payload(payment_request) part.set_payload(payment_request)
Encoders.encode_base64(part) encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename="payreq.btc"') part.add_header('Content-Disposition', 'attachment; filename="payreq.btc"')
msg.attach(part) msg.attach(part)
s = smtplib.SMTP_SSL(self.imap_server, timeout=2) s = smtplib.SMTP_SSL(self.imap_server, timeout=2)

View File

@ -1 +1 @@
from plugin import HW_PluginBase from .plugin import HW_PluginBase

View File

@ -12,8 +12,6 @@ from electrum.plugins import BasePlugin, hook
from electrum.i18n import _ from electrum.i18n import _
class LabelsPlugin(BasePlugin): class LabelsPlugin(BasePlugin):
def __init__(self, parent, config, name): def __init__(self, parent, config, name):
@ -83,7 +81,7 @@ class LabelsPlugin(BasePlugin):
bundle = {"labels": [], bundle = {"labels": [],
"walletId": wallet_id, "walletId": wallet_id,
"walletNonce": self.get_nonce(wallet)} "walletNonce": self.get_nonce(wallet)}
for key, value in wallet.labels.iteritems(): for key, value in wallet.labels.items():
try: try:
encoded_key = self.encode(wallet, key) encoded_key = self.encode(wallet, key)
encoded_value = self.encode(wallet, value) encoded_value = self.encode(wallet, value)
@ -135,12 +133,12 @@ class LabelsPlugin(BasePlugin):
def start_wallet(self, wallet): def start_wallet(self, wallet):
nonce = self.get_nonce(wallet) nonce = self.get_nonce(wallet)
self.print_error("wallet", wallet.basename(), "nonce is", nonce) self.print_error("wallet", wallet.basename(), "nonce is", nonce)
mpk = wallet.get_fingerprint() mpk = wallet.get_fingerprint().encode('ascii')
if not mpk: if not mpk:
return return
password = hashlib.sha1(mpk).digest().encode('hex')[:32] password = hashlib.sha1(mpk).hexdigest()[:32].encode('ascii')
iv = hashlib.sha256(password).digest()[:16] 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) self.wallets[wallet] = (password, iv, wallet_id)
# If there is an auth token we can try to actually start syncing # If there is an auth token we can try to actually start syncing
t = threading.Thread(target=self.pull_thread, args=(wallet, False)) t = threading.Thread(target=self.pull_thread, args=(wallet, False))

View File

@ -9,7 +9,7 @@ from electrum_gui.qt import EnterButton
from electrum_gui.qt.util import ThreadedButton, Buttons from electrum_gui.qt.util import ThreadedButton, Buttons
from electrum_gui.qt.util import WindowModalDialog, OkButton from electrum_gui.qt.util import WindowModalDialog, OkButton
from labels import LabelsPlugin from .labels import LabelsPlugin
class Plugin(LabelsPlugin): class Plugin(LabelsPlugin):

View File

@ -3,8 +3,8 @@ from electrum.plugins import BasePlugin, hook
from electrum.i18n import _ from electrum.i18n import _
import random import random
class Plugin(BasePlugin):
class Plugin(BasePlugin):
vkb = None vkb = None
vkb_index = 0 vkb_index = 0
@ -25,7 +25,7 @@ class Plugin(BasePlugin):
self.vkb_index += 1 self.vkb_index += 1
def virtual_keyboard(self, i, pw): def virtual_keyboard(self, i, pw):
i = i%3 i = i % 3
if i == 0: if i == 0:
chars = 'abcdefghijklmnopqrstuvwxyz ' chars = 'abcdefghijklmnopqrstuvwxyz '
elif i == 1: elif i == 1:
@ -35,9 +35,9 @@ class Plugin(BasePlugin):
n = len(chars) n = len(chars)
s = [] s = []
for i in xrange(n): for i in range(n):
while True: while True:
k = random.randint(0,n-1) k = random.randint(0, n - 1)
if k not in s: if k not in s:
s.append(k) s.append(k)
break break
@ -53,7 +53,7 @@ class Plugin(BasePlugin):
l_button.setFixedWidth(25) l_button.setFixedWidth(25)
l_button.setFixedHeight(25) l_button.setFixedHeight(25)
l_button.clicked.connect(add_target(chars[s[i]])) 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) vbox.addLayout(grid)