Exemplo n.º 1
0
def main(argv):

    """
        Main procedure to generate C array with keys
    """

    parser = argparse.ArgumentParser(description="Generates SQLite database with"
        " keys and serial number.")
    parser.add_argument('config_file', help="project specific configuration file"
        )
    args = parser.parse_args()

    config = ConfigParser.ConfigParser()
    config.read(args.config_file)
    con = sqlite3.connect(config.get('database', 'filename'))

    while 1:
        serialno = uuid.uuid4().bytes
        oem_factory_token = '%s%s' %(serialno, '\xFF')
        customer_factory_token = '%s%s' %(serialno, '\x00\xFF')

        private_key = generate_private_key(config.get('tools', 'private_key_cmd'))
        public_key = generate_public_key(config.get('tools', 'public_key_cmd'), private_key)
        sk = SigningKey.from_der(private_key)
        pk = VerifyingKey.from_der(public_key)

        embedded_private_key = generate_private_key(config.get('tools', 'private_key_cmd'))
        embedded_public_key = generate_public_key(config.get('tools', 'public_key_cmd'), embedded_private_key)
        embedded_sk = SigningKey.from_der(embedded_private_key)
        embedded_pk = VerifyingKey.from_der(embedded_public_key)

        embedded_private_key_sig = embedded_sk.sign(oem_factory_token, hashfunc=sha256)
        assert embedded_pk.verify(embedded_private_key_sig, oem_factory_token, hashfunc=sha256)

        oem_factory_token_sig = sk.sign(oem_factory_token, hashfunc=sha256)
        assert pk.verify(oem_factory_token_sig, oem_factory_token, hashfunc=sha256)

        customer_factory_token_sig = sk.sign(customer_factory_token, hashfunc=sha256)
        assert pk.verify(customer_factory_token_sig, customer_factory_token, hashfunc=sha256)

        debug_token_sig = sk.sign(serialno, hashfunc=sha256)
        assert pk.verify(debug_token_sig, serialno, hashfunc=sha256)

        public_key_compressed = ecc_compress(pk.to_string())

        with con:
            cur = con.cursor()
            cur.execute(config.get('database', 'create'))
            cur.execute(config.get('database', 'insert'),
                        (sqlite3.Binary(private_key),
                         sqlite3.Binary(public_key),
                         sqlite3.Binary(public_key_compressed),
                         sqlite3.Binary(embedded_private_key),
                         sqlite3.Binary(embedded_public_key),
                         sqlite3.Binary(embedded_sk.to_string()),
                         sqlite3.Binary(serialno),
                         sqlite3.Binary(oem_factory_token_sig),
                         sqlite3.Binary(customer_factory_token_sig),
                         sqlite3.Binary(debug_token_sig)))
Exemplo n.º 2
0
def validate_encrypted_message(msg, sig_key='sender', sig_required=False):

    # Verify Keys in DER Format
    try:
        sender_key = from_sec(msg.sender_public_key) or VerifyingKey.from_der(
            msg.sender_public_key)
    except Exception as e:
        log.warn("sender_public_key NOT in DER Format")
        raise EncryptedMessageValidationError(
            'sender_public_key not in DER format')

    try:
        receiver_key = from_sec(
            msg.receiver_public_key) or VerifyingKey.from_der(
                msg.receiver_public_key)
    except Exception as e:
        log.warn("receiver_public_key NOT in DER Format")
        raise EncryptedMessageValidationError(
            'receiver_public_key not in DER format')

    # Validate Nonce
    if not msg.nonce or msg.nonce < (int(time.time() * 1000000) -
                                     config.ir_nonce_allowable * 1000000):
        log.warn("InvoiceRequest Nonce Missing or Before %d Seconds Ago" %
                 config.ir_nonce_allowable)
        raise NonceValidationError('Invalid Nonce')

    if not msg.signature:
        if not sig_required:
            return
        else:
            raise EncryptedMessageValidationError('Signature Required')

    # Validate Signature
    try:
        sig_verify = msg.signature
        msg.signature = ''
        if sig_key == 'sender':
            sender_key.verify(sig_verify,
                              msg.SerializeToString(),
                              hashfunc=sha256,
                              sigdecode=sigdecode_der)
        elif sig_key == 'receiver':
            receiver_key.verify(sig_verify,
                                msg.SerializeToString(),
                                hashfunc=sha256,
                                sigdecode=sigdecode_der)
        else:
            raise Exception('Invalid sig_key argument')
        msg.signature = sig_verify
    except Exception as e:
        log.warn('Signature Validation Failed: %s' % str(e))
        raise EncryptedMessageValidationError('Invalid Signature')
Exemplo n.º 3
0
def process_invoicerequest(message, id):

    resolver = PluginManager.get_plugin('RESOLVER', config.resolver_type)

    if isinstance(message, ProtocolMessage):

        invoice_request = InvoiceRequest()
        invoice_request.ParseFromString(message.serialized_message)

        # Validate Public Key
        vk = from_sec(request.headers.get('x-identity').decode('hex')) or VerifyingKey.from_der(request.headers.get('x-identity').decode('hex'))
        allowed_keys = [vk.to_der(), to_sec(vk, False), to_sec(vk, True)]

        if invoice_request.sender_public_key not in allowed_keys:
            log.warn("InvoiceRequest Public Key Does Not Match X-Identity Public Key")
            return create_json_response(False, 'InvoiceRequest Public Key Does Not Match X-Identity Public Key', 400)

        if invoice_request.pki_type == 'x509+sha256':
            log.debug("InvoiceRequest Contains X509 Certificate, Validating")

            if invoice_request.pki_data and not invoice_request.signature:
                log.warn('Submitted InvoiceRequest Missing Signature')
                return create_json_response(False, 'Requests including x509 cert must include signature', 400)

            # Verify signature if cert and signature are present
            if invoice_request.pki_data and invoice_request.signature:

                try:
                    x509_certs = X509Certificates()
                    x509_certs.ParseFromString(invoice_request.pki_data)

                    cert_data = ssl.DER_cert_to_PEM_cert(x509_certs.certificate[0])
                    cert = crypto.load_certificate(crypto.FILETYPE_PEM, cert_data)
                except Exception as e:
                    log.warn('Unable to load given x509 certificate [ID: %s]: %s' % (id, str(e)))
                    return create_json_response(False, 'Invalid x509 Certificate', 400)

                try:
                    sig_validate_ir = InvoiceRequest()
                    sig_validate_ir.ParseFromString(message.serialized_message)
                    sig_validate_ir.signature = ""
                    crypto.verify(cert, invoice_request.signature, sig_validate_ir.SerializeToString(), 'sha256')
                    log.info("InvoiceRequest Signature is Valid")
                except Exception as e:
                    log.info('Bad Signature Encountered During Signature Validation [ID: %s]: %s' % (id, str(e)))
                    return create_json_response(False, 'InvoiceRequest Signature Verification Error', 401)

    try:
        log.info('Adding InvoiceRequest %s' % id)
        ret_tx_id = resolver.add_paymentprotocol_message(message, id=id)
        if not ret_tx_id:
            log.error("Unexpected Add InvoiceRequest Failure [ID: %s]" % (id))
            return create_json_response(False, 'Unknown System Error, Please Try Again Later', 503)

        pp_tx_url = '%s/paymentprotocol/%s' % (request.host_url.rstrip('/'), ret_tx_id)
        log.debug('Accepted InvoiceRequest [ID: %s]' % id)
        return create_json_response(status=202, headers={'Access-Control-Expose-Headers': 'Location', 'Location':pp_tx_url})
    except Exception as e:
        log.error("Unexpected exception adding InvoiceRequest [ID: %s]: %s" % (id, str(e)))
        return create_json_response(False, 'Unknown System Error, Please Try Again Later', 503)
Exemplo n.º 4
0
    def verify(self, verify_key_path):
        """Verify the package using a DER or PEM encoded public key"""
        if not HAVE_CRYPTO:
            raise Exception("ecdsa library not installed")

        raw_key_data = ""
        with open(verify_key_path, "rb") as f:
            raw_key_data = f.read()

        vk = None
        try:
            vk = VerifyingKey.from_der(raw_key_data)
        except:
            pass

        try:
            vk = VerifyingKey.from_pem(raw_key_data)
        except:
            pass

        if vk is None:
            raise Exception("Could not load public key")

        sig = self.pkg.read_signature()
        digest = self.pkg.read_digest()

        return vk.verify_digest(sig, digest, sigdecode=sigdecode_der)
Exemplo n.º 5
0
 def importKey(data):
     'Import a key from der or hex string.'
     if isinstance(data, str):
         data = bytes.fromhex(data)
     if not isinstance(data, bytes):
         raise TypeError("Invalid data type.")
     return ECPublicKey(VerifyingKey.from_der(data))
Exemplo n.º 6
0
def verify(pubKey, message, signature):
    try:
        vk = VerifyingKey.from_der(pubKey)
        hashed = _policy_[vk.curve.name][1](message).digest()
        if vk.verify(signature, hashed):
            return True
        else:
            return False
    except Exception,e:
       return False
Exemplo n.º 7
0
def ecdsa_verify(der_pubkey_hex, signature, message):
    # cast appropriately to bytes
    message = ensure_bytes(message)
    der = bytes.fromhex(der_pubkey_hex)
    signature = bytes.fromhex(signature)

    vk = VerifyingKey.from_der(der)
    try:
        return vk.verify(signature, message)
    except BadSignatureError:
        return False
 def _verify_key_validity(self, pub_key):
     '''
     confirms that the supplied key is valid
     :param pub_key:
     :return: true if the key is valid, false otherwise
     '''
     try:
         pub_key = VerifyingKey.from_der()
     except:
         logging.exception('')
         logging.error('key invalid')
         return False
Exemplo n.º 9
0
def validate_encrypted_message(msg, sig_key='sender', sig_required=False):

    # Verify Keys in DER Format
    try:
        sender_key = from_sec(msg.sender_public_key) or VerifyingKey.from_der(msg.sender_public_key)
    except Exception as e:
        log.warn("sender_public_key NOT in DER Format")
        raise EncryptedMessageValidationError('sender_public_key not in DER format')

    try:
        receiver_key = from_sec(msg.receiver_public_key) or VerifyingKey.from_der(msg.receiver_public_key)
    except Exception as e:
        log.warn("receiver_public_key NOT in DER Format")
        raise EncryptedMessageValidationError('receiver_public_key not in DER format')

    # Validate Nonce
    if not msg.nonce or msg.nonce < (int(time.time() * 1000000) - config.ir_nonce_allowable * 1000000):
        log.warn("InvoiceRequest Nonce Missing or Before %d Seconds Ago" % config.ir_nonce_allowable)
        raise NonceValidationError('Invalid Nonce')

    if not msg.signature:
        if not sig_required:
            return
        else:
            raise EncryptedMessageValidationError('Signature Required')

    # Validate Signature
    try:
        sig_verify = msg.signature
        msg.signature = ''
        if sig_key == 'sender':
            sender_key.verify(sig_verify, msg.SerializeToString(), hashfunc=sha256, sigdecode=sigdecode_der)
        elif sig_key == 'receiver':
            receiver_key.verify(sig_verify, msg.SerializeToString(), hashfunc=sha256, sigdecode=sigdecode_der)
        else:
            raise Exception('Invalid sig_key argument')
        msg.signature = sig_verify
    except Exception as e:
        log.warn('Signature Validation Failed: %s' % str(e))
        raise EncryptedMessageValidationError('Invalid Signature')
Exemplo n.º 10
0
    def crypto_transfer(self, owner, amount, receiver, challenge, signature):
        print('crypto_transfer(%s, %s)' % (amount, receiver))

        #Create address by hashing public key
        public_key = VerifyingKey.from_der(owner)
        public_key_hash = hashlib.sha3_256()
        public_key_hash.update(public_key.to_der())
        address = '11x' + public_key_hash.hexdigest()[24:]
        print('Address: ', address)

        message = challenge + b"|" + bytes(f'{amount}', "utf-8") + b"|" + str.encode(receiver)
        check   = public_key.verify(signature, message, hashlib.sha256, util.sigdecode_der)
        print('Signature verification:', check)
