예제 #1
0
 def parse(self, r):
     try:
         self.data = pb2.PaymentRequest()
         self.data.ParseFromString(r)
     except:
         self.error = "cannot parse payment request"
         return
     self.details = pb2.PaymentDetails()
     self.details.ParseFromString(self.data.serialized_payment_details)
     for o in self.details.outputs:
         addr = transaction.get_address_from_output_script(o.script)[1]
         self.outputs.append(('address', addr, o.amount))
     self.memo = self.details.memo
     self.payment_url = self.details.payment_url
예제 #2
0
 def parse(self, r):
     self.id = bitcoin.sha256(r)[0:16].encode('hex')
     try:
         self.data = pb2.PaymentRequest()
         self.data.ParseFromString(r)
     except:
         self.error = "cannot parse payment request"
         return
     self.details = pb2.PaymentDetails()
     self.details.ParseFromString(self.data.serialized_payment_details)
     self.outputs = []
     for o in self.details.outputs:
         addr = transaction.get_address_from_output_script(o.script)[1]
         self.outputs.append((TYPE_ADDRESS, addr, o.amount))
     self.memo = self.details.memo
     self.payment_url = self.details.payment_url
예제 #3
0
 def parse(self, r):
     self.id = bitcoin.sha256(r)[0:16].encode('hex')
     try:
         self.data = pb2.PaymentRequest()
         self.data.ParseFromString(r)
     except:
         self.error = "cannot parse payment request"
         return
     self.details = pb2.PaymentDetails()
     self.details.ParseFromString(self.data.serialized_payment_details)
     self.outputs = []
     for o in self.details.outputs:
         addr = transaction.get_address_from_output_script(o.script)[1]
         self.outputs.append((TYPE_ADDRESS, addr, o.amount))
     self.memo = self.details.memo
     self.payment_url = self.details.payment_url
예제 #4
0
    def verify(self):

        if not ca_list:
            self.error = "Trusted certificate authorities list not found"
            return False

        paymntreq = self.data
        if not paymntreq.signature:
            self.error = "No signature"
            return

        cert = paymentrequest_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]))
            x.slow_parse()
            x509_chain.append(x)
            if i == 0:
                try:
                    x.check_date()
                    x.check_name(self.domain)
                except Exception as e:
                    self.error = str(e)
                    return
            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"
            return False

        for i in range(1, cert_num):
            x = x509_chain[i]
            prev_x = x509_chain[i - 1]

            algo, sig, data = prev_x.extract_sig()
            sig = bytearray(sig[5:])
            pubkey = x.publicKey
            if algo.getComponentByName("algorithm") == x509.ALGO_RSA_SHA1:
                verify = pubkey.hashAndVerify(sig, data)
            elif algo.getComponentByName("algorithm") == x509.ALGO_RSA_SHA256:
                hashBytes = bytearray(hashlib.sha256(data).digest())
                prefixBytes = bytearray(
                    [
                        0x30,
                        0x31,
                        0x30,
                        0x0D,
                        0x06,
                        0x09,
                        0x60,
                        0x86,
                        0x48,
                        0x01,
                        0x65,
                        0x03,
                        0x04,
                        0x02,
                        0x01,
                        0x05,
                        0x00,
                        0x04,
                        0x20,
                    ]
                )
                verify = pubkey.verify(sig, prefixBytes + hashBytes)
            else:
                self.error = "Algorithm not supported"
                util.print_error(self.error, algo.getComponentByName("algorithm"))
                return

            if not verify:
                self.error = "Certificate not Signed by Provided CA Certificate Chain"
                return

        ca = x509_chain[cert_num - 1]
        supplied_CA_fingerprint = ca.getFingerprint()
        supplied_CA_names = ca.extract_names()
        CA_OU = supplied_CA_names["OU"]

        x = ca_list.get(supplied_CA_fingerprint)
        if x:
            x.slow_parse()
            names = x.extract_names()
            CA_match = True
            if names["CN"] != supplied_CA_names["CN"]:
                print "ERROR: Trusted CA CN Mismatch; however CA has trusted fingerprint"
                print "Payment will continue with manual verification."
        else:
            CA_match = False

        pubkey0 = x509_chain[0].publicKey
        sig = paymntreq.signature
        paymntreq.signature = ""
        s = paymntreq.SerializeToString()
        sigBytes = bytearray(sig)
        msgBytes = bytearray(s)

        if paymntreq.pki_type == "x509+sha256":
            hashBytes = bytearray(hashlib.sha256(msgBytes).digest())
            prefixBytes = bytearray(
                [
                    0x30,
                    0x31,
                    0x30,
                    0x0D,
                    0x06,
                    0x09,
                    0x60,
                    0x86,
                    0x48,
                    0x01,
                    0x65,
                    0x03,
                    0x04,
                    0x02,
                    0x01,
                    0x05,
                    0x00,
                    0x04,
                    0x20,
                ]
            )
            verify = pubkey0.verify(sigBytes, prefixBytes + hashBytes)
        elif paymntreq.pki_type == "x509+sha1":
            verify = pubkey0.hashAndVerify(sigBytes, msgBytes)
        else:
            self.error = "ERROR: Unsupported PKI Type for Message Signature"
            return False

        if not verify:
            self.error = "ERROR: Invalid Signature for Payment Request Data"
            return False

        ### SIG Verified
        self.details = pay_det = paymentrequest_pb2.PaymentDetails()
        self.details.ParseFromString(paymntreq.serialized_payment_details)

        for o in pay_det.outputs:
            addr = transaction.get_address_from_output_script(o.script)[1]
            self.outputs.append(("address", addr, o.amount))

        self.memo = self.details.memo

        if CA_match:
            self.status = "Signed by Trusted CA:\n" + CA_OU
        else:
            self.status = "Supplied CA Not Found in Trusted CA Store."

        self.payment_url = self.details.payment_url

        return True
