Ejemplo n.º 1
0
    def __encrypt_data(self, data, encrypted_data_encryption_key=None,
                       data_iv=None):
        """
        Encrypt data and encode in base64 format.
        If key is None or "" or null, use session key.
        If key is "-" skip encryption and just encode base64.

        Parameters:
        data                          Data to encrypt
        encrypted_data_encryption_key Encryption private key.
                                      Pass "-" for no encryption.
                                      Pass "" or None to encrypt with
                                      the session key
        data_iv                       IV for data

        Returns:
        Encrypted (if requested) and base64 encoded data.
        """
        data = data.encode("UTF-8")
        if encrypted_data_encryption_key is None or \
                encrypted_data_encryption_key == "" or \
                encrypted_data_encryption_key == "null":
            enc_data = crypto_utility.encrypt_data(
                data, self.session_key, self.session_iv
            )
            return crypto_utility.byte_array_to_base64(enc_data)
        elif encrypted_data_encryption_key == "-":
            # Skip encryption and just encode workorder data to
                        # base64 format.
            enc_data = crypto_utility.byte_array_to_base64(data)
            return enc_data
        else:
            enc_data = crypto_utility.encrypt_data(
                            data, encrypted_data_encryption_key, data_iv)
            return crypto_utility.byte_array_to_base64(enc_data)
Ejemplo n.º 2
0
    def __encrypt_workorder_indata(self,
                                   input_json_params,
                                   session_key,
                                   session_iv,
                                   worker_encryption_key,
                                   data_key=None,
                                   data_iv=None):
        """
        Function to encrypt inData of workorder
        Parameters:
            - input_json_params is inData and outData elements within the
              work order request as per Trusted Compute EEA API 6.1.7
              Work Order Data Formats.
            - session_key is a one-time encryption key generated by the
              participant submitting the work order.
            - session_iv is an initialization vector if required by the
              data encryption algorithm (encryptedSessionKey).
              The default is all zeros.
            - data_key is a one time key generated by participant used to
              encrypt work order indata
            - data_iv is an initialization vector used along with data_key.
              Default is all zeros.
        """

        indata_objects = input_json_params['inData']
        input_json_params['inData'] = indata_objects
        logger.info("Encrypting Workorder Data")

        i = 0
        for item in indata_objects:
            data = item['data'].encode('UTF-8')
            e_key = item['encryptedDataEncryptionKey'].encode('UTF-8')

            if (not e_key) or (e_key == "null".encode('UTF-8')):
                enc_data = crypto_utility.encrypt_data(data, session_key,
                                                       session_iv)
                input_json_params['inData'][i]['data'] = \
                    crypto_utility.byte_array_to_base64(enc_data)
                logger.debug("encrypted indata - %s",
                             crypto_utility.byte_array_to_base64(enc_data))
            elif e_key == "-".encode('UTF-8'):
                # Skip encryption and just encode workorder data to
                # base64 format.
                input_json_params['inData'][i]['data'] = \
                    crypto_utility.byte_array_to_base64(data)
            else:
                enc_data = crypto_utility.encrypt_data(data, data_key, data_iv)
                input_json_params['inData'][i]['data'] = \
                    crypto_utility.byte_array_to_base64(enc_data)
                logger.debug("encrypted indata - %s",
                             crypto_utility.byte_array_to_base64(enc_data))
            i = i + 1

        logger.debug("Workorder InData after encryption: %s", indata_objects)
Ejemplo n.º 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.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 = crypto_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 test_encrypt_data(iv, enc_sess_key, data):
    data_bytes = bytes(data, 'ascii')
    enc_req_hash = crypto_utility.encrypt_data(data_bytes, enc_sess_key, iv)
    if enc_req_hash:
        logging.info("Test case: test_encrypt_data PASS...")
    else:
        logging.info("Test case: test_encrypt_data FAIL...")
    return enc_req_hash
