Pyfhel: homomorphic encryption arithmetic in Python with NumPy arrays
PYthon For Homomorphic Encryption Libraries, perform encrypted computations such as sum, mult, scalar product or matrix multiplication in Python, with NumPy compatibility. Uses SEAL/PALISADE as backends, implemented using Cython.
At a glance
- What is it?
- Pyfhel is a Cython and C++ library that performs addition, subtraction, multiplication, exponentiation and scalar product directly on encrypted integers and on approximate floats, wrapping SEAL and OpenFHE behind a single interface so the arithmetic looks like ordinary NumPy operations. The install compiles, and that is the main cost of adopting it.
- Who is it for?
- Adopt Pyfhel if you are prototyping homomorphic computation in Python and want NumPy-shaped operations on ciphertexts without writing C++ against SEAL yourself, and expect to compile a native extension rather than install a wheel. Do not adopt it if you need a pure Python install or a stable public API for production cryptography.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 53 days ago.
- What is it written in?
- Mainly Cython, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Arithmetic that never decrypts
Pyfhel is a Python library for Addition, Subtraction, Multiplication and Scalar Product over encrypted integers, in the BFV and BGV schemes, and over approximated floating point values in the CKKS scheme. It acts as an optimized Python API for C++ Homomorphic Encryption libraries.
The idea is the standard one from the homomorphic encryption literature, and the reason it matters is that the operations are performed on ciphertexts directly. A client encrypts a value, sends the ciphertext to a server, the server computes on it without holding the key, and the client decrypts the result. The server never sees the plaintext.
The scheme choice follows the data type. BFV and BGV are for exact integer arithmetic, with a modulus, so operations are modular and results are exact within that modulus. CKKS is for approximate floating point, which is what makes machine learning on encrypted data possible at all, at the cost of precision that the caller has to budget for.
The interface is what distinguishes this from the raw C++ libraries. The Summary section says Pyfhel uses a syntax similar to normal arithmetics with the usual operators, and the repository is described as implementing functionalities of multiple Homomorphic Encryption libraries such as addition, multiplication, exponentiation or scalar product in Python. The stated use is both for simple Homomorphic Encryption Demos and for complex problems such as Machine Learning algorithms.
So the value proposition is not new cryptography. It is that the cryptography is usable from Python with arrays, which is what makes experimentation realistic.
Afhel underneath, two backends on top
The layering is the design decision that makes the library work across backends.
Pyfhel is built on top of Afhel, an Abstraction Homomorphic Encryption Libraries in C++, and Afhel serves as the common API for all backends. The backends listed in the project table are SEAL from Microsoft and OpenFHE, the latter marked as work in progress, and the note says both are shipped alongside Pyfhel.
That distinction matters when you are choosing a backend. The README also credits the original collaborators, Melek Onen at EURECOM and Laurent Gomez at SAP Labs, alongside the authors Alberto Ibarrondo of IDEMIA and EURECOM and Alexander Viand of ETH Zurich, and the project was presented at the 9th Workshop on Encrypted Computing and Applied Homomorphic Cryptography.
The consequence of the abstraction is that the objects Pyfhel hands you are not SEAL objects. They are Afhel objects, and the SEAL or OpenFHE implementation sits underneath. If you need a feature the abstraction does not expose, the escape route is into Afhel rather than into SEAL directly, which is a smaller surface to learn but still not nothing.
The backend choice is also a performance and parameter choice, since key size, security level and plaintext modulus are set per backend and scheme. A scheme with a large modulus supports deeper multiplication chains at a cost in ciphertext size and speed, and the documentation does not summarise those trade-offs, so they are things to work out per use case.
Installing it means compiling it
This is the practical reality of the project and it should come first in any evaluation. The install warning is explicit: it takes several minutes to compile and install, be patient.
From PyPI, the command is a normal pip install.
pip install PyfhelTo get the latest version you clone the repository with all the submodules and install from the directory, and the recursive clone is not optional because the backends are submodules.
git clone --recursive https://github.com/ibarrond/Pyfhel.git
pip install .Uninstalling is pip uninstall Pyfhel.
The reason for the compilation is in the language row of the project table: Python 3.10 or newer, with Cython and C++, and a warning that a C++17 compiler is required. The tested compilers are gcc6 to gcc14 on Linux, macOS and Windows WSL, plus MSVC2017 and MSVC2019 on Windows, and the pyproject.toml classifiers list the C++ and Cython languages for that reason.
The macOS case has its own wrinkle, because Homebrew's GCC is keg-only and the compiler has to be pointed at explicitly. The documentation gives the shell snippet that detects Apple Silicon versus Intel, exports CC and CXX to the most recent gcc and g++ in the Homebrew prefix, and sets MACOSX_DEPLOYMENT_TARGET to the product version to avoid version mismatch warnings.
The Docker path avoids the host compiler entirely, since the provided Dockerfile installs Python and clones the repository with --recursive inside the image and pip installs from there. Building is docker build --tag 'pyfhel-docker' . and running it interactively is docker run -it pyfhel-docker, with the Python version defaulting to 3.12 and the virtual environment location to /home/venv, both configurable in the Dockerfile.
What the examples directory shows you
The examples folder is the best documentation of what the library actually does, because the file names describe a progression from hello world to genuinely useful work.
Demo_1_HelloWorld is the starting point, and Demo_2_Integer_BFV moves to exact integer arithmetic under BFV. Demo_3_Float_CKKS does the same for approximate floats under CKKS, which is the pair that shows the two scheme families side by side. Demo_4_SaveNRestore covers serialising an encryption context and reading it back, the operation you need the moment a computation spans more than one process.
Then the interesting ones. Demo_5_CS_Client and Demo_5bis_CS_Server are a client and a server pair, which is the multi-party pattern: the client encrypts, the server computes on ciphertexts, the client decrypts. Demo_6_MultDepth is about multiplication depth, which is the practical limit on any homomorphic computation because each multiplication consumes noise budget. Demo_7_ScalarProd does a scalar product on encrypted data, one of the operations that appear constantly in private analytics.
Demo_8_HammingDist computes an encrypted Hamming distance, and that is the one to look at if your interest is privacy-preserving similarity search, for example matching a face embedding or a document fingerprint without disclosing either. Demo_9_Integer_BGV covers the second integer scheme.
Two more sit alongside them. Demo_WAHC21 relates to a workshop paper, and examples/README.rst explains the set. Since the demonstrations are in the repository with their outputs in the documentation, you can read the sequence as a tutorial rather than as a list of unrelated samples.
The NumPy compatibility, and where it stops
The description claims NumPy compatibility, and the dependencies list confirms the shape of the design: numpy at 2.1 or newer is the only runtime requirement.
A single numpy dependency for a cryptography library tells you that the data representation is the point. Ciphertexts are held in arrays, operations are elementwise, and a computation over a vector of encrypted values is expressed the way you would write it for plaintext. That is what makes the library usable for the Machine Learning use case the documentation names, where the interesting work is a vector operation rather than a single scalar.
The limit is that NumPy compatibility is an interface property, not a performance property. Elementwise operations on ciphertexts are not free the way they are on plaintext, because each element involves polynomial arithmetic under a modulus. A large vector operation can be correct and still be slow, and the multiplication depth limit applies to the whole chain rather than to each element independently. The library will not tell you where the noise budget is going; the applications of the CKKS scheme, where the plaintext is approximate, are also the ones where the result carries error.
So the NumPy compatibility is best understood as the reason the library is pleasant to write against, and not as a claim that encrypted computation costs the same as unencrypted computation. Anyone planning a real deployment has to budget for both the depth of the circuit and the precision of the result.
Where this library stops being the right choice
There are three limits, and they come from the same place, which is that this is a research and prototyping library rather than a production cryptography product.
The first is the install. There is no wheel to download, so every installation compiles C++ and Cython, and on macOS the compiler has to be pointed at by hand because of the keg-only Homebrew layout. On a managed platform or a locked-down CI image, that is a packaging problem before it is a cryptography problem.
The second is the stability of the surface. The project describes itself as providing a common API over the backends through Afhel, and the OpenFHE backend is marked as work in progress, which tells you the abstraction is still settling. A library at version 3.5.0 with a young backend and a research origin is fine to build a prototype on and a poor foundation for something that has to keep working for years.
The third is that homomorphic encryption is expensive, and no interface can change that. The scheme parameters set the noise budget, the budget sets the multiplication depth, and the depth sets what you can compute. A library that makes the syntax pleasant does not make the underlying computation cheap, and anyone evaluating Pyfhel should decide early whether their workload fits inside a noise budget at all, because that question is settled by the algorithm and not by the binding.
On alternatives, the honest comparison is between the layers rather than between libraries. You can call SEAL or OpenFHE directly from C++ and skip both Pyfhel and Afhel, which is more work but gives you the full API. Or you can use a pure Python implementation of a scheme, which installs cleanly and is easy to read, at the cost of the speed the C++ backends exist to provide. Pyfhel sits deliberately in the middle, optimising the Python API over a C++ engine, and the case for it is strongest when you want the ergonomics of NumPy with the throughput of the native libraries.
Editorial conclusion
Adopt Pyfhel if you are prototyping homomorphic computation in Python and want NumPy-shaped operations on ciphertexts without writing C++ against SEAL yourself, and expect to compile a native extension rather than install a wheel. Do not adopt it if you need a pure Python install or a stable public API for production cryptography. Before you start, confirm you have a C++17 compiler, and note the last push was on 2026-08-31 with release v3.5.0 from 2025-08-21.
Frequently asked questions
What is Pyfhel and which encryption schemes does it support?
It is a Python library for addition, subtraction, multiplication and scalar product over encrypted integers in the BFV and BGV schemes and over approximated floating point values in the CKKS scheme, implemented with Cython and C++ over the SEAL and OpenFHE backends.
How do I install Pyfhel?
Run pip install Pyfhel from PyPI, which takes several minutes to compile. For the latest version, clone the repository with --recursive to include the backend submodules and run pip install ., and a Dockerfile is provided for a container build.
What does Pyfhel need from the host system?
A C or C++ compiler with C++17 support. The tested compilers are gcc6 to gcc14 on Linux, macOS and Windows WSL, and MSVC2017 and MSVC2019 on Windows, and macOS users with Homebrew must export CC and CXX to point at the Homebrew GCC.
What is Afhel and how does it relate to Pyfhel?
Pyfhel is built on top of Afhel, an Abstraction Homomorphic Encryption Libraries in C++, and Afhel serves as the common API for all backends, with SEAL and OpenFHE shipped alongside and the OpenFHE backend marked as work in progress.
Does Pyfhel work with NumPy arrays?
Yes, NumPy compatibility is a stated feature and numpy at 2.1 or newer is the only runtime dependency, so ciphertexts are held in arrays and operations are elementwise. The arithmetic is nevertheless far more expensive than on plaintext, and the multiplication depth of a computation is bounded by the scheme's noise budget.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/ibarrond-pyfhel)Was this useful?