Example #1
0
def test_verify_encryption_key_signature():

    enc_key_sig_byte = crypto_utility.string_to_byte_array(worker_enc_key)
    enc_key_hash = crypto_utility.compute_message_hash(enc_key_sig_byte)

    try:
        # sign encryption key
        status, enc_key_signature = \
                sig_obj.generate_signature(enc_key_hash, worker_signing_key)
        enc_key_signature = \
            crypto_utility.base64_to_byte_array(enc_key_signature)
        enc_key_signature_hex = \
            crypto_utility.byte_array_to_hex(enc_key_signature)

        status = sig_obj.verify_encryption_key_signature(
            enc_key_signature_hex, worker_enc_key, worker_verifying_key)
        if status == SignatureStatus.PASSED:
            logging.info("PASSED: verify_encryption_key_signature")
            return 0
        else:
            logging.info("FAILED: verify_encryption_key_signature")
            return 1
    except Exception as err:
        logging.info("FAILED: verify_encryption_key_signature")
        return 1
Example #2
0
def test_generate_client_signature():

    logging.info("Testing generate_client_signature...")

    worker_obj = worker.SGXWorkerDetails()
    worker_obj.encryption_key = worker_enc_key
    encrypted_session_key = crypto_utility.generate_encrypted_key(
                   session_key, worker_obj.encryption_key)
    encrypted_session_key_hex = \
        crypto_utility.byte_array_to_hex(encrypted_session_key)

    read_json = read_json_file("wo_request.json", ["./"])
    wo_submit_request = json.loads(read_json)
    wo_request = wo_submit_request["params"]
    wo_request["workOrderId"] = work_order_id
    wo_request["workerId"] = worker_id
    wo_request["requesterId"] = requester_id
    wo_request["sessionKeyIv"] = session_key_iv
    wo_request["encryptedSessionKey"] = encrypted_session_key_hex
    wo_request["requesterNonce"] = requester_nonce

    try:
        input_json_str = json.dumps(wo_submit_request)
        input_json_str, status = sig_obj.generate_client_signature(
            input_json_str, worker_obj, client_private_key, session_key,
            session_iv, encrypted_session_key)

        if status == SignatureStatus.PASSED:
            logging.info("PASSED: generate_client_signature")
            return 0
        else:
            logging.info("FAILED: generate_client_signature")
            return 1
    except Exception as err:
        return 1