예제 #5
0
    def verify(self):

        if not ca_list:
            self.error = "Trusted certificate authorities list not found"
            return False

        paymntreq = self.data
        if not paymntreq.signature:
            self.error = "No signature"
            return

        cert = paymentrequest_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]))
            x.slow_parse()
            x509_chain.append(x)
            if i == 0:
                try:
                    x.check_date()
                    x.check_name(self.domain)
                except Exception as e:
                    self.error = str(e)
                    return
            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"
            return False

        for i in range(1, cert_num):
            x = x509_chain[i]
            prev_x = x509_chain[i - 1]

            algo, sig, data = prev_x.extract_sig()
            sig = bytearray(sig[5:])
            pubkey = x.publicKey
            if algo.getComponentByName('algorithm') == x509.ALGO_RSA_SHA1:
                verify = pubkey.hashAndVerify(sig, data)
            elif algo.getComponentByName('algorithm') == x509.ALGO_RSA_SHA256:
                hashBytes = bytearray(hashlib.sha256(data).digest())
                prefixBytes = bytearray([
                    0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
                    0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
                ])
                verify = pubkey.verify(sig, prefixBytes + hashBytes)
            else:
                self.error = "Algorithm not supported"
                util.print_error(self.error,
                                 algo.getComponentByName('algorithm'))
                return

            if not verify:
                self.error = "Certificate not Signed by Provided CA Certificate Chain"
                return

        ca = x509_chain[cert_num - 1]
        supplied_CA_fingerprint = ca.getFingerprint()
        supplied_CA_names = ca.extract_names()
        CA_OU = supplied_CA_names['OU']

        x = ca_list.get(supplied_CA_fingerprint)
        if x:
            x.slow_parse()
            names = x.extract_names()
            CA_match = True
            if names['CN'] != supplied_CA_names['CN']:
                print "ERROR: Trusted CA CN Mismatch; however CA has trusted fingerprint"
                print "Payment will continue with manual verification."
        else:
            CA_match = False

        pubkey0 = x509_chain[0].publicKey
        sig = paymntreq.signature
        paymntreq.signature = ''
        s = paymntreq.SerializeToString()
        sigBytes = bytearray(sig)
        msgBytes = bytearray(s)

        if paymntreq.pki_type == "x509+sha256":
            hashBytes = bytearray(hashlib.sha256(msgBytes).digest())
            prefixBytes = bytearray([
                0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
                0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
            ])
            verify = pubkey0.verify(sigBytes, prefixBytes + hashBytes)
        elif paymntreq.pki_type == "x509+sha1":
            verify = pubkey0.hashAndVerify(sigBytes, msgBytes)
        else:
            self.error = "ERROR: Unsupported PKI Type for Message Signature"
            return False

        if not verify:
            self.error = "ERROR: Invalid Signature for Payment Request Data"
            return False

        ### SIG Verified
        self.details = pay_det = paymentrequest_pb2.PaymentDetails()
        self.details.ParseFromString(paymntreq.serialized_payment_details)

        for o in pay_det.outputs:
            addr = transaction.get_address_from_output_script(o.script)[1]
            self.outputs.append(('address', addr, o.amount))

        self.memo = self.details.memo

        if CA_match:
            self.status = 'Signed by Trusted CA:\n' + CA_OU
        else:
            self.status = "Supplied CA Not Found in Trusted CA Store."

        self.payment_url = self.details.payment_url

        return True
