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 and the entire code flow is given in the example app which can be downloaded.


1. Algorithm Configuration

Install the FHE SDK (enyafhe) using npm with the following command in your project path.

npm install enyafhe

After installing the SDK, use algo_add.py to name and parametrize your algorithm. This Python script is located in the ./node_modules/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

Use the Configure function to set the client token and the algorithm name.

import EnyaFHE from 'enyafhe';
  
// Configure()
EnyaFHE.Configure({
  CLIENT_TOKEN: "f7edB8a8A4D7dff85d2CB7E5", //your client token
  algo_name: "test"                       //the algorithm you defined in the back end
})

3. Simple usage

We provide a high-level EnyaFHE.FHE() function that should handle many use cases without extra configuration. Just follow this example:

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(function(result{
  console.log(result)
}))

If you want to write your own FHE functions, keep reading.


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. Function with names containing `RN` are designed for React Native, and functions without the `RN` designator are for use in the Node environment.

PrivateKeyGen()

Generates a private key. The private key needs to be generated first, before generating the other three keys.

const private_key = EnyaFHE.PrivateKeyGen();

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);