示例#1
0
def _get_work_order_result(response_json, session_key, session_key_iv):
    encrypt = worker_encryption.WorkerEncrypt()
    encrypt.decrypt_work_order_data_json(response_json["result"]["outData"],
                                         session_key, session_key_iv)
    decrypted_out_bytes = response_json["result"]["outData"][0]["data"]
    decrypted_out_msg = decrypted_out_bytes.decode("UTF-8")
    return decrypted_out_msg
示例#2
0
 def __init__(self):
     super().__init__()
     self._worker_registry_list_instance = None
     self._worker_instance = None
     self._work_order_instance = None
     self._work_order_receipt_instance = None
     self.encrypt = worker_encryption.WorkerEncrypt()
     self.signer = worker_signing.WorkerSign()
示例#3
0
    def register_wo_processor(self, unique_verification_id,
                              encryption_key,
                              proof_data, mr_enclave):
        """
        Request to register this WPE with the KME

        Parameters :
            @param unique_verification_id - Unique verifying key received from
            KME.
            @param encryption_key - encryption key of WPE
            @param proof_data - The IAS attestation report/DCAP quote
            @param mr_enclave - MRENCLAVE for this WPE
        Returns :
            @returns status - The status of the registration.
                              True, for success. None, in case of errors.
        """
        workload_id = "kme-reg"
        registration_params = {
            "unique_id": unique_verification_id,
            "proof_data": proof_data,
            "wpe_encryption_key": encryption_key,
            "mr_enclave": mr_enclave
        }
        in_data = [json.dumps(registration_params)]

        # Create session key and iv to sign work order request
        worker_encrypt = worker_encryption.WorkerEncrypt()
        session_key = worker_encrypt.generate_key()
        session_iv = worker_encrypt.generate_iv()

        wo_req = self._construct_wo_req(
            in_data, workload_id, self._worker.encryption_key,
            session_key, session_iv)

        response = self._post_and_get_result(wo_req)

        if "result" in response:
            wo_response_json = response["result"]
            if "error" not in wo_response_json and self._verify_res_signature(
                    wo_response_json, self._worker.verification_key,
                    wo_req["params"]["requesterNonce"]):
                decrypted_res = worker_encrypt.decrypted_response(
                    wo_response_json, session_key, session_iv)
                # Response contains an array of results. In this case, the
                # array has single element and the data field is of interest.
                # It is integer with status of registration.
                return decrypted_res[0]['data']
            return None
        else:
            logger.error("Could not register this WPE with the KME : {}"
                         .format(response))
            return None
示例#4
0
 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)
示例#5
0
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_bytes = input_data_str.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)
示例#6
0
    def get_unique_verification_key(self, verification_key_nonce):
        """
        Request wrapper to get a unique id from the KME

        Parameters :
            @param verification_key_nonce - Random nonce generated by this WPE
        Returns :
            @returns result - Result received from the KME which includes the
                              public verification key which is supposed to be
                              included in REPORTDATA by the WPE. None, in case
                              of failure.
        """
        workload_id = "kme-uid"
        in_data = [verification_key_nonce]

        # Create session key and iv to sign work order request
        worker_encrypt = worker_encryption.WorkerEncrypt()
        session_key = worker_encrypt.generate_key()
        session_iv = worker_encrypt.generate_iv()

        wo_req = self._construct_wo_req(
            in_data, workload_id, self._worker.encryption_key,
            session_key, session_iv)

        response = self._post_and_get_result(wo_req)

        if "result" in response:
            wo_response_json = response["result"]
            if self._verify_res_signature(wo_response_json,
                                          self._worker.verification_key,
                                          wo_req["params"]["requesterNonce"]):
                decrypted_res = worker_encrypt.decrypted_response(
                    wo_response_json, session_key, session_iv)
                # Response contains an array of results. In this case, the
                # array has single element and the data field is of interest.
                # The data contains result,verification_key and
                # verification_key_signature delimited by ' '.
                # @TODO : Update to use multiple out_data fields.
                return decrypted_res[0]['data']
            return None
        else:
            logger.error("Could not get a unique id from the KME : {}"
                         .format(response))
            return None