Ejemplo n.º 5
0
 def __encrypt_data(self,
                    data,
                    encrypted_data_encryption_key=None,
                    data_iv=None):
     data = data.encode("UTF-8")
     if encrypted_data_encryption_key is None or \
             encrypted_data_encryption_key == "" or \
             encrypted_data_encryption_key == "null":
         enc_data = crypto_utility.encrypt_data(data, self.session_key,
                                                self.session_iv)
         return crypto.byte_array_to_base64(enc_data)
     elif encrypted_data_encryption_key == "-".encode('UTF-8'):
         # Skip encryption and just encode workorder data to
         # base64 format.
         enc_data = crypto.byte_array_to_base64(data)
         return enc_data
     else:
         enc_data = crypto_utility.encrypt_data(
             data, encrypted_data_encryption_key, data_iv)
         return crypto.byte_array_to_base64(enc_data)
Ejemplo n.º 6
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)
Ejemplo n.º 7
0
    def generate_client_signature(
            self, input_json_str, worker, private_key, session_key,
            session_iv, encrypted_session_key, data_key=None, data_iv=None):
        """
        Function to generate client signature
        Parameters:
            - input_json_str is requester Work Order Request payload in a
              JSON-RPC based format defined 6.1.1 Work Order Request Payload
            - worker is a worker object to store all the common details of
              worker as per Trusted Compute EEA API 8.1
              Common Data for All Worker Types
            - private_key is Client private key
            - session_key is one time session key generated by the participant
              submitting the work order.
            - session_iv is an initialization vector if required by the
              data encryption algorithm (encryptedSessionKey).
              The default is all zeros.
            - data_key is a one time key generated by participant used to
              encrypt work order indata
            - data_iv is an initialization vector used along with data_key.
              Default is all zeros.
            - encrypted_session_key is a encrypted version of session_key.
        Returns a tuple containing signature and status
        """

        if (self.__payload_json_check(input_json_str) is False):
            logger.error("ERROR: Signing the request failed")
            return input_json_str, SignatureStatus.FAILED

        if (self.tcs_worker['HashingAlgorithm'] != worker.hashing_algorithm):
            logger.error(
                "ERROR: Signing the request failed. Hashing " +
                "algorithm is not supported for %s", worker.hashing_algorithm)
            return input_json_str, SignatureStatus.FAILED

        if (self.tcs_worker['SigningAlgorithm'] != worker.signing_algorithm):
            logger.error(
                "ERROR: Signing the request failed. Signing " +
                "algorithm is not supported for %s", worker.signing_algorithm)
            return input_json_str, SignatureStatus.FAILED

        input_json = json.loads(input_json_str)
        input_json_params = input_json['params']
        input_json_params["sessionKeyIv"] = byte_array_to_hex_str(session_iv)

        encrypted_session_key_str = byte_array_to_hex_str(
            encrypted_session_key)
        self.__encrypt_workorder_indata(
            input_json_params, session_key,
            session_iv, worker.encryption_key, data_key, data_iv)

        if "requesterNonce" in input_json_params:
            if len(input_json_params["requesterNonce"]) == 0:
                # [NO_OF_BYTES] 16 BYTES for nonce.
                # This is the recommendation by NIST to
                # avoid collisions by the "Birthday Paradox".
                input_json_params["requesterNonce"] = secrets.token_hex(
                    NO_OF_BYTES)
            elif not is_valid_hex_str(input_json_params["requesterNonce"]):
                logger.error("Invalid data format for requesterNonce")
                return input_json_params, SignatureStatus.FAILED
        else:
            logger.error("Missing parameter requesterNonce")
            return input_json_params, SignatureStatus.FAILED

        hash_string_1 = self.__calculate_hash_on_concatenated_string(
            input_json_params, input_json_params["requesterNonce"].encode(
                'UTF-8'
            ))
        data_objects = input_json_params['inData']
        hash_string_2 = self.calculate_datahash(data_objects)

        hash_string_3 = ""
        if 'outData' in input_json_params:
            data_objects = input_json_params['outData']
            hash_string_3 = self.calculate_datahash(data_objects)

        concat_string = hash_string_1 + hash_string_2 + hash_string_3
        concat_hash = bytes(concat_string, 'UTF-8')
        final_hash = crypto.compute_message_hash(concat_hash)

        encrypted_request_hash = crypto_utility.encrypt_data(
            final_hash, session_key, session_iv)
        encrypted_request_hash_str = \
            byte_array_to_hex_str(encrypted_request_hash)
        logger.debug("encrypted request hash: \n%s",
                     encrypted_request_hash_str)

        # Update the input json params
        input_json_params["encryptedRequestHash"] = encrypted_request_hash_str
        status, signature = self.generate_signature(final_hash, private_key)
        if status is False:
            return input_json_str, SignatureStatus.FAILED
        input_json_params['requesterSignature'] = signature
        input_json_params["encryptedSessionKey"] = encrypted_session_key_str
        # Temporary mechanism to share client's public key. Not a part of Spec
        input_json_params['verifyingKey'] = self.public_key
        input_json['params'] = input_json_params
        input_json_str = json.dumps(input_json)
        logger.info("Request Json successfully Signed")

        return input_json_str, SignatureStatus.PASSED
