This project is designed as an HTTP extension for an FHE feature or plan, and integrated with existing HTTP services and standards. It allows users to specify their preferred service feature or plan by appending a specific field to the HTTP header when making requests to web services. It will support the web devtools as a packages.
Based on tfhe-rs, this project is developed in Rust to implement functionalities for HTTP interactions and is bound to Python, Node.js, and ES6. The binding allows users to run fhe program in Python and Javascript. The core logic of fhe computation are defined in the fhe_http_core module.
FHE computation enables clients to delegate computation tasks to servers. Clients use a client key which is generated by themselves to encrypt the values. After encryption, clients send the encrypted values and a server key to the servers. Once the server key is received and set by the servers, the servers can execute the FHE computation on the ciphertexts. The computation result remains encrypted and is supposed to be sent back to the clients, who can then decrypt it to obtain the result in plaintext.
This library is primarily implemented in Rust, with bindings available for multiple languages:
- Python: Utilizes PyO3 library to seamlessly integrate Rust with Python.
- Node.js: Utilizes Neon-rs@1.1.0-alpha.0 to provide fast and efficient Node.js bindings for Rust .
- Web (ES6): Compiles to WebAssembly using wasm-pack, enabling integration with modern web applications.
$ cd fhe-http/fhe_http_web
$ npm install
$ npm run tfhe-build // wasm pack tfhe-rs
$ npm run build
$ npm link
// change to web application dir
$ cd <web project path>
$ npm link fhe_http_web
import init, { FheUint64, TfheConfigBuilder, TfheClientKey, TfheCompressedServerKey } from "fhe_http_web";
import { uint8ArrayToBase64, base64ToUint8Array, createFheHeader } from "fhe_http_web/extend";
async function IntegerEcryptionTest() {
await init();
let config = TfheConfigBuilder.default().build();
let cks = TfheClientKey.generate(config);
let sks = TfheCompressedServerKey.new(cks);
let ct1 = FheUint64.encrypt_with_client_key(BigInt(3), cks);
let ct2 = FheUint64.encrypt_with_client_key(BigInt(4), cks);
let raw_ct1 = ct1.serialize();
let raw_ct2 = ct2.serialize();
let result = {
clientKey: uint8ArrayToBase64(cks.serialize()),
serverKey: uint8ArrayToBase64(sks.serialize()),
ciphertext1: uint8ArrayToBase64(raw_ct1),
ciphertext2: uint8ArrayToBase64(raw_ct2),
};
return result;
}
async function IntegerDecryptionTest(result: string, cks: string) {
await init();
let decoded_cks = base64ToUint8Array(cks);
let decoded_result = base64ToUint8Array(result);
let deserialized_cks = TfheClientKey.deserialize(decoded_cks);
let deserialized_result = FheUint64.deserialize(decoded_result);
let decrypted_result = deserialized_result.decrypt(deserialized_cks);
console.log("Decrypted result: ", decrypted_result);
return decrypted_result;
}
async function execute () {
const encryption_data = await IntegerEcryptionTest();
const header = createFheHeader("self-defined", "tfhe:0.7.2");
let response = await fetch("http://localhost:3001", {
method: "POST",
headers: {
"Content-Type": "application/json",
...header,
},
body: JSON.stringify(encryption_data),
});
let computed_data = await response.json();
let decrypted_result = await IntegerDecryptionTest(
computed_data["result"],
encryption_data.clientKey
);
}
$ cd fhe-http/fhe_http_js
$ npm install
$ npm run build
$ npm link
// change to Node.js application dir
$ cd <nodejs project path>
$ npm link fhe_http_js
// do something here ...
const fheHttp = require("fhe_http_js");
const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const app = express();
const corsOptions = {
origin: "*", //(https://your-client-app.com)
optionsSuccessStatus: 200,
};
app.use(cors(corsOptions));
app.use(bodyParser.json({ limit: "5000mb" }));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
// route
app.get("/", (req, res) => {
res.send("Hello World");
});
app.post("/", async (req, res) => {
let data = req.body;
let fheOps = new fheHttp.FheOps();
let encrypted_a = fheHttp.base64ToUint8Array(data["ciphertext1"]);
let encrypted_b = fheHttp.base64ToUint8Array(data["ciphertext2"]);
let server_key = fheHttp.base64ToUint8Array(data["serverKey"]);
fheHttp.setServerKey(server_key);
let encrypted_c = fheOps.add(encrypted_a, encrypted_b, "Uint64");
let encoded_c = fheHttp.uint8ArrayToBase64(encrypted_c);
let result = { result: encoded_c, status: "success" };
res.json(result);
});
app.listen(3001, () => {
console.log("Server is running on port 3001");
});