示例#7
0
    def get_unique_verification_key(self, verification_key_nonce):
        """
        Request wrapper to get a unique id from the KME

        Parameters :
            @param verification_key_nonce - Random nonce generated by this WPE
        Returns :
            @returns result - Result received from the KME which includes the
                              public verification key which is supposed to be
                              included in REPORTDATA by the WPE. None, in case
                              of failure.
        """
        workload_id = "kme-uid"
        in_data = [verification_key_nonce]

        logger.info("in wpe_requester.py get_unique_verification_key")

        # Create session key and iv to sign work order request
        worker_encrypt = worker_encryption.WorkerEncrypt()
        session_key = worker_encrypt.generate_session_key()
        session_iv = worker_encrypt.generate_iv()

        wo_req = self._construct_wo_req(in_data, workload_id,
                                        self._worker.encryption_key,
                                        session_key, session_iv)

        response = self._post_and_get_result(wo_req)

        if "result" in response:
            wo_response_json = response["result"]
            if self._verify_res_signature(wo_response_json,
                                          self._worker.verification_key,
                                          wo_req["params"]["requesterNonce"]):
                return self.decrypt_wo_response(wo_response_json, session_key,
                                                session_iv, worker_encrypt)
            return None
        else:
            logger.error(
                "Could not get a unique id from the KME : {}".format(response))
            return None
示例#8
0
    def preprocess_work_order(self, wo_request, encryption_key):
        """
        Request to preprocess a work order

        Parameters :
            @param wo_request - The original work order request as str
            @param encryption_key - WPE's public encryption key
        Returns :
            @returns result - Result from KME that includes the workorder
                              key info. error response, in case of failure.
        """
        workload_id = "kme-preprocess"
        in_data = [wo_request, encryption_key]

        # Create session key and iv to sign work order request
        worker_encrypt = worker_encryption.WorkerEncrypt()
        session_key = worker_encrypt.generate_key()
        session_iv = worker_encrypt.generate_iv()

        wo_req = self._construct_wo_req(
            in_data, workload_id, self._worker.encryption_key,
            session_key, session_iv)

        response = self._post_and_get_result(wo_req)

        if "result" in response:
            wo_response_json = response["result"]
            if self._verify_res_signature(wo_response_json,
                                          self._worker.verification_key,
                                          wo_req["params"]["requesterNonce"]):
                decrypted_res = worker_encrypt.decrypted_response(
                    wo_response_json, session_key, session_iv)
                # Response contains an array of results. In this case, the
                # array has single element and the data field is of interest.
                return decrypted_res[0]['data']
            return None
        else:
            logger.error("Could not preprocess work order at KME : {}"
                         .format(response))
            return response
示例#9
0
    def preprocess_work_order(self, wo_request, encryption_key):
        """
        Request to preprocess a work order

        Parameters :
            @param wo_request - The original work order request as str
            @param encryption_key - WPE's public encryption key
        Returns :
            @returns result - Result from KME that includes the workorder
                              key info. error response, in case of failure.
        """
        workload_id = "kme-preprocess"
        in_data = [wo_request, encryption_key]

        # Create session key and iv to sign work order request
        worker_encrypt = worker_encryption.WorkerEncrypt()
        session_key = worker_encrypt.generate_session_key()
        session_iv = worker_encrypt.generate_iv()

        wo_req = self._construct_wo_req(in_data, workload_id,
                                        self._worker.encryption_key,
                                        session_key, session_iv)

        response = self._post_and_get_result(wo_req)

        if "result" in response:
            wo_response_json = response["result"]
            logger.info("verify result signature\n\n")
            if self._verify_res_signature(wo_response_json,
                                          self._worker.verification_key,
                                          wo_req["params"]["requesterNonce"]):
                return self.decrypt_wo_response(wo_response_json, session_key,
                                                session_iv, worker_encrypt)
            return None
        else:
            logger.error(
                "Could not preprocess work order at KME : {}".format(response))
            return response
