def _verify_work_order_request(self, input_json, session_key, session_key_iv): """ Verify work order request integrity. Verifies work order request hash. Parameters : input_json: JSON work order request session_key: Session key of the client which submitted this work order session_key_iv: iv corresponding to teh session key Returns : JSON RPC response containing result or error. """ # Decrypt request hash encrypted_req_hash_hex = input_json["params"]["encryptedRequestHash"] encrypted_req_hash = bytes.fromhex(encrypted_req_hash_hex) try: decrypt_req_hash = self.encrypt.decrypt_data(encrypted_req_hash, session_key, session_key_iv) except Exception as e: logger.error("Decryption of request hash: %s", e) return False # Compute work order request hash req_hash = worker_hash.WorkerHash().calculate_request_hash( input_json["params"]) # Compare decrypted request hash with expected value if decrypt_req_hash.hex() == req_hash.hex(): return True else: return False
def _encrypt_and_sign_response(self, session_key, session_key_iv, output_json): """ Encrypt outdata and compute worker signature. Parameters : session_key: Session key of the client which submitted this work order session_key_iv: iv corresponding to teh session key output_json: Pre-populated response json Returns : JSON RPC response with worker signature """ # Encrypt outData self.encrypt.encrypt_work_order_data_json( output_json["result"]["outData"], session_key, session_key_iv) # Compute worker signature res_hash = worker_hash.WorkerHash().calculate_response_hash( output_json["result"]) res_hash_sign = self.sign.sign_message(res_hash) res_hash_sign_b64 = self.encrypt.byte_array_to_base64(res_hash_sign) output_json["result"]["workerSignature"] = res_hash_sign_b64 return output_json
def verify_response_signature(self, response_json, worker_verify_key): """ Verifies work order response signature. Parameters : response_json : Work order Response JSON RPC as per TC Spec v1.1 section 6.1 worker_verify_key: worker ECDSA verifying key as serialized PEM bytes. Returns : Boolean. """ if "result" not in response_json: logger.error("result not present in reponse json") return False if "workerSignature" not in response_json["result"]: logger.error("workerSignature not present in reponse json") return False res_hash_bytes = worker_hash.WorkerHash().calculate_response_hash( response_json["result"]) worker_sig = response_json["result"]["workerSignature"] worker_sig_bytes = base64.b64decode(worker_sig.encode("UTF-8")) verify = self.verify_signature_from_pubkey(worker_sig_bytes, res_hash_bytes, worker_verify_key) return verify
def _generate_worker_keys(self): """ Generates worker signing and encryption keys. """ # Generate worker signing key logger.info("Generate worker signing and encryption keys") self.sign = worker_signing.WorkerSign() self.sign.generate_signing_key() self.worker_public_sign_key = self.sign.get_public_sign_key() # Generate worker encryption key self.encrypt = worker_encryption.WorkerEncrypt() self.encrypt.generate_rsa_key() self.worker_public_enc_key = self.encrypt.get_rsa_public_key() # Sign worker encryption key hash hash_obj = worker_hash.WorkerHash() hash_val = hash_obj.compute_message_hash(self.worker_public_enc_key) self.worker_public_enc_key_sign = self.sign.sign_message(hash_val)
def _create_work_order_response(self, input_json, out_data, session_key, session_key_iv): """ Creates work order response JSON object. Parameters : input_json: JSON work order request out_data: output data dictionary which has data in plain text session_key: Session key of the client which submitted this work order session_key_iv: iv corresponding to teh session key Returns : JSON RPC response containing result. """ output_json = dict() output_json["jsonrpc"] = "2.0" output_json["id"] = input_json["id"] output_json["result"] = dict() output_json["result"]["workloadId"] = \ input_json["params"]["workloadId"] output_json["result"]["workOrderId"] = \ input_json["params"]["workOrderId"] output_json["result"]["workerId"] = \ input_json["params"]["workerId"] output_json["result"]["requesterId"] = \ input_json["params"]["requesterId"] workerNonce = ''.join(random.choices(string.ascii_uppercase + string.digits, k=16)) output_json["result"]["workerNonce"] = \ self.encrypt.byte_array_to_base64( workerNonce.encode("UTF-8")) output_json["result"]["outData"] = [out_data] # Encrypt outData self.encrypt.encrypt_work_order_data_json( output_json["result"]["outData"], session_key, session_key_iv) # Compute worker signature res_hash = worker_hash.WorkerHash().calculate_response_hash( output_json["result"]) res_hash_sign = self.sign.sign_message(res_hash) res_hash_sign_b64 = self.encrypt.byte_array_to_base64(res_hash_sign) output_json["result"]["workerSignature"] = res_hash_sign_b64 return output_json
def _create_work_order_request(workload_id, input_data_str, session_key, session_key_iv, worker_signup_json): worker_enc_key_str = worker_signup_json["encryption_key"] encrypt = worker_encryption.WorkerEncrypt() encrypted_session_key = encrypt.encrypt_session_key( session_key, worker_enc_key_str) msg = input_data_str msg_bytes = msg.encode("UTF-8") input_json = dict() input_json["jsonrpc"] = "2.0" input_json["method"] = "WorkOrderSubmit" input_json["id"] = "1" input_json["params"] = dict() input_json["params"]["encryptedSessionKey"] = encrypted_session_key.hex() if session_key_iv: input_json["params"]["sessionKeyIv"] = session_key_iv.hex() input_json["params"]["workloadId"] = workload_id.encode("UTF-8").hex() input_json["params"]["workOrderId"] = secrets.token_hex(32) worker_id = hashlib.sha256("graphene-hello".encode("UTF-8")).hexdigest() input_json["params"]["workerId"] = worker_id input_json["params"]["requesterId"] = secrets.token_hex(32) input_json["params"]["requesterNonce"] = secrets.token_hex(32) in_data = dict() in_data["index"] = 0 in_data["dataHash"] = "" in_data["data"] = msg_bytes in_data["encryptedDataEncryptionKey"] = "null" in_data["iv"] = "" input_json["params"]["inData"] = [in_data] # Encrypt inData encrypt.encrypt_work_order_data_json(input_json["params"]["inData"], session_key, session_key_iv) req_hash = worker_hash.WorkerHash().calculate_request_hash( input_json["params"]) encrypted_req_hash = encrypt.encrypt_data(req_hash, session_key, session_key_iv) input_json["params"]["encryptedRequestHash"] = encrypted_req_hash.hex() return json.dumps(input_json)