For the complete documentation index, see llms.txt. This page is also available as Markdown.

JS on WASM API

This document outlines how to use the TFHE-rs WebAssembly (WASM) client API for key generation, encryption, and decryption, providing setup examples for Node.js and web browsers.

TFHE-rs supports WASM client API, which includes functionality for key generation, encryption, and decryption. However, it does not support FHE computations.

We publish multiple wasm packages. They differ in two ways: the runtime they target, and how much of the API they include.

For the runtime:

  • Node.js, for Node.js applications or packages.

  • The browser, where parallelism is optional and comes in two flavors: standard SharedArrayBuffer threads, which need cross-origin isolation (COOP/COEP headers), or a Service Worker coordinator that works without it.

For the API:

  • The full package exposes the whole client API (Boolean, shortint and integer) and compact public-key encryption.

  • The client package is a smaller build with only compact encryption and zero-knowledge proofs, for when all you do on the client side is build and prove compact ciphertext lists.

Client (compact) API

The client package (the build_*_client targets) keeps only what a client needs to generate keys and build compact ciphertext lists:

Keys and configuration

  • init_panic_hook(): forward Rust panics to the JS console.

  • TfheConfig: cryptographic configuration, via TfheConfig.default().

  • TfheClientKey: the secret key (generate, generate_with_seed, safe_serialize / safe_deserialize).

  • TfheCompactPublicKey: the public encryption key (new, safe_serialize / safe_deserialize / safe_deserialize_conformant).

Compact encryption

  • CompactCiphertextListBuilder: push clear values (push_u2 to push_u2048, push_i2 to push_i2048, push_boolean), then call build, build_packed or build_packed_seeded.

  • CompactCiphertextList: the built list, obtained from CompactCiphertextList.builder(publicKey).

  • FheTypes: enum identifying the type of each element.

Zero-knowledge proofs (require the zk-pok feature)

  • CompactPkeCrs: the common reference string (from_config, safe_serialize / safe_deserialize).

  • ProvenCompactCiphertextList: a list built together with a proof through CompactCiphertextListBuilder.build_with_proof_packed(...); supports len, is_empty, get_kind_of, safe_serialize / safe_deserialize.

  • ZkComputeLoad: Proof or Verify.

There is no server key, and no way to expand or decrypt ciphertexts; the Boolean and shortint modules are gone too. Reach for the full package when you need any of that.

Node.js

Example:

Web

When using the Web WASM target, you should call an additional init function. With parallelism enabled, you need to call another additional initThreadPool function.

Example:

Web (cross-origin parallelism)

Standard multi-threading in WASM requires cross-origin isolation (COOP/COEP headers) to enable SharedArrayBuffer. Some deployment environments cannot set these headers (e.g., when embedding in third-party pages or certain hosting platforms).

TFHE-rs provides an alternative parallelism mode that works without cross-origin isolation by using a Service Worker coordinator and a message-passing-based worker pool. This mode is used to accelerate zero-knowledge proof computation in the browser.

Setup

Cross-origin parallelism requires a coordinator Service Worker (coordinator.js) to be served at the root of your application. After compiling with make build_web_js_api, the pkg/ directory will contain a coordinator.js module; you can simply copy it at the root of your web server.

Initialization from the main thread

If your application runs entirely from the main page (no dedicated Web Worker), you can initialize everything in one call:

Since the main thread JS cannot block, you need to build the list using the dedicated async method:

To reduce the overhead of synchronization between workers, it is advised to offload the encryption process to a Web Worker using a library like Comlink. In this case, the coordinator must be registered on the main thread before the worker initializes the pool:

Main thread (index.js):

Web Worker (worker.js):

Runtime detection

You can detect at runtime whether cross-origin isolation is available and fall back to cross-origin workers automatically:

Compiling the WASM API

Use the provided Makefile in the TFHE-rs repository to compile for the desired target. Each command produces a package in tfhe/pkg.

Full API (Boolean, shortint and integer):

  • make build_node_js_api: Node.js API

  • make build_web_js_api: browser API, sequential or cross-origin parallelism

  • make build_web_js_api_parallel: browser API with SharedArrayBuffer parallelism (requires cross-origin isolation)

Client (compact) API (compact encryption + zero-knowledge proofs only, lighter package):

  • make build_node_js_api_client: Node.js client API

  • make build_web_js_api_client: browser client API, sequential or cross-origin parallelism

  • make build_web_js_api_parallel_client: browser client API with SharedArrayBuffer parallelism

The compiled WASM packages are located in tfhe/pkg (the output directory of the web client builds can be overridden with the WEB_CLIENT_OUT_DIR variable).

The packages are also published on npm:

Package
Build command
Description

tfhe

build_web_js_api_parallel

Browser, full API, SharedArrayBuffer parallelism

tfhe-compat

build_web_js_api

Browser, full API, cross-origin parallelism

node-tfhe

build_node_js_api

Node.js, full API

tfhe-client

build_web_js_api_parallel_client

Browser, client API, SharedArrayBuffer parallelism

tfhe-client-compat

build_web_js_api_client

Browser, client API, cross-origin parallelism

Extra steps for web bundlers

When using the browser API with parallelism, some extra step might be needed depending on the bundler used:

Usage with Webpack

If you're using Webpack v5 (version >= 5.25.1), you don't need to do anything special, as it already supports bundling Workers out of the box.

Usage with Parcel

Parcel v2 also recognises the used syntax and works out of the box.

Usage with Rollup

For Rollup, you'll need @surma/rollup-plugin-off-main-thread plugin (version >= 2.1.0) which brings the same functionality and was tested with this crate.

Alternatively, you can use Vite which has necessary plugins built-in.

(Taken from RReverser/wasm-bindgen-rayon)

Using the JS on WASM API

TFHE-rs uses WASM to provide a JavaScript (JS) binding to the client-side primitives, like key generation and encryption within the Boolean, shortint and integer modules.

Currently, there are several limitations. Due to a lack of threading support in WASM, key generation can be too slow to be practical for bigger parameter sets.

Some parameter sets lead to the FHE keys exceeding the 2GB memory limit of WASM, making these parameter sets virtually unusable.

First steps using TFHE-rs JS on WASM API

Setting up TFHE-rs JS on WASM API for Node.js programs

To build the JS on WASM bindings for TFHE-rs, install wasm-pack and the necessary rust toolchain. Clone the TFHE-rs repository and build using the following commands (this will build using the default branch, you can check out a specific tag depending on your requirements):

The command above targets Node.js. To generate a binding for a web browser, use --target=web. However, this tutorial does not cover that particular use case.

The Boolean, shortint and integer features are enabled here, but it's possible to use them individually. To build the lighter client-only package instead, drop the default features and enable integer-client-js-wasm-api (optionally with zk-pok), as done by the build_*_client Makefile targets.

After the build, a new directory pkg is available in the tfhe directory.

Commented code to generate keys for shortint and encrypt a ciphertext

Make sure to update the path of the required clause in the example below to match the location of the TFHE package that was just built.

Then, you can run the example.js script using node as follows:

Last updated

Was this helpful?