JuliaCrypto / SEAL.jl

SEAL.jl is an easy-to-use wrapper for the original SEAL library and supports homomorphic encryption with the BFV and CKKS schemes.

Home Page:https://juliacrypto.github.io/SEAL.jl/stable

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Add Julian API for SEAL.jl

sloede opened this issue · comments

Right now, the SEAL.jl API intentionally follows the SEAL C++ API very closely. The motivation for this is to make it easy to convert an example written for the SEAL C++ to SEAL.jl without having to look up different function names etc. However, this approach comes with the huge downside that it SEAL.jl is not as intuitive to use as other Julia packages. Therefore, I propose to add a Julian API on top of the C++-style API and only expose the C++ API through, e.g., a submodule. This way, it is still possible to translate C++ to Julia code almost verbatim, but anyone starting directly with SEAL.jl (without prior experience with SEAL) can have a much more user-friendly API. The downside, of course, would be that two APIs have to be kept up-to-date and that translating all operations from the "raw" C++ API is probably hard to achieve. Therefore, I think it would be sufficient to support the most common operations in the high-level API, accepting that not all functionality is exposed.

Note: This issue could also be a good starting point to discuss a possible common API for all Julia HE packages.

Note: This issue description with the proposed API will be updated frequently as work progresses.

Types

To start with, let's define some types. The idea is that all types may carry enough information (and references to other types) such that virtually all operations do not require to think about the underlying HE scheme, except where explicitly desired or where it is unavoidable. This may, of course, incur some performance penalties, which we will accept for now.

struct EncryptionContext end
struct Ciphertext end
struct Plaintext end
struct PublicKey end
struct SecretKey end
struct RelinKey end
struct GaloisKey end

EncryptionContext is to be a container for multiple, lower-level objects that hold all required information about encoding and encryption. Ciphertext and Plaintext hold references to the corresponding EncryptionContext such that all operations are supported.

Functions

# Encryption context
function EncryptionContext(::CKKSScheme, poly_modulus_degree, coeff_modulus) end
function EncryptionContext(::BFVScheme, poly_modulus_degree, plain_modulus, coeff_modulus) end
# ^^^ these are not fully thought through yet!

# Encrypt/decrypt: No manual encoding required!
function encrypt(raw_data, ec::EncryptionContext)::Ciphertext end # Raw data can be any of `Float64`, `Int`, or a `Vector` thereof
function decrypt(encrypted)::Vector{Real} end

# Basic arithmetics
function Base.:(+)(c1::Ciphertext, c2::Ciphertext)::Ciphertext end
function Base.:(+)(c::Ciphertext, p::Plaintext)::Ciphertext end
function Base.:(+)(c::Ciphertext, raw_data)::Ciphertext end # `raw_data` is automatically converted
function Base.:(*)(c1::Ciphertext, c2::Ciphertext)::Ciphertext end
function Base.:(*)(c::Ciphertext, p::Plaintext)::Ciphertext end
function Base.:(*)(c::Ciphertext, raw_data)::Ciphertext end # `raw_data` is automatically converted
function Base.circshift(c::Ciphertext, shifts)::Ciphertext end

# HE operations
function relinearize(c::Ciphertext)::Ciphertext end
function rescale(c::Ciphertext, levels)::Ciphertext end
rescale(c::Ciphertext) = rescale(c, 1)

# Serialization (should be supported for all types)
function write(io::IO, x) end
function read(io::IO, x) end

Limitations

As stated above, the API might not support all possible operations directly and would also prioritize convenience over performance where it makes sense. For example, it is preferable to return new Ciphertexts instead of modifying them in-place, even if that increases memory requirements. Furthermore, while it should be open enough to be extensible in the future, for now only the BFV and CKKS schemes have to be supported.

Open question: Encoding/encryption parameters as Julia type parameters?

Should we augment all instances of Ciphertext (and Plaintext?) with parameters that encode their current encryption/encoding state? That would make them much uglier when used on the REPL (or when understanding error messages), but could allow to catch implementation errors already at compile time and add a lot of type stability to the code using the API.

For example, if Ciphertext would carry the encoding BFV or CKKS, we could have

function decrypt(encrypted::Ciphertext{BFV})::Vector{Int} end
function decrypt(encrypted::Ciphertext{CKKS})::Vector{Float64} end

Similarly, we could prevent operations on ciphertext of different lengths (i.e., after multiplication) or prevent users from applying operations that are only supported by one encoding (e.g., CKKS) to BFV-encoded data.