Python SDK for GPU-accelerated CKKS homomorphic encryption inference
Project description
fhe-sdk
Python library for GPU-accelerated fully homomorphic encryption (FHE) inference over neural networks. Wraps HEonGPU (C++/CUDA) via pybind11. Scheme is always CKKS; users never interact with raw cryptographic objects.
Two public packages: api (high-level — FHEContext, Sequential, Linear, Conv2D, ReLU, Square) and core (enums, errors, base Layer ABC). The _backend extension is an implementation detail and not part of the public API.
Full API reference: docs/API.md.
System requirements
This is a CUDA library — every install runs nvcc. The CI / development target is the stack below; older or newer versions may work but are not tested.
| Component | Required version | Notes |
|---|---|---|
| NVIDIA GPU | Compute capability ≥ 7.0 (Volta or newer) | Pascal and older lack the tensor-core primitives HEonGPU uses. |
| NVIDIA driver | ≥ 535 | Whatever ships with CUDA 12.8. |
| CUDA Toolkit | 12.8 | nvcc --version must report 12.8. Set CUDA_HOME so find_package(CUDAToolkit) resolves. |
| Python | 3.11 or 3.12 | 3.13 untested; 3.10 and below not supported. |
| CMake | ≥ 3.30 | HEonGPU's requirement. pip install cmake works if your distro ships an older one. |
| GCC / G++ | 11–13 | Must be CUDA-12.8 compatible. GCC 14 is rejected by nvcc. |
| Ninja | optional | Speeds up the build (pip install ninja); CMake falls back to Make otherwise. |
| Git | any recent | Needed to clone the HEonGPU submodule at install time. |
| Disk | ~2 GB free | HEonGPU + bindings build artifacts. |
OS support: Linux only. Tested on Ubuntu 22.04 / 24.04. WSL2 works if CUDA is correctly forwarded. macOS and Windows native are not supported (HEonGPU is CUDA-only).
Installation
From PyPI
pip install fhe-sdk
This downloads the source distribution and triggers a local CMake + CUDA build (≈ 8–15 minutes on a modern desktop). HEonGPU is cloned and built as part of the install.
From source (development)
git clone --recurse-submodules https://github.com/Rcontre360/thesis-ucv-FHE.git
cd thesis-ucv-FHE/sdk
pip install -e .
If you forgot --recurse-submodules:
git submodule update --init --recursive
Verify
from api import FHEContext
from core.enums import SecurityLevel
ctx = (
FHEContext()
.set_poly_modulus_degree(8192)
.set_coeff_modulus_bit_sizes([60, 40, 40, 60])
.set_scale(2**40)
.set_security_level(SecurityLevel.SEC128)
.build()
)
print("OK")
If the import fails with ImportError: libheongpu.so or similar, the install completed but the runtime can't locate the C++ library — usually because CUDA_HOME / LD_LIBRARY_PATH is unset. Re-run the install in a fresh terminal after sourcing your CUDA env.
Quickstart
Crypto primitives
from fhe_sdk import FHEContext
from fhe_sdk.enums import SecurityLevel
# Build a context (fluent setter API)
ctx = (
FHEContext()
.set_poly_modulus_degree(8192)
.set_coeff_modulus_bit_sizes([60, 40, 40, 60])
.set_scale(2**40)
.set_security_level(SecurityLevel.SEC128)
.build()
)
# Or use the one-call default (equivalent to the above)
ctx = FHEContext.default()
# Encode only — produces a Plaintext (not encrypted)
values: list[float] = [0.1, 0.5, -0.3, 0.9]
pt = ctx.encode(values)
# Encrypt — accepts list[float] or Plaintext
ct = ctx.encrypt(values) # encode + encrypt in one step
ct = ctx.encrypt(pt) # encrypt an already-encoded Plaintext
# Arithmetic on Ciphertext
a = ctx.encrypt([1.0, 2.0, 3.0, 4.0])
b = ctx.encrypt([0.5, 0.5, 0.5, 0.5])
pt_b = ctx.encode([0.5, 0.5, 0.5, 0.5])
c = a + b # ct + ct — homomorphic addition, free
d = a * b # ct * ct — homomorphic multiply, consumes one level
e = a + pt_b # ct + Plaintext — free
f = a * pt_b # ct * Plaintext — consumes one level
g = a * 2.0 # ct * scalar
h = a + [1.0, 2.0, 3.0, 4.0] # ct + list[float] — auto-encodes on the fly
# Decrypt
result: list[float] = ctx.decrypt(d)
result: list[float] = d.decrypt() # shorthand
Neural network inference
This example loads a pre-trained PyTorch model and runs encrypted inference.
import torch
import torch.nn as torch_nn
from fhe_sdk import FHEContext
from fhe_sdk.nn import Sequential, Linear, Square
# Pre-trained PyTorch model
class SmallNet(torch_nn.Module):
def __init__(self):
super().__init__()
self.fc1 = torch_nn.Linear(64, 64)
self.fc2 = torch_nn.Linear(64, 10)
def forward(self, x):
return self.fc2(self.fc1(x) ** 2)
torch_model = SmallNet()
# torch_model.load_state_dict(torch.load("weights.pt"))
# FHE context — default gives 2 usable levels, enough for one Square activation
ctx = FHEContext.default()
# Build the FHE model
fhe_model = Sequential(
Linear(in_features=64, out_features=64),
Square(),
Linear(in_features=64, out_features=10),
)
# Load weights from the pre-trained PyTorch layers
fhe_model[0].load_from_torch(torch_model.fc1)
fhe_model[2].load_from_torch(torch_model.fc2)
# Encrypted inference
plaintext_input: list[float] = [0.0] * 64 # replace with real features
enc_input = ctx.encrypt(plaintext_input)
enc_output = fhe_model(enc_input) # Ciphertext of size 10
result: list[float] = enc_output.decrypt() # list[float] of length 10
fhe_model(enc_input) is identical to fhe_model.forward(enc_input).
Loading weights from NumPy
import numpy as np
from fhe_sdk.nn import Linear
W = np.random.randn(10, 64).astype(np.float64)
b = np.random.randn(10).astype(np.float64)
layer = Linear(in_features=64, out_features=10)
layer.load_weights(W, b) # accepts numpy.ndarray, torch.Tensor, or list[list[float]]
Depth Budget Guide
CKKS represents ciphertexts relative to a chain of modulus primes (q_0 * q_1 * ... * q_L). Each multiplication consumes one prime. When all intermediate primes are exhausted, no further multiplications are possible.
usable_levels = len(coeff_modulus_bit_sizes) - 2
The first and last primes are special and not consumed by computations — a chain of length 4 gives 2 usable levels.
Level cost per layer type
| Layer / Operation | Levels consumed |
|---|---|
Linear |
0 — matrix-vector multiply uses plaintext weights |
Square |
1 |
ApproxReLU(degree=3) |
2 |
ApproxReLU(degree=5) |
3 |
ApproxSigmoid(degree=3) |
2 |
ApproxSigmoid(degree=5) |
3 |
Add 1 extra level as a safety margin.
Example: 2-layer network with Square
Sequential(Linear(64,64), Square(), Linear(64,10))
Levels needed: 1. With margin: 2. Chain length: 4.
ctx = (
FHEContext()
.set_poly_modulus_degree(8192)
.set_coeff_modulus_bit_sizes([60, 40, 40, 60]) # 2 usable levels
.set_scale(2**40)
.build()
)
# Equivalent: FHEContext.default()
Example: deeper network with ApproxReLU
Sequential(
Linear(128, 64), ApproxReLU(degree=3), # 2 levels
Linear(64, 64), ApproxReLU(degree=3), # 2 levels
Linear(64, 10),
)
Levels needed: 4. With margin: 5. Chain length: 7. Requires poly_modulus_degree=16384 to keep the larger modulus sum within the 128-bit security bound.
ctx = (
FHEContext()
.set_poly_modulus_degree(16384)
.set_coeff_modulus_bit_sizes([60, 40, 40, 40, 40, 40, 60]) # 5 usable levels
.set_scale(2**40)
.build()
)
Crypto Parameter Reference
poly_modulus_degree |
coeff_modulus_bit_sizes |
Total bits | Usable levels | Max slots | Notes |
|---|---|---|---|---|---|
4096 |
[40, 20, 40] |
100 | 1 | 2048 | Minimal. Linear models only. |
8192 |
[60, 40, 40, 60] |
200 | 2 | 4096 | Default. One Square or one ApproxReLU(degree=3) + margin. |
8192 |
[60, 40, 40, 40, 60] |
240 | 3 | 4096 | One ApproxReLU(degree=3) + one Square, with margin. |
16384 |
[60, 40, 40, 40, 40, 40, 60] |
320 | 5 | 8192 | Two ApproxReLU(degree=3) activations, with margin. |
16384 |
[60, 50, 50, 50, 50, 50, 50, 60] |
420 | 6 | 8192 | Deeper models or degree-5 activations. |
32768 |
[60, 40, 40, 40, 40, 40, 40, 40, 40, 60] |
540 | 8 | 16384 | Deep models; large input vectors. |
poly_modulus_degreemust be a power of 2.- Max encrypted vector length is
poly_modulus_degree / 2. - Interior primes should have bit size equal to
log2(scale). Mismatches cause growing noise after rescaling. - Exceeding the security-level bit-sum limit causes
build()to raiseValueError. - Use
SecurityLevel.SEC192orSEC256for tighter security; this requires a largerpoly_modulus_degreeor shorter chain.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file fhe_sdk-0.1.0.tar.gz.
File metadata
- Download URL: fhe_sdk-0.1.0.tar.gz
- Upload date:
- Size: 378.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5e36becc1b7dcae0403ebd8c67c456ea2a9d0607f7db5912aa4d97fc4aa9f0f2
|
|
| MD5 |
acb0623418ec1cf9bb17da179a66b983
|
|
| BLAKE2b-256 |
6f9173dd4e7ce08346e0d7c28230a70e893d414900f88e63a033c13ed0eddda7
|