Quickstart

Secure Computation.

Integrate privacy-preserving computation in your JavaScript client apps with speed and efficiency.

Our JavaScript SDK allows you to focus on the client-side implementation of privacy-preserving computation, which amounts to sending protected user data to our API and reporting the results to the user. On the server side, Enya and our SDK ensures reliable infra management and security.
This Quickstart gives a brief overview of the SDK and walks you through the steps of using the SDK in your own project. We will focus on Secure Multi-party Computation (SMC) in this Quickstart - there is another approach called Fully Homomorphic Encryption (FHE), which you can learn more about elsewhere in the documentation.
  • 1
    Install the SDK
    Step 1: Obtain your access tokens and the SDK
    Email support@enya.ai to request your secret tokens and the SDK. You will receive a MASTER_TOKEN and a CLIENT_TOKEN - the MASTER_TOKEN is used to configure the back-end (e.g. to configure your algorithms). The CLIENT_TOKEN allows your app to access the Enya servers. Please keep the tokens safe do not share your tokens with others - a typical security mistake is to hard-code tokens into code that is then made available through a public github repo. If you lose your tokens or they have been compromised, please contact us and we will send you new ones.
  • 2
    Your First Secure Computation
    The Enya SDK makes privacy-preserving computation effortless and straightforward. There are only a few simple steps to computing your first result:
    Step 1: Your First Secure Computation
    After installing the SDK, use algo_add.py to name and parametrize your linear algorithm. This Python script is located in the /enyasmc/utility_client folder. Assuming your master token is c8b85fcc3c3a13673251e109, you wish to call your algorithm 'MyFirstAlgo', you have three coefficients, and you have decided to use secure multi-party computation, run
    # algo_add.py [-h] -s MASTER_TOKEN -n ALGO_NAME -t ALGO_TYPE (='smc'|'fhe') -c COEFFICIENT
    python3 algo_add.py -s c8b85fcc3c3a13673251e109 -n MyFirstAlgo -t smc -c [1, 0.1, 1]
    Your coefficients are stored securely and can't be accessed by others. Note that algo_add.py needs the requests module to run. Make sure to install it (e.g. with pip) before running the script.

    After adding your algorithm, you can use algo_list.py to check your algorithm.
    # algo_list.py [-h] -s MASTER_TOKEN
    python3 algo_list.py -s master_token
    algo_list.py returns all configured algorithms, each identified via a unique id. You can use algo_delete.py to delete algorithms that you no longer need using their unique ids.
    # algo_delete.py [-h] -s MASTER_TOKEN -i ALGO_ID
    python3 algo_delete.py -s master_token -i algo_id
    Step 2: Configure the SDK in the Client App
    Specifiy your CLIENT_TOKEN and algo_name to configure the SDK.
    import EnyaSMC from 'enyasmc';

    EnyaSMC.Configure({
     CLIENT_TOKEN: "f7edB8a8A4D7dff85d2CB7E5",
     algo_name: "MyFirstAlgo"
    })
    Step 3: Provide the Client Data
    // if the data are in array form
    const
    user_data_array = [number, number, number, ...];
    EnyaSMC.input(user_data_array);

    // if the data are provided as an object
    const user_data_object = {data_1: number, data_2: number, data_3: number, ...};
    EnyaSMC.input(Object.values(user_data_object));
    Make sure that the length of client data vector is the same as the number of terms you configured for your algorithm, otherwise the computation will return an error.
    // example of well formed inputs and settings
    client_input           = [  1, 23,   3, 0.7,   5, 0.4] // (sent by the app)
    algorithm_coefficients = [0.1,  2, 0.1,  19, 0.8,   9] // (specified when configuring the compute back end)
    Step 4: Compute
    Finally, compute and get the result:
    //EnyaSMC.Linear() returns the inner product of the client vector and the algorithm_coefficients.
    EnyaSMC.Linear()
    Note: This method is asynchronous. Use promises to handle the asynchronous result of the operation. Suitable example code is:
    EnyaSMC.Linear().then(function(result{
     
    console.log(result)
    }))
  • 3
    The Computation Result
    The EnyaSMC.Linear() function returns the result of the computation and various status flags which can be used to determine whether the calculation was successful.
    /* Successful */
    {
    secure_result: dot_product_final, status_code: 200}
    /* Failed */
    {
    status_code: 404}
    The status code of a successful computation is 200 and of a failed computation is 404. Calculations may fail due to setting errors (see error messages). Additional information about algorithm settings is given here.