Example #3
0
 def add_encrypted_request_hash(self):
     """
     Calculates request hash 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_utility.byte_array_to_base64(
         crypto_utility.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_utility.compute_message_hash(concat_hash)
     encrypted_request_hash = crypto_utility.encrypt_data(
         self.final_hash, self.session_key, self.session_iv)
     encrypted_request_hash_hex = crypto_utility.byte_array_to_hex(
         encrypted_request_hash)
     self.params_obj["encryptedRequestHash"] = encrypted_request_hash_hex
Example #4
0
 def calculate_request_hash(self, input_json):
     """
     Function to create the work order request hash
     as defined in EEA spec 6.1.8.1
     Parameters:
         - input_json is dictionary contains work order request payload
           as define EEA spec 6.1.1
     Returns hash of work order request as string
     """
     wo_request_params = input_json["params"]
     concat_string = wo_request_params["requesterNonce"] + \
         wo_request_params["workOrderId"] + \
         wo_request_params["workerId"] + \
         wo_request_params["workloadId"] + \
         wo_request_params["requesterId"]
     concat_bytes = bytes(concat_string, "UTF-8")
     # SHA-256 hashing is used
     hash_1 = crypto_utility.byte_array_to_base64(
         crypto_utility.compute_message_hash(concat_bytes))
     hash_2 = self.calculate_datahash(wo_request_params["inData"])
     hash_3 = ""
     if "outData" in wo_request_params and \
             len(wo_request_params["outData"]) > 0:
         hash_3 = self.calculate_datahash(wo_request_params["outData"])
     concat_hash = hash_1 + hash_2 + hash_3
     concat_hash = bytes(concat_hash, "UTF-8")
     final_hash = crypto_utility.compute_message_hash(concat_hash)
     final_hash_str = crypto_utility.byte_array_to_hex(final_hash)
     return final_hash_str
Example #5
0
    def __init__(self,
                 work_order_id,
                 worker_id,
                 workload_id,
                 requester_id,
                 session_key,
                 session_iv,
                 requester_nonce,
                 verifying_key=None,
                 payload_format="JSON-RPC",
                 response_timeout_msecs=6000,
                 result_uri=None,
                 notify_uri=None,
                 worker_encryption_key=None,
                 data_encryption_algorithm=None):
        self.params_obj = {}
        self.set_work_order_id(work_order_id)
        self.set_response_timeout_msecs(response_timeout_msecs)
        self.set_payload_format(payload_format)
        if result_uri:
            self.set_result_uri(result_uri)
        if notify_uri:
            self.set_notify_uri(notify_uri)
        self.set_worker_id(worker_id)
        self.set_workload_id(workload_id)
        self.set_requester_id(requester_id)
        if worker_encryption_key:
            self.set_worker_encryption_key(
                worker_encryption_key.encode("UTF-8").hex())
        if data_encryption_algorithm:
            self.set_data_encryption_algorithm(data_encryption_algorithm)

        encrypted_session_key = crypto_utility.generate_encrypted_key(
            session_key, worker_encryption_key)
        self.set_encrypted_session_key(
            crypto_utility.byte_array_to_hex(encrypted_session_key))

        self.session_iv = session_iv
        self.set_session_key_iv(crypto_utility.byte_array_to_hex(session_iv))
        self.set_requester_nonce(requester_nonce)
        self.params_obj["encryptedRequestHash"] = ""
        self.params_obj["requesterSignature"] = ""
        self.params_obj["inData"] = []
        self.session_key = session_key
Example #6
0
    def __init__(
            self, work_order_id, worker_id, workload_id,
            requester_id, session_key, session_iv,
            requester_nonce, verifying_key=None, payload_format="JSON-RPC",
            response_timeout_msecs=6000, result_uri=None,
            notify_uri=None, worker_encryption_key=None,
            data_encryption_algorithm=None):

        self.params_obj = {}
        self.set_work_order_id(work_order_id)
        self.set_response_timeout_msecs(response_timeout_msecs)
        self.set_payload_format(payload_format)
        if result_uri:
            self.set_result_uri(result_uri)
        if notify_uri:
            self.set_notify_uri(notify_uri)
        self.set_worker_id(worker_id)
        self.set_workload_id(workload_id)
        self.set_requester_id(requester_id)
        if worker_encryption_key:
                self.set_worker_encryption_key(
                    worker_encryption_key)
        if data_encryption_algorithm:
            self.set_data_encryption_algorithm(data_encryption_algorithm)
        if worker_encryption_key and session_key:
            try:
                encrypted_session_key = crypto_utility.generate_encrypted_key(
                    session_key, worker_encryption_key)
                self.set_encrypted_session_key(
                    crypto_utility.byte_array_to_hex(encrypted_session_key))
            except Exception as err:
                raise ValueError("Encrypting Session key failed: \
Invalid session key or worker encryption key")

        self.session_iv = session_iv
        self.set_session_key_iv(
            crypto_utility.byte_array_to_hex(session_iv)
        )
        self.set_requester_nonce(requester_nonce)
        self.params_obj["encryptedRequestHash"] = ""
        self.params_obj["requesterSignature"] = ""
        self.params_obj["inData"] = []
        self.session_key = session_key
    def update_receipt(self, work_order_id, update_type, update_data,
                       signing_key):
        """
        Update the existing work order receipt with
        update_type and update_data.

        Parameters:
        work_order_id Work order ID whose receipt
                      needs to be updated
        update_type   Update type. These values correspond to
                      receipt status as defined in EEA Spec 7.1.1
        update_data   Update-specific data that depends on
                      the workOrderStatus
        Returns:
        JSON RPC work order update receipt request of type dictionary
        """
        data = update_data
        if update_type in [
                ReceiptCreateStatus.PROCESSED.value,
                ReceiptCreateStatus.COMPLETED.value
        ]:
            # Work Order Receipt status is set to be completed or processed,
            # then update_data should be work order response.
            wo_resp_str = json.dumps(update_data)
            wo_resp_bytes = bytes(wo_resp_str, "UTF-8")
            # Hash of work order response is update_data
            wo_resp_hash = crypto_utility.compute_message_hash(wo_resp_bytes)
            wo_resp_hash_str = crypto_utility.byte_array_to_hex(wo_resp_hash)
            data = wo_resp_hash_str
        public_key = signing_key.verifying_key.to_pem().decode("ascii")
        updater_id = crypto_utility.strip_begin_end_public_key(public_key)

        wo_receipt_update = {
            "workOrderId": work_order_id,
            "updaterId": updater_id,
            "updateType": update_type,
            "updateData": data,
            "signatureRules":
            self.HASHING_ALGORITHM + "/" + self.SIGNING_ALGORITHM,
            "receiptVerificationKey": public_key
        }
        wo_receipt_str = wo_receipt_update["workOrderId"] + \
            str(wo_receipt_update["updateType"]) + \
            wo_receipt_update["updateData"]
        wo_receipt_bytes = bytes(wo_receipt_str, "UTF-8")
        wo_receipt_hash = crypto_utility.compute_message_hash(wo_receipt_bytes)
        status, wo_receipt_sign = self.sig_obj.generate_signature(
            wo_receipt_hash, signing_key)
        if status is False:
            # if generating signature failed.
            wo_receipt_update["updateSignature"] = ""
            raise Exception("Generate signature is failed")
        else:
            wo_receipt_update["updateSignature"] = wo_receipt_sign
        return wo_receipt_update
    def __validate_work_order_receipt_update_req(self, wo_receipt_req):
        """
        Function to validate the work order receipt create request parameters
        Parameters:
                - wo_receipt_req is work order receipt request as dictionary
        Returns - tuple containing validation status(Boolean) and error
                  message(string)
        """
        valid_params = [
            "workOrderId", "updaterId", "updateType", "updateData",
            "updateSignature", "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", "updaterId"]:
                    if not is_valid_hex_str(wo_receipt_req[key]):
                        return False, "invalid data parameter for " + key
                elif key in ["updateData", "updateSignature"]:
                    try:
                        base64.b64decode(wo_receipt_req[key])
                    except Exception:
                        return False, "Invalid data format for " + key
        update_type = wo_receipt_req["params"]["updateType"]
        try:
            update_enum_value = ReceiptCreateStatus(update_type)
        except Exception as err:
            return False, "Invalid receipt update type {}: {}".format(
                update_enum_value, str(err))

        # If update type is completed or processed,
        # it is a hash value of the Work Order Response
        if wo_receipt_req["params"]["updateType"] in [
                ReceiptCreateStatus.PROCESSED.value,
                ReceiptCreateStatus.COMPLETED.value
        ]:
            wo_id = wo_receipt_req["params"]["workOrderId"]
            # Load the work order response and calculate it's hash
            wo_resp = self.kv_helper.get("wo-responses", wo_id)
            wo_resp_bytes = bytes(wo_resp, "UTF-8")
            wo_resp_hash = worker_hash.WorkerHash().compute_message_hash(
                wo_resp_bytes)
            wo_resp_hash_str = crypto_utility.byte_array_to_hex(wo_resp_hash)
            if wo_resp_hash_str != wo_receipt_req["params"]["updateData"]:
                return False, "Invalid Update data in the request"
        # If all validation is pass
        return True, ""
Example #9
0
 def add_encrypted_request_hash(self):
     """
     Calculates request hash based on EEA trusted-computing spec 6.1.8.1
     and set encryptedRequestHash parameter in the request.
     """
     try:
         sig_obj = signature.ClientSignature()
         self.request_hash = sig_obj.calculate_request_hash(self.params_obj)
         encrypted_request_hash = crypto_utility.encrypt_data(
             self.request_hash, self.session_key, self.session_iv)
         enc_request_hash_hex = crypto_utility.byte_array_to_hex(
             encrypted_request_hash)
         self.params_obj["encryptedRequestHash"] = enc_request_hash_hex
         return None
     except Exception as err:
         return util.create_error_response(
             WorkOrderStatus.INVALID_PARAMETER_FORMAT_OR_VALUE, 0, err)
Example #10
0
def local_main(config):
    global input_json_str
    if not input_json_str and not input_json_dir:
        LOGGER.error("JSON input file is not provided")
        exit(1)

    if not output_json_file_name:
        LOGGER.error("JSON output file is not provided")
        exit(1)

    if not server_uri:
        LOGGER.error("Server URI is not provided")
        exit(1)

    LOGGER.info("Execute work order")
    uri_client = HttpJrpcClient(server_uri)
    response = None
    wo_id = None
    if input_json_dir:
        directory = os.fsencode(input_json_dir)
        files = os.listdir(directory)

        for file in sorted(files):
            LOGGER.info("---------------- Input file name: %s -------------\n",
                        file.decode("utf-8"))
            input_json_str = futils.read_json_file(
                (directory.decode("utf-8") + file.decode("utf-8")))
            # -----------------------------------------------------------------

            # If Client request is WorkOrderSubmit, a requester payload's
            # signature with the requester private signing key is generated.
            if "WorkOrderSubmit" in input_json_str:
                # Update workOrderId , workerId and workloadId
                input_json_obj = json.loads(input_json_str)
                wo_id = hex(random.randint(1, 2**64 - 1))
                input_json_obj["params"]["workOrderId"] = wo_id
                input_json_obj["params"]["workerId"] = worker_id

                # Convert workloadId to a hex string and update the request
                workload_id = input_json_obj["params"]["workloadId"]
                workload_id_hex = workload_id.encode("UTF-8").hex()
                input_json_obj["params"]["workloadId"] = workload_id_hex

                encrypt = worker_encryption.WorkerEncrypt()
                # Generate session key, session iv and encrypted session key
                session_key = encrypt.generate_session_key()
                session_iv = encrypt.generate_iv()
                encrypted_session_key = encrypt.encrypt_session_key(
                    session_key, worker_obj.encryption_key)

                input_json_obj["params"]["encryptedSessionKey"] = \
                    crypto_utility.byte_array_to_hex(encrypted_session_key)
                input_json_obj["params"]["sessionKeyIv"] = \
                    crypto_utility.byte_array_to_hex(session_iv)

                if "requesterNonce" in input_json_obj["params"]:
                    if len(input_json_obj["params"]["requesterNonce"]) == 0:
                        # [NO_OF_BYTES] 16 BYTES for nonce.
                        # This is the recommendation by NIST to
                        # avoid collisions by the "Birthday Paradox".
                        requester_nonce = secrets.token_hex(NO_OF_BYTES)
                        input_json_obj["params"]["requesterNonce"] = \
                            requester_nonce
                requester_nonce = input_json_obj["params"]["requesterNonce"]

                # Encode data in inData
                for data_obj in input_json_obj["params"]["inData"]:
                    encoded_data = data_obj["data"].encode('UTF-8')
                    data_obj["data"] = encoded_data

                # Encrypt inData
                encrypt.encrypt_work_order_data_json(
                    input_json_obj["params"]["inData"], session_key,
                    session_iv)
                req_hash = worker_hash.WorkerHash().calculate_request_hash(
                    input_json_obj["params"])
                encrypted_req_hash = encrypt.encrypt_data(
                    req_hash, session_key, session_iv)
                input_json_obj["params"]["encryptedRequestHash"] = \
                    encrypted_req_hash.hex()
                signer = worker_signing.WorkerSign()
                signer.generate_signing_key()
                wo_req_sig = signer.sign_message(req_hash)
                input_json_obj["params"]["requesterSignature"] = \
                    crypto_utility.byte_array_to_base64(wo_req_sig)
                input_json_obj["params"]["verifyingKey"] = \
                    signer.get_public_sign_key().decode('utf-8')
                input_json_str = json.dumps(input_json_obj)
                if input_json_str is None:
                    continue
            # -----------------------------------------------------------------

            # Update the worker ID
            if response:
                if "workerId" in input_json_str:
                    # Retrieve the worker id from the "WorkerRetrieve"
                    # response and update the worker id information for
                    # further json requests.
                    if "result" in response and \
                            "ids" in response["result"].keys() and \
                            len(response["result"]["ids"]) > 0:
                        input_json_final = json.loads(input_json_str)
                        worker_id = response["result"]["ids"][0]
                        input_json_final["params"]["workerId"] = worker_id
                        input_json_str = json.dumps(input_json_final)
                        LOGGER.info(
                            "********** Worker details Updated with "
                            "Worker ID*********\n%s\n", input_json_str)

            # -----------------------------------------------------------------
            if "WorkOrderGetResult" in input_json_str or \
                    "WorkOrderReceiptRetrieve" in input_json_str:
                input_json_obj = json.loads(input_json_str)
                input_json_obj["params"]["workOrderId"] = wo_id
                input_json_str = json.dumps(input_json_obj)

            LOGGER.info("*********Request Json********* \n%s\n",
                        input_json_str)
            response = uri_client._postmsg(input_json_str)
            LOGGER.info("**********Received Response*********\n%s\n", response)

            # -----------------------------------------------------------------

            # Worker details are loaded into Worker_Obj
            if "WorkerRetrieve" in input_json_str and "result" in response:
                worker_obj.load_worker(response["result"]["details"])
            # -----------------------------------------------------------------

            # Poll for "WorkOrderGetResult" and break when you get the result
            while ("WorkOrderGetResult" in input_json_str
                   and "result" not in response):
                if response["error"]["code"] != WorkOrderStatus.PENDING:
                    break
                response = uri_client._postmsg(input_json_str)
                LOGGER.info("Received Response: %s, \n \n ", response)
                time.sleep(3)

            # -----------------------------------------------------------------

            # Verify the signature
            if "WorkOrderGetResult" in input_json_str:
                if "error" in response:
                    # Response has error, hence skip Signature verification
                    LOGGER.info("Work order response has error; "
                                "skipping signature verification")
                    continue
                sig_bool = signer.verify_signature(response['result'],
                                                   worker_obj.verification_key,
                                                   requester_nonce)
                try:
                    if sig_bool > 0:
                        LOGGER.info("Signature Verified")
                        encrypt.decrypt_work_order_data_json(
                            response['result']['outData'], session_key,
                            session_iv)
                    else:
                        LOGGER.info("Signature verification Failed")
                        exit(1)
                except Exception as e:
                    LOGGER.error("ERROR: Failed to verify signature of " +
                                 "work order response")
                    exit(1)

            # -----------------------------------------------------------------
    else:
        LOGGER.info("Input Request %s", input_json_str)
        response = uri_client._postmsg(input_json_str)
        LOGGER.info("Received Response: %s , \n \n ", response)

    exit(0)
Example #11
0
    def create_request(self,
                       work_order_id,
                       worker_id,
                       workload_id,
                       requester_id,
                       session_key,
                       session_iv,
                       requester_nonce,
                       verifying_key=None,
                       payload_format="JSON-RPC",
                       response_timeout_msecs=6000,
                       result_uri=None,
                       notify_uri=None,
                       worker_encryption_key=None,
                       data_encryption_algorithm=None,
                       encrypted_session_key=None):
        """validate and creates workorder request with received values"""
        if work_order_id:
            self.set_work_order_id(work_order_id)
        self.set_response_timeout_msecs(response_timeout_msecs)
        self.set_payload_format(payload_format)
        self.set_requester_nonce(requester_nonce)
        self.session_key = session_key
        self.set_workload_id(workload_id)
        self.set_worker_id(worker_id)
        if requester_id is not None:
            self.set_requester_id(requester_id)
        if session_iv:
            self.set_session_key_iv(
                crypto_utility.byte_array_to_hex(session_iv))
        if result_uri:
            self.set_result_uri(result_uri)
        if notify_uri:
            self.set_notify_uri(notify_uri)
        if worker_encryption_key:
            self.set_worker_encryption_key(worker_encryption_key)
        if data_encryption_algorithm:
            self.set_data_encryption_algorithm(data_encryption_algorithm)

        self.set_encrypted_session_key(encrypted_session_key)

        code, err_msg = WOcheck.schema_validation("sdk_WorkOrderSubmit",
                                                  self.params_obj)

        # When the WorkorderSubmit request fails basic Json Validation
        # the init object created is deleted to avoid futhur processing
        # on that object by the user.
        if not code:
            return util.create_error_response(
                WorkOrderStatus.INVALID_PARAMETER_FORMAT_OR_VALUE, 0, err_msg)

        self.set_worker_encryption_key(
            worker_encryption_key.encode("UTF-8").hex())

        self.session_iv = session_iv
        self.params_obj["encryptedRequestHash"] = ""
        self.params_obj["requesterSignature"] = ""
        self.params_obj["inData"] = list()
        if encrypted_session_key is None:
            try:
                encrypted_session_key = crypto_utility.generate_encrypted_key(
                    session_key, worker_encryption_key)
                self.set_encrypted_session_key(
                    crypto_utility.byte_array_to_hex(encrypted_session_key))
            except Exception as err:
                return util.create_error_response(
                    WorkOrderStatus.INVALID_PARAMETER_FORMAT_OR_VALUE, 0, err)
        return None
Example #12
0
    "gTVuC8crfJBUt+zOpiXUv8DaD+kVdAdDdZlgHBW2K9gcivXDegAz84WPbhDrQ3CM\n"\
    "M9SJ22B99CR1eG/ez/wzY0GiAZOCIB31IWk34Ehc8tTKjm8fVnXWvYJnXKxACnYd\n"\
    "3isoueUA1x01+U0HDnY5ZR0CAwEAAQ==\n"\
    "-----END PUBLIC KEY-----\n"

sig_obj = signature.ClientSignature()

# client values
worker_id = secrets.token_hex(32)
work_order_id = secrets.token_hex(32)
requester_id = secrets.token_hex(32)
requester_nonce = secrets.token_hex(16)

session_key = crypto_utility.generate_key()
session_iv = crypto_utility.generate_iv()
session_key_iv = crypto_utility.byte_array_to_hex(session_iv)

client_private_key = crypto_utility.generate_signing_keys()
client_public_key = crypto_utility.get_verifying_key(client_private_key)

# worker values
worker_nonce = secrets.token_hex(16)
worker_enc_key = rsa_public_key

worker_signing_key = crypto_utility.generate_signing_keys()
worker_verifying_key = crypto_utility.get_verifying_key(worker_signing_key)


# -----------------------------------------------------------------------------
def test_calculate_datahash():
    read_json = read_json_file("wo_request.json", ["./"])