示例#10
0
def _generate_session_key_iv():
    encrypt = worker_encryption.WorkerEncrypt()
    session_key = encrypt.generate_session_key()
    session_key_iv = encrypt.generate_iv()
    return (session_key, session_key_iv)
示例#11
0
def Main(args=None):
    parser = GenericClient(args)
    generic_client_obj = None
    if parser.is_direct_mode():
        generic_client_obj = DirectModelGenericClient(parser.get_config())
    elif parser.get_blockchain_type() in ["fabric", "ethereum"]:
        generic_client_obj = ProxyModelGenericClient(
            parser.get_config(), parser.get_blockchain_type())
    else:
        logging.error("Invalid inputs to generic client")
        sys.exit(-1)

    # Retrieve JSON RPC uri from registry list
    if not parser.uri() and parser.mode() == "listing":
        self._uri = self.retrieve_uri_from_registry_list(self._config)
    # Prepare worker
    worker_id = parser.get_worker_id()
    if worker_id is None:
        logging.error("worker id is missing")
        sys.exit(-1)

    if worker_id is None:
        logging.error("\n Unable to get worker {}\n".format(worker_id))
        sys.exit(-1)

    # Retrieve worker details
    worker_obj = generic_client_obj.get_worker_details(worker_id)
    if worker_obj is None:
        logging.error("Unable to retrieve worker details\n")
        sys.exit(-1)

    encrypt = worker_encrypt.WorkerEncrypt()
    # Create session key and iv to sign work order request
    session_key = encrypt.generate_session_key()
    session_iv = encrypt.generate_iv()

    # Do worker verification
    generic_client_obj.do_worker_verification(worker_obj)

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

    # Create work order
    if parser.in_data_plain_text():
        # As per TC spec, if encryptedDataEncryptionKey is "-" then
        # input data is not encrypted
        encrypted_data_encryption_key = "-"
    else:
        # As per TC spec, if encryptedDataEncryptionKey is not
        # provided then set it to None which means
        # use default session key to encrypt input data
        encrypted_data_encryption_key = None

    code, wo_params = generic_client_obj.create_work_order_params(
        worker_id, parser.workload_id(), parser.in_data(),
        worker_obj.encryption_key, session_key, session_iv,
        encrypted_data_encryption_key)

    if not code:
        logging.error("Work order request creation failed \
                \n {}".format(wo_params))
        sys.exit(-1)

    signer = worker_signing.WorkerSign()
    client_private_key = signer.generate_signing_key()
    if parser.requester_signature():
        # Add requester signature and requester verifying_key
        if wo_params.add_requester_signature(client_private_key) is False:
            logging.info("Work order request signing failed")
            sys.exit(-1)

    submit_status, wo_submit_res = generic_client_obj.submit_work_order(
        wo_params)

    if submit_status:
        # Create receipt
        if parser.show_receipt():
            generic_client_obj.create_work_order_receipt(
                wo_params, client_private_key)
        work_order_id = wo_params.get_work_order_id()
        # Retrieve work order result
        status, wo_res = generic_client_obj.get_work_order_result(
            work_order_id)

        # Check if result field is present in work order response
        if status:
            # Verify work order response signature
            if generic_client_obj.verify_wo_response_signature(
                    wo_res['result'], worker_obj.verification_key,
                    wo_params.get_requester_nonce()) is False:
                logging.error("Work order response signature"
                              " verification Failed")
                sys.exit(-1)
            # Decrypt work order response
            if parser.show_decrypted_output():
                decrypted_res = generic_client_obj.decrypt_wo_response(
                    wo_res['result'])
                logging.info(
                    "\nDecrypted response:\n {}".format(decrypted_res))
        else:
            logging.error("\n Work order get result failed\n")
            sys.exit(-1)

        if parser.show_receipt():
            # Retrieve receipt
            retrieve_wo_receipt = \
                generic_client_obj.retrieve_work_order_receipt(
                    work_order_id)
            # Verify receipt signature
            if retrieve_wo_receipt:
                if "result" in retrieve_wo_receipt:
                    if generic_client_obj.verify_receipt_signature(
                            retrieve_wo_receipt) is False:
                        logging.error("Receipt signature verification Failed")
                        sys.exit(-1)
                else:
                    logging.info("Work Order receipt retrieve failed")
                    sys.exit(-1)
    else:
        logging.error("Work order submit failed {}".format(wo_submit_res))
        sys.exit(-1)
