URI: 
       tcheck SSL certificate in config dialog - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit a9e74da11c8db7e19f69128fde0d15de426c7696
   DIR parent 7b3e1dafd42ce8548563b1acea55649be90b2e60
  HTML Author: ThomasV <thomasv@gitorious>
       Date:   Wed,  5 Aug 2015 20:49:45 +0200
       
       check SSL certificate in config dialog
       
       Diffstat:
         M gui/qt/main_window.py               |      37 +++++++++++++++++++------------
         M lib/paymentrequest.py               |     140 +++++++++++++++++--------------
       
       2 files changed, 101 insertions(+), 76 deletions(-)
       ---
   DIR diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py
       t@@ -2529,6 +2529,7 @@ class ElectrumWindow(QMainWindow):
                tx_widgets = []
                id_widgets = []
        
       +        # language
                lang_help = _('Select which language is used in the GUI (after restart).')
                lang_label = HelpLabel(_('Language') + ':', lang_help)
                lang_combo = QComboBox()
       t@@ -2631,20 +2632,28 @@ class ElectrumWindow(QMainWindow):
                alias_e.editingFinished.connect(on_alias_edit)
                id_widgets.append((alias_label, alias_e))
        
       -        msg = _('Chain of SSL certificates, used to create BIP70 payment requests. ')\
       -              +_('Put your certificate at the top of the list, and the root CA at the end')
       -        SSL_cert_label = HelpLabel(_('SSL certificate') + ':', msg)
       -        SSL_cert = self.config.get('ssl_chain','')
       -        SSL_cert_e = QLineEdit(SSL_cert)
       -        SSL_cert_e.editingFinished.connect(lambda: self.config.set_key('ssl_chain', str(SSL_cert_e.text())))
       -        id_widgets.append((SSL_cert_label, SSL_cert_e))
       -
       -        msg = _('Path to your SSL private key, used to sign BIP70 payment requests.')
       -        SSL_key_label = HelpLabel(_('SSL private key') + ':', msg)
       -        SSL_key = self.config.get('ssl_privkey','')
       -        SSL_key_e = QLineEdit(SSL_key)
       -        SSL_key_e.editingFinished.connect(lambda: self.config.set_key('ssl_privkey', str(SSL_key_e.text())))
       -        id_widgets.append((SSL_key_label, SSL_key_e))
       +        # SSL certificate
       +        msg = ' '.join([
       +            _('SSL certificate used to sign payment requests.'),
       +            _('Use setconfig to set ssl_chain and ssl_privkey.'),
       +        ])
       +        if self.config.get('ssl_privkey') or self.onfig.get('ssl_chain'):
       +            try:
       +                SSL_identity = paymentrequest.check_ssl_config(self.config)
       +                SSL_error = None
       +            except BaseException as e:
       +                SSL_identity = "error"
       +                SSL_error = str(e)
       +        else:
       +            SSL_identity = ""
       +            SSL_error = None
       +        SSL_id_label = HelpLabel(_('SSL certificate') + ':', msg)
       +        SSL_id_e = QLineEdit(SSL_identity)
       +        SSL_id_e.setStyleSheet(RED_BG if SSL_error else GREEN_BG if SSL_identity else '')
       +        if SSL_error:
       +            SSL_id_e.setToolTip(SSL_error)
       +        SSL_id_e.setReadOnly(True)
       +        id_widgets.append((SSL_id_label, SSL_id_e))
        
                units = ['BTC', 'mBTC', 'bits']
                msg = _('Base unit of your wallet.')\
   DIR diff --git a/lib/paymentrequest.py b/lib/paymentrequest.py
       t@@ -119,75 +119,22 @@ class PaymentRequest:
                    return False
        
            def verify_x509(self, paymntreq):
       -        """ verify chain of certificates. The last certificate is the CA"""
                if not ca_list:
                    self.error = "Trusted certificate authorities list not found"
                    return False
                cert = pb2.X509Certificates()
                cert.ParseFromString(paymntreq.pki_data)
       -        cert_num = len(cert.certificate)
       -        x509_chain = []
       -        for i in range(cert_num):
       -            x = x509.X509()
       -            x.parseBinary(bytearray(cert.certificate[i]))
       -            x509_chain.append(x)
       -            if i == 0:
       -                try:
       -                    x.check_date()
       -                except Exception as e:
       -                    self.error = str(e)
       -                    return
       -                self.requestor = x.get_common_name()
       -                if self.requestor.startswith('*.'):
       -                    self.requestor = self.requestor[2:]
       -            else:
       -                if not x.check_ca():
       -                    self.error = "ERROR: Supplied CA Certificate Error"
       -                    return
       -        if not cert_num > 1:
       -            self.error = "ERROR: CA Certificate Chain Not Provided by Payment Processor"
       +        # verify the chain of certificates
       +        try:
       +            x, ca = verify_cert_chain(cert.certificate)
       +        except BaseException as e:
       +            self.error = str(e)
                    return False
       -        # if the root CA is not supplied, add it to the chain
       -        ca = x509_chain[cert_num-1]
       -        if ca.getFingerprint() not in ca_list:
       -            keyID = ca.get_issuer_keyID()
       -            f = ca_keyID.get(keyID)
       -            if f:
       -                root = ca_list[f]
       -                x509_chain.append(root)
       -            else:
       -                self.error = "Supplied CA Not Found in Trusted CA Store."
       -                return False
       -        # verify the chain of signatures
       -        cert_num = len(x509_chain)
       -        for i in range(1, cert_num):
       -            x = x509_chain[i]
       -            prev_x = x509_chain[i-1]
       -            algo, sig, data = prev_x.get_signature()
       -            sig = bytearray(sig)
       -
       -            pubkey = rsakey.RSAKey(x.modulus, x.exponent)
       -
       -            if algo == x509.ALGO_RSA_SHA1:
       -                verify = pubkey.hashAndVerify(sig, data)
       -            elif algo == x509.ALGO_RSA_SHA256:
       -                hashBytes = bytearray(hashlib.sha256(data).digest())
       -                verify = pubkey.verify(sig, x509.PREFIX_RSA_SHA256 + hashBytes)
       -            elif algo == x509.ALGO_RSA_SHA384:
       -                hashBytes = bytearray(hashlib.sha384(data).digest())
       -                verify = pubkey.verify(sig, x509.PREFIX_RSA_SHA384 + hashBytes)
       -            elif algo == x509.ALGO_RSA_SHA512:
       -                hashBytes = bytearray(hashlib.sha512(data).digest())
       -                verify = pubkey.verify(sig, x509.PREFIX_RSA_SHA512 + hashBytes)
       -            else:
       -                self.error = "Algorithm not supported"
       -                util.print_error(self.error, algo.getComponentByName('algorithm'))
       -                return False
       -            if not verify:
       -                self.error = "Certificate not Signed by Provided CA Certificate Chain"
       -                return False
       +        # get requestor name
       +        self.requestor = x.get_common_name()
       +        if self.requestor.startswith('*.'):
       +            self.requestor = self.requestor[2:]
                # verify the BIP70 signature
       -        x = x509_chain[0]
                pubkey0 = rsakey.RSAKey(x.modulus, x.exponent)
                sig = paymntreq.signature
                paymntreq.signature = ''
       t@@ -330,6 +277,75 @@ def sign_request_with_alias(pr, alias, alias_privkey):
        
        
        
       +def verify_cert_chain(chain):
       +    """ Verify a chain of certificates. The last certificate is the CA"""
       +    # parse the chain
       +    cert_num = len(chain)
       +    x509_chain = []
       +    for i in range(cert_num):
       +        x = x509.X509()
       +        x.parseBinary(bytearray(chain[i]))
       +        x509_chain.append(x)
       +        if i == 0:
       +            x.check_date()
       +        else:
       +            if not x.check_ca():
       +                raise BaseException("ERROR: Supplied CA Certificate Error")
       +    if not cert_num > 1:
       +        raise BaseException("ERROR: CA Certificate Chain Not Provided by Payment Processor")
       +    # if the root CA is not supplied, add it to the chain
       +    ca = x509_chain[cert_num-1]
       +    if ca.getFingerprint() not in ca_list:
       +        keyID = ca.get_issuer_keyID()
       +        f = ca_keyID.get(keyID)
       +        if f:
       +            root = ca_list[f]
       +            x509_chain.append(root)
       +        else:
       +            raise BaseException("Supplied CA Not Found in Trusted CA Store.")
       +    # verify the chain of signatures
       +    cert_num = len(x509_chain)
       +    for i in range(1, cert_num):
       +        x = x509_chain[i]
       +        prev_x = x509_chain[i-1]
       +        algo, sig, data = prev_x.get_signature()
       +        sig = bytearray(sig)
       +        pubkey = rsakey.RSAKey(x.modulus, x.exponent)
       +        if algo == x509.ALGO_RSA_SHA1:
       +            verify = pubkey.hashAndVerify(sig, data)
       +        elif algo == x509.ALGO_RSA_SHA256:
       +            hashBytes = bytearray(hashlib.sha256(data).digest())
       +            verify = pubkey.verify(sig, x509.PREFIX_RSA_SHA256 + hashBytes)
       +        elif algo == x509.ALGO_RSA_SHA384:
       +            hashBytes = bytearray(hashlib.sha384(data).digest())
       +            verify = pubkey.verify(sig, x509.PREFIX_RSA_SHA384 + hashBytes)
       +        elif algo == x509.ALGO_RSA_SHA512:
       +            hashBytes = bytearray(hashlib.sha512(data).digest())
       +            verify = pubkey.verify(sig, x509.PREFIX_RSA_SHA512 + hashBytes)
       +        else:
       +            raise BaseException("Algorithm not supported")
       +            util.print_error(self.error, algo.getComponentByName('algorithm'))
       +        if not verify:
       +            raise BaseException("Certificate not Signed by Provided CA Certificate Chain")
       +
       +    return x509_chain[0], ca
       +
       +
       +def check_ssl_config(config):
       +    import pem
       +    key_path = config.get('ssl_privkey')
       +    cert_path = config.get('ssl_chain')
       +    with open(key_path, 'r') as f:
       +        params = pem.parse_private_key(f.read())
       +        privkey = rsakey.RSAKey(*params)
       +    with open(cert_path, 'r') as f:
       +        s = f.read()
       +        bList = pem.dePemList(s, "CERTIFICATE")
       +    # verify chain
       +    x, ca = verify_cert_chain(bList)
       +    # verify pubkey
       +    return x.get_common_name()
       +
        def sign_request_with_x509(pr, key_path, cert_path):
            import pem
            with open(key_path, 'r') as f: