This is an test package for Python Fhe Http
Project description
FHE-HTTP-Python
Introduce
- Fully Homomorphic Encryption (FHE) is a technology that enables processing encrypted data without decrypting it. This allows clients to delegate computations, such as machine learning (ML) tasks to resource-equipped servers without revealing their own data. It can also be used for applications like Private Information Retrieval (PIR). For more details about FHE, please refer to the tfhe-rs documentation.
- This project offers a Python interface for using tfhe-rs. Additionally, a zk-experimental version is supported, enabling the server to verify encrypted values before computation begins, and assembly code execution allows clients to define the computation process/
- Currently, gpu acceleration of tfhe-rs is not yet available in this project.
Required
- rust^1.77.1 stable
- python^3.10
- environment:
ubuntu-22.04
macos arm64
macos x86-64
How to use
About Package
// download from from PyPI
$ pip install fhe-http
// Build fhe-http package from source
// This will create a package in site-packages of pip
$ cd fhe-http/fhe_http_python
$ maturin develop
Run Tests
// After package downloaded or built
# cd fhe-http/fhe_http_python
# python tests/*
Details of usage
#Basic Fhe Computation
Description
This basic version of 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.
Supported
- operations:
add
,sub
,mul
,div
,rem
,and
,or
,xor
,shr
,shl
,not
,and
,neg
- FheType:
Int64
Uint64
Example usage
import fhe_http as py_fhe
# initialize keys
key_gen = py_fhe.KeyGenerator()
key_gen.init_keys()
client_key = key_gen.get_client_key()
server_key = key_gen.get_server_key()
# Server Side:
# set server key for ciphertext computation
sk_setter = py_fhe.ServerKeySetter()
decompressed_server_key = sk_setter.decompress_server_key(server_key)
sk_setter.set_server_key(decompressed_server_key)
# Client Side:
# use Fhe module to encrypt
fhe = py_fhe.Fhe(client_key)
# Client Side:
# encryt value
serailizer = py_fhe.Serializer()
data_type = py_fhe.create_fhe_value_type("Int64")
encrypted_a = fhe.encrypt(serailizer.from_i64(123), data_type)
encrypted_b = fhe.encrypt(serailizer.from_i64(456), data_type)
# Server Side:
# using FheOps module to have ciphertext computation
fhe_ops = py_fhe.FheOps()
encrypted_c = fhe_ops.add(encrypted_a, encrypted_b, data_type)
# Client side:
# decrypt computation result
decrypted_c = fhe.decrypt(encrypted_c, data_type)
c = serailizer.to_i64(decrypted_c)
assert c == 123 + 456
#ZK-experimental Fhe Computation
Description
This zk-experimental feature allows servers to verify encrypted values sent by clients before starting the FHE execution, preventing the processing of invalid or malicious values. Clients must use a public key, generated with zk public parameters, to encrypt the values. Servers verify these encrypted values by leveraging the zk public parameters (the same one used to generate public key). After completing the FHE computation, clients will receive the same result as they would using the non-zk feature.
Supported
- operations:
add
,sub
,mul
,div
,rem
,and
,or
,xor
,shr
,shl
,not
,and
,neg
- ProvenFheType:
ProvenInt64
ProvenUint64
Example usage
import fhe_http as py_fhe
# initialize keys
key_gen = py_fhe.KeyGenerator()
key_gen.init_keys()
client_key = key_gen.get_client_key()
server_key = key_gen.get_server_key()
public_key = key_gen.get_public_key()
# initialize zk params
public_zk_params = py_fhe.get_public_zk_params(msg=2, carry=2)
# Server Side:
# set server key for ciphertext computation
sk_setter = py_fhe.ServerKeySetter()
decompressed_server_key = sk_setter.decompress_server_key(server_key)
sk_setter.set_server_key(decompressed_server_key)
# Client Side:
# use Fhe module to encrypt
fhe = py_fhe.Fhe(client_key, public_key)
# Client Side:
# encryt value with public_zk_params
serailizer = py_fhe.Serializer()
proven_fhe_type = py_fhe.create_proven_fhe_value_type("ProvenInt64")
encrypted_a = fhe.proven_encrypt(serailizer.from_i64(123), proven_fhe_type, public_zk_params)
encrypted_b = fhe.proven_encrypt(serailizer.from_i64(456), proven_fhe_type, public_zk_params)
# Server Side:
# using ProvenFheOps module to have ciphertext computation
proven_ops = py_fhe.ProvenFheOps()
encrypted_c = proven_ops.add(encrypted_a, encrypted_b, proven_fhe_type, public_zk_params, public_key)
# Client Side:
decrypted_c = fhe.decrypt(encrypted_c, proven_fhe_type)
c = serailizer.to_u64(decrypted_c)
assert c == 123 + 456
#Assembly Code Fhe execution
Description
This assembly feature allows clients to define a function that includes multiple operations. The assembler.code_wrapper
is a decorator that parses Python code into self-defined assembly code (see the example code below). Clients can define the function's parameters and send the encrypted actual values corresponding to those parameters to a server. Upon receiving the encrypted parameters, the server executes the assembly code and responds with the fhe computation results to the client.
Supported
- operations:
add
,sub
,mul
,div
,rem
,and
,or
,xor
,shr
,shl
,not
,and
neg
is temporarily not supported in assembly code execution.
- Type:
Int64
Uint64
Example usage
import fhe_http as py_fhe
from fhe_http.assembler.assembler import Assembler
def generate_keys():
key_gen = py_fhe.KeyGenerator()
key_gen.init_keys()
client_key = key_gen.get_client_key()
server_key = key_gen.get_server_key()
return client_key, server_key
def set_server_key(server_key):
sk_setter = py_fhe.ServerKeySetter()
decompressed_server_key = sk_setter.decompress_server_key(server_key)
sk_setter.set_server_key(decompressed_server_key)
def encrypt(num: int, client_key, data_type: str = "Uint64"):
serailizer = py_fhe.Serializer()
fhe_value = py_fhe.create_fhe_value_type(data_type)
fhe = py_fhe.Fhe(client_key)
return fhe.encrypt(serailizer.from_i64(num), fhe_value)
def decrypt(encrypted_num, client_key, data_type: str = "Uint64"):
serailizer = py_fhe.Serializer()
fhe_value = py_fhe.create_fhe_value_type(data_type)
fhe = py_fhe.Fhe(client_key)
return serailizer.to_i64(fhe.decrypt(encrypted_num, fhe_value))
def get_asm_code():
assembler = Assembler()
@assembler.code_wrapper
def operation(i, j, two, three):
a = i + j
b = a >> two
c = two << three
d = c - b
return d
return "\n".join(operation.assembly)
if __name__ == "__main__":
assembly = get_asm_code()
client_key, server_key = generate_keys()
set_server_key(server_key)
encrypted = py_fhe.execute_assembly(
assembly,
{
"i": encrypt(25, client_key),
"j": encrypt(21, client_key),
"two": encrypt(2, client_key),
"three": encrypt(3, client_key),
},
py_fhe.create_fhe_value_type("Uint64"),
)
decrypted = decrypt(encrypted, client_key)
print(decrypted)
Interaction via Http
Decription
This python package also provide some function for http request. For example: setting the header to comfirm the fhe protocol, and some json related operation for both body and header (see below exmaple)
Example usage
Execution
$ pip install fastapi uvicorn requests fhe-http
// machine 1
$ python3 server_test.py
// machine 2
$ python3 client_test.py
Client Side
# file name: client_test.py
import json
import fastapi
import uvicorn
from fastapi import Body
from pydantic import BaseModel
import fhe_http as py_fhe
app = fastapi.FastAPI()
class Addition(BaseModel):
a: str
b: str
server_key: str
def encrypt(num: int, client_key, data_type: str = "Int64"):
serailizer = py_fhe.Serializer()
fhe_value = py_fhe.create_fhe_value_type(data_type)
fhe = py_fhe.Fhe(client_key)
return fhe.encrypt(serailizer.from_i64(num), fhe_value)
def set_server_key(server_key):
sk_setter = py_fhe.ServerKeySetter()
decompressed_server_key = sk_setter.decompress_server_key(server_key)
sk_setter.set_server_key(decompressed_server_key)
@app.post("/")
async def post_request(data: Addition = Body(...)):
print("Received request")
data_type = py_fhe.create_fhe_value_type("Int64")
data_json = json.loads(data.model_dump_json())
encrypted_a = py_fhe.decode_fhe_value(data_json["a"])
encrypted_b = py_fhe.decode_fhe_value(data_json["b"])
server_key = py_fhe.decode_fhe_value(data_json["server_key"])
set_server_key(server_key)
fhe_ops = py_fhe.FheOps()
encrypted_c = fhe_ops.add(encrypted_a, encrypted_b, data_type)
encoded_c = py_fhe.encode_fhe_value(encrypted_c)
return {"result": encoded_c, "status": "success"}
if __name__ == "__main__":
uvicorn.run("server_test:app", host="localhost", port=8000, reload=True)
Server Side
# file name: server_test.py
# client.py
import json
import requests
import fhe_http as py_fhe
def generate_keys():
key_gen = py_fhe.KeyGenerator()
key_gen.init_keys()
client_key = key_gen.get_client_key()
server_key = key_gen.get_server_key()
return client_key, server_key
def decrypt(encrypted_num, client_key, data_type: str = "Int64"):
serailizer = py_fhe.Serializer()
fhe_value = py_fhe.create_fhe_value_type(data_type)
fhe = py_fhe.Fhe(client_key)
return serailizer.to_i64(fhe.decrypt(encrypted_num, fhe_value))
def send_post_request(url):
header = json.loads(py_fhe.create_fhe_header("123"))
client_key, server_key = generate_keys()
data = {"a": 123123123, "b": 123}
data_type = py_fhe.create_fhe_value_type("Int64")
encrypt_json = py_fhe.encrypt_fhe_body(
[("a", data_type), ("b", data_type)], data, client_key
)
encrypt_json = json.loads(encrypt_json)
payload_str = py_fhe.set_server_key_to_json(server_key, encrypt_json)
payload = json.loads(payload_str)
response = requests.post(url, json=payload, headers=header)
response = response.json()
encrypted_c = py_fhe.decode_fhe_value(response["result"])
c = decrypt(encrypted_c, client_key)
assert c == 123123246
if __name__ == "__main__":
server_url = "http://localhost:8000"
send_post_request(server_url)
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
File details
Details for the file fhe-http-0.2.47.tar.gz
.
File metadata
- Download URL: fhe-http-0.2.47.tar.gz
- Upload date:
- Size: 25.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.10.12
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | be7bfbc12ef53212784f3c85aa7ccbfab325d724b212f2562c8c938dbc441201 |
|
MD5 | 716ea8c411ca94b147f4c84422596080 |
|
BLAKE2b-256 | 37ad9c3e3edeefd46d3d9c301ba803d9bd4678bf73b8443044dd2f7120db29c5 |
File details
Details for the file fhe_http-0.2.47-cp310-cp310-macosx_14_0_universal2.whl
.
File metadata
- Download URL: fhe_http-0.2.47-cp310-cp310-macosx_14_0_universal2.whl
- Upload date:
- Size: 1.4 MB
- Tags: CPython 3.10, macOS 14.0+ universal2 (ARM64, x86-64)
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.10.12
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | c16d7be87b1995890dbc4d08ff1504b80354455a281ebd53f4798e03b4fb5c84 |
|
MD5 | bf5eaf3077b7d802d06ec04d546f8a50 |
|
BLAKE2b-256 | 1a2a4a167aebe27b28a3595d19b13a493ebec1770df0af1aec7faf727c4a485e |
File details
Details for the file fhe_http-0.2.47-cp310-cp310-macosx_12_0_x86_64.whl
.
File metadata
- Download URL: fhe_http-0.2.47-cp310-cp310-macosx_12_0_x86_64.whl
- Upload date:
- Size: 1.6 MB
- Tags: CPython 3.10, macOS 12.0+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.10.12
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 255e8c3389a942c9f80cf158bf9b76681da3f51abc0b164477b00f7e63088634 |
|
MD5 | c9670f38338d3bcf52ceae8882b26c39 |
|
BLAKE2b-256 | f7bda4c53ab205cebbe17867ea105b9ec2526598fd5e6fb9cc8ca967820a673b |