Exemplo n.º 11
0
 def load(cls, message):
     _key = deepcopy(message)
     _message_pb = cert_pb.Certificate()
     if isinstance(_key, dict):
         _message_pb.publicKey = _key.pop("publicKey")
         _message_pb.version = VERSION_MAP[_key.pop("version")]
         _message_pb.keyType = ECDSA_CURVES[_key.pop("keyType")]
     else:
         _message_pb.version = _key.version
         _message_pb.keyType = _key.keyType
         _message_pb.publicKey = _key.publicKey
     if _message_pb.keyType not in CURVE_NAMES:
         raise Exception("Unknown curve")
     curve_name = CURVE_NAMES[_message_pb.keyType]
     if _ECDSAKeyHelper(VerifyingKey.from_der(_message_pb.publicKey)).curve_name != curve_name:
         raise Exception("Curve mismatch")
     return cls._load(_key, _message_pb)
Exemplo n.º 12
0
def main(argv):

    """
        Main procedure to sign a binary
    """


    parser = argparse.ArgumentParser(description='convert der to raw')
    parser.add_argument('-s','--secretkey_file', help='Secret key', required=True)
    parser.add_argument('-p','--publickey_file', help='Public key', required=True)
    args = parser.parse_args()

    secretkey_file = args.secretkey_file
    publickey_file = args.publickey_file


    privkey = SigningKey.from_der(open(secretkey_file).read())
    pubkey = VerifyingKey.from_der(open(publickey_file).read())

    open(secretkey_file[0:-4] + ".bin", "wb").write(privkey.to_string())
    open(publickey_file[0:-4] + ".bin", "wb").write(pubkey.to_string())
Exemplo n.º 13
0
def validate_tx_in(tx_in, transaction, a_unspent_tx_outs):
    referenced_u_tx_out = find_unspent_tx_out(tx_in['tx_out_id'],
                                              tx_in['tx_out_index'],
                                              a_unspent_tx_outs)

    if not referenced_u_tx_out:
        print('referenced txOut not found: ' + json.dumps(tx_in))
        return False

    address = referenced_u_tx_out['address']

    key = VerifyingKey.from_der(address.decode("hex"))
    signature = tx_in['signature'].decode("hex")
    valid_signature = key.verify(signature, transaction['id'].encode())
    if not valid_signature:
        print('invalid txIn signature: %s txId: %s address: %s',
              tx_in['signature'], transaction['id'],
              referenced_u_tx_out['address'])
        return False

    return True
Exemplo n.º 14
0
def verify_sign(message, signature, key):
    ''''Load the verifying key, message, and signature and verify the signature (assume SHA-1 hash)

			Args:
					message (:obj:`bytes`):  signed data
					signature (:obj:`string`): string representation of signature
					key (:obj:`obj`):certificate owner name string hash

			Return:
					signature (:obj:`string`): string representation of signature
	'''

    # Load the verifying key, message, and signature and verify the signature (assume SHA-1 hash):

    vk = VerifyingKey.from_der(b64decode(key['public']))
    sig = b64decode(signature)
    try:
        vk.verify(sig, message)
        print("good signature")
        return True
    except BadSignatureError:
        print("BAD SIGNATURE")
    return False
Exemplo n.º 15
0
def main(argv):
    """
        Main procedure to sign a binary
    """

    parser = argparse.ArgumentParser(description='convert der to raw')
    parser.add_argument('-s',
                        '--secretkey_file',
                        help='Secret key',
                        required=True)
    parser.add_argument('-p',
                        '--publickey_file',
                        help='Public key',
                        required=True)
    args = parser.parse_args()

    secretkey_file = args.secretkey_file
    publickey_file = args.publickey_file

    privkey = SigningKey.from_der(open(secretkey_file).read())
    pubkey = VerifyingKey.from_der(open(publickey_file).read())

    open(secretkey_file[0:-4] + ".bin", "wb").write(privkey.to_string())
    open(publickey_file[0:-4] + ".bin", "wb").write(pubkey.to_string())
