Skip to content

Security guarantees

The Microservice Encryption solution guarantees to each participant that:

  • they are actually running the computation on a secure hardware enclave (and not some simulator)
  • the operator of the enclave (Cosmian on its public platform) has not tampered with any parameter of the computation
  • their code/data can only be read by the secure enclave, neither its operator, nor its hoster (Azure on the public platform), nor any other participant
  • the list of participants is correct (number and identities)
  • the code provided by the Code Provider has the expected signature
  • the rest of the software stack is correct and correctly identified (hence verifiable)

The security protocol and cryptographic primitives used to achieve these goals are described in the next paragraphs

Protocol Overview

On the Cosmian public platform:

  1. The Computation Owner (CO) creates the computation with the list of all participants emails. The CO also generates 3 words from the BIP39 list: the pre-shared secret. The CO sends these words to the other participants and only them (the pre-shared secret gives access to the computation).

  2. All participants, Code Provider (CP), Data Providers (DP) and Result Consumers (RC) create a Cosmian account, generate an asymmetric key pair and register their public key to Cosmian.

  3. The CP generates a symmetric key and send its code encrypted with it.

    As soon as every participant has registered and the CP has sent the code, Cosmian starts the secure enclave, which generates the enclave identity (an asymmetric key pair to secure the key exchange and some other parts allowing to check that the computation is secured by an Intel SGX enclave)

  4. The CP, DP and RC verify the manifest and its signatures:

    • the list of participants is coherent
    • the enclave has not been tampered (attesting Cosmian is using real hardware enclave and has not been tampered with any parameters)

Then the participants send their symmetric keys and the pre-shared secret (sealed with the public key of the secure enclave) and sign it with their private key (the one from the asymmetric key pair).

At this step, only the secure enclave can decrypt the symmetric keys (used for code and data decryption, or results encryption).

The secure enclave also checks: - for the seal box signature - that all participants share the same pre-shared secret: if one participant doesn’t have the same pre-shared secret, the enclave will refuse to run the computation.

> As soon as all participant symmetric keys have been provisioned to the enclave, Cosmian starts automatically the computation.
  1. All participants can check the status of the computation (exit code, stdout and stderr). If the computation is successful, the RC downloads the results and decrypts them locally with its symmetric key.

When not on the public platform, or when Cosmian is not the operator of the enclave, the process is identical save from the registration step on the public platform.

Flow diagram


Enclave Identity

As soon as every participant has registered and the CP has sent the code the enclave identity is generated. The enclave identity is available inside the Computation object of the Cosmian clients (see examples as Code Provider, Data Provider or as Result Consumer).

This identity is unique and ensure the participants that the code is running inside the Intel SGX enclave.

If the code change, the identity change

In case the code need to change (because of a problem or any other reason), the identity will be reset and re-generated. Every participant will need to check again the validity of the information and send back their symmetric keys sealed with the new public key.

Enclave Public key

The enclave public key allows participants to send their symmetric keys knowing that Cosmian or any other third-parties cannot read it. Their symmetric keys can only be decrypted inside the enclave to read the code/data or encrypt the results.

Enclave Manifest

The enclave manifest lists all the binaries and libraries with corresponding signatures running on the enclave, including the secret code of the CP. The manifest is signed by the enclave (see quote) and guarantees what is actually running for this computation.

entrypoint = \"file:/usr/lib/x86_64-linux-gnu/gramine/\"
log_level = \"error\"
argv_src_file = \"file:scripts/args\"
pal_internal_mem_size = \"128M\"
preload = \"\"

entrypoint = \"/usr/bin/python3.8\"

