Python wrapper for the main cryptographic capabilities of the OpenFHE C++ library. OpenFHE-Python provides a more user-friendly interface for Python developers, while keeping the efficiency of C++ FHE operations.
- Breaking changes in v1.6
- Installing using pip
- Running from Docker
- Building from Source
- Running Examples
- OpenFHE Python Wrapper Documentation
- Contributing Guide
- The
FHECKKSRNSclass is no longer exposed to Python. Its static depth helpers are now static methods ofCryptoContext: replaceFHECKKSRNS.GetBootstrapDepth(...)withCryptoContext.GetBootstrapDepth(...)(both overloads keep their signatures). - The
BinFHEContextattributesSaveJSON,LoadJSON,SaveBinary,LoadBinary,SavePortableBinary,LoadPortableBinary,GetParams,GetLWEScheme,GetBinFHEScheme, andGetRefreshKeywere removed. They could never be called successfully in v1.5.1 (their argument or return types were not exposed to Python), buthasattrchecks on them now returnFalse. Use the module-levelSerializeToFile/Deserialize*functions for serialization, andGetN()/GetQ()for the common parameter queries.
On Ubuntu, openfhe-python can be installed using pip. All available releases are listed at Python Package Index OpenFHE Release History. Find the release for your version of Ubuntu and run
pip install openfhe==<openfhe_package_version>
Once installed, any python example at https://github.com/openfheorg/openfhe-python/tree/main/examples can be executed.
Note that Ubuntu LTS 22.04 and 24.04 are currently supported. pip uninstall can be used to uninstall the openfhe package.
We recommend installing the wrapper from PyPI using pip, as this is the simplest method.
If you prefer to build from source, you can use the openfhe-python-packager on Linux or follow the build instructions below. The packager generates a wheel that can be installed with pip.
The legacy build instructions below are for other operating systems where openfhe-python-packager may not work.
Before building, make sure you have the following dependencies installed:
- OpenFHE 1.6.1+ by following the instructions in OpenFHE Documentation
- Python 3.10+
- pybind11 2.12+ (minimum enforced by cmake)
- numpy (runtime): the module imports numpy at load time and uses it for the array fast paths — encoding plaintexts directly from 1-D numpy arrays (
MakeCKKSPackedPlaintext,MakePackedPlaintext,MakeCoefPackedPlaintext) and returning decoded values as numpy arrays (Plaintext.GetRealPackedValueArray,GetCKKSPackedValueArray,GetPackedValueArray,GetCoefPackedValueArray). Runtime dependencies are listed in requirements.txt (pip install -r requirements.txt); wheels built by the packager declare them automatically. pybind11 older than 2.12 silently corrupts numpy-2 arrays, which is why cmake enforces that minimum.
We recommend following OpenFHE C++ installation instructions first (which covers Linux, Windows and MacOS) and then getting back to this repo. See notes on installing pybind11 below
To install OpenFHE-python directly to your system, ensure the dependencies are set up. Then clone the repository, open a terminal in the repo folder and run the following commands:
pip install "pybind11[global]"
pip install -r requirements.txt # runtime dependencies of the module (numpy)
mkdir build
cd build
cmake .. # Alternatively, cmake .. -DCMAKE_PREFIX_PATH=/path/to/installed/openfhe if you installed OpenFHE elsewhere
make
make install # You may have to run sudo make installWith the default install prefix, make install copies the module directly into the site-packages directory of the Python interpreter cmake found (this also works inside virtual environments), so import openfhe works with no further setup.
Cmake will automatically find the python installation path, if unwanted, you can specify the python path by adding -DPYTHON_EXECUTABLE_PATH=/path/to/python to the cmake command.
Build directories created with an older version of this repository should be deleted and recreated: cmake records the default-prefix choice only on a build directory's first configure, so a stale directory installs to /usr/local instead of site-packages (cmake prints a warning when this happens).
If you install to a custom location instead (cmake .. -DCMAKE_INSTALL_PREFIX=/your/path), add that location to the PYTHONPATH environment variable so Python can find the module:
export PYTHONPATH=/your/path:$PYTHONPATH
Independently of where the Python module is installed, if you see an error saying that one of the OpenFHE .so libraries cannot be found when running a Python example, add the directory containing the OpenFHE C++ libraries to LD_LIBRARY_PATH. This is only needed when OpenFHE itself was installed somewhere the dynamic linker does not search by default.
Alternatively you can install the library and handle the linking via Conda. Clone the repository, open a terminal in the repo folder and run the following commands:
conda create -n ${ENV_NAME} python=3.{X} anacondawhere ${ENV_NAME} should be replaced with the name of your environment, and {X} should be replaced with your desired python version (3.10 or newer). For example you might have conda create -n openfhe_python python=3.12 anaconda. Now, you would install pybind11 either via:
pip install "pybind11[global]" or via conda install -c conda-forge pybind11, but for now we recommend using the first method, with pip. Some users have reported issues when using the conda pybind11
Also install the module's runtime dependencies into the environment: pip install -r requirements.txt (or conda install numpy). The module imports them at load time, so import openfhe fails without them.
Now, you would clone the repository, and run the following commands to install :
mkdir build
cd build
cmake .. # Add in -DCMAKE_PREFIX_PATH=/path/to/installed/openfhe if you installed OpenFHE elsewhere
make
make install # You may have to run sudo make installWith the conda environment active, make install places the module directly into that environment's site-packages, so import openfhe works without further setup. If cmake picked up a different Python, re-run cmake in a fresh build directory and pass -DPYTHON_EXECUTABLE_PATH=$(which python).
Run tests with pytest, which may be called pytest-3 on your system. The tests import the module, so the runtime dependencies must be installed (pip install -r requirements.txt; already satisfied if you installed the wheel with pip). See the testing readme for more information.
pytest [--run-long]To get familiar with the OpenFHE Python API, check out the examples:
- FHE for arithmetic over integers (BFV):
- FHE for arithmetic over integers (BGV):
- FHE for arithmetic over real numbers (CKKS):
- Simple Code Example
- Simple Code Example with Serialization
- Simple Code Example for Complex Numbers
- Advanced Code Example
- Advanced Code Example for High-Precision CKKS
- Arbitrary Smooth Function Evaluation
- Polynomial Evaluation
- Linear Weighted Sum Evaluation
- Decryption with Noise Flooding
- Releasing Memory Used by Precomputations
- CKKS with Composite Scaling:
- CKKS Bootstrapping:
- Simple CKKS Bootstrapping Example
- Advanced CKKS Bootstrapping Example
- Double-Precision (Iterative) Bootstrapping Example
- Simple Bootstrapping Example with Composite Scaling
- Double-Precision (Iterative) Bootstrapping Example with Composite Scaling
- Serialization of Bootstrapping Keys
- Functional Bootstrapping for RLWE Ciphertexts
- Fourier-Extension (FE) Functional Bootstrapping
- Operations over Encrypted Vectors (BFV and CKKS):
- Proxy Re-Encryption (PRE):
- FHE for Boolean circuits and larger plaintext spaces (FHEW/TFHE):
- Simple Code Example with Symmetric Encryption
- Simple Code Example with the AP Bootstrapping Method
- Simple Code Example with the LMKCDEY Bootstrapping Method
- Multi-Input Gates Example
- Truth Table Example
- Code with JSON Serialization
- Code with Binary Serialization
- Large-Precision Comparison
- Small-Precision Arbitrary Function Evaluation
- Homomorphic Digit Decomposition
- Homomorphic Flooring
- JSON Serialization for Large-Precision Sign Evaluation with Dynamic Bootstrapping Keys
- Binary Serialization for Large-Precision Sign Evaluation with Dynamic Bootstrapping Keys
- FHEW/TFHE with Public-Key Encryption:
- Scheme Switching:
- Threshold FHE:
The compute-heavy bindings — evaluation, key generation, encryption/decryption, encoding, and (de)serialization — release the Python GIL for the duration of the native call, so Python threads (e.g. a concurrent.futures.ThreadPoolExecutor) run OpenFHE operations genuinely in parallel and can share one in-memory CryptoContext.
The thread-safety contract is the same as the OpenFHE C++ library's: concurrent evaluation calls are safe (they only read the evaluation keys), but the library's static evaluation-key maps are not synchronized. Keys must not be generated, inserted, or deserialized (EvalMultKeyGen, EvalRotateKeyGen, InsertEvalMultKey, DeserializeEvalMultKeyString, ...) while another thread evaluates or serializes with them — set up the context and all evaluation keys first, then fan out to worker threads. Note that OpenFHE also parallelizes single operations internally with OpenMP; when running many operations across Python threads, consider reducing OMP_NUM_THREADS to avoid oversubscription.