Skip to main content

No project description provided

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.

Environment Required

  • rust^1.77.1 stable installation
  • python^3.10
  • Apple silicon chip (pkg installation on PyPI)

How to use

About Package

// download from from PyPI
$ pip install fhe-http

// Build fhe-http package from source
$ cd fhe-http/fhe_http_python/fhe
$ 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

fhe_http-0.2.43.tar.gz (11.6 kB view details)

Uploaded Source

Built Distribution

fhe_http-0.2.43-cp311-cp311-macosx_13_0_arm64.whl (1.4 MB view details)

Uploaded CPython 3.11 macOS 13.0+ ARM64

File details

Details for the file fhe_http-0.2.43.tar.gz.

File metadata

  • Download URL: fhe_http-0.2.43.tar.gz
  • Upload date:
  • Size: 11.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.11.8

File hashes

Hashes for fhe_http-0.2.43.tar.gz
Algorithm Hash digest
SHA256 566dd33b9d39a1579562536c2e60c6adf85bbe246b729c4b9b8253cd63156718
MD5 7015165973e1b5518be1ff00c79be6aa
BLAKE2b-256 042254ebd5d1afac1cad140258e407fcf168014e775c9237e40964d0c4f32fc0

See more details on using hashes here.

File details

Details for the file fhe_http-0.2.43-cp311-cp311-macosx_13_0_arm64.whl.

File metadata

File hashes

Hashes for fhe_http-0.2.43-cp311-cp311-macosx_13_0_arm64.whl
Algorithm Hash digest
SHA256 98ca465591dbfa8fe6b0d5fe510f0d166f2115a7f28436322c9ce733b8fb1557
MD5 4bf9aba9846456dcf951919071c83693
BLAKE2b-256 3294670ec8ac20178348eab43facb8b0dc3f1cb85c632776a1095931e4ea8f43

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page