Beispiel #1
0
def _send_work_order_request(workload_id, input_data_str,
                             worker_signup_json, socket):
    # Generate session key and iv
    (session_key, session_key_iv) = _generate_session_key_iv()
    # Create work order request
    input_json_str = _create_work_order_request(workload_id,
                                                input_data_str,
                                                session_key,
                                                session_key_iv,
                                                worker_signup_json)
    json_request = _create_json_request("ProcessWorkOrder",
                                        input_json_str)
    # Send work order
    logger.info("Send work order request via zmq\n")
    response = _send_request_zmq(socket, json.dumps(json_request))
    # Parse response
    response_json = json.loads(response)
    # check work order response
    if "result" in response_json:
        # Verify response signature
        sign = worker_signing.WorkerSign()
        worker_verify_key = worker_signup_json["verifying_key"]
        worker_verify_key_bytes = worker_verify_key.encode("UTF-8")
        verify = sign._verify_wo_response_signature(
            response_json['result'], worker_verify_key_bytes)
        if verify:
            logger.info("Work order result verification success")
            decrypt_out_message = _get_work_order_result(response_json,
                                                         session_key,
                                                         session_key_iv)
            logger.info("Work order result : {}".format(decrypt_out_message))
        else:
            logger.error("Work order result verification fail")
    elif "error" in response_json:
        logger.error("Work order execution failed")
Beispiel #2
0
    def _encrypt_and_sign_response(self, session_key, session_key_iv,
                                   output_json):
        """
        Encrypt outdata and compute worker signature.

        Parameters :
            session_key: Session key of the client which submitted
                        this work order
            session_key_iv: iv corresponding to teh session key
            output_json: Pre-populated response json
        Returns :
            JSON RPC response with worker signature

        """
        # Encrypt outData
        self.encrypt.encrypt_work_order_data_json(
            output_json["result"]["outData"], session_key, session_key_iv)
        # Compute worker signature
        res_hash = worker_hash.WorkerHash().calculate_response_hash(
            output_json["result"])
        # Get PEM encoded signing key from bytes
        signing_key_str = self.pre_proc_wo_keys['signing_key'].decode('utf-8')
        self.sign = worker_signing.WorkerSign()
        res_hash_sign = self.sign.sign_message(res_hash, signing_key_str)
        res_hash_sign_b64 = crypto_utility.byte_array_to_base64(res_hash_sign)
        output_json["result"]["workerSignature"] = res_hash_sign_b64

        return output_json
Beispiel #3
0
    def _verify_res_signature(self, work_order_res,
                              worker_verification_key,
                              requester_nonce):
        """
        Verify work order result signature

        Parameters :
            @param work_order_res - Result from work order response
            @param worker_verification_key - Worker verification key
            @param requester_nonce - requester generated nonce in work
            order request
        Returns :
            @returns True - If verification succeeds
                    False - If verification fails
        """
        signer = worker_signing.WorkerSign()
        status = signer.verify_signature(
            work_order_res,
            worker_verification_key,
            requester_nonce)
        if status == SignatureStatus.PASSED:
            logger.info("Signature verification successful")
        else:
            logger.error("Signature verification failed")
            return False
        return True
Beispiel #4
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()
 def __init__(self, kv_helper, worker_id):
     self._kv_helper = kv_helper
     self._worker_id = worker_id
     # Key pair for work order receipt signing
     # This is temporary approach
     signer = worker_signing.WorkerSign()
     signer.generate_signing_key()
     self.private_key = signer.sign_private_key
     self.public_key = signer.get_public_sign_key()
    def __init__(self, kv_helper):
        """
        Function to perform init activity
        Parameters:
            - kv_helper is a object of lmdb database
        """

        self.kv_helper = kv_helper
        self.__workorder_receipt_on_boot()
        # Special index 0xFFFFFFFF value to fetch last update to receipt
        self.LAST_RECEIPT_INDEX = 1 << 32
        # Supported hashing and signing algorithms
        self.SIGNING_ALGORITHM = "SECP256K1"
        self.HASHING_ALGORITHM = "SHA-256"
        self.signer = worker_signing.WorkerSign()
        self.hasher = worker_hash.WorkerHash()