예제 #6
0
class PaymentRequest:
    def __init__(self, url):
        self.url = url
        self.outputs = []
        self.error = ""

    def get_amount(self):
        return sum(map(lambda x: x[1], self.outputs))

    def verify(self):
        u = urlparse.urlparse(self.url)
        self.domain = u.netloc

        try:
            connection = httplib.HTTPConnection(
                u.netloc) if u.scheme == 'http' else httplib.HTTPSConnection(
                    u.netloc)
            connection.request("GET", u.geturl(), headers=REQUEST_HEADERS)
            resp = connection.getresponse()
        except:
            self.error = "cannot read url"
            return

        paymntreq = paymentrequest_pb2.PaymentRequest()
        try:
            r = resp.read()
            paymntreq.ParseFromString(r)
        except:
            self.error = "cannot parse payment request"
            return

        sig = paymntreq.signature
        if not sig:
            self.error = "No signature"
            return

        cert = paymentrequest_pb2.X509Certificates()
        cert.ParseFromString(paymntreq.pki_data)
        cert_num = len(cert.certificate)

        x509_1 = X509.load_cert_der_string(cert.certificate[0])
        if self.domain != x509_1.get_subject().CN:
            validcert = False
            try:
                SANs = x509_1.get_ext("subjectAltName").get_value().split(",")
                for s in SANs:
                    s = s.strip()
                    if s.startswith("DNS:") and s[4:] == self.domain:
                        validcert = True
                        print "Match SAN DNS"
                    elif s.startswith("IP:") and s[3:] == self.domain:
                        validcert = True
                        print "Match SAN IP"
                    elif s.startswith("email:") and s[6:] == self.domain:
                        validcert = True
                        print "Match SAN email"
            except Exception, e:
                print "ERROR: No SAN data"
            if not validcert:
                ###TODO: check for wildcards
                self.error = "ERROR: Certificate Subject Domain Mismatch and SAN Mismatch"
                return

        x509 = []
        CA_OU = ''

        if cert_num > 1:
            for i in range(cert_num - 1):
                x509.append(X509.load_cert_der_string(cert.certificate[i + 1]))
                if x509[i].check_ca() == 0:
                    self.error = "ERROR: Supplied CA Certificate Error"
                    return
            for i in range(cert_num - 1):
                if i == 0:
                    if x509_1.verify(x509[i].get_pubkey()) != 1:
                        self.error = "ERROR: Certificate not Signed by Provided CA Certificate Chain"
                        return
                else:
                    if x509[i - 1].verify(x509[i].get_pubkey()) != 1:
                        self.error = "ERROR: CA Certificate not Signed by Provided CA Certificate Chain"
                        return

            supplied_CA_fingerprint = x509[cert_num - 2].get_fingerprint()
            supplied_CA_CN = x509[cert_num - 2].get_subject().CN
            CA_match = False

            x = ca_list.get(supplied_CA_fingerprint)
            if x:
                CA_OU = x.get_subject().OU
                CA_match = True
                if x.get_subject().CN != supplied_CA_CN:
                    print "ERROR: Trusted CA CN Mismatch; however CA has trusted fingerprint"
                    print "Payment will continue with manual verification."
            else:
                print "ERROR: Supplied CA Not Found in Trusted CA Store."
                print "Payment will continue with manual verification."
        else:
            self.error = "ERROR: CA Certificate Chain Not Provided by Payment Processor"
            return False

        paymntreq.signature = ''
        s = paymntreq.SerializeToString()
        pubkey_1 = x509_1.get_pubkey()

        if paymntreq.pki_type == "x509+sha256":
            pubkey_1.reset_context(md="sha256")
        elif paymntreq.pki_type == "x509+sha1":
            pubkey_1.reset_context(md="sha1")
        else:
            self.error = "ERROR: Unsupported PKI Type for Message Signature"
            return False

        pubkey_1.verify_init()
        pubkey_1.verify_update(s)
        if pubkey_1.verify_final(sig) != 1:
            self.error = "ERROR: Invalid Signature for Payment Request Data"
            return False

        ### SIG Verified

        self.payment_details = pay_det = paymentrequest_pb2.PaymentDetails()
        pay_det.ParseFromString(paymntreq.serialized_payment_details)

        if pay_det.expires and pay_det.expires < int(time.time()):
            self.error = "ERROR: Payment Request has Expired."
            return False

        for o in pay_det.outputs:
            addr = transaction.get_address_from_output_script(o.script)[1]
            self.outputs.append((addr, o.amount))

        self.memo = pay_det.memo

        if CA_match:
            print 'Signed By Trusted CA: ', CA_OU

        print "payment url", pay_det.payment_url
        return True