Exemplo n.º 16
0
    def test_bip75_flow(self):

        ###################
        # Load Crypto Keys
        ###################
        self.x509_sender_cert = crypto.load_certificate(
            crypto.FILETYPE_PEM, SENDER_CERT)
        self.x509_sender_cert_privkey = crypto.load_privatekey(
            crypto.FILETYPE_PEM, SENDER_CERT_PRIVKEY)

        self.x509_receiver_cert = crypto.load_certificate(
            crypto.FILETYPE_PEM, RECEIVER_CERT)
        self.x509_receiver_cert_privkey = crypto.load_privatekey(
            crypto.FILETYPE_PEM, RECEIVER_CERT_PRIVKEY)

        ################################
        # Register Addressimo Endpoint
        ################################
        self.register_endpoint()

        #########################
        # Create InvoiceRequest
        #########################
        log.info("Building InvoiceRequest")

        sender_certs = X509Certificates()
        sender_certs.certificate.append(
            ssl.PEM_cert_to_DER_cert(
                crypto.dump_certificate(crypto.FILETYPE_PEM,
                                        self.x509_sender_cert)))

        invoice_request = InvoiceRequest()
        invoice_request.sender_public_key = BIP75FunctionalTest.sender_sk.get_verifying_key(
        ).to_der()
        invoice_request.amount = 75
        invoice_request.pki_type = 'x509+sha256'
        invoice_request.pki_data = sender_certs.SerializeToString()
        invoice_request.notification_url = 'https://notify.me/longId'
        invoice_request.signature = ""

        # Handle x509 Signature
        sig = crypto.sign(self.x509_sender_cert_privkey,
                          invoice_request.SerializeToString(), 'sha256')
        invoice_request.signature = sig

        ##################################
        # Create Encrypted InvoiceRequest
        ##################################
        eir = self.create_encrypted_protocol_message(
            message=invoice_request,
            receiver_pubkey=BIP75FunctionalTest.receiver_sk.get_verifying_key(
            ),
            sender_pubkey=BIP75FunctionalTest.sender_sk.get_verifying_key(),
            private_key=BIP75FunctionalTest.sender_sk)

        BIP75FunctionalTest.identifier = eir.identifier

        #############################
        # Sign & Submit HTTP Request
        #############################
        post_url = "%s/address/%s/resolve" % (self.get_server_url(),
                                              self.addressimo_endpoint_id)
        msg_sig = BIP75FunctionalTest.sender_sk.sign(self.get_signing_data(
            post_url, 'post', eir.SerializeToString()),
                                                     hashfunc=sha256,
                                                     sigencode=sigencode_der)

        ir_headers = {
            'X-Identity':
            BIP75FunctionalTest.sender_sk.get_verifying_key().to_der().encode(
                'hex'),
            'X-Signature':
            msg_sig.encode('hex'),
            'Content-Type':
            'application/bitcoin-encrypted-paymentprotocol-message',
            'Content-Transfer-Encoding':
            'binary'
        }
        log.info("Submitting InvoiceRequest using an EncryptedProtocolMessage")
        response = requests.post(post_url,
                                 headers=ir_headers,
                                 data=eir.SerializeToString())

        # Validate Response
        self.assertEqual(202, response.status_code)
        self.assertTrue(
            response.headers.get('Location').startswith(
                'https://%s/paymentprotocol' % config.site_url))
        self.payment_id = response.headers.get('Location').rsplit('/', 1)[1]
        log.info('Payment ID: %s' % self.payment_id)

        ###############################################
        # Get Pending InvoiceRequests from Addressimo
        ###############################################
        sign_url = "%s/address/%s/paymentprotocol" % (
            self.get_server_url(), self.addressimo_endpoint_id)
        msg_sig = BIP75FunctionalTest.receiver_sk.sign(self.get_signing_data(
            sign_url, 'get'),
                                                       hashfunc=sha256,
                                                       sigencode=sigencode_der)

        ir_req_headers = {
            'X-Identity':
            BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der().
            encode('hex'),
            'X-Signature':
            msg_sig.encode('hex')
        }

        log.info("Retrieving Encrypted InvoiceRequests")
        response = requests.get(sign_url, headers=ir_req_headers)

        log.info(
            "Encrypted InvoiceRequest Retrieval Response [CODE: %d | TEXT: %s]"
            % (response.status_code, response.text))
        self.assertEqual(200, response.status_code)
        self.assertIsNotNone(response.text)

        ###############################################
        # Retrieve and Decrypt Encrypted InvoiceRequest
        ###############################################
        received_eir = None
        for epm in response.json()['encrypted_protocol_messages']:
            _local_msg = self.parse_protocol_message(epm.decode('hex'))
            if _local_msg.message_type == ProtocolMessageType.Value(
                    'INVOICE_REQUEST'
            ) and _local_msg.identifier == BIP75FunctionalTest.identifier:
                received_eir = _local_msg

        if not received_eir:
            self.fail('Failed to Retrieve Encrypted InvoiceRequest message')

        sender_vk = VerifyingKey.from_der(received_eir.sender_public_key)
        self.assertEqual(
            received_eir.receiver_public_key,
            BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der())

        received_invoice_request = self.get_decrypted_protocol_message(
            received_eir, sender_vk, BIP75FunctionalTest.receiver_sk)

        #########################
        # Create PaymentRequest
        #########################
        log.info("Building PaymentRequest")

        pd = PaymentDetails()
        pd.network = 'main'
        output = pd.outputs.add()
        output.amount = received_invoice_request.amount
        output.script = 'paymesomemoneyhere'.encode('hex')
        pd.time = int(datetime.utcnow().strftime('%s'))
        pd.expires = int(
            (datetime.utcnow() + timedelta(seconds=3600)).strftime('%s'))
        pd.memo = ''
        pd.payment_url = ''
        pd.merchant_data = ''

        receiver_certs = X509Certificates()
        receiver_certs.certificate.append(
            ssl.PEM_cert_to_DER_cert(
                crypto.dump_certificate(crypto.FILETYPE_PEM,
                                        self.x509_receiver_cert)))

        pr = PaymentRequest()
        pr.payment_details_version = 1
        pr.pki_type = 'x509+sha256'
        pr.pki_data = receiver_certs.SerializeToString()
        pr.serialized_payment_details = pd.SerializeToString()
        pr.signature = ''

        sig = crypto.sign(self.x509_receiver_cert_privkey,
                          pr.SerializeToString(), 'sha256')
        pr.signature = sig

        log.info('Encapsulating PaymentRequest in EncryptedProtocolMessage')
        epr = self.create_encrypted_protocol_message(
            message=pr,
            receiver_pubkey=BIP75FunctionalTest.receiver_sk.get_verifying_key(
            ),
            sender_pubkey=BIP75FunctionalTest.sender_sk.get_verifying_key(),
            private_key=BIP75FunctionalTest.receiver_sk,
            identifier=BIP75FunctionalTest.identifier)

        sign_url = "%s/address/%s/paymentprotocol" % (
            self.get_server_url(), self.addressimo_endpoint_id)
        msg_sig = BIP75FunctionalTest.receiver_sk.sign(self.get_signing_data(
            sign_url, 'post', epr.SerializeToString()),
                                                       hashfunc=sha256,
                                                       sigencode=sigencode_der)

        ir_req_headers = {
            'X-Identity':
            BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der().
            encode('hex'),
            'X-Signature':
            msg_sig.encode('hex'),
            'Content-Type':
            'application/bitcoin-encrypted-paymentprotocol-message',
            'Content-Transfer-Encoding':
            'binary'
        }

        log.info("Submitting PaymentRequest using an EncryptedProtocolMessage")
        response = requests.post(sign_url,
                                 data=epr.SerializeToString(),
                                 headers=ir_req_headers)
        log.info('Submit PaymentRequest Response: %s' % response.text)
        self.assertEqual(200, response.status_code)

        ##############################################################################
        # Delete InvoiceRequest after the PaymentRequest was submitted successfully
        ##############################################################################
        delete_url = "%s/address/%s/paymentprotocol/%s/invoice_request" % (
            self.get_server_url(), self.addressimo_endpoint_id,
            received_eir.identifier.encode('hex'))
        msg_sig = BIP75FunctionalTest.receiver_sk.sign(self.get_signing_data(
            delete_url, 'delete'),
                                                       hashfunc=sha256,
                                                       sigencode=sigencode_der)

        ir_delete_headers = {
            'X-Identity':
            BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der().
            encode('hex'),
            'X-Signature':
            msg_sig.encode('hex')
        }
        response = requests.delete(delete_url, headers=ir_delete_headers)
        self.assertEqual(response.status_code, requests.codes.no_content)

        #####################################
        # Retrieve Encrypted PaymentRequest
        #####################################
        log.info("Retrieving PaymentRequest")

        sign_url = "%s/paymentprotocol/%s" % (self.get_server_url(),
                                              self.payment_id)
        msg_sig = BIP75FunctionalTest.sender_sk.sign(self.get_signing_data(
            sign_url, 'get'),
                                                     hashfunc=sha256,
                                                     sigencode=sigencode_der)
        get_message_headers = {
            'X-Identity':
            BIP75FunctionalTest.sender_sk.get_verifying_key().to_der().encode(
                'hex'),
            'X-Signature':
            msg_sig.encode('hex')
        }
        response = requests.get(sign_url, headers=get_message_headers)
        self.assertIsNotNone(response)

        self.assertIn('Content-Type', response.headers)
        self.assertEqual('application/json',
                         response.headers.get('Content-Type'))

        received_epr = None
        for epm in response.json()['encrypted_protocol_messages']:
            _local_msg = self.parse_protocol_message(epm.decode('hex'))
            if _local_msg.message_type == ProtocolMessageType.Value(
                    'PAYMENT_REQUEST'
            ) and _local_msg.identifier == BIP75FunctionalTest.identifier:
                received_epr = _local_msg

        log.info('Received Encrypted PaymentRequest')

        self.assertEqual(
            BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der(),
            received_epr.receiver_public_key)
        self.assertEqual(
            BIP75FunctionalTest.sender_sk.get_verifying_key().to_der(),
            received_epr.sender_public_key)

        # Decrypt Response
        returned_paymentrequest = self.get_decrypted_protocol_message(
            message=received_epr,
            pubkey=VerifyingKey.from_der(received_epr.receiver_public_key),
            privkey=BIP75FunctionalTest.sender_sk)

        self.assertEqual(1, returned_paymentrequest.payment_details_version)
        self.assertEqual(pr.pki_type, returned_paymentrequest.pki_type)
        self.assertEqual(pr.pki_data, returned_paymentrequest.pki_data)
        self.assertEqual(pd.SerializeToString(),
                         returned_paymentrequest.serialized_payment_details)
        self.assertEqual(pr.signature, returned_paymentrequest.signature)

        #######################################
        # Create / Submit Payment
        #######################################
        payment = Payment()
        payment.merchant_data = 'nodusttxs'.encode('hex')
        payment.transactions.append('btc_tx'.encode('hex'))
        out = payment.refund_to.add()
        out.script = 'myp2shaddress'.encode('hex')

        encrypted_payment = self.create_encrypted_protocol_message(
            message=payment,
            receiver_pubkey=VerifyingKey.from_der(
                received_epr.receiver_public_key),
            sender_pubkey=VerifyingKey.from_der(
                received_epr.sender_public_key),
            private_key=BIP75FunctionalTest.sender_sk,
            identifier=BIP75FunctionalTest.identifier)

        # Submit Payment
        sign_url = "%s/paymentprotocol/%s" % (self.get_server_url(),
                                              self.payment_id)
        msg_sig = BIP75FunctionalTest.sender_sk.sign(self.get_signing_data(
            sign_url, 'post', encrypted_payment.SerializeToString()),
                                                     hashfunc=sha256,
                                                     sigencode=sigencode_der)

        ep_req_headers = {
            'X-Identity':
            BIP75FunctionalTest.sender_sk.get_verifying_key().to_der().encode(
                'hex'),
            'X-Signature':
            msg_sig.encode('hex'),
            'Content-Type':
            'application/bitcoin-encrypted-paymentprotocol-message',
            'Content-Transfer-Encoding':
            'binary'
        }

        log.info("Submitting Payment using an EncryptedProtocolMessage")
        response = requests.post(sign_url,
                                 data=encrypted_payment.SerializeToString(),
                                 headers=ep_req_headers)
        log.info('Submit Payment Response: %s' % response.text)
        self.assertEqual(200, response.status_code)

        ##############################################################################
        # Delete PaymentRequest after the Payment was submitted successfully
        ##############################################################################
        delete_url = "%s/paymentprotocol/%s/%s/payment_request" % (
            self.get_server_url(), self.payment_id,
            received_eir.identifier.encode('hex'))
        msg_sig = BIP75FunctionalTest.receiver_sk.sign(self.get_signing_data(
            delete_url, 'delete'),
                                                       hashfunc=sha256,
                                                       sigencode=sigencode_der)

        ir_delete_headers = {
            'X-Identity':
            BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der().
            encode('hex'),
            'X-Signature':
            msg_sig.encode('hex')
        }
        response = requests.delete(delete_url, headers=ir_delete_headers)
        self.assertEqual(response.status_code, requests.codes.no_content)

        ############################
        # Retrieve Payment
        ############################
        log.info("Retrieving Payment")

        sign_url = "%s/paymentprotocol/%s" % (self.get_server_url(),
                                              self.payment_id)
        msg_sig = BIP75FunctionalTest.receiver_sk.sign(self.get_signing_data(
            sign_url, 'get'),
                                                       hashfunc=sha256,
                                                       sigencode=sigencode_der)
        get_message_headers = {
            'X-Identity':
            BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der().
            encode('hex'),
            'X-Signature':
            msg_sig.encode('hex')
        }

        response = requests.get(sign_url, headers=get_message_headers)
        self.assertIsNotNone(response)

        self.assertIn('Content-Type', response.headers)
        self.assertEqual('application/json',
                         response.headers.get('Content-Type'))

        returned_ep = None
        for epm in response.json()['encrypted_protocol_messages']:
            _local_msg = self.parse_protocol_message(epm.decode('hex'))
            if _local_msg.message_type == ProtocolMessageType.Value(
                    'PAYMENT'
            ) and _local_msg.identifier == BIP75FunctionalTest.identifier:
                returned_ep = _local_msg

        self.assertEqual(
            BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der(),
            returned_ep.receiver_public_key)
        self.assertEqual(
            BIP75FunctionalTest.sender_sk.get_verifying_key().to_der(),
            returned_ep.sender_public_key)
        self.assertEqual(encrypted_payment.encrypted_message,
                         returned_ep.encrypted_message)

        payment_msg = self.get_decrypted_protocol_message(
            message=returned_ep,
            pubkey=VerifyingKey.from_der(returned_ep.sender_public_key),
            privkey=BIP75FunctionalTest.receiver_sk)

        self.assertEqual('nodusttxs'.encode('hex'), payment_msg.merchant_data)
        self.assertEqual(1, len(payment_msg.transactions))
        self.assertEqual('btc_tx'.encode('hex'), payment_msg.transactions[0])

        #######################################
        # Create / Submit PaymentACK
        #######################################
        paymentack = PaymentACK()
        paymentack.payment.CopyFrom(payment_msg)
        paymentack.memo = 'Payment ACKed'

        encrypted_paymentack = self.create_encrypted_protocol_message(
            message=paymentack,
            receiver_pubkey=VerifyingKey.from_der(epr.receiver_public_key),
            sender_pubkey=VerifyingKey.from_der(epr.sender_public_key),
            private_key=BIP75FunctionalTest.receiver_sk,
            identifier=BIP75FunctionalTest.identifier)

        # Submit PaymentAck
        sign_url = "%s/paymentprotocol/%s" % (self.get_server_url(),
                                              self.payment_id)
        msg_sig = BIP75FunctionalTest.receiver_sk.sign(self.get_signing_data(
            sign_url, 'post', encrypted_paymentack.SerializeToString()),
                                                       hashfunc=sha256,
                                                       sigencode=sigencode_der)

        ep_req_headers = {
            'X-Identity':
            BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der().
            encode('hex'),
            'X-Signature':
            msg_sig.encode('hex'),
            'Content-Type':
            'application/bitcoin-encrypted-paymentprotocol-message',
            'Content-Transfer-Encoding':
            'binary'
        }

        log.info("Submitting PaymentAck using an EncryptedProtocolMessage")
        response = requests.post(sign_url,
                                 data=encrypted_paymentack.SerializeToString(),
                                 headers=ep_req_headers)
        log.info('Submit PaymentAck Response: %s' % response.text)
        self.assertEqual(200, response.status_code)

        ##############################################################################
        # Delete Payment after the PaymentACK was submitted successfully
        ##############################################################################
        delete_url = "%s/address/%s/paymentprotocol/%s/payment" % (
            self.get_server_url(), self.addressimo_endpoint_id,
            received_eir.identifier.encode('hex'))
        msg_sig = BIP75FunctionalTest.receiver_sk.sign(self.get_signing_data(
            delete_url, 'delete'),
                                                       hashfunc=sha256,
                                                       sigencode=sigencode_der)

        ir_delete_headers = {
            'X-Identity':
            BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der().
            encode('hex'),
            'X-Signature':
            msg_sig.encode('hex')
        }
        response = requests.delete(delete_url, headers=ir_delete_headers)
        self.assertEqual(response.status_code, requests.codes.no_content)

        ###############################
        # Retrieve PaymentAck
        ###############################
        log.info("Retrieving EncryptedPaymentAck")
        sign_url = "%s/paymentprotocol/%s" % (self.get_server_url(),
                                              self.payment_id)
        msg_sig = BIP75FunctionalTest.receiver_sk.sign(self.get_signing_data(
            sign_url, 'get'),
                                                       hashfunc=sha256,
                                                       sigencode=sigencode_der)
        get_message_headers = {
            'X-Identity':
            BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der().
            encode('hex'),
            'X-Signature':
            msg_sig.encode('hex')
        }
        response = requests.get(sign_url, headers=get_message_headers)
        self.assertIsNotNone(response)

        self.assertIn('Content-Type', response.headers)
        self.assertEqual('application/json',
                         response.headers.get('Content-Type'))

        returned_epa = None
        for epm in response.json()['encrypted_protocol_messages']:
            _local_msg = self.parse_protocol_message(epm.decode('hex'))
            if _local_msg.message_type == ProtocolMessageType.Value(
                    'PAYMENT_ACK'
            ) and _local_msg.identifier == BIP75FunctionalTest.identifier:
                returned_epa = _local_msg

        log.info('Received PaymentACK')

        self.assertEqual(
            BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der(),
            returned_ep.receiver_public_key)
        self.assertEqual(
            BIP75FunctionalTest.sender_sk.get_verifying_key().to_der(),
            returned_ep.sender_public_key)
        self.assertEqual(encrypted_paymentack.encrypted_message,
                         returned_epa.encrypted_message)

        paymentack_msg = self.get_decrypted_protocol_message(
            message=returned_epa,
            pubkey=VerifyingKey.from_der(returned_epa.sender_public_key),
            privkey=BIP75FunctionalTest.receiver_sk)
        self.assertEqual(paymentack_msg, paymentack)

        ##############################################################################
        # Delete PaymentACK after the PaymentACK was retrieved successfully
        ##############################################################################
        delete_url = "%s/address/%s/paymentprotocol/%s/payment_ack" % (
            self.get_server_url(), self.addressimo_endpoint_id,
            received_eir.identifier.encode('hex'))
        msg_sig = BIP75FunctionalTest.receiver_sk.sign(self.get_signing_data(
            delete_url, 'delete'),
                                                       hashfunc=sha256,
                                                       sigencode=sigencode_der)

        ir_delete_headers = {
            'X-Identity':
            BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der().
            encode('hex'),
            'X-Signature':
            msg_sig.encode('hex')
        }
        response = requests.delete(delete_url, headers=ir_delete_headers)
        self.assertEqual(response.status_code, requests.codes.no_content)

        ################################
        # Delete Addressimo Endpoint
        ################################
        self.cleanup_endpoint()
Exemplo n.º 17
0
FAIL = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'

AS_IDENTITY = SigningKey.from_der(
    bytes.fromhex(
        '30770201010420fb37dbd38e48cfc41475e50dd52d7328102bd31cf881e4'
        'e163c58e5f150aa1f2a00a06082a8648ce3d030107a144034200047069be'
        'd49cab8ffa5b1c820271aef0bc0c8f5cd149e05c5b9e37686da06d02bd5f'
        '7bc35ea8265be7c5e276ad7e7d0eb05e4a0551102a66bba88b02b5eb4c33'
        '55'))

