예제 #1
0
    def __encrypt_workorder_indata(self, input_json_params, encrypted_session_key, session_iv):
        """
        Function to encrypt inData of workorder
        Parameters:
            - input_json_params is inData and outData elements within work order request as per TCF API 6.1.7 Work Order Data Formats
            - encrypted_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.
        """

        indata_objects = input_json_params['inData']
        indata_objects.sort(key=lambda x: x['index'])
        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 = utility.encrypt_data(data, encrypted_session_key, session_iv)
                input_json_params['inData'][i]['data'] = crypto.byte_array_to_base64(enc_data)
                input_json_params['inData'][i]['iv'] = input_json_params["sessionKeyIv"]
                logger.debug("encrypted indata - %s", crypto.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.byte_array_to_base64(data)
            else:
                #TODO: Explore the necessity of session iv
                enc_data = utility.encrypt_data(data, e_key, "0")
                input_json_params['inData'][i]['data'] = crypto.byte_array_to_base64(enc_data)
                input_json_params['inData'][i]['iv'] = format("0", '02x')
                logger.debug("encrypted indata - %s", crypto.byte_array_to_base64(enc_data))
            i = i + 1

        logger.debug("Workorder InData after encryption: %s", indata_objects)
예제 #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 TCF 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']
        indata_objects.sort(key=lambda x: x['index'])
        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 = utility.encrypt_data(data, session_key, session_iv)
                input_json_params['inData'][i]['data'] = \
                    crypto.byte_array_to_base64(enc_data)
                logger.debug(
                    "encrypted indata - %s",
                    crypto.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.byte_array_to_base64(data)
            else:
                enc_data = utility.encrypt_data(data, data_key, data_iv)
                input_json_params['inData'][i]['data'] = \
                    crypto.byte_array_to_base64(enc_data)
                logger.debug("encrypted indata - %s",
                             crypto.byte_array_to_base64(enc_data))
            i = i + 1

        logger.debug("Workorder InData after encryption: %s", indata_objects)
예제 #3
0
def main():
    logging.info("Executing Unit test cases for encryption at client")
    client = signature.ClientSignature()
    msg = "This is client request"
    iv = client.generate_sessioniv()
    enc_sess_key = test_encrypt_session_key(client, iv)
    if enc_sess_key:
        enc_data = test_encrypt_data(client, iv, enc_sess_key[:16], msg)
        if enc_data:
            b64_enc_data = crypto.byte_array_to_base64(enc_data)
            b64_enc_sess_key = crypto.byte_array_to_base64(enc_sess_key[:16])
            iv_hex = crypto.byte_array_to_hex(iv)
            test_decrypt_data(client, iv_hex, b64_enc_sess_key, msg, b64_enc_data)
    logging.info("Unit test case execution for encryption/decryption complete.")
예제 #4
0
    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)
예제 #5
0
    def calculate_datahash(self, data_objects):
        """
        Function to calculate a hash value of the array concatenating dataHash, data,
        encryptedDataEncryptionKey, iv for each item in the inData/outData array
        Parameters:
            - data_objects is each item in inData or outData part of workorder request as per TCF API 6.1.7 Work Order Data Formats
        """

        hash_str = ""
        for item in data_objects:
            datahash = "".encode('UTF-8')
            e_key = "".encode('UTF-8')
            iv = "".encode('UTF-8')
            if 'dataHash' in item:
                datahash = item['dataHash'].encode('UTF-8')
            data = item['data'].encode('UTF-8')
            if 'encryptedDataEncryptionKey' in item:
                e_key = item['encryptedDataEncryptionKey'].encode('UTF-8')
            if 'iv' in item:
                iv = item['iv'].encode('UTF-8')
            concat_string = datahash + data + e_key + iv
            concat_hash = bytes(concat_string)
            hash = crypto.compute_message_hash(concat_hash)
            hash_str = hash_str + crypto.byte_array_to_base64(hash)

        return hash_str
예제 #6
0
 def calculate_request_hash(self, input_json):
     """
     Function to create the work order reuest 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.byte_array_to_base64(
         crypto.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.compute_message_hash(concat_hash)
     final_hash_str = crypto.byte_array_to_hex(final_hash)
     return final_hash_str
예제 #7
0
    def __calculate_hash_on_concatenated_string(
            self, input_json_params, nonce_hash):
        """
        Function to calculate a hash value of the string concatenating the
        following values:
        requesterNonce, workOrderId, workerId, workloadId, and requesterId.
        Parameters:
            - input_json_params is a collection of parameters,
              as per TCF APi 6.1.1 Work Order Request Payload
            - nonce_hash is SHA256 hashed value of a random string generated by
              the participant.
        """

        workorder_id = (input_json_params['workOrderId']).encode('UTF-8')
        worker_id = (input_json_params['workerId']).encode('UTF-8')
        workload_id = "".encode('UTF-8')
        if 'workloadId' in input_json_params:
            workload_id = (input_json_params['workloadId']).encode('UTF-8')
        requester_id = (input_json_params['requesterId']).encode('UTF-8')

        concat_string = nonce_hash + workorder_id + worker_id + workload_id + \
            requester_id
        concat_hash = bytes(concat_string)
        # SHA-256 hashing is used
        hash_1 = crypto.compute_message_hash(concat_hash)
        result_hash = crypto.byte_array_to_base64(hash_1)

        return result_hash
예제 #8
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 = 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 = utility.encrypt_data(data,
                                         encrypted_data_encryption_key,
                                         data_iv)
         return crypto.byte_array_to_base64(enc_data)
예제 #9
0
    def __generate_signature(self, hash, private_key):
        """
        Function to generate signature object
        Parameters:
            - hash is the combined array of all hashes calculated on the message
            - private_key is Client private key
        """

        self.private_key = private_key
        self.public_key = self.private_key.GetPublicKey().Serialize()
        signature_result = self.private_key.SignMessage(hash)
        signature_base64 = crypto.byte_array_to_base64(signature_result)
        return signature_base64
예제 #10
0
    def __process_encryption_key_get(self, input_json_str, response):
        """
        Function to process get encryption key request.
        Parameters:
            - input_json_str is a work order request json as per TCF API 6.1.10 Get Encryption Key Request Payload
            - response is the response object to be returned
        """

        input_json = json.loads(input_json_str)
        worker_id = str(input_json['params']['workerId'])
        value = self.kv_helper.get("workers", worker_id)

        if value is not None:
            json_dict = json.loads(value)
            response["result"] = {}
            response["result"]["workerId"] = worker_id
            encryptionKey = json_dict["details"]["workerTypeData"][
                "encryptionKey"]
            try:
                encryptionKeyNonce = json_dict["details"]["workerTypeData"][
                    "encryptionKeyNonce"]
            except:
                encryptionKeyNonce = crypto.random_bit_string(NO_OF_BYTES)
            tag = ""
            response["result"]["encryptionKey"] = encryptionKey
            response["result"]["encryptionKeyNonce"] = encryptionKeyNonce
            response["result"]["tag"] = tag
            #calculate signature
            concat_string = worker_id.encode('UTF-8') + encryptionKey.encode(
                'UTF-8') + encryptionKeyNonce.encode('UTF-8') + tag.encode(
                    'UTF-8')
            concat_hash = bytes()
            concat_hash = bytes(concat_string)
            hash_1 = crypto.compute_message_hash(concat_hash)
            s1 = crypto.byte_array_to_base64(hash_1)
            # Requires worker private key to sign.
            # signature =  self.PrivateKey.SignMessage(hash)
            response["result"]["signature"] = s1
        else:
            # Workorder id already exists
            response['error'] = {}
            response['error'][
                'code'] = WorkorderError.INVALID_PARAMETER_FORMAT_OR_VALUE
            response['error'][
                'message'] = 'Worker Id not found in the database. Hence invalid parameter'

        return response
예제 #11
0
 def generate_signature(self, hash, private_key):
     """
     Function to generate signature object
     Parameters:
         - hash is the combined array of all hashes calculated on the message
         - private_key is Client private key
     Returns tuple(status, signature)
     """
     try:
         self.private_key = private_key
         self.public_key = self.private_key.GetPublicKey().Serialize()
         signature_result = self.private_key.SignMessage(hash)
         signature_base64 = crypto.byte_array_to_base64(signature_result)
     except:
         logger.error("Exception occured during signature generation")
         return False, None
     return True, signature_base64
예제 #12
0
def decrypt_data(encryption_key, iv, data):
    """
    Function to decrypt the outData in the result
    Parameters:
        - encryption_key is the key used to decrypt the encrypted data of response.
        - iv is an initialization vector if required by the data encryption algorithm. The default is all zeros.
        - data is the parameter data in outData part of workorder request as per TCF API 6.1.7 Work Order Data Formats
    """
    if not data:
        logger.debug("Outdata is empty, nothing to decrypt")
        return
    data_byte = crypto.base64_to_byte_array(data)
    logger.debug("encrypted_session_key: %s", encryption_key)
    decrypt_result = crypto.SKENC_DecryptMessage(encryption_key,
                                                 crypto.hex_to_byte_array(iv),
                                                 data_byte)
    result = base64.b64decode(crypto.byte_array_to_base64(decrypt_result))
    logger.info("Decryption Result at Client - %s ", result)
예제 #13
0
    def EncryptionKeyGet(self, **params):
        """
        Function to process get encryption key request.
        Parameters:
            - param is the 'param' object in the a worker request as per TCF
                API 6.1.10 Get Encryption Key Request Payload
        """

        worker_id = str(params['workerId'])
        value = self.kv_helper.get("workers", worker_id)

        if value is None:
            raise JSONRPCDispatchException(
                WorkerError.INVALID_PARAMETER_FORMAT_OR_VALUE,
                "Worker id not found in the database. Hence invalid parameter")

        worker_type_data = json.loads(value).get("details").get(
            "workerTypeData")
        encryptionKey = worker_type_data["encryptionKey"]
        try:
            encryptionKeyNonce = worker_type_data["encryptionKeyNonce"]
        except:
            encryptionKeyNonce = crypto.random_bit_string(NO_OF_BYTES)

        tag = ""
        # calculate signature
        concat_string = worker_id.encode('UTF-8') + encryptionKey.encode(
            'UTF-8') + encryptionKeyNonce.encode('UTF-8') + tag.encode('UTF-8')
        concat_hash = bytes()
        concat_hash = bytes(concat_string)
        hash_1 = crypto.compute_message_hash(concat_hash)
        s1 = crypto.byte_array_to_base64(hash_1)
        # Requires worker private key to sign.
        # signature =  self.PrivateKey.SignMessage(hash)

        result = {
            "workerId": worker_id,
            "encryptionKey": encryptionKey,
            "encryptionKeyNonce": encryptionKeyNonce,
            "tag": "",
            "signature": s1,
        }

        return result
예제 #14
0
    def evaluate(self) :
        serialized_byte_array = crypto.string_to_byte_array(self.work_order)
        encrypted_request = crypto.byte_array_to_base64(serialized_byte_array)

        try :
            encoded_encrypted_response = self.enclave_service.send_to_sgx_worker(encrypted_request)
            assert encoded_encrypted_response
        except :
            logger.exception('workorder request invocation failed')
            raise

        try :
            decrypted_response = crypto.base64_to_byte_array(encoded_encrypted_response)
            response_string = crypto.byte_array_to_string(decrypted_response)
            response_parsed = json.loads(response_string[0:-1])
        except :
            logger.exception('workorder response is invalid')
            raise

        return response_parsed
예제 #15
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 TCF 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 intialization 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 None

        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 None

        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 None

        input_json = json.loads(input_json_str)
        input_json_params = input_json['params']
        input_json_params["sessionKeyIv"] = ''.join(
            format(i, '02x') for i in session_iv)

        encrypted_session_key_str = ''.join(
            format(i, '02x') for i in encrypted_session_key)
        self.__encrypt_workorder_indata(input_json_params, session_key,
                                        session_iv, worker.encryption_key,
                                        data_key, data_iv)

        if input_json_params["requesterNonce"] and \
            is_hex(input_json_params["requesterNonce"]):
            nonce = crypto.string_to_byte_array(
                input_json_params["requesterNonce"])
        else:
            # [NO_OF_BYTES] 16 BYTES for nonce, is the recommendation by NIST to
            # avoid collisions by the "Birthday Paradox".
            nonce = crypto.random_bit_string(NO_OF_BYTES)

        request_nonce_hash = crypto.compute_message_hash(nonce)
        nonce_hash = (
            crypto.byte_array_to_base64(request_nonce_hash)).encode('UTF-8')
        hash_string_1 = self.__calculate_hash_on_concatenated_string(
            input_json_params, nonce_hash)
        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']
            data_objects.sort(key=lambda x: x['index'])
            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 = utility.encrypt_data(final_hash, session_key,
                                                      session_iv)
        encrypted_request_hash_str = ''.join(
            format(i, '02x') for i in 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 == False:
            return 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['requesterNonce'] = crypto.byte_array_to_base64(
            request_nonce_hash)
        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
예제 #16
0
    else:
        logger.error(
            "ERROR: Symmetric decryption (random IV) " +
            "invalid key detection test failed: ", exc)
        sys.exit(-1)

try:
    iv = crypto.SKENC_GenerateIV("A message")
except Exception as exc:
    logger.error(
        "ERROR: Symmetric encryption deterministic iv generation " +
        "test failed: ", exc)
    sys.exit(-1)
logger.debug(
    "Symmetric encryption deterministic iv generation test successful!")

try:
    rand = crypto.random_bit_string(16)
except Exception as exc:
    logger.error("ERROR: Random number generation failed: ", exc)
    sys.exit(-1)
logger.debug("Random number generation successful!")

hash = crypto.compute_message_hash(rand)
bhash = bytearray(hash)
b64hash = crypto.byte_array_to_base64(bhash)
logger.debug("Hash computed!")
crypto.base64_to_byte_array(b64hash)
logger.debug("SWIG CRYPTO_WRAPPER TEST SUCCESSFUL!")
sys.exit(0)