nonpie_binary = true
remote_attestation = true
enclave_size = \"16G\"
thread_num = 256
allowed_files = [ \"file:/tmp\", \"file:data/\", \"file:result/\",]
isvprodid = 0
isvsvn = 0
debug = false
require_avx = false
require_avx512 = false
require_mpx = false
require_pkru = false
require_amx = false
support_exinfo = false
enable_stats = false
uri = \"file:/usr/bin/python3.8\"
sha256 = \"2e833afd6114ff314d879486c01ec19d3d94ef6f8c808d193fb329c98c674097\"

uri = \"file:/usr/lib/x86_64-linux-gnu/gramine/\"
sha256 = \"71b1ae48299dcdad622c5e32d910bb6aa6d457a79eca9b4824031ecb338c9512\"

uri = \"file:/usr/lib/x86_64-linux-gnu/gramine/runtime/glibc/crt1.o\"
sha256 = \"b3776343a45a120f700a5d19c0cf9b5caf185707770cb7d269326f0389eaf3de\"


uri = \"file:/usr/lib/python3.8/\"
sha256 = \"c653077012c19153838cae221f1ac73ecef8bcfc49e25e54c6bc7b187e18185f\"

uri = \"file:/usr/lib/python3.8/\"
sha256 = \"60006f906a2aad59a81a4e4e0ca36b69088848623edc8598c0b2a41d9f30565d\"

uri = \"file:/usr/lib/python3.8/\"
sha256 = \"8fe91980080cc3f3d687bfa4078489ebe25fb28005170a8232a3eee75f94d3b4\"

uri = \"file:/usr/lib/python3.8/\"
sha256 = \"37defeb4f5df6b41c62d8bcedab2f4bea24a2c2cc97f70e08c81e0ef17888246\"

 [many, many more lines]


The quote from the enclave is attested using a remote attestation process, guaranteeing that it is actually signed by a valid SGX enclave (and not some simulator).

    "exp": 1651104032,
    "iat": 1651075232,
    "is-debuggable": "False,",
    "iss": "https: //",
    "jti": "c0af5cf6f3116e7f6b668f362842268f7fdf925a405d17d48f67a84f891cf3bb",
    "maa-attestationcollateral": {
        "qeidcertshash": "a64d649198507d8b57e33f63ab266838f43f327bd4aacc78510b6976ed046e10",
        "qeidcrlhash": "3dbcd25597ba0548bf32240b3079d4310151756f17e5537d3015b16e399acad5",
        "qeidhash": "7701f64700b7f505d7b4b7a93e45d5cde8cfc865b60f1dd49ecbee9790c3372e",
        "quotehash": "0c330dd9b79d10228fa12c35a27062a8c9c5f73bf30f3be0cbd9bd34d2292754",
        "tcbinfocertshash": "a64d649198507d8b57e33f63ab266838f43f327bd4aacc78510b6976ed046e10",
        "tcbinfocrlhash": "3dbcd25597ba0548bf32240b3079d4310151756f17e5537d3015b16e399acad5",
        "tcbinfohash": "88149197195950562cc097ad0267a66de7c08e0189bddeb3977d8e2b6a05fd45"
    "nbf": 1651075232,
    "product-id": 0,
    "sgx-mrenclave": "929f66c365fce9ebcd2e6a809f938b4305dfc2f9094a6b726e3e2b6abe9413a7",
    "sgx-mrsigner": "c1c161d0dd996e8a9847de67ea2c00226761f7715a2c422d3012ac10795a1ef5",
    "svn": 0,
    "tee": "sgx",
    "x-ms-attestation-type": "sgx",
    "x-ms-policy": {
        "is-debuggable": "False,",
        "product-id": 0,
        "sgx-mrenclave": "929f66c365fce9ebcd2e6a809f938b4305dfc2f9094a6b726e3e2b6abe9413a7",
        "sgx-mrsigner": "c1c161d0dd996e8a9847de67ea2c00226761f7715a2c422d3012ac10795a1ef5",
        "svn": 0,
        "tee": "sgx"
    "x-ms-policy-hash": "bROrN897ZfWmWY2V0FLUlu3uwk5xatGnKYHn3zBbSlw",
    "x-ms-sgx-collateral": {
        "qeidcertshash": "a64d649198507d8b57e33f63ab266838f43f327bd4aacc78510b6976ed046e10",
        "qeidcrlhash": "3dbcd25597ba0548bf32240b3079d4310151756f17e5537d3015b16e399acad5",
        "qeidhash": "7701f64700b7f505d7b4b7a93e45d5cde8cfc865b60f1dd49ecbee9790c3372e",
        "quotehash": "0c330dd9b79d10228fa12c35a27062a8c9c5f73bf30f3be0cbd9bd34d2292754",
        "tcbinfocertshash": "a64d649198507d8b57e33f63ab266838f43f327bd4aacc78510b6976ed046e10",
        "tcbinfocrlhash": "3dbcd25597ba0548bf32240b3079d4310151756f17e5537d3015b16e399acad5",
        "tcbinfohash": "88149197195950562cc097ad0267a66de7c08e0189bddeb3977d8e2b6a05fd45"
    "x-ms-sgx-is-debuggable": "False,",
    "x-ms-sgx-mrenclave": "929f66c365fce9ebcd2e6a809f938b4305dfc2f9094a6b726e3e2b6abe9413a7",
    "x-ms-sgx-mrsigner": "c1c161d0dd996e8a9847de67ea2c00226761f7715a2c422d3012ac10795a1ef5",
    "x-ms-sgx-product-id": 0,
    "x-ms-sgx-report-data": "21be4c8ec9c488fa0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "x-ms-sgx-svn": 0,
    "x-ms-ver": "1.0"

Serialized Args

The serialized arguments are sent to the gramine process and read inside the enclave. They contain all the fingerprints of the participants’ public keys. The participants can check the number of fingerprints and match these to the public PGP keys of the participants to ensure Cosmian didn’t add or remove participants from the computation.

Serialized Args binary format

The arguments are serialized for Gramine in binary, they can be difficult to parse so the Cosmian client will provide helpers to check the content. Feel free to create your own parser if you need to do your own checks.


The entrypoint is the only unencrypted file from the code provider. His goal is to read the data, run the encrypted algorithm and save the results. Every participant can see this file and check that only authorized actions are performed. For example:

  • checking that Cosmian didn’t change the entrypoint to leak the data (thanks to the entrypoint hash inside the manifest)

Cryptographic Primitives

Most of the cryptographic primitives used are those from the NaCl-family: X25519 (RFC 7748) for Elliptic Curve Diffie-Hellman (ECDH) Key Exchange, Ed25519 (RFC 8032) for Digital Signature and XSalsa20-Poly1305 (RFC 7539) for Authenticated Encryption with Associated Data (AEAD).

Public Key Primitives

X25519 and ed25519 are based on Curve25519 using the Montgomery curve for the former and the bi-rationnally equivalent twisted Edwards curve for the latter.

Both forms have ~128-bit security level with 256-bit private/public key (see RFC 7748#section-4.1).

Symmetric Primitives

XSalsa20 symmetric-key stream cipher uses 256-bit key and 192-bit nonce (XSalsa20 is an extension of Salsa20 to use 192-bit nonce instead of the 64-bit nonce). The implementation used in crypto_box NaCl-family is using 20 rounds and offers ~251-bit security according to the best cryptanalysis technique as of 2021 (see draft-josefsson-salsa20-tls-04#security).

In addition, Poly1305 Message-Authentication Code (MAC) with 256-bit key is used to obtain the XSalsa20-Poly1305 AEAD algorithm.


The tree dependency of the software implemented in Cosmian Microservice Encryption solution is the following:

Server      cosmian_lib_sgx [Python]
            ├── cosmian_sgx_crypto [C]
            │   ├── libsodium [C]
            │   └── Intel SGX instructions [ASM]
Client      cosmian_secure_computation_client [Python]
            ├── pynacl [Python]
            │   └── libsodium [C]

The server library cosmian_lib_sgx must be used by the CP in the Python code to manage I/O and cryptographic operations while the client librarycosmian_secure_computation_client is meant to be used by every participants (CP, DP and RC).

Software Stack

Secure enclaves such as Intel SGX© (Software Guard eXtension) are hardware technology designed to keep running processes memory data encrypted at anytime in a secure memory part. In that way, no malicious user, even with root privileges on the machine, can dump the memory process to steal the content.

We rely on the Gramine library OS (owned by Intel) to execute arbitrary Python code inside Intel SGX and it forces us to keep a consistent base software stack:

  • Ubuntu 20.04 LTS
  • Linux kernel >= 5.11
  • Gramine == v1.1
  • Intel SGX SDK >= 2.15.1
  • Intel SGX DCAP >= 1.12
  • Azure DCAP client >= 1.10 (for Microsoft Azure)

We currently offer to run secure computations on OVH where Intel SGX 2 is available. Other providers will be available soon.

© Copyright 2018-2022 Cosmian. All rights reserved