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)))
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')
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)
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)
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))
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
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
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')
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)
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)
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())
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
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
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())
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()
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'
def verifying_key(self): if self._verifying_key is None: self._verifying_key = VerifyingKey.from_der(self._der) return self._verifying_key
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)
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')
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)
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)
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)))
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()
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"
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]
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')
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)
"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(