AS_PUBLIC_KEY: VerifyingKey = VerifyingKey.from_der(
    bytes.fromhex(
        "3059301306072a8648ce3d020106082a8648ce3d030107034200047069be"
        "d49cab8ffa5b1c820271aef0bc0c8f5cd149e05c5b9e37686da06d02bd5f"
        "7bc35ea8265be7c5e276ad7e7d0eb05e4a0551102a66bba88b02b5eb4c33"
        "55"))

RS_IDENTITY: SigningKey = SigningKey.from_der(
    bytes.fromhex(
        "307702010104200ffc411715d3cc4917bd27ac4f310552b085b1ca0bb0a8"
        "bbb9d8931d651544c1a00a06082a8648ce3d030107a144034200046cc415"
        "12d92fb03cb3b35bed5b494643a8a8a55503e87a90282c78d6c58a7e3c88"
        "a21c0287e7e8d76b0052b1f1a2dcebfea57714c1210d42f17b335adcb76d"
        "7a"))

RS_PUBLIC_KEY: VerifyingKey = VerifyingKey.from_der(
    bytes.fromhex(
        '3059301306072a8648ce3d020106082a8648ce3d030107034200046cc415'
        '12d92fb03cb3b35bed5b494643a8a8a55503e87a90282c78d6c58a7e3c88'
Exemplo n.º 18
0
 def verifying_key(self):
     if self._verifying_key is None:
         self._verifying_key = VerifyingKey.from_der(self._der)
     return self._verifying_key
Exemplo n.º 19
0
    def test_bip75_flow(self):

        ###################
        # Load Crypto Keys
        ###################
        self.x509_sender_cert = crypto.load_certificate(crypto.FILETYPE_PEM, SENDER_CERT)
        self.x509_sender_cert_privkey = crypto.load_privatekey(crypto.FILETYPE_PEM, SENDER_CERT_PRIVKEY)

        self.x509_receiver_cert = crypto.load_certificate(crypto.FILETYPE_PEM, RECEIVER_CERT)
        self.x509_receiver_cert_privkey = crypto.load_privatekey(crypto.FILETYPE_PEM, RECEIVER_CERT_PRIVKEY)

        #########################
        # Create InvoiceRequest
        #########################
        log.info("Building InvoiceRequest")

        sender_certs = X509Certificates()
        sender_certs.certificate.append(ssl.PEM_cert_to_DER_cert(crypto.dump_certificate(crypto.FILETYPE_PEM, self.x509_sender_cert)))

        invoice_request = InvoiceRequest()
        invoice_request.sender_public_key = BIP75FunctionalTest.sender_sk.get_verifying_key().to_der()
        invoice_request.amount = 75
        invoice_request.pki_type = 'x509+sha256'
        invoice_request.pki_data = sender_certs.SerializeToString()
        invoice_request.notification_url = 'https://notify.me/longId'
        invoice_request.signature = ""

        # Handle x509 Signature
        sig = crypto.sign(self.x509_sender_cert_privkey, invoice_request.SerializeToString(), 'sha1')
        invoice_request.signature = sig

        ##################################
        # Create Encrypted InvoiceRequest
        ##################################
        eir = self.create_encrypted_protocol_message(
            message=invoice_request,
            receiver_pubkey=BIP75FunctionalTest.receiver_sk.get_verifying_key(),
            sender_pubkey=BIP75FunctionalTest.sender_sk.get_verifying_key(),
            private_key=BIP75FunctionalTest.sender_sk
        )

        BIP75FunctionalTest.identifier = eir.identifier

        #############################
        # Sign & Submit HTTP Request
        #############################
        post_url = "%s/address/testid/resolve" % self.get_server_url()
        msg_sig = BIP75FunctionalTest.sender_sk.sign(post_url + eir.SerializeToString())

        ir_headers = {
            'X-Identity': BIP75FunctionalTest.sender_sk.get_verifying_key().to_der().encode('hex'),
            'X-Signature': msg_sig.encode('hex'),
            'Content-Type': 'application/bitcoin-encrypted-paymentprotocol-message',
            'Content-Transfer-Encoding': 'binary'
        }
        log.info("Submitting InvoiceRequest using an EncryptedProtocolMessage")
        response = requests.post(post_url, headers=ir_headers, data=eir.SerializeToString())

        # Validate Response
        self.assertEqual(202, response.status_code)
        self.assertTrue(response.headers.get('Location').startswith('https://%s/paymentprotocol' % config.site_url))
        self.payment_id = response.headers.get('Location').rsplit('/', 1)[1]
        log.info('Payment ID: %s' % self.payment_id)

        ###############################################
        # Get Pending InvoiceRequests from Addressimo
        ###############################################
        sign_url = "%s/address/testid/paymentprotocol" % self.get_server_url()
        msg_sig = BIP75FunctionalTest.receiver_sk.sign(sign_url)

        ir_req_headers = {
            'X-Identity': BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der().encode('hex'),
            'X-Signature': msg_sig.encode('hex')
        }

        log.info("Retrieving Encrypted InvoiceRequests")
        response = requests.get(sign_url, headers=ir_req_headers)

        log.info("Encrypted InvoiceRequest Retrieval Response [CODE: %d | TEXT: %s]" % (response.status_code, response.text))
        self.assertEqual(200, response.status_code)
        self.assertIsNotNone(response.text)

        ###############################################
        # Retrieve and Decrypt Encrypted InvoiceRequest
        ###############################################
        received_eir = None
        for epm in response.json()['encrypted_protocol_messages']:
            _local_msg = self.parse_protocol_message(epm.decode('hex'))
            if _local_msg.message_type == ProtocolMessageType.Value('INVOICE_REQUEST') and _local_msg.identifier == BIP75FunctionalTest.identifier:
                received_eir = _local_msg

        if not received_eir:
            self.fail('Failed to Retrieve Encrypted InvoiceRequest message')

        sender_vk = VerifyingKey.from_der(received_eir.sender_public_key)
        self.assertEqual(received_eir.receiver_public_key, BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der())

        received_invoice_request = self.get_decrypted_protocol_message(received_eir, sender_vk, BIP75FunctionalTest.receiver_sk)

        #########################
        # Create PaymentRequest
        #########################
        log.info("Building PaymentRequest")

        pd = PaymentDetails()
        pd.network = 'main'
        output = pd.outputs.add()
        output.amount = received_invoice_request.amount
        output.script = 'paymesomemoneyhere'.encode('hex')
        pd.time = int(datetime.utcnow().strftime('%s'))
        pd.expires = int((datetime.utcnow() + timedelta(seconds=3600)).strftime('%s'))
        pd.memo = ''
        pd.payment_url = ''
        pd.merchant_data = ''

        receiver_certs = X509Certificates()
        receiver_certs.certificate.append(ssl.PEM_cert_to_DER_cert(crypto.dump_certificate(crypto.FILETYPE_PEM, self.x509_receiver_cert)))

        pr = PaymentRequest()
        pr.payment_details_version = 1
        pr.pki_type = 'x509+sha256'
        pr.pki_data = receiver_certs.SerializeToString()
        pr.serialized_payment_details = pd.SerializeToString()
        pr.signature = ''

        sig = crypto.sign(self.x509_receiver_cert_privkey, pr.SerializeToString(), 'sha1')
        pr.signature = sig

        log.info('Encapsulating PaymentRequest in EncryptedProtocolMessage')
        epr = self.create_encrypted_protocol_message(
            message=pr,
            receiver_pubkey=BIP75FunctionalTest.receiver_sk.get_verifying_key(),
            sender_pubkey=BIP75FunctionalTest.sender_sk.get_verifying_key(),
            private_key=BIP75FunctionalTest.receiver_sk,
            identifier=BIP75FunctionalTest.identifier
        )

        sign_url = "%s/address/testid/paymentprotocol" % self.get_server_url()
        msg_sig = BIP75FunctionalTest.receiver_sk.sign(sign_url + epr.SerializeToString())

        ir_req_headers = {
            'X-Identity': BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der().encode('hex'),
            'X-Signature': msg_sig.encode('hex'),
            'Content-Type': 'application/bitcoin-encrypted-paymentprotocol-message',
            'Content-Transfer-Encoding': 'binary'
        }

        log.info("Submitting PaymentRequest using an EncryptedProtocolMessage")
        response = requests.post(sign_url, data=epr.SerializeToString(), headers=ir_req_headers)
        log.info('Submit PaymentRequest Response: %s' % response.text)
        self.assertEqual(200, response.status_code)

        ##############################################################################
        # Delete InvoiceRequest after the PaymentRequest was submitted successfully
        delete_url = "%s/address/testid/paymentprotocol/%s/invoice_request" % (self.get_server_url(), received_eir.identifier.encode('hex'))
        msg_sig = BIP75FunctionalTest.receiver_sk.sign(delete_url)

        ir_delete_headers = {
            'X-Identity': BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der().encode('hex'),
            'X-Signature': msg_sig.encode('hex')
        }
        response = requests.delete(delete_url, headers=ir_delete_headers)
        self.assertEqual(response.status_code, requests.codes.no_content)

        #####################################
        # Retrieve Encrypted PaymentRequest
        #####################################
        log.info("Retrieving PaymentRequest")

        sign_url = "%s/paymentprotocol/%s" % (self.get_server_url(), self.payment_id)
        msg_sig = BIP75FunctionalTest.receiver_sk.sign(sign_url)
        get_message_headers = {
            'X-Identity': BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der().encode('hex'),
            'X-Signature': msg_sig.encode('hex')
        }
        response = requests.get(sign_url, headers=get_message_headers)
        self.assertIsNotNone(response)

        self.assertIn('Content-Type', response.headers)
        self.assertEqual('application/json', response.headers.get('Content-Type'))

        received_epr = None
        for epm in response.json()['encrypted_protocol_messages']:
            _local_msg = self.parse_protocol_message(epm.decode('hex'))
            if _local_msg.message_type == ProtocolMessageType.Value('PAYMENT_REQUEST') and _local_msg.identifier == BIP75FunctionalTest.identifier:
                received_epr = _local_msg

        log.info('Received Encrypted PaymentRequest')

        self.assertEqual(BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der(), received_epr.receiver_public_key)
        self.assertEqual(BIP75FunctionalTest.sender_sk.get_verifying_key().to_der(), received_epr.sender_public_key)

        # Decrypt Response
        returned_paymentrequest = self.get_decrypted_protocol_message(
            message=received_epr,
            pubkey=VerifyingKey.from_der(received_epr.receiver_public_key),
            privkey=BIP75FunctionalTest.sender_sk
        )

        self.assertEqual(1, returned_paymentrequest.payment_details_version)
        self.assertEqual(pr.pki_type, returned_paymentrequest.pki_type)
        self.assertEqual(pr.pki_data, returned_paymentrequest.pki_data)
        self.assertEqual(pd.SerializeToString(), returned_paymentrequest.serialized_payment_details)
        self.assertEqual(pr.signature, returned_paymentrequest.signature)

        #######################################
        # Create / Submit Payment
        #######################################
        payment = Payment()
        payment.merchant_data = 'nodusttxs'.encode('hex')
        payment.transactions.append('btc_tx'.encode('hex'))
        out = payment.refund_to.add()
        out.script = 'myp2shaddress'.encode('hex')

        encrypted_payment = self.create_encrypted_protocol_message(
            message=payment,
            receiver_pubkey=VerifyingKey.from_der(received_epr.receiver_public_key),
            sender_pubkey=VerifyingKey.from_der(received_epr.sender_public_key),
            private_key=BIP75FunctionalTest.sender_sk,
            identifier=BIP75FunctionalTest.identifier
        )

        # Submit Payment
        sign_url = "%s/paymentprotocol/%s" % (self.get_server_url(), self.payment_id)
        msg_sig = BIP75FunctionalTest.sender_sk.sign(sign_url + encrypted_payment.SerializeToString())

        ep_req_headers = {
            'X-Identity': BIP75FunctionalTest.sender_sk.get_verifying_key().to_der().encode('hex'),
            'X-Signature': msg_sig.encode('hex'),
            'Content-Type': 'application/bitcoin-encrypted-paymentprotocol-message',
            'Content-Transfer-Encoding': 'binary'
        }

        log.info("Submitting Payment using an EncryptedProtocolMessage")
        response = requests.post(sign_url, data=encrypted_payment.SerializeToString(), headers=ep_req_headers)
        log.info('Submit Payment Response: %s' % response.text)
        self.assertEqual(200, response.status_code)

        ##############################################################################
        # Delete PaymentRequest after the Payment was submitted successfully
        delete_url = "%s/paymentprotocol/%s/%s/payment_request" % (self.get_server_url(), self.payment_id, received_eir.identifier.encode('hex'))
        msg_sig = BIP75FunctionalTest.receiver_sk.sign(delete_url)

        ir_delete_headers = {
            'X-Identity': BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der().encode('hex'),
            'X-Signature': msg_sig.encode('hex')
        }
        response = requests.delete(delete_url, headers=ir_delete_headers)
        self.assertEqual(response.status_code, requests.codes.no_content)

        ############################
        # Retrieve Payment
        ############################
        log.info("Retrieving Payment")

        sign_url = "%s/paymentprotocol/%s" % (self.get_server_url(), self.payment_id)
        msg_sig = BIP75FunctionalTest.receiver_sk.sign(sign_url)
        get_message_headers = {
            'X-Identity': BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der().encode('hex'),
            'X-Signature': msg_sig.encode('hex')
        }

        response = requests.get(sign_url, headers=get_message_headers)
        self.assertIsNotNone(response)

        self.assertIn('Content-Type', response.headers)
        self.assertEqual('application/json', response.headers.get('Content-Type'))

        returned_ep = None
        for epm in response.json()['encrypted_protocol_messages']:
            _local_msg = self.parse_protocol_message(epm.decode('hex'))
            if _local_msg.message_type == ProtocolMessageType.Value('PAYMENT') and _local_msg.identifier == BIP75FunctionalTest.identifier:
                returned_ep = _local_msg

        self.assertEqual(BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der(), returned_ep.receiver_public_key)
        self.assertEqual(BIP75FunctionalTest.sender_sk.get_verifying_key().to_der(), returned_ep.sender_public_key)
        self.assertEqual(encrypted_payment.encrypted_message, returned_ep.encrypted_message)

        payment_msg = self.get_decrypted_protocol_message(
            message=returned_ep,
            pubkey=VerifyingKey.from_der(returned_ep.sender_public_key),
            privkey=BIP75FunctionalTest.receiver_sk
        )

        self.assertEqual('nodusttxs'.encode('hex'), payment_msg.merchant_data)
        self.assertEqual(1, len(payment_msg.transactions))
        self.assertEqual('btc_tx'.encode('hex'), payment_msg.transactions[0])


        #######################################
        # Create / Submit PaymentACK
        #######################################
        paymentack = PaymentACK()
        paymentack.payment.CopyFrom(payment_msg)
        paymentack.memo = 'Payment ACKed'

        encrypted_paymentack = self.create_encrypted_protocol_message(
            message=paymentack,
            receiver_pubkey=VerifyingKey.from_der(epr.receiver_public_key),
            sender_pubkey=VerifyingKey.from_der(epr.sender_public_key),
            private_key=BIP75FunctionalTest.receiver_sk,
            identifier=BIP75FunctionalTest.identifier
        )

        # Submit PaymentAck
        sign_url = "%s/paymentprotocol/%s" % (self.get_server_url(), self.payment_id)
        msg_sig = BIP75FunctionalTest.receiver_sk.sign(sign_url + encrypted_paymentack.SerializeToString())

        ep_req_headers = {
            'X-Identity': BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der().encode('hex'),
            'X-Signature': msg_sig.encode('hex'),
            'Content-Type': 'application/bitcoin-encrypted-paymentprotocol-message',
            'Content-Transfer-Encoding': 'binary'
        }

        log.info("Submitting PaymentAck using an EncryptedProtocolMessage")
        response = requests.post(sign_url, data=encrypted_paymentack.SerializeToString(), headers=ep_req_headers)
        log.info('Submit PaymentAck Response: %s' % response.text)
        self.assertEqual(200, response.status_code)

        ##############################################################################
        # Delete Payment after the PaymentACK was submitted successfully
        delete_url = "%s/address/testid/paymentprotocol/%s/payment" % (self.get_server_url(), received_eir.identifier.encode('hex'))
        msg_sig = BIP75FunctionalTest.receiver_sk.sign(delete_url)

        ir_delete_headers = {
            'X-Identity': BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der().encode('hex'),
            'X-Signature': msg_sig.encode('hex')
        }
        response = requests.delete(delete_url, headers=ir_delete_headers)
        self.assertEqual(response.status_code, requests.codes.no_content)

        ###############################
        # Retrieve PaymentAck
        ###############################
        log.info("Retrieving EncryptedPaymentAck")
        sign_url = "%s/paymentprotocol/%s" % (self.get_server_url(), self.payment_id)
        msg_sig = BIP75FunctionalTest.receiver_sk.sign(sign_url)
        get_message_headers = {
            'X-Identity': BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der().encode('hex'),
            'X-Signature': msg_sig.encode('hex')
        }
        response = requests.get(sign_url, headers=get_message_headers)
        self.assertIsNotNone(response)

        self.assertIn('Content-Type', response.headers)
        self.assertEqual('application/json', response.headers.get('Content-Type'))

        returned_epa = None
        for epm in response.json()['encrypted_protocol_messages']:
            _local_msg = self.parse_protocol_message(epm.decode('hex'))
            if _local_msg.message_type == ProtocolMessageType.Value('PAYMENT_ACK') and _local_msg.identifier == BIP75FunctionalTest.identifier:
                returned_epa = _local_msg

        log.info('Received PaymentACK')

        self.assertEqual(BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der(), returned_ep.receiver_public_key)
        self.assertEqual(BIP75FunctionalTest.sender_sk.get_verifying_key().to_der(), returned_ep.sender_public_key)
        self.assertEqual(encrypted_paymentack.encrypted_message, returned_epa.encrypted_message)

        paymentack_msg = self.get_decrypted_protocol_message(
            message=returned_epa,
            pubkey=VerifyingKey.from_der(returned_epa.sender_public_key),
            privkey=BIP75FunctionalTest.receiver_sk
        )
        self.assertEqual(paymentack_msg, paymentack)

        ##############################################################################
        # Delete PaymentACK after the PaymentACK was retrieved successfully
        delete_url = "%s/address/testid/paymentprotocol/%s/payment_ack" % (self.get_server_url(), received_eir.identifier.encode('hex'))
        msg_sig = BIP75FunctionalTest.receiver_sk.sign(delete_url)

        ir_delete_headers = {
            'X-Identity': BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der().encode('hex'),
            'X-Signature': msg_sig.encode('hex')
        }
        response = requests.delete(delete_url, headers=ir_delete_headers)
        self.assertEqual(response.status_code, requests.codes.no_content)
Exemplo n.º 20
0
def submit_paymentprotocol_message(id=None, tx_id=None, ignore_pubkey_verify=False):

    resolver = PluginManager.get_plugin('RESOLVER', config.resolver_type)

    if not id and not tx_id:
        log.error('Missing ID and TX_ID, Returning Error')
        return create_json_response(False, 'Invalid Payment Protocol Message Retrieval Attempt', 400)

    if request.content_type not in PAYMENT_PROTOCOL_CONTENT_TYPES:
        log.warn('Received Request with Invalid Content-Type [CONTENT-TYPE: %s]' % str(request.content_type))
        return create_json_response(False, 'Invalid Content-Type for Payment Protocol Message', 400)

    if request.headers.get('Content-Transfer-Encoding', '') != 'binary':
        log.warn("PaymentProtocol Message Content-Transfer-Encoding IS NOT set to binary")
        return create_json_response(False, 'PaymentProtocol Message Content-Transfer-Encoding MUST be binary', 400)

    ##########################################################
    # Verify ID or TX Exists (and is correctly configured
    ##########################################################
    if id:

        if not ignore_pubkey_verify:
            not_verified = verify_public_key()
            if not_verified:
                return not_verified

        try:
            id_obj = resolver.get_id_obj(id)
        except Exception as e:
            log.error('Exception retrieving id_obj [ID: %s | Exception: %s]' % (id, str(e)))
            return create_json_response(False, 'Exception Occurred, Please Try Again Later.', 503)

        if not id_obj:
            log.error('Unable to retrieve id_obj [ID: %s]' % id)
            return create_json_response(False, 'ID Not Recognized', 404)

        if not id_obj.paymentprotocol_only:
            log.warn("PaymentProtocol Endpoint POST Submitted to Non-PaymentProtocol Endpoint")
            return create_json_response(False, 'Not a PaymentProtocol Endpoint', 400)

    if tx_id and not resolver.get_paymentprotocol_messages(tx_id=tx_id):

        log.error('No Messages Exist, Unable to Add Message to Transaction [TX ID: %s]' % str(tx_id))
        return create_json_response(False, 'Transaction Does Not Exist', 404)

    ########################################
    # Handle ProtocolMessages
    ########################################
    message = parse_paymentprotocol_message(request.get_data())
    if not message:
        log.error('Unable to Parse Payment Protocol Message, Returning an Error')
        return create_json_response(False, 'Unable to Parse Payment Protocol', 400)

    # Verify Identifier is Set
    if not message.identifier:
        log.warn('Identifier is Missing from Payment Protocol Message, Rejecting')
        return create_json_response(False, 'Payment Protocol Message Missing Required Field: identifier', 400)

    if isinstance(message, ProtocolMessage) and message.message_type != ProtocolMessageType.Value('INVOICE_REQUEST'):
        log.warn("Non-InvoiceRequest Message Send via Protocol Message")
        return create_json_response(False, 'Only InvoiceRequest Messages May Be Send Using ProtocolMessages, all others require EncryptedProtocolMessages', 400)

    #################################################
    # Verify Encrypted Protocol Message Signatures
    #################################################
    if isinstance(message, EncryptedProtocolMessage):

        required_identity = message.sender_public_key
        text_identity = 'sender'
        if message.message_type in [ProtocolMessageType.Value('PAYMENT_REQUEST'), ProtocolMessageType.Value('PAYMENT_ACK')]:
            required_identity = message.receiver_public_key
            text_identity = 'receiver'

        # Determine Possible Values the sender_public_key could have
        vk = from_sec(request.headers.get('x-identity').decode('hex')) or VerifyingKey.from_der(request.headers.get('x-identity').decode('hex'))
        pk_vals = [vk.to_der().encode('hex'), to_sec(vk, False).encode('hex'), to_sec(vk, True).encode('hex')]

        # Verify the Sender is the message signer
        if required_identity.encode('hex') not in pk_vals:
            log.warn("Message %s Public Key Does Not Match X-Identity Public Key" % text_identity)
            return create_json_response(False, 'Message %s Public Key Does Not Match X-Identity Public Key' % text_identity, 400)

        # Check Nonce is Increasing
        if message.message_type != ProtocolMessageType.Value('INVOICE_REQUEST') and resolver.get_tx_last_nonce(message, id=id) > message.nonce:
            log.warn('PaymentProtocol EncryptedProtocolMessage Submitted with Invalid Nonce')
            return create_json_response(False, 'Nonce is Not Valid', 400)

        # Validate Encrypted Message
        try:
            validate_encrypted_message(message, sig_key=text_identity, sig_required=True)
        except EncryptedMessageValidationError as e:
            return create_json_response(False, str(e), 400)
        except NonceValidationError as e:
            return create_json_response(False, str(e), 400, data={'utime': int(time.time() * 1000000)})

    # Process Submission
    if message.message_type == ProtocolMessageType.Value('INVOICE_REQUEST'):
        return process_invoicerequest(message, id)
    elif message.message_type == ProtocolMessageType.Value('PAYMENT_REQUEST'):
        return process_paymentrequest(message, id)
    else:
        ret_tx_id = resolver.add_paymentprotocol_message(message, id=id, tx_id=tx_id)
        if not ret_tx_id:
            log.error('Unknown Failure Occurred Adding PaymentProtocol message to service')
            return create_json_response(False, 'Message Store Failed', 500)
        return create_json_response(True, 'Payment Protocol message accepted')
Exemplo n.º 21
0
 def verify(self, signature: bytes, message: bytes) -> bool:
     vk = VerifyingKey.from_der(self.public_key)
     return vk.verify(signature,
                      message,
                      hashfunc=sha256,
                      sigdecode=sigdecode_der)
Exemplo n.º 22
0
def process_invoicerequest(message, id):

    resolver = PluginManager.get_plugin('RESOLVER', config.resolver_type)

    if isinstance(message, ProtocolMessage):

        invoice_request = InvoiceRequest()
        invoice_request.ParseFromString(message.serialized_message)

        # Validate Public Key
        try:
            vk = from_sec(request.headers.get('x-identity').decode(
                'hex')) or VerifyingKey.from_der(
                    request.headers.get('x-identity').decode('hex'))
        except UnexpectedDER as e:
            log.warn('X-Identity Public Key Not in SEC or DER Format')
            return create_json_response(
                False, 'X-Identity Not Valid SEC or DER ECDSA Public Key', 400)

        allowed_keys = [vk.to_der(), to_sec(vk, False), to_sec(vk, True)]

        if invoice_request.sender_public_key not in allowed_keys:
            log.warn(
                "InvoiceRequest Public Key Does Not Match X-Identity Public Key"
            )
            return create_json_response(
                False,
                'InvoiceRequest Public Key Does Not Match X-Identity Public Key',
                400)

        if invoice_request.pki_type == 'x509+sha256':
            log.debug("InvoiceRequest Contains X509 Certificate, Validating")

            if invoice_request.pki_data and not invoice_request.signature:
                log.warn('Submitted InvoiceRequest Missing Signature')
                return create_json_response(
                    False,
                    'Requests including x509 cert must include signature', 400)

            # Verify signature if cert and signature are present
            if invoice_request.pki_data and invoice_request.signature:

                try:
                    x509_certs = X509Certificates()
                    x509_certs.ParseFromString(invoice_request.pki_data)

                    cert_data = ssl.DER_cert_to_PEM_cert(
                        x509_certs.certificate[0])
                    cert = crypto.load_certificate(crypto.FILETYPE_PEM,
                                                   cert_data)
                except Exception as e:
                    log.warn(
                        'Unable to load given x509 certificate [ID: %s]: %s' %
                        (id, str(e)))
                    return create_json_response(False,
                                                'Invalid x509 Certificate',
                                                400)

                try:
                    sig_validate_ir = InvoiceRequest()
                    sig_validate_ir.ParseFromString(message.serialized_message)
                    sig_validate_ir.signature = ""
                    crypto.verify(cert, invoice_request.signature,
                                  sig_validate_ir.SerializeToString(),
                                  'sha256')
                    log.info("InvoiceRequest Signature is Valid")
                except Exception as e:
                    log.info(
                        'Bad Signature Encountered During Signature Validation [ID: %s]: %s'
                        % (id, str(e)))
                    return create_json_response(
                        False, 'InvoiceRequest Signature Verification Error',
                        401)

    try:
        log.info('Adding InvoiceRequest %s' % id)
        ret_tx_id = resolver.add_paymentprotocol_message(message, id=id)
        if not ret_tx_id:
            log.error("Unexpected Add InvoiceRequest Failure [ID: %s]" % (id))
            return create_json_response(
                False, 'Unknown System Error, Please Try Again Later', 503)

        pp_tx_url = '%s/paymentprotocol/%s' % (request.host_url.rstrip('/'),
                                               ret_tx_id)
        log.debug('Accepted InvoiceRequest [ID: %s]' % id)
        return create_json_response(status=202,
                                    headers={
                                        'Access-Control-Expose-Headers':
                                        'Location',
                                        'Location': pp_tx_url
                                    })
    except Exception as e:
        log.error("Unexpected exception adding InvoiceRequest [ID: %s]: %s" %
                  (id, str(e)))
        return create_json_response(
            False, 'Unknown System Error, Please Try Again Later', 503)
Exemplo n.º 23
0
def delete_paymentprotocol_message(identifier, message_type, id=None, tx_id=None):

    resolver = PluginManager.get_plugin('RESOLVER', config.resolver_type)

    if id:
        not_verified = verify_public_key()
        if not_verified:
            return not_verified

    if not id and not tx_id:
        log.error('Missing ID and TX_ID, Returning Error')
        return create_json_response(False, 'Invalid Payment Protocol Message Retrieval Attempt', 400)

    if id:
        try:
            id_obj = resolver.get_id_obj(id)
        except Exception as e:
            log.error('Exception retrieving id_obj [ID: %s | Exception: %s]' % (id, str(e)))
            return create_json_response(False, 'Exception Occurred, Please Try Again Later.', 500)

        if not id_obj:
            log.error('Unable to retrieve id_obj [ID: %s]' % id)
            return create_json_response(False, 'ID Not Recognized', 404)

        messages = resolver.get_paymentprotocol_messages(id=id)

    if tx_id:
        messages = resolver.get_paymentprotocol_messages(tx_id=tx_id)

    vk = from_sec(request.headers.get('x-identity').decode('hex')) or VerifyingKey.from_der(request.headers.get('x-identity').decode('hex'))
    allowed_keys = [vk.to_der(), to_sec(vk, False), to_sec(vk, True)]

    for transaction_id, tx in messages.iteritems():
        for msg in tx.get('messages', []):

            parsed_msg = parse_paymentprotocol_message(msg)

            if parsed_msg.identifier != identifier.decode('hex'):
                log.debug('Skipping Non-Matching Identifier [TYPE: %s | TX: %s]' % (message_type.upper(), transaction_id))
                continue

            if isinstance(parsed_msg, EncryptedProtocolMessage) and (parsed_msg.sender_public_key in allowed_keys or parsed_msg.receiver_public_key in allowed_keys):

                if resolver.delete_paymentprotocol_message(identifier.decode('hex'), message_type, tx_id=transaction_id):
                    log.info('Deleted PaymentProtocol Message [TYPE: %s | TX: %s]' % (message_type.upper(), transaction_id))
                    return create_json_response(True, 'Payment Protocol Message Deleted', 204)

                else:
                    log.info('PaymentProtocol Message Delete Failure [TYPE: %s | TX: %s]' % (message_type.upper(), transaction_id))
                    return create_json_response(False, 'Payment Protocol Message Does Not Exist', 404)

            elif isinstance(parsed_msg, ProtocolMessage) and parsed_msg.message_type == ProtocolMessageType.Value('INVOICE_REQUEST'):

                if parsed_msg.message_type == 'InvoiceRequest' and (parsed_msg.sender_public_key in allowed_keys or id == tx.get('receiver')):

                    if resolver.delete_paymentprotocol_message(identifier.decode('hex'), message_type, tx_id=transaction_id):
                        log.info('Deleted PaymentProtocol Message [TYPE: %s | TX: %s]' % (message_type.upper(), transaction_id))
                        return create_json_response(True, 'Payment Protocol Message Deleted', 204)

                    else:
                        log.info('PaymentProtocol Message Delete Failure [TYPE: %s | TX: %s]' % (message_type.upper(), transaction_id))
                        return create_json_response(False, 'Payment Protocol Message Delete Failed, Try Again Later', 503)

    return create_json_response(False, 'Matching Payment Protocol Message Not Found', 404)
def main(argv):
    """
        Main procedure to generate C array with keys
    """

    parser = argparse.ArgumentParser(
        description="Generates SQLite database with"
        " keys and serial number.")
    parser.add_argument('config_file',
                        help="project specific configuration file")
    args = parser.parse_args()

    config = ConfigParser.ConfigParser()
    config.read(args.config_file)
    con = sqlite3.connect(config.get('database', 'filename'))

    while 1:
        serialno = uuid.uuid4().bytes
        oem_factory_token = '%s%s' % (serialno, '\xFF')
        customer_factory_token = '%s%s' % (serialno, '\x00\xFF')

        private_key = generate_private_key(
            config.get('tools', 'private_key_cmd'))
        public_key = generate_public_key(config.get('tools', 'public_key_cmd'),
                                         private_key)
        sk = SigningKey.from_der(private_key)
        pk = VerifyingKey.from_der(public_key)

        embedded_private_key = generate_private_key(
            config.get('tools', 'private_key_cmd'))
        embedded_public_key = generate_public_key(
            config.get('tools', 'public_key_cmd'), embedded_private_key)
        embedded_sk = SigningKey.from_der(embedded_private_key)
        embedded_pk = VerifyingKey.from_der(embedded_public_key)

        embedded_private_key_sig = embedded_sk.sign(oem_factory_token,
                                                    hashfunc=sha256)
        assert embedded_pk.verify(embedded_private_key_sig,
                                  oem_factory_token,
                                  hashfunc=sha256)

        oem_factory_token_sig = sk.sign(oem_factory_token, hashfunc=sha256)
        assert pk.verify(oem_factory_token_sig,
                         oem_factory_token,
                         hashfunc=sha256)

        customer_factory_token_sig = sk.sign(customer_factory_token,
                                             hashfunc=sha256)
        assert pk.verify(customer_factory_token_sig,
                         customer_factory_token,
                         hashfunc=sha256)

        debug_token_sig = sk.sign(serialno, hashfunc=sha256)
        assert pk.verify(debug_token_sig, serialno, hashfunc=sha256)

        public_key_compressed = ecc_compress(pk.to_string())

        with con:
            cur = con.cursor()
            cur.execute(config.get('database', 'create'))
            cur.execute(
                config.get('database', 'insert'),
                (sqlite3.Binary(private_key), sqlite3.Binary(public_key),
                 sqlite3.Binary(public_key_compressed),
                 sqlite3.Binary(embedded_private_key),
                 sqlite3.Binary(embedded_public_key),
                 sqlite3.Binary(
                     embedded_sk.to_string()), sqlite3.Binary(serialno),
                 sqlite3.Binary(oem_factory_token_sig),
                 sqlite3.Binary(customer_factory_token_sig),
                 sqlite3.Binary(debug_token_sig)))
Exemplo n.º 25
0

if __name__ == "__main__":
    from ecdsa import VerifyingKey, SigningKey

    rs_identity = SigningKey.from_der(
        bytes.fromhex(
            "307702010104200ffc411715d3cc4917bd27ac4f310552b085b1ca0bb0a8"
            "bbb9d8931d651544c1a00a06082a8648ce3d030107a144034200046cc415"
            "12d92fb03cb3b35bed5b494643a8a8a55503e87a90282c78d6c58a7e3c88"
            "a21c0287e7e8d76b0052b1f1a2dcebfea57714c1210d42f17b335adcb76d"
            "7a"))

    as_public_key = VerifyingKey.from_der(
        bytes.fromhex(
            "3059301306072a8648ce3d020106082a8648ce3d030107034200047069be"
            "d49cab8ffa5b1c820271aef0bc0c8f5cd149e05c5b9e37686da06d02bd5f"
            "7bc35ea8265be7c5e276ad7e7d0eb05e4a0551102a66bba88b02b5eb4c33"
            "55"))

    loop = asyncio.get_event_loop()
    root = resource.Site()
    server = TemperatureServer(audience="tempSensor0",
                               identity=rs_identity,
                               as_url='http://localhost:8080',
                               as_public_key=as_public_key,
                               site=root)
    asyncio.ensure_future(Context.create_server_context(server.site),
                          loop=loop)
    loop.run_forever()
Exemplo n.º 26
0
def _check_host_sct(host_name):

    logs_list_json = requests.get(config.CT_LOGS_LIST)
    logs = {}

    try:
        logs_aux = logs_list_json.json().get('logs')

        for l in logs_aux:

            log_id = hashlib.sha256(l.get('key').decode(
                'base64')).digest().encode('base64').replace('\n', '')

            entry = {
                'url': 'https://' + l.get('url'),
                'key': l.get('key'),
                'log_name': l.get('description')
            }

            logs.update({log_id: entry})

    except ValueError as e:
        print "Error at logs list updating, using default list instead.\n\tError details: " + repr(
            e)

        with open('logs_data.json', 'r') as ld:
            logs = json.load(ld)

    host_name = host_name
    continue_exec = True

    global pos
    pos = 0

    sct_version = []
    sct_log = []
    sct_timestamp = []
    sct_extensions = []
    sct_signature_type = []
    sct_signature = []
    sct_type = []
    sct_number = 0
    precert_exists = False

    try:
        print "\n** Connecting to host: " + host_name + "... **\n"

        # TODO: Replace os.popen by subprocess or directly use Python code instead openssl (e.g. M2Crypto).
        tmp = os.popen("openssl s_client -showcerts -servername " + host_name +
                       " -connect " + host_name +
                       ":443 </dev/null 2>&1").read()

        begin_cert_str = '-----BEGIN CERTIFICATE-----'
        end_cert_str = '-----END CERTIFICATE-----'
        begin_cert_index = tmp.index(begin_cert_str)
        end_cert_index = tmp.index(end_cert_str)
        certificate_pem = tmp[begin_cert_index +
                              len(begin_cert_str):end_cert_index]

        issuer_pem = tmp[end_cert_index + len(end_cert_str):]
        begin_cert_index = issuer_pem.index(begin_cert_str)
        end_cert_index = issuer_pem.index(end_cert_str)
        issuer_pem = issuer_pem[begin_cert_index +
                                len(begin_cert_str):end_cert_index]

        cert = crypto.load_certificate(
            crypto.FILETYPE_PEM,
            begin_cert_str + certificate_pem + end_cert_str)

        cert_der = crypto.dump_certificate(crypto.FILETYPE_ASN1, cert=cert)

    except Exception as e:
        print "Error: Certificate not found for host " + host_name
        continue_exec = False

    if continue_exec:

        print "\n** Looking for embedded SCT in certificate **"

        type = ""

        for i in range(cert.get_extension_count()):

            if cert.get_extension(i).get_short_name() == 'ct_precert_scts':
                sct_raw_precert = bytearray()
                sct_raw_precert = cert.get_extension(i).get_data()
                type = "precert"

        if type == "precert":
            precert_exists = True
            sct_number += extract_sct_info(sct_raw_precert, sct_version,
                                           sct_log, sct_timestamp,
                                           sct_extensions, sct_signature_type,
                                           sct_signature, sct_type, type)
        else:
            print "\t> No embedded sct found on host's certificate"
            # NO SCT

        try:
            print "\n** Looking for SCTs in TLS extensions**"

            try:
                openssl_path = os.environ["OPENSSL_PATH"]
            except:
                openssl_path = "openssl"

            Args = [openssl_path]
            Args.extend([
                "s_client", "-serverinfo", "18", "-connect",
                "%s:443" % host_name, "-servername", host_name
            ])

            openssl_process = subprocess.Popen(Args,
                                               stdin=open('/dev/null', 'r'),
                                               stdout=subprocess.PIPE,
                                               stderr=subprocess.PIPE)
            openssl_process_stdout, OpenSSL_stderr = openssl_process.communicate(
            )
            openssl_process_exitcode = openssl_process.wait()

            if openssl_process_exitcode != 0:
                print("Error: OpenSSL can't connect to %s" % host_name)
                print("\tError details" + OpenSSL_stderr)
            begin_cert_str_ext18 = '-----BEGIN SERVERINFO FOR EXTENSION 18-----'
            end_cert_str_ext18 = '-----END SERVERINFO FOR EXTENSION 18-----'
            begin_cert_index = openssl_process_stdout.index(
                begin_cert_str_ext18)
            end_cert_index = openssl_process_stdout.index(end_cert_str_ext18)
            sct_raw_tls = bytearray()
            sct_raw_tls = openssl_process_stdout[
                begin_cert_index +
                len(begin_cert_str_ext18):end_cert_index].decode('base64')

            type = "tls"
            sct_number += extract_sct_info(sct_raw_tls, sct_version, sct_log,
                                           sct_timestamp, sct_extensions,
                                           sct_signature_type, sct_signature,
                                           sct_type, type)
        except:
            # NO TLS
            print "\t> No sct found on TLS"

        cert_aux_filename = host_name + ".pem"

        if not os.path.exists('tmp'):
            os.makedirs('tmp')

        try:

            print "\n** Looking for SCTs in OCSP response **"

            command = "openssl s_client -connect " + host_name + ":443 2>&1 < /dev/null | sed -n '/-----BEGIN/,/-----END/p' | cat > tmp/" + cert_aux_filename
            tmp = os.popen(command).read()

            command = "openssl s_client -connect " + host_name + ":443 2>&1 -showcerts < /dev/null | sed -n '/-----BEGIN/,/-----END/p' | perl -0777 -pe 's/.*?-{5}END\sCERTIFICATE-{5}\n//s' | cat > tmp/chain_" + cert_aux_filename
            tmp = os.popen(command).read()

            command = "openssl x509 -noout -ocsp_uri -in tmp/" + cert_aux_filename
            tmp = os.popen(command).read()
            m = re.search('http://(.+?)\n', tmp)

            if m is not None:
                print "\t> OCSP address not found"
                # TODO: Don't continue execution

            ocsp_url = m.group(1).replace('\n', '')

            command = "openssl ocsp -issuer tmp/chain_" + cert_aux_filename + " -cert tmp/" + cert_aux_filename \
                + " -respout tmp/" + cert_aux_filename + ".tmp -url http://" + ocsp_url \
                + " -header HOST " + ocsp_url + " -VAfile tmp/chain_" + cert_aux_filename + "2>&1"
            tmp = os.popen(command).read()

            with open('tmp/' + cert_aux_filename + ".tmp",
                      mode='rb') as file:  # b is important -> binary
                sct_raw_ocsp = file.read()

            start_sct = sct_raw_ocsp.encode('hex').index(
                '060a2b06010401d679020405') + len('060a2b06010401d679020405')
            sct_raw_ocsp = sct_raw_ocsp.encode('hex')[start_sct:].decode('hex')
            pos = 1
            length = _read_fixed_bytes(1, sct_raw_ocsp).encode('hex')
            if length[0] < 8:
                bytes_to_read = int(length, 16)
                sct_raw_ocsp = _read_fixed_bytes(bytes_to_read, sct_raw_ocsp)
            else:
                sct_raw_ocsp = _read_var_bytes(int(length[1], 16),
                                               sct_raw_ocsp)

            type = "ocsp"
            sct_number += extract_sct_info(sct_raw_ocsp, sct_version, sct_log,
                                           sct_timestamp, sct_extensions,
                                           sct_signature_type, sct_signature,
                                           sct_type, type)
        except Exception as e:
            # NO OCSP
            print "\t> No sct found in OCSP response"

        finally:
            if os.path.exists('tmp/' + cert_aux_filename + '.tmp'):
                os.remove('tmp/' + cert_aux_filename + '.tmp')

            if os.path.exists('tmp/chain_' + cert_aux_filename):
                os.remove('tmp/chain_' + cert_aux_filename)

            if os.path.exists('tmp/' + cert_aux_filename):
                os.remove('tmp/' + cert_aux_filename)

        if precert_exists:
            issuer = crypto.load_certificate(
                crypto.FILETYPE_PEM,
                begin_cert_str + issuer_pem + end_cert_str)
            issuer_public_key = issuer.get_pubkey().to_cryptography_key(
            ).public_bytes(Encoding.DER, PublicFormat.SubjectPublicKeyInfo)
            m = hashlib.sha256()
            m.update(issuer_public_key)
            issuer_public_key = m.digest()

        tbs = bytearray()

        pos = 1
        length = _read_fixed_bytes(1, cert_der).encode('hex')
        if int(length[0], 16) < 8:
            pos += 2
        else:
            pos += int(length[1], 16) + 1

        length = _read_fixed_bytes(1, cert_der).encode('hex')
        if int(length[0], 16) < 8:
            tbs_hex = _read_fixed_bytes(int(length, 16),
                                        cert_der).encode('hex')
        else:
            tbs_hex = _read_var_bytes(int(length[1], 16),
                                      cert_der).encode('hex')

        if precert_exists:
            sct_sequence_hex = sct_raw_precert.encode('hex')
            length = hex(len(sct_raw_precert)).replace('0x', '') \
                if len(hex(len(sct_raw_precert)).replace('0x', '')) % 2 == 0 \
                else '0'+hex(len(sct_raw_precert)).replace('0x', '')

            sct_sequence_hex = '060a2b06010401d679020402048' + str(
                len(length) / 2) + length + sct_sequence_hex
            length = hex(len(sct_sequence_hex.decode('hex'))).replace('0x', '') \
                if len(hex(len(sct_sequence_hex.decode('hex'))).replace('0x', '')) % 2 == 0 \
                else '0' + hex(len(sct_sequence_hex.decode('hex'))).replace('0x', '')

            sct_sequence_hex = '308' + str(
                len(length) / 2) + length + sct_sequence_hex

            tbs = tbs_hex.decode('hex')
            pos = 1
            # Skip Version
            _read_var_bytes(1, tbs)
            pos += 1
            # Skip Fingerprint
            _read_var_bytes(1, tbs)
            pos += 1
            # Skip signature type
            _read_var_bytes(1, tbs)
            pos += 1
            # Skip Issuer
            length = _read_fixed_bytes(1, tbs).encode('hex')
            if int(length[0], 16) < 8:
                _read_fixed_bytes(int(length, 16), tbs)
            else:
                _read_var_bytes(int(length[1], 16), tbs)
            pos += 1
            # Skip Valid date
            _read_var_bytes(1, tbs)

            pos += 1
            # Skip Subject
            length = _read_fixed_bytes(1, tbs).encode('hex')
            if int(length[0], 16) < 8:
                _read_fixed_bytes(int(length, 16), tbs)
            else:
                _read_var_bytes(int(length[1], 16), tbs)

            pos += 1
            # Skip RSA encryption
            length = _read_fixed_bytes(1, tbs).encode('hex')
            if int(length[0], 16) < 8:
                _read_fixed_bytes(int(length, 16), tbs)
            else:
                _read_var_bytes(int(length[1], 16), tbs)

            original_extensions_hex = tbs[pos:].encode('hex')

            pos += 1
            # Skip Sequence tag
            length = _read_fixed_bytes(1, tbs).encode('hex')
            if int(length[0], 16) < 8:
                pos += 1
            else:
                pos += 2

            pos += 1
            # Skip Sequence tag
            length = _read_fixed_bytes(1, tbs).encode('hex')
            if int(length[0], 16) < 8:
                pos += 1
            else:
                pos += 2

            extensions_hex = tbs[pos:].encode('hex')
            extensions_hex = extensions_hex.replace(sct_sequence_hex, '')
            extensions = extensions_hex.decode('hex')
            length = hex(len(extensions)).replace('0x', '') \
                if len(hex(len(extensions)).replace('0x', '')) % 2 == 0 \
                else '0' + hex(len(extensions)).replace('0x', '')

            extensions_hex = '308' + str(
                len(length) / 2) + length + extensions_hex
            length = hex(len(extensions_hex.decode('hex'))).replace('0x', '') \
                if len(hex(len(extensions_hex.decode('hex'))).replace('0x', '')) % 2 == 0 \
                else '0' + hex(len(extensions_hex.decode('hex'))).replace('0x', '')

            extensions_hex = 'a38' + str(
                len(length) / 2) + length + extensions_hex

            tbs_hex = tbs_hex.replace(original_extensions_hex, extensions_hex)
            tbs = tbs_hex.decode('hex')
            length = hex(len(tbs)).replace('0x', '') \
                if len(hex(len(tbs)).replace('0x', '')) % 2 == 0 \
                else '0' + hex(len(tbs)).replace('0x', '')

            tbs_hex = '308' + str(len(length) / 2) + length + tbs_hex
            tbs = tbs_hex.decode('hex')

        print "\n** Logs detected in SCTs **"

        for i in range(sct_number):

            log_id = sct_log[i].encode('base64').replace('\n', '')

            log = logs.get(log_id)

            if log is not None:

                log_name = log.get('log_name')

                print "\t> " + log_name + " (" + sct_type[i] + ")"

                try:
                    if sct_type[i] == "precert":
                        length = hex(len(tbs)).replace(
                            '0x', '') if len(hex(len(tbs)).replace(
                                '0x', '')) % 2 == 0 else '0' + hex(
                                    len(tbs)).replace('0x', '')
                        message = sct_version[i] + '00'.decode('hex') + sct_timestamp[i] + '0001'.decode('hex') + issuer_public_key +\
                                  '00'.decode('hex') + length.decode('hex') + tbs + sct_extensions[i]
                    else:
                        length = hex(len(cert_der)).replace(
                            '0x',
                            '') if len(hex(len(cert_der)).replace(
                                '0x', '')) % 2 == 0 else '0' + hex(
                                    len(cert_der)).replace('0x', '')
                        message = sct_version[i] + '00'.decode('hex') + sct_timestamp[i] + '0000'.decode('hex') + \
                                  '00'.decode('hex') + length.decode('hex') + cert_der + sct_extensions[i]

                    public_key = log.get('key')

                    verified_signature = False

                    if sct_signature_type[i].encode('hex') == '0403':
                        pub = VerifyingKey.from_der(
                            public_key.decode('base64'))
                        verified_signature = pub.verify(
                            sct_signature[i],
                            message,
                            hashfunc=hashlib.sha256,
                            sigdecode=ecdsa.util.sigdecode_der)
                    else:
                        rsakey = RSA.importKey(public_key.decode('base64'))
                        signer = PKCS1_v1_5.new(rsakey)
                        digest = SHA256.new()
                        digest.update(message)
                        verified_signature = signer.verify(
                            digest, sct_signature[i])

                    print "\t\t└─ Verified signature: " + str(
                        verified_signature) + "\n"
                except Exception as e:
                    print "Error occurred with log " + log_name + "\n\tError details: " + repr(
                        e)
            else:
                print "\t> Unknown log"
Exemplo n.º 27
0
def keyRead():
    with open(keypath + 'private.der', 'rb') as f:
        sk = SigningKey.from_der(f.read())
    with open(keypath + 'public.der', 'rb') as f:
        vk = VerifyingKey.from_der(f.read())
    return [sk,vk]
Exemplo n.º 28
0
def submit_paymentprotocol_message(id=None,
                                   tx_id=None,
                                   ignore_pubkey_verify=False):

    resolver = PluginManager.get_plugin('RESOLVER', config.resolver_type)

    if not id and not tx_id:
        log.error('Missing ID and TX_ID, Returning Error')
        return create_json_response(
            False, 'Invalid Payment Protocol Message Retrieval Attempt', 400)

    if request.content_type not in PAYMENT_PROTOCOL_CONTENT_TYPES:
        log.warn(
            'Received Request with Invalid Content-Type [CONTENT-TYPE: %s]' %
            str(request.content_type))
        return create_json_response(
            False, 'Invalid Content-Type for Payment Protocol Message', 400)

    if request.headers.get('Content-Transfer-Encoding', '') != 'binary':
        log.warn(
            "PaymentProtocol Message Content-Transfer-Encoding IS NOT set to binary"
        )
        return create_json_response(
            False,
            'PaymentProtocol Message Content-Transfer-Encoding MUST be binary',
            400)

    ##########################################################
    # Verify ID or TX Exists (and is correctly configured
    ##########################################################
    if id:

        if not ignore_pubkey_verify:
            not_verified = verify_public_key()
            if not_verified:
                return not_verified

        try:
            id_obj = resolver.get_id_obj(id)
        except Exception as e:
            log.error('Exception retrieving id_obj [ID: %s | Exception: %s]' %
                      (id, str(e)))
            return create_json_response(
                False, 'Exception Occurred, Please Try Again Later.', 503)

        if not id_obj:
            log.error('Unable to retrieve id_obj [ID: %s]' % id)
            return create_json_response(False, 'ID Not Recognized', 404)

        if not id_obj.paymentprotocol_only:
            log.warn(
                "PaymentProtocol Endpoint POST Submitted to Non-PaymentProtocol Endpoint"
            )
            return create_json_response(False,
                                        'Not a PaymentProtocol Endpoint', 400)

    if tx_id and not resolver.get_paymentprotocol_messages(tx_id=tx_id):

        log.error(
            'No Messages Exist, Unable to Add Message to Transaction [TX ID: %s]'
            % str(tx_id))
        return create_json_response(False, 'Transaction Does Not Exist', 404)

    ########################################
    # Handle ProtocolMessages
    ########################################
    message = parse_paymentprotocol_message(request.get_data())
    if not message:
        log.error(
            'Unable to Parse Payment Protocol Message, Returning an Error')
        return create_json_response(False, 'Unable to Parse Payment Protocol',
                                    400)

    # Verify Identifier is Set
    if not message.identifier:
        log.warn(
            'Identifier is Missing from Payment Protocol Message, Rejecting')
        return create_json_response(
            False,
            'Payment Protocol Message Missing Required Field: identifier', 400)

    if isinstance(
            message, ProtocolMessage
    ) and message.message_type != ProtocolMessageType.Value('INVOICE_REQUEST'):
        log.warn("Non-InvoiceRequest Message Send via Protocol Message")
        return create_json_response(
            False,
            'Only InvoiceRequest Messages May Be Send Using ProtocolMessages, all others require EncryptedProtocolMessages',
            400)

    #################################################
    # Verify Encrypted Protocol Message Signatures
    #################################################
    if isinstance(message, EncryptedProtocolMessage):

        required_identity = message.sender_public_key
        text_identity = 'sender'
        if message.message_type in [
                ProtocolMessageType.Value('PAYMENT_REQUEST'),
                ProtocolMessageType.Value('PAYMENT_ACK')
        ]:
            required_identity = message.receiver_public_key
            text_identity = 'receiver'

        # Determine Possible Values the sender_public_key could have
        try:
            vk = from_sec(request.headers.get('x-identity').decode(
                'hex')) or VerifyingKey.from_der(
                    request.headers.get('x-identity').decode('hex'))
        except UnexpectedDER as e:
            log.warn('X-Identity Public Key Not in SEC or DER Format')
            return create_json_response(
                False, 'X-Identity Not Valid SEC or DER ECDSA Public Key', 400)

        pk_vals = [
            vk.to_der().encode('hex'),
            to_sec(vk, False).encode('hex'),
            to_sec(vk, True).encode('hex')
        ]

        # Verify the Sender is the message signer
        if required_identity.encode('hex') not in pk_vals:
            log.warn(
                "Message %s Public Key Does Not Match X-Identity Public Key" %
                text_identity)
            return create_json_response(
                False,
                'Message %s Public Key Does Not Match X-Identity Public Key' %
                text_identity, 400)

        # Check Nonce is Increasing
        if message.message_type != ProtocolMessageType.Value(
                'INVOICE_REQUEST') and resolver.get_tx_last_nonce(
                    message, id=id) > message.nonce:
            log.warn(
                'PaymentProtocol EncryptedProtocolMessage Submitted with Invalid Nonce'
            )
            return create_json_response(False, 'Nonce is Not Valid', 400)

        # Validate Encrypted Message
        try:
            validate_encrypted_message(message,
                                       sig_key=text_identity,
                                       sig_required=True)
        except EncryptedMessageValidationError as e:
            return create_json_response(False, str(e), 400)
        except NonceValidationError as e:
            return create_json_response(
                False, str(e), 400, data={'utime': int(time.time() * 1000000)})

    # Process Submission
    if message.message_type == ProtocolMessageType.Value('INVOICE_REQUEST'):
        return process_invoicerequest(message, id)
    elif message.message_type == ProtocolMessageType.Value('PAYMENT_REQUEST'):
        return process_paymentrequest(message, id)
    else:
        ret_tx_id = resolver.add_paymentprotocol_message(message,
                                                         id=id,
                                                         tx_id=tx_id)
        if not ret_tx_id:
            log.error(
                'Unknown Failure Occurred Adding PaymentProtocol message to service'
            )
            return create_json_response(False, 'Message Store Failed', 500)
        return create_json_response(True, 'Payment Protocol message accepted')
Exemplo n.º 29
0
def delete_paymentprotocol_message(identifier,
                                   message_type,
                                   id=None,
                                   tx_id=None):

    resolver = PluginManager.get_plugin('RESOLVER', config.resolver_type)

    if id:
        not_verified = verify_public_key()
        if not_verified:
            return not_verified

    if not id and not tx_id:
        log.error('Missing ID and TX_ID, Returning Error')
        return create_json_response(
            False, 'Invalid Payment Protocol Message Retrieval Attempt', 400)

    if id:
        try:
            id_obj = resolver.get_id_obj(id)
        except Exception as e:
            log.error('Exception retrieving id_obj [ID: %s | Exception: %s]' %
                      (id, str(e)))
            return create_json_response(
                False, 'Exception Occurred, Please Try Again Later.', 500)

        if not id_obj:
            log.error('Unable to retrieve id_obj [ID: %s]' % id)
            return create_json_response(False, 'ID Not Recognized', 404)

        messages = resolver.get_paymentprotocol_messages(id=id)

    if tx_id:
        messages = resolver.get_paymentprotocol_messages(tx_id=tx_id)

    try:
        vk = from_sec(request.headers.get('x-identity').decode(
            'hex')) or VerifyingKey.from_der(
                request.headers.get('x-identity').decode('hex'))
    except UnexpectedDER as e:
        log.warn('X-Identity Public Key Not in SEC or DER Format')
        return create_json_response(
            False, 'X-Identity Not Valid SEC or DER ECDSA Public Key', 400)

    allowed_keys = [vk.to_der(), to_sec(vk, False), to_sec(vk, True)]

    for transaction_id, tx in messages.iteritems():
        for msg in tx.get('messages', []):

            parsed_msg = parse_paymentprotocol_message(msg)

            if parsed_msg.identifier != identifier.decode('hex'):
                log.debug(
                    'Skipping Non-Matching Identifier [TYPE: %s | TX: %s]' %
                    (message_type.upper(), transaction_id))
                continue

            if isinstance(parsed_msg, EncryptedProtocolMessage) and (
                    parsed_msg.sender_public_key in allowed_keys
                    or parsed_msg.receiver_public_key in allowed_keys):

                if resolver.delete_paymentprotocol_message(
                        identifier.decode('hex'),
                        message_type,
                        tx_id=transaction_id):
                    log.info(
                        'Deleted PaymentProtocol Message [TYPE: %s | TX: %s]' %
                        (message_type.upper(), transaction_id))
                    return create_json_response(
                        True, 'Payment Protocol Message Deleted', 204)

                else:
                    log.info(
                        'PaymentProtocol Message Delete Failure [TYPE: %s | TX: %s]'
                        % (message_type.upper(), transaction_id))
                    return create_json_response(
                        False, 'Payment Protocol Message Does Not Exist', 404)

            elif isinstance(
                    parsed_msg, ProtocolMessage
            ) and parsed_msg.message_type == ProtocolMessageType.Value(
                    'INVOICE_REQUEST'):

                ir = InvoiceRequest()
                ir.ParseFromString(parsed_msg.serialized_message)

                if parsed_msg.message_type == ProtocolMessageType.Value(
                        'INVOICE_REQUEST') and (ir.sender_public_key
                                                in allowed_keys
                                                or id == tx.get('receiver')):

                    if resolver.delete_paymentprotocol_message(
                            identifier.decode('hex'),
                            message_type,
                            tx_id=transaction_id):
                        log.info(
                            'Deleted PaymentProtocol Message [TYPE: %s | TX: %s]'
                            % (message_type.upper(), transaction_id))
                        return create_json_response(
                            True, 'Payment Protocol Message Deleted', 204)

                    else:
                        log.info(
                            'PaymentProtocol Message Delete Failure [TYPE: %s | TX: %s]'
                            % (message_type.upper(), transaction_id))
                        return create_json_response(
                            False,
                            'Payment Protocol Message Delete Failed, Try Again Later',
                            503)

    return create_json_response(False,
                                'Matching Payment Protocol Message Not Found',
                                404)
Exemplo n.º 30
0
        "55"
    )
)

loop = asyncio.get_event_loop()
app = web.Application(loop=loop)
server = AuthorizationServer(as_identity, app.router)

# Pre-register resource servers
server.register_resource_server(
    audience="tempSensor0",
    scopes=['read_temperature', 'post_led'],
    public_key=VerifyingKey.from_der(
        bytes.fromhex(
            "3059301306072a8648ce3d020106082a8648ce3d030107034200046cc415"
            "12d92fb03cb3b35bed5b494643a8a8a55503e87a90282c78d6c58a7e3c88"
            "a21c0287e7e8d76b0052b1f1a2dcebfea57714c1210d42f17b335adcb76d"
            "7a"
        )
    )
)

# Pre-register clients
server.register_client(
    client_id="ace_client_1",
    client_secret=b"ace_client_1_secret_123456",
    grants=[
        Grant(audience="tempSensor0", scopes=["read_temperature", "post_led"])
    ]
)

server.register_client(