Beispiel #7
0
    def verify_receipt_signature(self, receipt_update_retrieve):
        """
        Verify work order receipt signature
        """
        signer = worker_signing.WorkerSign()
        status = signer.verify_update_receipt_signature(
            receipt_update_retrieve['result'])
        if status == SignatureStatus.PASSED:
            logging.info(
                "Work order receipt retrieve signature verification " +
                "successful")
        else:
            logging.error(
                "Work order receipt retrieve signature verification failed!!")
            return False

        return True
Beispiel #8
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)
Beispiel #9
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)
Beispiel #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)
Beispiel #11
0
def parse_command_line(config, args):
    LOGGER.info("***************** AVALON *****************")
    global input_json_str
    global input_json_dir
    global server_uri
    global output_json_file_name
    global worker_obj
    global worker_id
    global private_key
    global encrypted_session_key
    global session_iv
    global requester_nonce

    parser = argparse.ArgumentParser()
    parser.add_argument("--logfile",
                        help="Name of the log file. " +
                        "Use __screen__ for standard output",
                        type=str)
    parser.add_argument("-p",
                        "--private_key",
                        help="Private Key of the Client",
                        type=str,
                        default=None)
    parser.add_argument("--loglevel", help="Logging level", type=str)
    parser.add_argument("-i",
                        "--input_file",
                        help="JSON input file name",
                        type=str,
                        default="input.json")
    parser.add_argument("--input_dir",
                        help="Logging level",
                        type=str,
                        default=[])
    parser.add_argument("-c",
                        "--connect_uri",
                        help="URI to send requests to",
                        type=str,
                        default=[])
    parser.add_argument("output_file",
                        help="JSON output file name",
                        type=str,
                        default="output.json",
                        nargs="?")

    options = parser.parse_args(args)

    if config.get("Logging") is None:
        config["Logging"] = {"LogFile": "__screen__", "LogLevel": "INFO"}
    if options.logfile:
        config["Logging"]["LogFile"] = options.logfile
    if options.loglevel:
        config["Logging"]["LogLevel"] = options.loglevel.upper()

    input_json_str = None
    input_json_dir = None

    if options.connect_uri:
        server_uri = options.connect_uri
    else:
        LOGGER.error("ERROR: Please enter the server URI")

    if options.input_dir:
        LOGGER.info("Load Json Directory from %s", options.input_dir)
        input_json_dir = options.input_dir
    elif options.input_file:
        try:
            LOGGER.info("load JSON input from %s", options.input_file)
            with open(options.input_file, "r") as file:
                input_json_str = file.read()
        except Exception as err:
            LOGGER.error("ERROR: Failed to read from file %s: %s",
                         options.input_file, str(err))
    else:
        LOGGER.info("No input found")

    if options.output_file:
        output_json_file_name = options.output_file
    else:
        output_json_file_name = None

    if options.private_key:
        private_key = options.private_key
    else:
        # Generating the private Key for the client
        private_key = worker_signing.WorkerSign().generate_signing_key()

    # Initializing Worker Object
    worker_obj = worker.SGXWorkerDetails()
Beispiel #12
0
 def __init__(self):
     self.SIGNING_ALGORITHM = "SECP256K1"
     self.HASHING_ALGORITHM = "SHA-256"
     self.signer = worker_signing.WorkerSign()
     self.signer.generate_signing_key()
     self.hasher = worker_hash.WorkerHash()
Beispiel #13
0
 def __init__(self):
     self.params_obj = {}
     self.signer = worker_signing.WorkerSign()
     self.encrypt = worker_encryption.WorkerEncrypt()
     self.hasher = worker_hash.WorkerHash()