예제 #7
0
class PaymentRequest:
    def __init__(self, config):
        self.config = config
        self.outputs = []
        self.error = ""
        self.dir_path = os.path.join(self.config.path, 'requests')
        if not os.path.exists(self.dir_path):
            os.mkdir(self.dir_path)

    def read(self, url):
        self.url = url
        u = urlparse.urlparse(url)
        self.domain = u.netloc
        try:
            connection = httplib.HTTPConnection(
                u.netloc) if u.scheme == 'http' else httplib.HTTPSConnection(
                    u.netloc)
            connection.request("GET", u.geturl(), headers=REQUEST_HEADERS)
            response = connection.getresponse()
        except:
            self.error = "cannot read url"
            return

        try:
            r = response.read()
        except:
            self.error = "cannot read"
            return

        self.id = bitcoin.sha256(r)[0:16].encode('hex')
        filename = os.path.join(self.dir_path, self.id)
        with open(filename, 'w') as f:
            f.write(r)

        return self.parse(r)

    def get_status(self):
        if self.error:
            return self.error
        else:
            return self.status

    def read_file(self, key):
        filename = os.path.join(self.dir_path, key)
        with open(filename, 'r') as f:
            r = f.read()

        self.parse(r)

    def parse(self, r):
        try:
            self.data = paymentrequest_pb2.PaymentRequest()
            self.data.ParseFromString(r)
        except:
            self.error = "cannot parse payment request"
            return

    def verify(self):
        try:
            from M2Crypto import X509
        except:
            self.error = "cannot import M2Crypto"
            return False

        if not ca_list:
            self.error = "Trusted certificate authorities list not found"
            return False

        paymntreq = self.data
        sig = paymntreq.signature
        if not sig:
            self.error = "No signature"
            return

        cert = paymentrequest_pb2.X509Certificates()
        cert.ParseFromString(paymntreq.pki_data)
        cert_num = len(cert.certificate)

        x509_1 = X509.load_cert_der_string(cert.certificate[0])
        if self.domain != x509_1.get_subject().CN:
            validcert = False
            try:
                SANs = x509_1.get_ext("subjectAltName").get_value().split(",")
                for s in SANs:
                    s = s.strip()
                    if s.startswith("DNS:") and s[4:] == self.domain:
                        validcert = True
                        print "Match SAN DNS"
                    elif s.startswith("IP:") and s[3:] == self.domain:
                        validcert = True
                        print "Match SAN IP"
                    elif s.startswith("email:") and s[6:] == self.domain:
                        validcert = True
                        print "Match SAN email"
            except Exception, e:
                print "ERROR: No SAN data"
            if not validcert:
                ###TODO: check for wildcards
                self.error = "ERROR: Certificate Subject Domain Mismatch and SAN Mismatch"
                return

        x509 = []
        CA_OU = ''

        if cert_num > 1:
            for i in range(cert_num - 1):
                x509.append(X509.load_cert_der_string(cert.certificate[i + 1]))
                if x509[i].check_ca() == 0:
                    self.error = "ERROR: Supplied CA Certificate Error"
                    return
            for i in range(cert_num - 1):
                if i == 0:
                    if x509_1.verify(x509[i].get_pubkey()) != 1:
                        self.error = "ERROR: Certificate not Signed by Provided CA Certificate Chain"
                        return
                else:
                    if x509[i - 1].verify(x509[i].get_pubkey()) != 1:
                        self.error = "ERROR: CA Certificate not Signed by Provided CA Certificate Chain"
                        return

            supplied_CA_fingerprint = x509[cert_num - 2].get_fingerprint()
            supplied_CA_CN = x509[cert_num - 2].get_subject().CN
            CA_match = False

            x = ca_list.get(supplied_CA_fingerprint)
            if x:
                CA_OU = x.get_subject().OU
                CA_match = True
                if x.get_subject().CN != supplied_CA_CN:
                    print "ERROR: Trusted CA CN Mismatch; however CA has trusted fingerprint"
                    print "Payment will continue with manual verification."
            else:
                print "ERROR: Supplied CA Not Found in Trusted CA Store."
                print "Payment will continue with manual verification."
        else:
            self.error = "ERROR: CA Certificate Chain Not Provided by Payment Processor"
            return False

        paymntreq.signature = ''
        s = paymntreq.SerializeToString()
        pubkey_1 = x509_1.get_pubkey()

        if paymntreq.pki_type == "x509+sha256":
            pubkey_1.reset_context(md="sha256")
        elif paymntreq.pki_type == "x509+sha1":
            pubkey_1.reset_context(md="sha1")
        else:
            self.error = "ERROR: Unsupported PKI Type for Message Signature"
            return False

        pubkey_1.verify_init()
        pubkey_1.verify_update(s)
        if pubkey_1.verify_final(sig) != 1:
            self.error = "ERROR: Invalid Signature for Payment Request Data"
            return False

        ### SIG Verified

        self.details = pay_det = paymentrequest_pb2.PaymentDetails()
        self.details.ParseFromString(paymntreq.serialized_payment_details)

        for o in pay_det.outputs:
            addr = transaction.get_address_from_output_script(o.script)[1]
            self.outputs.append((addr, o.amount))

        self.memo = self.details.memo

        if CA_match:
            self.status = 'Signed by Trusted CA:\n' + CA_OU

        self.payment_url = self.details.payment_url

        if self.has_expired():
            self.error = "ERROR: Payment Request has Expired."
            return False

        return True