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
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
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
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)