Ejemplo n.º 8
0
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("***************** AVALON *****************")

    # Connect to registry list and retrieve registry
    if not off_chain:
        direct_wrapper.init_worker_registry_list(config)
        registry_lookup_result = direct_wrapper.registry_lookup()
        if (registry_lookup_result[0] == 0):
            logger.warn("No registries found")
            sys.exit(1)
        registry_retrieve_result = direct_wrapper.registry_retrieve(
            registry_lookup_result[2][0])
        config["tcf"]["json_rpc_uri"] = registry_retrieve_result[0]

    # Prepare worker
    direct_wrapper.init_worker_registry(config)

    global worker_id
    if not worker_id:
        worker_lookup_json = jrpc_request.WorkerLookupJson(
            1, worker_type=1)
        worker_lookup_result = direct_wrapper.worker_lookup(
            worker_lookup_json)
        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)

    worker_retrieve_json = jrpc_request.WorkerRetrieveJson(2, worker_id)
    worker_obj.load_worker(
        direct_wrapper.worker_retrieve(
            worker_retrieve_json)["result"]["details"])

    logger.info("********** Worker details Updated with Worker ID" +
                "*********\n%s\n", worker_id)

    # Convert workloadId to hex
    workload_id = "echo-result"
    workload_id = workload_id.encode("UTF-8").hex()
    # Create work order
    wo_submit_json = jrpc_request.WorkOrderSubmitJson(
        3, 6000, "pformat",
        worker_id, workload_id, "0x2345",
        worker_encryption_key=base64.b64decode(
            worker_obj.worker_encryption_key).hex(),
        data_encryption_algorithm="AES-GCM-256")
    wo_id = wo_submit_json.get_work_order_id()

    # Sign work order
    private_key = utility.generate_signing_keys()
    session_key = utility.generate_key()
    session_iv = utility.generate_iv()
    encrypted_session_key = utility.generate_encrypted_key(
        session_key, worker_obj.worker_encryption_key)
    # Generate one time key used for encrypting inData
    data_key = utility.generate_key()
    # Initialization vector of size 12 bytes with all zeros.
    data_iv = bytearray(12)

    encrypted_key = utility.generate_encrypted_key(
        data_key, worker_obj.worker_encryption_key)
    encrypted_data_encryption_key = utility.encrypt_data(
        encrypted_key, session_key)
    encrypted_data_encryption_key_str = ''.join(
        format(i, '02x') for i in encrypted_data_encryption_key)
    data_iv_str = ''.join(format(i, '02x') for i in data_iv)
    wo_submit_json.add_in_data(
        message, None, encrypted_data_encryption_key_str, data_iv_str)
    # Submit work order
    direct_wrapper.init_work_order(config)
    direct_wrapper.work_order_submit(
        wo_submit_json, encrypted_session_key, worker_obj, private_key,
        session_key, session_iv, data_key, data_iv)

    # Retrieve result
    wo_get_result_json = jrpc_request.WorkOrderGetResultJson(4, wo_id)
    direct_wrapper.work_order_get_result(
        wo_get_result_json, session_key, session_iv, data_key, data_iv)