示例#12
0
def main(argv):

    encrypt = worker_encryption.WorkerEncrypt()

    # Test session key Encryption and Decryption
    encrypt.generate_rsa_key()
    worker_rsa_public_key = encrypt.get_rsa_public_key()
    logger.info("worker_rsa_public_key = {}".format(worker_rsa_public_key))

    session_key = encrypt.generate_session_key()
    encrypted_session_key = encrypt.encrypt_session_key(session_key)
    decrypted_session_key = encrypt.decrypt_session_key(encrypted_session_key)
    if session_key == decrypted_session_key:
        logger.info("Session key Encryption and Decryption Success")
    else:
        logger.error("Session key Encryption and Decryption Success")

    # Test Encryption and Decryption
    message = "Hello world"
    session_key = encrypt.generate_session_key()
    session_key_iv = encrypt.generate_iv()
    encrypt_msg_bytes = encrypt.encrypt_data(message.encode("utf-8"),
                                             session_key, session_key_iv)
    decrypt_message = encrypt.decrypt_data(encrypt_msg_bytes, session_key,
                                           session_key_iv)
    decrypt_message = decrypt_message.decode("utf-8")

    if message == decrypt_message:
        logger.info("Message Encryption and Decryption Success")
    else:
        logger.error("Message Encryption and Decryption Success")

    # Test inData Encryption and Decryption
    input_json = dict()
    input_json["jsonrpc"] = "2.0"
    input_json["method"] = "WorkOrderSubmit"
    input_json["id"] = "1"
    input_json["params"] = dict()

    inData = dict()
    inData["index"] = 0
    inData["dataHash"] = ""
    inData["data"] = message.encode("utf-8")
    inData["encryptedDataEncryptionKey"] = "null"
    inData["iv"] = ""
    input_json["params"]["inData"] = [inData]

    # Encrypt inData (will be done at client end)
    encrypt.encrypt_work_order_data_json(input_json["params"]["inData"],
                                         session_key, session_key_iv)
    # Decrypt inData
    encrypt.decrypt_work_order_data_json(input_json["params"]["inData"],
                                         session_key, session_key_iv)
    for item in input_json["params"]["inData"]:
        decrypted_data_bytes = item["data"]
        decrypted_data_str = decrypted_data_bytes.decode("UTF-8")
        logger.info("Decrypted data :{}".format(decrypted_data_str))

    if message == input_json["params"]["inData"][0]["data"].decode("UTF-8"):
        logger.info("inData Decryption Success")
    else:
        logger.error("inData Decryption Success")

    # Encrypt outData
    outData = inData
    out_message = "Received Hello world"
    outData["data"] = out_message.encode("UTF-8")
    input_json["params"]["outData"] = [outData]
    encrypt.encrypt_work_order_data_json(input_json["params"]["outData"],
                                         session_key, session_key_iv)

    # Decrypt outData (will be done at client end)
    encrypt.decrypt_work_order_data_json(input_json["params"]["outData"],
                                         session_key, session_key_iv)
    decrypted_out_bytes = input_json["params"]["outData"][0]["data"]
    decrypted_out_message = decrypted_out_bytes.decode("UTF-8")
    if out_message == decrypted_out_message:
        logger.info("outData Decryption Success")
    else:
        logger.error("outData Decryption Success")
示例#13
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)
示例#14
0
 def __init__(self):
     self.params_obj = {}
     self.signer = worker_signing.WorkerSign()
     self.encrypt = worker_encryption.WorkerEncrypt()
     self.hasher = worker_hash.WorkerHash()