Algorithms

Our JavaScript SDK allows you to use either Secure Multi-party Computation (SMC)

or Fully Homomorphic Encryption (FHE) to privately compute on sensitive data. For example, using SMC, a patient can learn about their disease risks without ever needing to send unprotected sensitive data to a doctor. Similarly, using FHE, a consumer can learn about financial products relevant to them without needing to share unencrypted financial data with a lender.
  • 1
    SMC or FHE?
    The table below covers some of the major differences between the two methods and helps you to pick the right one for you. High level - if your application is very sensitive to running time or you would like to provide a good user experience even on older phones, consider SMC. Otherwise, we recommend FHE.
    #
    FHE
    SMC
    Key Generation
    4 keys
    No keys
    Coefficients
    Integer
    Float
    Number of API Requests
    3
    7
    Speed
    50 Seconds
    5 Seconds
    Security
    FHE is more secure than SMC
    FHE is more secure than SMC
  • 2
    Secure Multi-party Computation (SMC)
    In SMC, there are generally three or more parties, all with distinct roles.

    Party 1 - The User enters (or otherwise provides) data and clicks 'compute'. After some delay - a few seconds - the result of the computation is displayed to them.

    Party 2 - The Algorithm Provider provides an algorithm, such as a linear function with N terms (and therefore N coefficients). From a developer perspective, you need to name your algorithm and specify its coefficients (on the API side) and configure and call our API (on the client side).

    Party 3 - The Random Number Provider provides special pairs of random numbers to the other parties. Using these random numbers and by sharing computation intermediates, the edge client (and/or the algorithm provider) can ultimately see the final result. In this type of computation, no party shares unprotected information with the other parties. For more details, see our Technology page.

    Here is what happens under the hood. After receiving inputs from the App user, EnyaSMC.Linear() requests random numbers, splits inputs, mixes the random numbers with the inputs, and shares some of the resulting values with the algorithm provider. That party also obtains random numbers and uses them to protect their secrets, in this case, their algorithm coefficients. To learn more, here is the 1991 publication on Beaver Triples (Efficient Multi-party Protocols Using Circuit Randomization).

    Notes: SMC requires far less computation client-side since it does not involve traditional key generation, except for needing Beaver Triples (which can be precomputed). However, compared to FHE, SMC involves multiple cycles of secret sharing with multiple servers and is therefore more dependent on reliable networking.
  • 3
    SMC - Algorithms / Notes
    We currently support simple linear functions on input data vectors. For example, a suitable linear function could be obtained through a linear regression on training data. Assuming your algorithm is

    f(y)=β1×x1+β2×x2+β3×x3+β4×x4,

    then your algorithm coefficients and user inputs would be

    [β1,β2,β3,β4] and [x1,x2,x3,x4],

    respectively. To give a specific example, imagine your algorithm is

    f(y)=0.3×x1+6×x2+0.34×x3+9×x4,

    then your algorithm coefficients would be [0.3,6,0.34,9]. As explained in the Quickstart, you can use algo_add.py to give your linear algorithm a convenient name (e.g. "CreditScore", "DiseaseRisk", or "LifeExpectancy") and specify the number of terms and its coefficients. In this example, when running algo_add.py you would set the model coefficients to '[0.3, 6, 0.34, 9]'. See Quickstart to learn more.

    There are several other considerations:
    1
    There is no limitation on the number of algorithm coefficients.
    2
    There is a limitation on the absolute magnitude of inputs, coefficients, and the results. If you have a coefficient such as β×1015​ and an inputs such as x×10−5, consider balancing them (i.e. β×105 and x×105) to facilitate calculations. Likewise, when your calculations might return values greater than 1015, consider reformulating the inputs and the algorithm coefficients - you can always multiply the computation results on the App side by a suitable factor before using the returned values.
    3
    The value of the optimal bitlength scales with the values of the input coefficients and the largest value of it is 10. Any positive integer can be used, but excessive bitlengths might cause errors by exceeding make numbers larger than the safe integers in JavaScript and cause errors. The default value should handle most calculations.
  • 4
    Fully Homomorphic Encryption (FHE)
    We use the BFVrns FHE scheme, which can can encrypt and decrypt all-integer vectors. FHE requires at least four keys (which must first be generated) and uses one of those keys (the public key) to encrypt the data. Once encrypted, FHE sends the ciphertext and compute authorization keys to the server and then checks for completion of the computation. Upon completion of the calculation, the SDK retrieves the result and decrypts it. FHE is generally more secure than SMC, since fewer parties are involved (typically only two) and all security relevant operations are executed client side. SMC involves at least three parties and the entire system can be jeopardized by a dishonest Beaver Triple provider. By contrast, in FHE, only lattice-crypto secured data leave the phone and therefore, even a malicious data recipient cannot see the sensitive data.
  • 5
    FHE - Algorithms / Notes
    Our test environment is React Native running on current phone hardware, such as an iPhone X, iPhone 11, or Samsung Galaxy Note 10. The actual FHE execution time will vary across devices and test environments. On an iPhone 11, FHE needs about 40 seconds to generate the four required keys (private key, public key, multiplication key, rotation key) - this process involves generating a large number of random integers. Since the heavy computation would otherwise block the UI, we use the next-frame package to maintain UI responsiveness during key generation.
