{"id":21741310,"url":"https://github.com/keplerc/paranoid-sgx","last_synced_at":"2026-05-11T04:48:47.644Z","repository":{"id":205874143,"uuid":"345520576","full_name":"KeplerC/paranoid-sgx","owner":"KeplerC","description":null,"archived":false,"fork":false,"pushed_at":"2022-06-08T20:51:58.000Z","size":68852,"stargazers_count":2,"open_issues_count":1,"forks_count":0,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-01-25T21:55:32.976Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/KeplerC.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2021-03-08T03:35:36.000Z","updated_at":"2023-11-06T20:39:04.000Z","dependencies_parsed_at":"2023-11-07T03:42:08.246Z","dependency_job_id":null,"html_url":"https://github.com/KeplerC/paranoid-sgx","commit_stats":null,"previous_names":["keplerc/paranoid-sgx"],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KeplerC%2Fparanoid-sgx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KeplerC%2Fparanoid-sgx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KeplerC%2Fparanoid-sgx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KeplerC%2Fparanoid-sgx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/KeplerC","download_url":"https://codeload.github.com/KeplerC/paranoid-sgx/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244717341,"owners_count":20498284,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-26T06:18:21.215Z","updated_at":"2026-05-11T04:48:47.534Z","avatar_url":"https://github.com/KeplerC.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c!--jekyll-front-matter\n---\n\ntitle: Quickstart Guide\n\noverview: Install Asylo, build, and run your first enclave!\n\nlocation: /_docs/guides/quickstart.md\n\norder: 10\n\nlayout: docs\n\ntype: markdown\n\ntoc: true\n\n---\n{% include home.html %}\njekyll-front-matter--\u003e\n\nThis guide demonstrates using Asylo to protect secret data from an attacker with\nroot privileges.\n\n## How to buid\n\nTo run the `paranoid-sgx` , first use the following set of commands to\n```bash\nMY_PROJECT=~/paranoid-sgx\ngit clone https://github.com/KeplerC/paranoid-sgx.git \"${MY_PROJECT}\"\n```\n\nNext, use Docker to build and run the `paranoid-sgx` application, using a\nsimulated enclave backend:\n\n```bash\nMY_PROJECT=~/paranoid-sgx\ndocker run -it --rm \\\n    -v bazel-cache:/root/.cache/bazel \\\n    -v \"${MY_PROJECT}\":/opt/my-project \\\n    -w /opt/my-project \\\n    keplerc/paranoid-asylo:latest \n```\nAfter entering the docker, run the application: \n```bash\n./scripts/run-server.sh \u0026\n./scripts/run-worker.sh\n```\nThe dockerfile for building `keplerc/paranoid-asylo:latest` is located in `./docker`.  \n\n### Run simple JS in SGX \nAfter entering the docker, run \n```bash\nbazel run //src:hello_world_sgx_sim -- --mode 4 --input_file \"/opt/my-project/src/input.js\"\n```\n\n### Run JS demo with PSL stack\n```\nMY_PROJECT=~/paranoid-sgx\nsudo docker run -it --rm \\\n    --net=host \\\n    -v bazel-cache:/root/.cache/bazel \\\n    -v \"${MY_PROJECT}\":/opt/my-project \\\n    -w /opt/my-project \\\n    keplerc/paranoid-asylo:latest \nfogrobotics\n\n(four different terminals)\n# start sync server\nbazel run //src:hello_world_sgx_sim -- --mode=7\n\n# start workers \nbazel run //src:hello_world_sgx_sim  --copt=-O3 -- --mode=6\n\n# start job dispatcher \nbazel run //src:hello_world_sgx_sim -- --mode=3\n\n# run benchmark\napt install python3-pip\npip3 install zmq\ncd frontend \npython3 run_benchmark.py\n\n```\n\n### Run CapsuleDB Local Demo \nModel\n```\n                                      ┌─────►CDB\n┌───────────┐     ┌────────────┐      │\n│test server├────►│root router ├──────┤\n└───────────┘     └────────────┘      ├─────►CDB\n                                      │\n                                      │\n                                      └─────►...\n```\n\nRun instructions\n```\n(three instances of same docker container)\n# start root router\nbazel run //src:hello_world_sgx_sim -- --mode=7\n\n# start CapusleDB worker\nbazel run //src:hello_world_sgx_sim  -- --mode=8\n\n# start testing client\nbazel run //src:capsuleDBIntegTests\n```\n\nOr you can put it as a background job and run both in the same instance. \n\n\n## Introduction\n\n### What is an enclave?\n\nOn traditional systems, the Operating System (OS) kernel has unrestricted access\nto a machine's hardware resources. The kernel typically exposes most of its\naccess permissions to a root user without any restrictions. Additionally, a root\nuser can extend or modify the kernel on a running system. As a result, if an\nattacker can execute code with root privileges, they can compromise every secret\nand bypass every security policy on the machine. For instance, if an attacker\nobtains root access on a machine that manages TLS keys, those keys may be\ncompromised.\n\nEnclaves are an emerging technology paradigm that changes this equation. An\nenclave is a special execution context where code can run protected from even\nthe OS kernel, with the guarantee that even a user running with root privileges\ncannot extract the enclave's secrets or compromise its integrity. Such\nprotections are enabled through hardware isolation technologies such as\n[Intel SGX](https://software.intel.com/en-us/sgx) or\n[ARM TrustZone](https://www.arm.com/products/security-on-arm/trustzone), or even\nthrough additional software layers such as a hypervisor. These technologies\nenable new forms of isolation beyond the usual kernel/user-space separation.\n\nNew security features are exciting for developers building secure applications,\nbut in practice there is a big gap between having a raw capability and\ndeveloping applications that leverage that capability. Building useful enclave\napplications requires tools to construct, load, and operate enclaves. Doing\nuseful work in an enclave requires programming-language support and access to\ncore platform libraries.\n\n### What is Asylo?\n\nAsylo is an open source framework for developing enclave applications. It\ndefines an abstract enclave model that can be mapped transparently onto a\nvariety of enclave technologies (a.k.a., _enclave backends_). Asylo provides a\nsoftware-development platform that supports a growing range of use cases. In a\nsense, the enclave backend can be viewed as a special-purpose embedded computer\nrunning inside a conventional machine, with Asylo providing the necessary\nruntime for that embedded computer.\n\nBelow, we walk through building a simple example enclave. The example\ndemonstrates initializing an enclave, passing arguments to code running inside\nthe enclave, encrypting those arguments inside the enclave, and returning the\nprocessed results. Even though this is a very simple example, it demonstrates\nthe basic functionality provided by Asylo and the steps required to utilize that\nfunctionality.\n\n## Getting started with the example code\n\nRun the following commands to grab our Docker container and download the example\nsource code used in this guide. See our\n[README](https://github.com/google/asylo/blob/master/README.md) for additional\ninstructions on Docker usage.\n\n```bash\ndocker pull gcr.io/asylo-framework/asylo\nMY_PROJECT=~/asylo-examples\nmkdir -p \"${MY_PROJECT}\"\nwget -q -O - https://github.com/google/asylo-examples/archive/master.tar.gz | \\\n    tar -zxv --strip 1 --directory \"${MY_PROJECT}\"\n```\n\nNote that you can set `MY_PROJECT` to any directory of your choice. This\nenvironment variable is later used in the instructions for\n[building and running](#building-and-running-an-enclave-application) the enclave\napplication in this example.\n\nThe example source code can be found in the\n[Asylo SDK](https://github.com/google/asylo/tree/master/asylo/examples) on\nGitHub.\n\n## Overall approach\n\nIn Asylo, an enclave runs in the context of a user-space application. However,\nfor security and portability reasons, Asylo does not support direct interactions\nbetween the enclave code and the OS. Instead, all enclave-to-OS interactions\nmust be mediated through code that runs outside the enclave. We refer to the\ncode running outside the enclave as the _untrusted application_ and the code\nrunning inside the enclave as the _trusted application_, or simply the\n_enclave_.\n\nHere, we focus on a model where a majority of the user-developed logic lives\ninside the enclave. In this model, users may have to write some boiler-plate\n(similar to what is presented later in this guide), but most of the code needed\nfor creating, launching, and interacting with enclaves is provided by the Asylo\nframework.\n\nAsylo takes an object-oriented approach to enclave application development.\nConceptually, an enclave is a collection of private data and private logic,\nalong with public methods to access it. To this end, Asylo models an enclave\nusing `TrustedApplication`, an abstract class that defines various enclave\nentry-points. To implement an enclave application, a developer creates a\nsubclass of `TrustedApplication` and implements the appropriate methods.\n\nThroughout this guide, we use both _trusted application_ and _enclave_ to refer\nto an instance of `TrustedApplication`.\n\n## Enclave interaction model\n\nIn Asylo, enclaves operate on\n[protocol-buffer messages](https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.message#Message);\nall enclave inputs and outputs are protocol buffers.\n\nWe refer to the process of switching from an untrusted application to an enclave\nas _entering the enclave_ and the process of switching from an enclave to an\nuntrusted application as _exiting an enclave_.\n\nIn Asylo, all enclave interactions are handled through an abstract class called\n`EnclaveClient`. The Asylo framework provides concrete implementations of this\nclass for each supported enclave technology. The `EnclaveClient` class defines\nseveral methods for entering an enclave. Enclave exits, on the other hand, are\nimplicit—they either happen automatically when an enclave entry finishes its\nwork, or they happen when an enclave requests services from the operating\nsystem.\n\nOf the various enclave-entry methods defined by the `EnclaveClient` interface,\nthree are of particular interest to Asylo users:\n\n*   `EnterAndInitialize`: This method takes an `EnclaveConfig` message\n    containing basic enclave configuration settings and passes it to the\n    enclave. This is a private method, and is implicitly invoked by the Asylo\n    framework when an enclave binary image is loaded.\n*   [`EnterAndRun`](https://asylo.dev/doxygen/classasylo_1_1EnclaveClient.html#enter-and-run):\n    This method takes an `EnclaveInput` message, passes it to the enclave, which\n    can populate the `EnclaveOutput` result. The `EnclaveInput` and\n    `EnclaveOutput` messages can be extended with\n    [protobuf extensions](https://developers.google.com/protocol-buffers/docs/proto#extensions)\n    by the developer to meet the data-processing requirements of the\n    application. This method is a public method, and may be called an arbitrary\n    number of times with different inputs after the enclave is initialized.\n*   `EnterAndFinalize`: This method takes an `EnclaveFinal` message, which may\n    contain any information needed by the enclave for finalization, and passes\n    that message to the enclave just before it is destroyed. This method is also\n    a private method of the `EnclaveClient` class, and is implicitly invoked by\n    the Asylo framework on enclave tear-down.\n\nEach `EnclaveClient` is associated with exactly one enclave, and the Asylo\nframework forwards calls to the above `EnclaveClient` methods to appropriate\nenclave methods on the corresponding `TrustedApplication` instance, which can be\noverridden by the enclave developer.\n\nThe `TrustedApplication` interface declares methods corresponding to the three\nentry methods defined by the `EnclaveClient` abstract class:\n\n*   [`Initialize`](https://asylo.dev/doxygen/classasylo_1_1TrustedApplication.html#initialize):\n    This method takes an `EnclaveConfig` message from\n    `EnclaveClient::EnterAndInitialize`, and initializes the enclave with the\n    configuration settings in the `EnclaveConfig`.\n*   [`Run`](https://asylo.dev/doxygen/classasylo_1_1TrustedApplication.html#run):\n    This method takes an `EnclaveInput` message from\n    `EnclaveClient::EnterAndRun`, populates an `EnclaveOutput` message, and\n    performs trusted execution.\n*   [`Finalize`](https://asylo.dev/doxygen/classasylo_1_1TrustedApplication.html#finalize):\n    This method takes an `EnclaveFinal` message from\n    `EnclaveClient::EnterAndFinalize`, and prepares the enclave for destruction.\n\n## Enclave lifecycle\n\nEntering an enclave is analogous to making a system call. The enclave entry\npoint represents a gateway to protected code with access to the enclave's\nresources. Arguments are copied into the enclave's protected memory on entry and\nresults are copied out on exit.\n\n```cpp\nABSL_FLAG(std::string, enclave_path, \"\",\n          \"Path to enclave binary image to load\");\nABSL_FLAG(std::string, message, \"\", \"Message to encrypt\");\n\nint main(int argc, char *argv[]) {\n  absl::ParseCommandLine(argc, argv);\n\n  constexpr char kEnclaveName[] = \"demo_enclave\";\n\n  const std::string message = absl::GetFlag(FLAGS_message);\n  LOG_IF(QFATAL, message.empty()) \u003c\u003c \"Empty --message flag.\";\n\n  const std::string enclave_path = absl::GetFlag(FLAGS_enclave_path);\n  LOG_IF(QFATAL, enclave_path.empty()) \u003c\u003c \"Empty --enclave_path flag.\";\n\n  // Part 1: Initialization\n\n  // Prepare |EnclaveManager| with default |EnclaveManagerOptions|\n  asylo::EnclaveManager::Configure(asylo::EnclaveManagerOptions());\n  auto manager_result = asylo::EnclaveManager::Instance();\n  LOG_IF(QFATAL, !manager_result.ok()) \u003c\u003c \"Could not obtain EnclaveManager\";\n\n  // Prepare |load_config| message.\n  asylo::EnclaveLoadConfig load_config;\n  load_config.set_name(kEnclaveName);\n\n  // Prepare |sgx_config| message.\n  auto sgx_config = load_config.MutableExtension(asylo::sgx_load_config);\n  sgx_config-\u003eset_debug(true);\n  auto file_enclave_config = sgx_config-\u003emutable_file_enclave_config();\n  file_enclave_config-\u003eset_enclave_path(enclave_path);\n\n  // Load Enclave with prepared |EnclaveManager| and |load_config| message.\n  asylo::EnclaveManager *manager = manager_result.ValueOrDie();\n  auto status = manager-\u003eLoadEnclave(load_config);\n  LOG_IF(QFATAL, !status.ok()) \u003c\u003c \"LoadEnclave failed with: \" \u003c\u003c status;\n\n  // Part 2: Secure execution\n\n  // Prepare |input| with |message| and create |output| to retrieve response\n  // from enclave.\n  asylo::EnclaveInput input;\n  SetEnclaveUserMessage(\u0026input, message);\n  asylo::EnclaveOutput output;\n\n  // Get |EnclaveClient| for loaded enclave and execute |EnterAndRun|.\n  asylo::EnclaveClient *const client = manager-\u003eGetClient(kEnclaveName);\n  status = client-\u003eEnterAndRun(input, \u0026output);\n  LOG_IF(QFATAL, !status.ok()) \u003c\u003c \"EnterAndRun failed with: \" \u003c\u003c status;\n\n  // Part 3: Finalization\n\n  // |DestroyEnclave| before exiting program.\n  asylo::EnclaveFinal empty_final_input;\n  status = manager-\u003eDestroyEnclave(client, empty_final_input);\n  LOG_IF(QFATAL, !status.ok()) \u003c\u003c \"DestroyEnclave failed with: \" \u003c\u003c status;\n\n  return 0;\n}\n```\n\nThe three enclave entry points are shown in the above code. Let's go through\neach part of the code.\n\n### Part 1: Initialization\n\nThe untrusted application performs the following steps to initialize the trusted\napplication:\n\n1.  Configures an instance of `EnclaveManager` with default options. The\n    `EnclaveManager` handles all enclave resources in an untrusted application.\n2.  Configures a `EnclaveLoadConfig` object to specify options for the\n    SgxLoadConfig to fetch the enclave binary image from disk.\n3.  Calls `EnclaveManager::LoadEnclave` to bind the enclave to the name `\"demo\n    enclave\"`. This call implicitly invokes the enclave's `Initialize` method.\n\n### Part 2: Secure execution\n\nThe untrusted application performs the following steps to securely execute a\nworkload in the trusted application:\n\n1.  Provides arbitrary input data in an `EnclaveInput`. This example uses a\n    single string protobuf extension to the `EnclaveInput` message. This\n    extension field is used to pass data to the enclave for encryption.\n2.  Gets a handle to the enclave via `EnclaveManager::GetClient`.\n3.  Invokes the enclave by calling `EnclaveClient::EnterAndRun`. This method is\n    the primary entry point used to dispatch messages to the enclave. It can be\n    called an arbitrary number of times.\n4.  Receives the result from the enclave in an `EnclaveOutput`. Developers can\n    add protobuf extensions to the `EnclaveOutput` message to provide arbitrary\n    output values from their enclave.\n\n### Part 3: Finalization\n\nThe untrusted application performs the following steps to finalize the trusted\napplication:\n\n1.  Provides arbitrary finalization data to the enclave and destroys the enclave\n    via `EnclaveManager::DestroyEnclave`.\n2.  Runs the enclave's `Finalize` method. The Asylo framework performs this step\n    implicitly during enclave destruction.\n\n## Writing an enclave application\n\nWe just saw how to initialize, run, and finalize an enclave using the Asylo\nframework. These calls happened on the untrusted side of the enclave boundary.\nNow, let us take a look at the code on the trusted side.\n\n```cpp\nconstexpr size_t kMaxMessageSize = 1 \u003c\u003c 16;\n\n// Dummy 128-bit AES key.\nconstexpr uint8_t kAesKey128[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05,\n                                  0x06, 0x07, 0x08, 0x09, 0x10, 0x11,\n                                  0x12, 0x13, 0x14, 0x15};\n\n// Encrypts a message against `kAesKey128` and returns a 12-byte nonce followed\n// by authenticated ciphertext, encoded as a hex string.\nconst StatusOr\u003cstd::string\u003e EncryptMessage(const std::string \u0026message) {\n  std::unique_ptr\u003cAeadCryptor\u003e cryptor;\n  ASYLO_ASSIGN_OR_RETURN(cryptor,\n                         AeadCryptor::CreateAesGcmSivCryptor(kAesKey128));\n\n  std::vector\u003cuint8_t\u003e additional_authenticated_data;\n  std::vector\u003cuint8_t\u003e nonce(cryptor-\u003eNonceSize());\n  std::vector\u003cuint8_t\u003e ciphertext(message.size() + cryptor-\u003eMaxSealOverhead());\n  size_t ciphertext_size;\n\n  ASYLO_RETURN_IF_ERROR(cryptor-\u003eSeal(\n      message, additional_authenticated_data, absl::MakeSpan(nonce),\n      absl::MakeSpan(ciphertext), \u0026ciphertext_size));\n\n  return absl::StrCat(BytesToHexString(nonce), BytesToHexString(ciphertext));\n}\n\nclass EnclaveDemo : public TrustedApplication {\n public:\n  EnclaveDemo() = default;\n\n  Status Run(const EnclaveInput \u0026input, EnclaveOutput *output) {\n    std::string user_message = GetEnclaveUserMessage(input);\n    std::string result;\n    ASYLO_ASSIGN_OR_RETURN(result, EncryptMessage(user_message));\n    std::cout \u003c\u003c \"Encrypted message:\" \u003c\u003c std::endl \u003c\u003c result \u003c\u003c std::endl;\n    return Status::OkStatus();\n  }\n\n  const std::string GetEnclaveUserMessage(const EnclaveInput \u0026input) {\n    return input.GetExtension(guide::asylo::enclave_input_demo).value();\n  }\n};\n```\n\nThe above snippet defines a class `EnclaveDemo`, which derives from\n`TrustedApplication`, and implements the enclave's secure execution logic in its\n`Run` method. This method encrypts the input message and prints the resulting\nciphertext.\n\nThe `TrustedApplication` base class provides default implementations for the\n`Initialize`, `Run`, and `Finalize` methods. The enclave author is expected to\noverride these methods as needed to implement their enclave's logic. As\ndemonstrated in this example, an enclave author typically would override the\n`TrustedApplication::Run` method to provide the core logic for their enclave,\nand use that method to interact with their enclave. Alternatively, the enclave\nauthor may launch an RPC server (e.g., a gRPC server) in the\n`TrustedApplication::Initialize` method, and then interact with their enclave\nvia RPCs. In this case, the developer may choose not to override the\n`TrustedApplication::Run` method. The Asylo framework is flexible, and allows\ndevelopers to use enclaves in a way that is most suitable to their needs.\n\n## Building and running an enclave application\n\nTo build our enclave application, we define several targets that utilize a\nsimulated backend. See the\n[overview](https://asylo.dev/about/overview.html#security-backends) for details\non all supported backends.\n\n```python\nproto_library(\n    name = \"demo_proto\",\n    srcs = [\"demo.proto\"],\n    deps = [\"@com_google_asylo//asylo:enclave_proto\"],\n)\n\ncc_proto_library(\n    name = \"demo_cc_proto\",\n    deps = [\":demo_proto\"],\n)\n\ncc_unsigned_enclave(\n    name = \"demo_enclave_unsigned.so\",\n    srcs = [\"demo_enclave.cc\"],\n    copts = ASYLO_DEFAULT_COPTS,\n    deps = [\n        \":demo_cc_proto\",\n        \"@com_google_absl//absl/base:core_headers\",\n        \"@com_google_absl//absl/strings\",\n        \"@com_google_asylo//asylo:enclave_runtime\",\n        \"@com_google_asylo//asylo/crypto:aead_cryptor\",\n        \"@com_google_asylo//asylo/util:cleansing_types\",\n        \"@com_google_asylo//asylo/util:status\",\n    ],\n)\n\ndebug_sign_enclave(\n    name = \"demo_enclave.so\",\n    unsigned = \"demo_enclave_unsigned.so\",\n)\n\nenclave_loader(\n    name = \"quickstart\",\n    srcs = [\"demo_driver.cc\"],\n    enclaves = {\"enclave\": \":demo_enclave.so\"},\n    loader_args = [\"--enclave_path='{enclave}'\"],\n    deps = [\n        \":demo_cc_proto\",\n        \"@com_google_absl//absl/flags:flag\",\n        \"@com_google_absl//absl/flags:parse\",\n        \"@com_google_asylo//asylo:enclave_client\",\n        \"@com_google_asylo//asylo/util:logging\",\n    ],\n)\n```\n\nThe [Bazel](https://bazel.build) BUILD file shown above defines our enclave's\nlogic in a `cc_unsigned_enclave` called `demo_enclave_unsigned.so`. This target\ncontains our implementation of `TrustedApplication` and is linked against the\nAsylo runtime. We use a `debug_sign_enclave` rule to generate an enclave that\nhas been signed with a debug key, and can be run in supported backends (e.g.,\nSGX simulation mode or on SGX hardware in debug mode).\n\nThe untrusted component is the target `:quickstart`, which contains code to\nhandle the logic of initializing, running, and finalizing the enclave, as well\nas sending and receiving messages through the enclave boundary. In a non-enclave\napplication, we would write `:quickstart` as a *cc_binary* target, but the\n`enclave_loader` rule streamlines the combination of driver and enclave targets.\nSpecifically, it ensures that *demo_driver.cc* is compiled with the host\ncrosstool, `:demo_enclave` is compiled with the enclave-backend-specific\ncrosstool, and that the untrusted enclave loader is invoked with a flag that\nspecifies the enclave's path.\n\nLet us now run the demo enclave inside the Docker image we downloaded\n[above](#getting-started-with-the-example-code). You can set the `--message`\nflag passed to the `//quickstart:quickstart_sgx_sim` target to contain any\nstring that you would like to encrypt.\n\nNote: The following command runs the enclave in simulation mode.\n\n```bash\ndocker run -it --rm \\\n    -v bazel-cache:/root/.cache/bazel \\\n    -v \"${MY_PROJECT}\":/opt/my-project \\\n    -w /opt/my-project \\\n    gcr.io/asylo-framework/asylo \\\n    bazel run //quickstart:quickstart_sgx_sim -- --message=\"Asylo Rocks\"\nEncrypted message:\n2dc402068266ba995608e0d4a16c1604b792355d4635dec43cf2888cf2036d2007772ed5f24e5c\n```\n\nCongratulations on building and running your first enclave application!\n\n## Further exercises\n\nNow you know enough about Asylo to begin modifying an enclave application. Here\nare some things to try:\n\n*   Note that our current example does not make use of the `output` variable\n    passed to `EnterAndRun`. Use `SetEnclaveOutputMessage` in `demo_enclave.cc`,\n    and `GetEnclaveOutputMessage` in `demo_driver.cc`, to return the encrypted\n    message from the enclave to the driver, and print it there. The application\n    output should remain unchanged.\n*   The `EnterAndRun` function can be called multiple times once the enclave is\n    initialized. Modify `demo_driver.cc` to add another call to `EnterAndRun`,\n    in order to re-enter enclave with a different message to encrypt.\n*   Use\n    [protobuf extensions](https://developers.google.com/protocol-buffers/docs/proto#extensions)\n    in the `EnclaveInput` message to support sending ciphertext into the enclave\n    for decryption, using the provided `DecryptMessage` function.\n\nA sample\n[solution](/quickstart/solution)\nis available on GitHub.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkeplerc%2Fparanoid-sgx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkeplerc%2Fparanoid-sgx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkeplerc%2Fparanoid-sgx/lists"}