def work_order_submit(self, wo_submit_json, encrypted_session_key, worker_obj, private_key, session_iv): if self.work_order == None: logger.error("ERROR: Work order adaptor not initialized") sys.exit(1) input_json_str = wo_submit_json.get_json_str() sig_obj = signature.ClientSignature() input_json_str = sig_obj.generate_client_signature( input_json_str, worker_obj, private_key, session_iv, encrypted_session_key) wo_submit_json.load_from_str(input_json_str) logger.info("*********Request Json********* \n%s\n", json.dumps(json.loads(input_json_str), indent=4)) response = self.work_order.work_order_submit( wo_submit_json.get_params(), wo_submit_json.get_in_data(), wo_submit_json.get_out_data(), id=wo_submit_json.get_id()) logger.info("**********Received Response*********\n%s\n", json.dumps(response, indent=4)) # Return signed workorder json return input_json_str
def add_encrypted_request_hash(self): """ calculates request has based on EEA trusted-computing spec 6.1.8.1 and set encryptedRequestHash parameter in the request. """ sig_obj = signature.ClientSignature() concat_string = self.get_requester_nonce() + \ self.get_work_order_id() + \ self.get_worker_id() + \ self.get_workload_id() + \ self.get_requester_id() concat_bytes = bytes(concat_string, "UTF-8") #SHA-256 hashing is used hash_1 = crypto.byte_array_to_base64( crypto.compute_message_hash(concat_bytes)) hash_2 = sig_obj.calculate_datahash(self.get_in_data()) hash_3 = "" out_data = self.get_out_data() if out_data and len(out_data) > 0: hash_3 = sig_obj.calculate_datahash(out_data) concat_hash = hash_1 + hash_2 + hash_3 concat_hash = bytes(concat_hash, "UTF-8") self.final_hash = crypto.compute_message_hash(concat_hash) encrypted_request_hash = utility.encrypt_data(self.final_hash, self.session_key, self.session_iv) self.params_obj["encryptedRequestHash"] = crypto.byte_array_to_hex( encrypted_request_hash)
def __validate_work_order_receipt_create_req(self, wo_receipt_req, wo_request): """ Function to validate the work order receipt create request parameters Parameters: - wo_receipt_req is work order receipt request as dictionary - wo_request is string containing jrpc work order request Returns - tuple containing validation status(Boolean) and error message(string) """ # Valid parameters list valid_params = [ "workOrderId", "workerServiceId", "workerId", "requesterId", "receiptCreateStatus", "workOrderRequestHash", "requesterGeneratedNonce", "requesterSignature", "signatureRules", "receiptVerificationKey" ] for key in wo_receipt_req["params"]: if key not in valid_params: return False, "Missing parameter " + key + " in the request" else: if key in [ "workOrderId", "workerServiceId", "workerId", "requesterId", "requesterGeneratedNonce" ]: if not is_valid_hex_str(wo_receipt_req["params"][key]): return False, "invalid data parameter for " + key elif key in ["workOrderRequestHash", "requesterSignature"]: try: base64.b64decode(wo_receipt_req["params"][key]) except Exception as e: return False, \ "Invalid data format for " + key receipt_type = wo_receipt_req["params"]["receiptCreateStatus"] try: receipt_enum_type = ReceiptCreateStatus(receipt_type) except Exception as err: return False, "Invalid receipt status type {}: {}".format( receipt_enum_type, str(err)) # Validate signing rules signing_rules = wo_receipt_req["params"]["signatureRules"] rules = signing_rules.split("/") if len(rules) == 2 and (rules[0] != self.HASHING_ALGORITHM or rules[1] != self.SIGNING_ALGORITHM): return False, "Unsupported the signing rules" signature_obj = signature.ClientSignature() # Verify work order request is calculated properly or not. wo_req_hash = \ signature_obj.calculate_request_hash(json.loads(wo_request)) if wo_req_hash != wo_receipt_req["params"]["workOrderRequestHash"]: return False, "Work order request hash does not match" # Verify requester signature with signing key in the request status = signature_obj.verify_create_receipt_signature(wo_receipt_req) if status != SignatureStatus.PASSED: return False, "Receipt create requester signature does not match" # If all parameters are verified in the request return True, ""
def add_requester_signature(self, private_key): """ Calculate the signature of the request as defined in TCF EEA spec 6.1.8.3 and set the requesterSignature parameter in the request """ sig_obj = signature.ClientSignature() self.params_obj["requesterSignature"] = sig_obj.generate_signature( self.final_hash, private_key) # public signing key is shared to enclave manager to verify the signature. # It is temporary approach to share the key with the worker. self.set_verifying_key(private_key.GetPublicKey().Serialize())
def evaluate(self, message): """Create and submit workorder and wait for result.""" self.result_text.set("Waiting for evaluation result...") self.update() # Create, sign, and submit workorder. # Convert workloadId to hex. workload_id = "heart-disease-eval" workload_id = workload_id.encode("UTF-8").hex() session_iv = utility.generate_iv() session_key = utility.generate_key() requester_nonce = secrets.token_hex(16) work_order_id = secrets.token_hex(32) requester_id = secrets.token_hex(32) wo_params = WorkOrderParams( work_order_id, worker_id, workload_id, requester_id, session_key, session_iv, requester_nonce, result_uri=" ", notify_uri=" ", worker_encryption_key=worker_obj.encryption_key, data_encryption_algorithm="AES-GCM-256") wo_params.add_in_data(message) wo_params.add_encrypted_request_hash() if requester_signature: private_key = utility.generate_signing_keys() # Add requester signature and requester verifying_key if wo_params.add_requester_signature(private_key) == \ False: logger.info("Work order request signing failed") exit(1) # Set text for JSON sidebar req_id = 51 self.request_json = wo_params.to_string() work_order_instance = direct_jrpc.create_work_order(config) response = work_order_instance.work_order_submit( wo_params.get_params(), wo_params.get_in_data(), wo_params.get_out_data(), id=req_id) logger.info("Work order submit response : {}\n ".format( json.dumps(response, indent=4))) if "error" in response and response["error"]["code"] != \ WorkOrderStatus.PENDING: sys.exit(1) req_id += 1 # Retrieve result and set GUI result text res = work_order_instance.work_order_get_result(work_order_id, req_id) self.result_json = json.dumps(res, indent=4) if "result" in res: sig_obj = signature.ClientSignature() status = sig_obj.verify_signature(res, worker_obj.verification_key) try: if status == SignatureStatus.PASSED: logger.info("Signature verification" + \ " Successful") decrypted_res = utility. \ decrypted_response( res, session_key, session_iv) logger.info("\n" + \ "Decrypted response:\n {}". format(decrypted_res)) else: logger.info("Signature verification" + \ " Failed") sys.exit(1) except: logger.info("ERROR: Failed to decrypt response") sys.exit(1) else: logger.info("\n Work order get result failed {}\n". \ format(res)) sys.exit(1) # Set text for JSON sidebar self.result_text.set(decrypted_res[0]["data"]) # Retrieve receipt # Set text for JSON sidebar wo_receipt_instance = direct_jrpc.create_work_order_receipt(config) req_id += 1 self.receipt_json = json.dumps( wo_receipt_instance.work_order_receipt_retrieve( work_order_id, req_id), indent=4)
def Main(args=None): ParseCommandLine(args) config["Logging"] = {"LogFile": "__screen__", "LogLevel": "INFO"} plogger.setup_loggers(config.get("Logging", {})) sys.stdout = plogger.stream_to_logger(logging.getLogger("STDOUT"), logging.DEBUG) sys.stderr = plogger.stream_to_logger(logging.getLogger("STDERR"), logging.WARN) logger.info("***************** TRUSTED COMPUTE FRAMEWORK (TCF)" + " *****************") # Connect to registry list and retrieve registry if not off_chain: registry_list_instance = direct_jrpc.create_worker_registry_list( config) # Lookup returns tuple, first element is number of registries and # second is element is lookup tag and # third is list of organization ids. registry_count, lookup_tag, registry_list = \ registry_list_instance.registry_lookup() logger.info("\n Registry lookup response: registry count: {} " + "lookup tag: {} registry list: {}\n".format( registry_count, lookup_tag, registry_list)) if (registry_count == 0): logger.warn("No registries found") sys.exit(1) # Retrieve the first registry details. registry_retrieve_result = registry_list_instance.registry_retrieve( registry_list[0]) logger.info("\n Registry retrieve response: {}\n".format( registry_retrieve_result)) config["tcf"]["json_rpc_uri"] = registry_retrieve_result[0] # Prepare worker req_id = 31 global worker_id worker_registry_instance = direct_jrpc.create_worker_registry(config) if not worker_id: worker_lookup_result = worker_registry_instance.worker_lookup( worker_type=WorkerType.TEE_SGX, id=req_id) logger.info("\n Worker lookup response: {}\n".format( json.dumps(worker_lookup_result, indent=4))) if "result" in worker_lookup_result and \ "ids" in worker_lookup_result["result"].keys(): if worker_lookup_result["result"]["totalCount"] != 0: worker_id = worker_lookup_result["result"]["ids"][0] else: logger.error("ERROR: No workers found") sys.exit(1) else: logger.error("ERROR: Failed to lookup worker") sys.exit(1) req_id += 1 worker_retrieve_result = worker_registry_instance.worker_retrieve( worker_id, req_id) logger.info("\n Worker retrieve response: {}\n".format( json.dumps(worker_retrieve_result, indent=4))) worker_obj.load_worker(worker_retrieve_result) logger.info( "**********Worker details Updated with Worker ID" + "*********\n%s\n", worker_id) # Convert workloadId to hex workload_id = "echo-result".encode("UTF-8").hex() work_order_id = secrets.token_hex(32) requester_id = secrets.token_hex(32) session_iv = utility.generate_iv() session_key = utility.generate_key() requester_nonce = secrets.token_hex(16) # Create work order wo_params = WorkOrderParams( work_order_id, worker_id, workload_id, requester_id, session_key, session_iv, requester_nonce, result_uri=" ", notify_uri=" ", worker_encryption_key=worker_obj.encryption_key, data_encryption_algorithm="AES-GCM-256") # Add worker input data if input_data_hash: # Compute data hash for data params inData data_hash = utility.compute_data_hash(message) # Convert data_hash to hex data_hash = hex_utils.byte_array_to_hex_str(data_hash) wo_params.add_in_data(message, data_hash) else: wo_params.add_in_data(message) # Encrypt work order request hash wo_params.add_encrypted_request_hash() private_key = utility.generate_signing_keys() if requester_signature: # Add requester signature and requester verifying_key if wo_params.add_requester_signature(private_key) is False: logger.info("Work order request signing failed") exit(1) # Submit work order logger.info("Work order submit request : %s, \n \n ", wo_params.to_string(req_id)) work_order_instance = direct_jrpc.create_work_order(config) req_id += 1 response = work_order_instance.work_order_submit(wo_params.get_params(), wo_params.get_in_data(), wo_params.get_out_data(), id=req_id) logger.info("Work order submit response : {}\n ".format( json.dumps(response, indent=4))) if "error" in response and response["error"]["code"] != \ WorkOrderStatus.PENDING: sys.exit(1) # Create receipt wo_receipt_instance = direct_jrpc.create_work_order_receipt(config) req_id += 1 # Create work order receipt object using WorkOrderReceiptRequest class wo_request = json.loads(wo_params.to_string(req_id)) wo_receipt_obj = WorkOrderReceiptRequest() wo_create_receipt = wo_receipt_obj.create_receipt( wo_request, ReceiptCreateStatus.PENDING.value, private_key) logger.info("Work order create receipt request : {} \n \n ".format( json.dumps(wo_create_receipt, indent=4))) # Submit work order create receipt jrpc request wo_receipt_resp = wo_receipt_instance.work_order_receipt_create( wo_create_receipt["workOrderId"], wo_create_receipt["workerServiceId"], wo_create_receipt["workerId"], wo_create_receipt["requesterId"], wo_create_receipt["receiptCreateStatus"], wo_create_receipt["workOrderRequestHash"], wo_create_receipt["requesterGeneratedNonce"], wo_create_receipt["requesterSignature"], wo_create_receipt["signatureRules"], wo_create_receipt["receiptVerificationKey"], req_id) logger.info("Work order create receipt response : {} \n \n ".format( wo_receipt_resp)) # Retrieve result req_id += 1 res = work_order_instance.work_order_get_result(work_order_id, req_id) logger.info("Work order get result : {}\n ".format( json.dumps(res, indent=4))) sig_obj = signature.ClientSignature() if "result" in res: status = sig_obj.verify_signature(res, worker_obj.verification_key) try: if status == SignatureStatus.PASSED: logger.info( "Work order response signature verification Successful") decrypted_res = utility.decrypted_response( res, session_key, session_iv) logger.info("\nDecrypted response:\n {}".format(decrypted_res)) if input_data_hash: decrypted_data = decrypted_res[0]["data"] data_hash_in_resp = (decrypted_res[0]["dataHash"]).upper() # Verify data hash in response if utility.verify_data_hash(decrypted_data, data_hash_in_resp) is False: sys.exit(1) else: logger.info("Signature verification Failed") sys.exit(1) except Exception as err: logger.error("ERROR: Failed to decrypt response: %s", str(err)) sys.exit(1) else: logger.info("\n Work order get result failed {}\n".format(res)) sys.exit(1) # Retrieve receipt receipt_res = wo_receipt_instance.work_order_receipt_retrieve( work_order_id, id=req_id) logger.info("\n Retrieve receipt response:\n {}".format( json.dumps(receipt_res, indent=4))) # Retrieve last update to receipt by passing 0xFFFFFFFF req_id += 1 receipt_update_retrieve = \ wo_receipt_instance.work_order_receipt_update_retrieve( work_order_id, None, 1 << 32, id=req_id) logger.info("\n Last update to receipt receipt is:\n {}".format( json.dumps(receipt_update_retrieve, indent=4))) status = sig_obj.verify_update_receipt_signature(receipt_update_retrieve) if status == SignatureStatus.PASSED: logger.info( "Work order receipt retrieve signature verification Successful") else: logger.info( "Work order receipt retrieve signature verification failed!!") sys.exit(1) # Receipt lookup based on requesterId req_id += 1 receipt_lookup_res = wo_receipt_instance.work_order_receipt_lookup( requester_id=requester_id, id=req_id) logger.info("\n Work order receipt lookup response :\n {}".format( json.dumps(receipt_lookup_res, indent=4)))
def __init__(self): self.sig_obj = signature.ClientSignature() self.SIGNING_ALGORITHM = "SECP256K1" self.HASHING_ALGORITHM = "SHA-256"
def ParseCommandLine(config, args): logger.info( '***************** TRUSTED COMPUTE FRAMEWORK (TCF)*****************') global input_json_str global input_json_dir global server_uri global output_json_file_name global consensus_file_name global sig_obj global worker_obj global private_key global encrypted_session_key global session_iv parser = argparse.ArgumentParser() parser.add_argument( "--logfile", help="Name of the log file, __screen__ for standard output", type=str) parser.add_argument("-p", "--private_key", help="Private Key of the Client", type=str, default=None) parser.add_argument("--loglevel", help="Logging level", type=str) parser.add_argument("-i", "--input_file", help="JSON input file name", type=str, default="input.json") parser.add_argument("--input_dir", help="Logging level", type=str, default=[]) parser.add_argument("-c", "--connect_uri", help="URI to send requests to", type=str, default=[]) parser.add_argument("output_file", help="JSON output file name", type=str, default="output.json", nargs="?") options = parser.parse_args(args) if config.get("Logging") is None: config["Logging"] = {"LogFile": "__screen__", "LogLevel": "INFO"} if options.logfile: config["Logging"]["LogFile"] = options.logfile if options.loglevel: config["Logging"]["LogLevel"] = options.loglevel.upper() input_json_str = None input_json_dir = None if options.connect_uri: server_uri = options.connect_uri else: logger.error("ERROR: Please enter the server URI") if options.input_dir: logger.info("Load Json Directory from %s", options.input_dir) input_json_dir = options.input_dir elif options.input_file: try: logger.info("load JSON input from %s", options.input_file) with open(options.input_file, "r") as file: input_json_str = file.read() except: logger.error("ERROR: Failed to read from file %s", options.input_file) else: logger.info("No input found") if options.output_file: output_json_file_name = options.output_file else: output_json_file_name = None if options.private_key: private_key = options.private_key else: # Generating the private Key for the client private_key = enclave_helper.generate_signing_keys() # Initializing Signature object, Worker Object sig_obj = signature.ClientSignature() worker_obj = worker.SGXWorkerDetails()
def Main(args=None): ParseCommandLine(args) config["Logging"] = {"LogFile": "__screen__", "LogLevel": "INFO"} plogger.setup_loggers(config.get("Logging", {})) sys.stdout = plogger.stream_to_logger(logging.getLogger("STDOUT"), logging.DEBUG) sys.stderr = plogger.stream_to_logger(logging.getLogger("STDERR"), logging.WARN) logger.info("***************** TRUSTED COMPUTE FRAMEWORK (TCF)" + " *****************") global direct_jrpc direct_jrpc = DirectJsonRpcApiConnector(config_file=None, config=config) global address if mode == "registry" and address: logger.error("\n Worker registry contract address is unsupported \n") sys.exit(-1) # Connect to registry list and retrieve registry global uri if not uri and mode == "listing": registry_list_instance = direct_jrpc.create_worker_registry_list( config) # Lookup returns tuple, first element is number of registries and # second is element is lookup tag and third is list of organization ids. registry_count, lookup_tag, registry_list = registry_list_instance.registry_lookup( ) logger.info( "\n Registry lookup response: registry count: {} lookup tag: {} registry list: {}\n" .format(registry_count, lookup_tag, registry_list)) if (registry_count == 0): logger.error("No registries found") sys.exit(1) # Retrieve the fist registry details. registry_retrieve_result = registry_list_instance.registry_retrieve( registry_list[0]) logger.info("\n Registry retrieve response: {}\n".format( registry_retrieve_result)) config["tcf"]["json_rpc_uri"] = registry_retrieve_result[0] # Prepare worker req_id = 31 global worker_id if not worker_id: worker_registry_instance = direct_jrpc.create_worker_registry(config) worker_lookup_result = worker_registry_instance.worker_lookup( worker_type=WorkerType.TEE_SGX, id=req_id) logger.info("\n Worker lookup response: {}\n".format( json.dumps(worker_lookup_result, indent=4))) if "result" in worker_lookup_result and \ "ids" in worker_lookup_result["result"].keys(): if worker_lookup_result["result"]["totalCount"] != 0: worker_id = worker_lookup_result["result"]["ids"][0] else: logger.error("ERROR: No workers found") sys.exit(1) else: logger.error("ERROR: Failed to lookup worker") sys.exit(1) req_id += 1 worker_retrieve_result = worker_registry_instance.worker_retrieve( worker_id, req_id) logger.info("\n Worker retrieve response: {}\n".format( json.dumps(worker_retrieve_result, indent=4))) if "error" in worker_retrieve_result: logger.error("Unable to retrieve worker details\n") sys.exit(1) # Initializing Worker Object worker_obj = worker_details.SGXWorkerDetails() worker_obj.load_worker(worker_retrieve_result) logger.info("**********Worker details Updated with Worker ID" + \ "*********\n%s\n", worker_id) # Convert workloadId to hex global workload_id workload_id = workload_id.encode("UTF-8").hex() work_order_id = secrets.token_hex(32) requester_id = secrets.token_hex(32) session_iv = utility.generate_iv() session_key = utility.generate_key() requester_nonce = secrets.token_hex(16) # Create work order wo_params = WorkOrderParams( work_order_id, worker_id, workload_id, requester_id, session_key, session_iv, requester_nonce, result_uri=" ", notify_uri=" ", worker_encryption_key=worker_obj.encryption_key, data_encryption_algorithm="AES-GCM-256") # Add worker input data global in_data for value in in_data: wo_params.add_in_data(value) # Encrypt work order request hash wo_params.add_encrypted_request_hash() if requester_signature: private_key = utility.generate_signing_keys() # Add requester signature and requester verifying_key if wo_params.add_requester_signature(private_key) == False: logger.info("Work order request signing failed") exit(1) # Submit work order logger.info("Work order submit request : %s, \n \n ", wo_params.to_string()) work_order_instance = direct_jrpc.create_work_order(config) req_id += 1 response = work_order_instance.work_order_submit(wo_params.get_params(), wo_params.get_in_data(), wo_params.get_out_data(), id=req_id) logger.info("Work order submit response : {}\n ".format( json.dumps(response, indent=4))) if "error" in response and response["error"][ "code"] != WorkOrderStatus.PENDING: sys.exit(1) # Retrieve result req_id += 1 res = work_order_instance.work_order_get_result(work_order_id, req_id) logger.info("Work order get result : {}\n ".format( json.dumps(res, indent=4))) if "result" in res: sig_obj = signature.ClientSignature() status = sig_obj.verify_signature(res, worker_obj.verification_key) try: if status == SignatureStatus.PASSED: logger.info("Signature verification Successful") decrypted_res = utility.decrypted_response( res, session_key, session_iv) if show_decrypted_output: logger.info( "\nDecrypted response:\n {}".format(decrypted_res)) else: logger.error("Signature verification Failed") sys.exit(1) except: logger.error("ERROR: Failed to decrypt response") sys.exit(1) else: logger.error("\n Work order get result failed {}\n".format(res)) sys.exit(1) if show_receipt: # Retrieve receipt wo_receipt_instance = direct_jrpc.create_work_order_receipt(config) req_id += 1 receipt_res = wo_receipt_instance.work_order_receipt_retrieve( work_order_id, id=req_id) logger.info("\Retrieve receipt response:\n {}".format( json.dumps(receipt_res, indent=4)))
def ParseCommandLine(config, args) : logger.info('***************** INTEL TRUSTED COMPUTE FRAMEWORK (TCF)*****************') global input_json_str global input_json_dir global server_uri global output_json_file_name global consensus_file_name global sig_obj global worker_obj global private_key parser = argparse.ArgumentParser() parser.add_argument('--logfile', help='Name of the log file, __screen__ for standard output', type=str) parser.add_argument('-p', '--private_key',help="Private Key of the Client", type=str, default=None) parser.add_argument('--loglevel', help='Logging level', type=str) parser.add_argument('-i', '--input_file', help='JSON input file name', type=str, default='input.json') parser.add_argument('--input_dir', help='Logging level', type=str, default=[]) parser.add_argument( '-c', '--connect_uri', help='URI to send requests to', type=str, default=[]) parser.add_argument( 'output_file', help='JSON output file name', type=str, default='output.json', nargs='?') options = parser.parse_args(args) if config.get('Logging') is None : config['Logging'] = { 'LogFile' : '__screen__', 'LogLevel' : 'INFO' } if options.logfile : config['Logging']['LogFile'] = options.logfile if options.loglevel : config['Logging']['LogLevel'] = options.loglevel.upper() input_json_str = None input_json_dir = None if options.connect_uri: server_uri = options.connect_uri else: logger.error("ERROR: Please enter the server URI") if options.input_dir: logger.info('Load Json Directory from %s',options.input_dir) input_json_dir = options.input_dir elif options.input_file: try: logger.info('load JSON input from %s', options.input_file) with open(options.input_file, "r") as file: input_json_str = file.read() except: logger.error("ERROR: Failed to read from file %s", options.input_file) else : logger.info('No input found') if options.output_file: output_json_file_name = options.output_file else: output_json_file_name = None if options.private_key: private_key = options.private_key else:#Generating the private Key for the client private_key = helper.generate_signing_keys() # Initializing Signature object, Worker Object sig_obj = signature.ClientSignature() worker_obj = worker.WorkerDetails()