FHE API

This document introduces the core FHE (Fully Homomorphic Encryption) API

and helps you to build FHE solutions. Each calculation requires several steps and function calls, but each call requires only rudimentary configuration.
  • 1
    Algorithm Configuration
    After installing the FHE SDK (enyafhe), use algo_add.py to name and parametrize your algorithm. This Python script is located in the enyafhe/utility_client folder. Provide your MASTER_TOKEN as one of the command line arguments. Note that the coefficients must all be integers.
    # algo_add.py [-h] -s MASTER_TOKEN -n ALGO_NAME -t ALGO_TYPE -c COEFFICIENT
    python3 algo_add.py -s master_token -n algo_name -t fhe -c [int, int, int]
    # example
    python3 algo_add.py -s '5b745EDBb3f55ab7A12F9bf7' -n 'test' -t 'fhe' -c '[0,1,9,4,1,6,0,123]'
    After setting your algorithm, you can use algo_list.py to check it and to list other algorithms you have set in the back end:
    # algo_list.py [-h] -s MASTER_TOKEN
    python3 algo_list.py -s master_token
    # example
    python3 algo_list.py -s '5b745EDBb3f55ab7A12F9bf7'
    algo_list.py returns all configured algorithms, their names, and their unique id. You can use algo_delete.py to delete algorithms via their unique id:
    # algo_delete.py [-h] -s MASTER_TOKEN -i ALGO_ID
    python3 algo_delete.py -s master_token -i algo_id
    # example
    python3 algo_delete.py -s '5b745EDBb3f55ab7A12F9bf7' -i '1581966285575-52abd00f'
  • 2
    Client Configuration
    import EnyaFHE from 'enyafhe';

    // Configure()
    EnyaFHE.Configure({
     CLIENT_TOKEN: "f7edB8a8A4D7dff85d2CB7E5", //your client token
     algo_name: "test"                       //the algorithm you defined in the back end})
    We provide a high-level EnyaFHE.FHE() function that should handle many use cases without extra configuration. Just follow this example:
  • 3
    Simple Usage
    Use the Configure function to set the client token and the algorithm name.
    import EnyaFHE from 'enyafhe';

    // Configure EnyaFHE...
    EnyaFHE.Configure({CLIENT_TOKEN: "f7edB8a8A4D7dff85d2CB7E5", algo_name: "test"})

    // Then, provide user data
    const user_data = [1, 3, 0, 9, 2];

    //and compute!
    EnyaFHE.FHE(user_data).then(
     result=>{
       console.log(result)
     }
    )
  • 4
    Key Generation
    We use the BFVrns FHE scheme, which uses four keys. Key generation is compute-intensive and reduces the responsiveness of the UI. Within React Native we recommend using the next-frame package to maintain the responsiveness of the UI during key generation. Functions with names containing `RN` are designed for React Native, and functions without the `RN` designator are for use in the Node environment.
    PublicKeyGen() and PublicKeyGenRN()

    Generates a public key.
    const publickey = EnyaFHE.PublicKeyGen(); //for Node
    or,
    const publickey = EnyaFHE.PublicKeyGenRN(); //use in React Native
    MultiKeyGen() and MultiKeyGenRN()

    Generates a multiplication key, which is required for multiplying vectors when computing the inner product.
    const multikey = EnyaFHE.MultiKeyGen(); //for Node
    or,
    const multikey = await EnyaFHE.MultiKeyGenRN(); // Asynchronous, for RN
    RotaKeyGen() and RotaKeyGenRN()

    Generates a rotation key, which is required for summing multiple terms when computing the inner product.
    const rotakey = EnyaFHE.RotaKeyGen(); //for Node
    or,
    const rotakey = await EnyaFHE.RotaKeyGenRN(); // Asynchronous, for RN
  • 5
    Encryption and Triggering the Calculation
    First, generate a random string as the unique computation id.
    // RandomPCR() - generates unique computation id
    const randompcr = EnyaFHE.RandomPCR()
    Then, pack and encrypt the user data.
    // Example user data
    const user_data = [1, 3, 0, 9, 2];

    // PackVector()
    const plaintext = EnyaFHE.PackVector(user_data);

    // EncryptVector()
    const ciphertext = EnyaFHE.EncryptVector(plaintext, publickey);
    Next, create the computation payload.
    // EnyaFHE.JSONPayload()
    const jsonpayload = EnyaFHE.JSONPayload(
     
    publickey,
     
    multikey,
     
    rotakey,
     
    ciphertext
    );
    And, finally, submit the data for computation.
    // SendData()
    const senddata = await EnyaFHE.SendData({ pcr: randompcr, data: jsonpayload });
    var status = senddata.json();
    /* Successful response: {status: true} */
  • 6
    Fetching and Decrypting the Result
    A typical computation takes 200 ms once all the data have been received.
    // Check for completion, and download once done...
    var status = false;
    var count = 0;
    while ((status == false) & (count < 5)) {
       
    await EnyaFHE.sleep(1000);
       /* Check the status of the calculation */
       
    const checkstatus = await EnyaFHE.CheckStatus(
           {
    pcr: randompcr }
       );
       
    const return_message = await checkstatus.json();
       
    status = return_message.API_result_ready;
       
    count = count + 1;
    }
    // once API_result_ready == True
    const getresult = await EnyaFHE.GetResult({ pcr: randompcr });
    var result = getresult.json();
    var ciphertext_string = result.ciphertext
    Once you have the result, decrypt it:
    // ReadCiphertext()
    const ciphertext_bignumber = EnyaFHE.ReadCiphertext(ciphertext_string);

    // DecryptVector()
    const text = EnyaFHE.DecryptVector(ciphertext_bignumber);