def make_payment_request(outputs, memo, time, expires, key_path, cert_path):
    pd = pb2.PaymentDetails()
    for script, amount in outputs:
        pd.outputs.add(amount=amount, script=script)
    pd.time = time
    pd.expires = expires
    pd.memo = memo
    pr = pb2.PaymentRequest()
    pr.serialized_payment_details = pd.SerializeToString()
    pr.signature = ''
    pr = pb2.PaymentRequest()
    pr.serialized_payment_details = pd.SerializeToString()
    pr.signature = ''
    if key_path and cert_path:
        import tlslite
        with open(key_path, 'r') as f:
            rsakey = tlslite.utils.python_rsakey.Python_RSAKey.parsePEM(
                f.read())
        with open(cert_path, 'r') as f:
            chain = tlslite.X509CertChain()
            chain.parsePemList(f.read())
        certificates = pb2.X509Certificates()
        certificates.certificate.extend(
            map(lambda x: str(x.bytes), chain.x509List))
        pr.pki_type = 'x509+sha256'
        pr.pki_data = certificates.SerializeToString()
        msgBytes = bytearray(pr.SerializeToString())
        hashBytes = bytearray(hashlib.sha256(msgBytes).digest())
        sig = rsakey.sign(x509.PREFIX_RSA_SHA256 + hashBytes)
        pr.signature = bytes(sig)
    return pr.SerializeToString()
Пример #2
0
 def parse(self, r):
     try:
         self.data = paymentrequest_pb2.PaymentRequest()
         self.data.ParseFromString(r)
     except:
         self.error = "cannot parse payment request"
         return
Пример #3
0
def make_unsigned_request(req):
    from transaction import Transaction
    addr = req['address']
    time = req.get('time', 0)
    exp = req.get('exp', 0)
    if time and type(time) != int:
        time = 0
    if exp and type(exp) != int:
        exp = 0
    amount = req['amount']
    if amount is None:
        amount = 0
    memo = req['memo']
    script = Transaction.pay_script(TYPE_ADDRESS, addr).decode('hex')
    outputs = [(script, amount)]
    pd = pb2.PaymentDetails()
    for script, amount in outputs:
        pd.outputs.add(amount=amount, script=script)
    pd.time = time
    pd.expires = time + exp if exp else 0
    pd.memo = memo
    pr = pb2.PaymentRequest()
    pr.serialized_payment_details = pd.SerializeToString()
    pr.signature = ''
    return pr
Пример #4
0
 def parse(self, r):
     if self.error:
         return
     self.id = bh2u(util.sha256(r)[0:16])
     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)
     if self.details.network == 'test':
         NetworkConstants.set_testnet()
     elif self.details.network == 'main':
         NetworkConstants.set_mainnet()
     else:
         self.error = "unknown network " + self.details.network
         return
     self.outputs = []
     for o in self.details.outputs:
         out_type, addr = util.get_address_from_output_script(o.script)
         self.outputs.append((out_type, addr, o.amount))
     self.memo = self.details.memo
     self.payment_url = self.details.payment_url
Пример #5
0
def payment_request():
    """Generates a http PaymentRequest object"""

    bc = RPCCaller(allow_default_conf=True)
    btc = CCoinAddress(bc.getnewaddress())

    #   Setting the 'amount' field to 0 (zero) should prompt the user to enter
    #   the amount for us but a bug in bitcoin core qt version 0.9.1 (at time of
    #   writing) wrongly informs us that the value is too small and aborts.
    #   https://github.com/bitcoin/bitcoin/issues/3095
    #   Also there can be no leading 0's (zeros).
    btc_amount = 100000
    serialized_pubkey = btc.to_scriptPubKey()

    pdo = o.PaymentDetails(network="regtest")
    # pdo.network = 'test'
    pdo.outputs.add(amount=btc_amount, script=serialized_pubkey)
    pdo.time = int(time())
    pdo.memo = 'String shown to user before confirming payment'
    pdo.payment_url = 'http://{}:{}/{}'.format(listen_on['host'],
                                               listen_on['port'], ack_url_path)

    pro = o.PaymentRequest()
    pro.serialized_payment_details = pdo.SerializeToString()

    sds_pr = pro.SerializeToString()

    headers = {
        'Content-Type': 'application/bitcoin-payment',
        'Accept': 'application/bitcoin-paymentrequest'
    }

    return sds_pr, headers
Пример #6
0
    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
Пример #7
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
Пример #8
0
 def verify(self, contacts):
     if not self.raw:
         self.error = "Empty request"
         return
     pr = pb2.PaymentRequest()
     pr.ParseFromString(self.raw)
     if not pr.signature:
         # the address will be dispayed as requestor
         self.requestor = None
         return True
     if pr.pki_type in ["x509+sha256", "x509+sha1"]:
         return self.verify_x509(pr)
     elif pr.pki_type in ["dnssec+btc", "dnssec+ecdsa"]:
         return self.verify_dnssec(pr, contacts)
     else:
         self.error = "ERROR: Unsupported PKI Type for Message Signature"
         return False
Пример #9
0
def make_unsigned_request(req):
    from transaction import Transaction
    addr = req['address']
    time = req['timestamp']
    amount = req['amount']
    if amount is None:
        amount = 0
    expires = req['expiration']
    memo = req['memo']
    script = Transaction.pay_script('address', addr).decode('hex')
    outputs = [(script, amount)]
    pd = pb2.PaymentDetails()
    for script, amount in outputs:
        pd.outputs.add(amount=amount, script=script)
    pd.time = time
    pd.expires = time + expires if expires else 0
    pd.memo = memo
    pr = pb2.PaymentRequest()
    pr.serialized_payment_details = pd.SerializeToString()
    pr.signature = ''
    return pr
 def verify(self):
     if not ca_list:
         self.error = "Trusted certificate authorities list not found"
         return False
     paymntreq = pb2.PaymentRequest()
     paymntreq.ParseFromString(self.raw)
     if not paymntreq.signature:
         self.error = "No signature"
         return
     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"
         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 = x.publicKey
         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
     # verify the BIP70 signature
     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())
         verify = pubkey0.verify(sigBytes,
                                 x509.PREFIX_RSA_SHA256 + 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.error = 'Signed by Trusted CA: ' + ca.get_common_name()
     return True
Пример #11
0
def decode_pr(addr):
    dat = http.request('GET', url_from_input(addr), headers={'Accept': 'application/bitcoin-paymentrequest'}).data
    req = paymentrequest_pb2.PaymentRequest().FromString(dat)
    return paymentrequest_pb2.PaymentDetails().FromString(req.serialized_payment_details)
Пример #12
0
def decode_pr(addr):
    req = urllib.request.Request(url_from_input(addr), headers={'Accept': 'application/bitcoin-paymentrequest'})
    with urllib.request.urlopen(req) as f:
        dat = f.read()
        req = paymentrequest_pb2.PaymentRequest().FromString(dat)
        return paymentrequest_pb2.PaymentDetails().FromString(req.serialized_payment_details)