Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

examples/6_serialization #4

Merged
merged 6 commits into from
Jul 5, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 180 additions & 0 deletions examples/6_serialization.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
include("utilities.jl")

using SEAL
using Printf


function example_serialization()
print_example_banner("Example: Serialization")

parms_stream = UInt8[]
data_stream1 = UInt8[]
data_stream2 = UInt8[]
data_stream3 = UInt8[]
data_stream4 = UInt8[]
sk_stream = UInt8[]

# Use `let` to create new variable scope to mimic curly braces-delimited blocks in C++

# Server
let
enc_parms = EncryptionParameters(SchemeType.CKKS)
poly_modulus_degree = 8192
set_poly_modulus_degree!(enc_parms, poly_modulus_degree)
set_coeff_modulus!(enc_parms, coeff_modulus_create(poly_modulus_degree, [50, 20, 50]))

resize!(parms_stream, save_size(enc_parms))
out_bytes = save!(parms_stream, enc_parms)
resize!(parms_stream, out_bytes)

print_line(@__LINE__)
println("EncryptionParameters: wrote ", out_bytes, " bytes")

print_line(@__LINE__)
println("EncryptionParameters: data size upper bound (compr_mode_type::none): ",
save_size(ComprModeType.none, enc_parms))
println(" EncryptionParameters: data size upper bound (compr_mode_type::deflate): ",
save_size(ComprModeType.deflate, enc_parms))

byte_buffer = Vector{UInt8}(undef, save_size(enc_parms))
save!(byte_buffer, length(byte_buffer), enc_parms)

enc_parms2 = EncryptionParameters()
load!(enc_parms2, byte_buffer, length(byte_buffer))

print_line(@__LINE__)
println("EncryptionParameters: parms == parms2: ", enc_parms == enc_parms2)
end

# Client
let
enc_parms = EncryptionParameters()
load!(enc_parms, parms_stream)

context = SEALContext(enc_parms)

keygen = KeyGenerator(context)
pk = public_key(keygen)
sk = secret_key(keygen)

resize!(sk_stream, save_size(sk))
out_bytes = save!(sk_stream, sk)
resize!(sk_stream, out_bytes)

rlk = relin_keys(keygen)

resize!(data_stream1, save_size(rlk))
size_rlk = save!(data_stream1, rlk)
resize!(data_stream1, size_rlk)

rlk_local = relin_keys_local(keygen)
resize!(data_stream2, save_size(rlk_local))
size_rlk_local = save!(data_stream2, rlk_local)
resize!(data_stream2, size_rlk_local)

print_line(@__LINE__)
println("Serializable<RelinKeys>: wrote ", size_rlk, " bytes")
println(" ", "RelinKeys (local): wrote ", size_rlk_local, " bytes")

initial_scale = 2.0^20
encoder = CKKSEncoder(context)
plain1 = Plaintext()
plain2 = Plaintext()
encode!(plain1, 2.3, initial_scale, encoder)
encode!(plain2, 4.5, initial_scale, encoder)

encryptor = Encryptor(context, pk)
encrypted1 = Ciphertext()
encrypted2 = Ciphertext()
encrypt!(encrypted1, plain1, encryptor)
encrypt!(encrypted2, plain2, encryptor)

sym_encryptor = Encryptor(context, sk)
sym_encrypted1 = encrypt_symmetric(plain1, sym_encryptor)
sym_encrypted2 = encrypt_symmetric(plain2, sym_encryptor)

resize!(data_stream2, save_size(sym_encrypted1))
size_sym_encrypted1 = save!(data_stream2, sym_encrypted1)
resize!(data_stream2, size_sym_encrypted1)
resize!(data_stream3, save_size(encrypted1))
size_encrypted1 = save!(data_stream3, encrypted1)
resize!(data_stream3, size_encrypted1)

print_line(@__LINE__)
println("Serializable<Ciphertext> (symmetric-key): wrote ", size_sym_encrypted1, " bytes")
println(" ", "Ciphertext (public-key): wrote ", size_encrypted1, " bytes")

resize!(data_stream3, save_size(sym_encrypted2))
size_sym_encrypted2 = save!(data_stream3, sym_encrypted2)
resize!(data_stream3, size_sym_encrypted2)
end

# Server
let
enc_parms = EncryptionParameters()
load!(enc_parms, parms_stream)
context = SEALContext(enc_parms)

evaluator = Evaluator(context)

rlk = RelinKeys()
encrypted1 = Ciphertext()
encrypted2 = Ciphertext()

load!(rlk, context, data_stream1)
load!(encrypted1, context, data_stream2)
load!(encrypted2, context, data_stream3)

encrypted_prod = Ciphertext()
multiply!(encrypted_prod, encrypted1, encrypted2, evaluator)
relinearize_inplace!(encrypted_prod, rlk, evaluator)
rescale_to_next_inplace!(encrypted_prod, evaluator)

resize!(data_stream4, save_size(encrypted_prod))
size_encrypted_prod = save!(data_stream4, encrypted_prod)
resize!(data_stream4, size_encrypted_prod)

print_line(@__LINE__)
println("Ciphertext (symmetric-key): wrote ", size_encrypted_prod, " bytes")
end

# Client
let
enc_parms = EncryptionParameters()
load!(enc_parms, parms_stream)
context = SEALContext(enc_parms)

sk = SecretKey()
load!(sk, context, sk_stream)
decryptor = Decryptor(context, sk)
encoder = CKKSEncoder(context)

encrypted_result = Ciphertext()
load!(encrypted_result, context, data_stream4)

plain_result = Plaintext()
decrypt!(plain_result, encrypted_result, decryptor)
slot_count_ = slot_count(encoder)
result = Vector{Float64}(undef, slot_count_)
decode!(result, plain_result, encoder)

print_line(@__LINE__)
println("Result: ")
print_vector(result, 3, 7)
end

pt = Plaintext("1x^2 + 3")
stream = Vector{UInt8}(undef, save_size(pt))
data_size = save!(stream, pt)
resize!(stream, data_size)

header = SEALHeader()
load_header!(header, stream)

print_line(@__LINE__)
println("Size written to stream: ", data_size, " bytes")
println(" ", "Size indicated in SEALHeader: ", header.size, " bytes")
println()

return
end
16 changes: 10 additions & 6 deletions src/SEAL.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,14 @@ export version_major, version_minor, version_patch, version
include("modulus.jl")
export Modulus, SecLevelType, bit_count, value, coeff_modulus_create, coeff_modulus_bfv_default

include("serialization.jl")
export ComprModeType, SEALHeader, load_header!

include("encryptionparams.jl")
export EncryptionParameters, SchemeType, get_poly_modulus_degree,
set_poly_modulus_degree!, set_coeff_modulus!, coeff_modulus,
scheme, plain_modulus, set_plain_modulus!, plain_modulus_batching, parms_id
scheme, plain_modulus, set_plain_modulus!, plain_modulus_batching, parms_id, save!,
save_size, load!

include("context.jl")
export SEALContext, first_parms_id, last_parms_id, get_context_data, key_context_data,
Expand All @@ -46,25 +50,25 @@ include("publickey.jl")
export PublicKey, parms_id

include("secretkey.jl")
export SecretKey, parms_id
export SecretKey, parms_id, save!, load!

include("galoiskeys.jl")
export GaloisKeys, parms_id

include("relinkeys.jl")
export RelinKeys, parms_id
export RelinKeys, parms_id, save_size, save!, load!

include("keygenerator.jl")
export KeyGenerator, public_key, secret_key, relin_keys_local, relin_keys, galois_keys_local

include("plaintext.jl")
export Plaintext, scale, scale!, parms_id, to_string
export Plaintext, scale, scale!, parms_id, to_string, save_size, save!

include("ciphertext.jl")
export Ciphertext, scale, scale!, parms_id, size, length
export Ciphertext, scale, scale!, parms_id, size, length, save_size, save!, load!

include("encryptor.jl")
export Encryptor, encrypt!
export Encryptor, encrypt!, encrypt_symmetric, encrypt_symmetric!

include("evaluator.jl")
export Evaluator, square!, square_inplace!, relinearize!, relinearize_inplace!, rescale_to_next!,
Expand Down
38 changes: 38 additions & 0 deletions src/ciphertext.jl
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,41 @@ function Base.size(encrypted::Ciphertext)
end
Base.length(encrypted::Ciphertext) = size(encrypted)[1]

function save_size(compr_mode, encrypted::Ciphertext)
result = Ref{Int64}(0)
retval = ccall((:Ciphertext_SaveSize, libsealc), Clong,
(Ptr{Cvoid}, UInt8, Ref{Int64}),
encrypted, compr_mode, result)
@check_return_value retval
return Int(result[])
end
save_size(encrypted::Ciphertext) = save_size(ComprModeType.default, encrypted)

function save!(buffer::DenseVector{UInt8}, length::Integer,
compr_mode::ComprModeType.ComprModeTypeEnum, encrypted::Ciphertext)
out_bytes = Ref{Int64}(0)
retval = ccall((:Ciphertext_Save, libsealc), Clong,
(Ptr{Cvoid}, Ref{UInt8}, UInt64, UInt8, Ref{Int64}),
encrypted, buffer, length, compr_mode, out_bytes)
@check_return_value retval
return Int(out_bytes[])
end
function save!(buffer::DenseVector{UInt8}, length::Integer, encrypted::Ciphertext)
return save!(buffer, length, ComprModeType.default, encrypted)
end
function save!(buffer::DenseVector{UInt8}, encrypted::Ciphertext)
return save!(buffer, length(buffer), encrypted)
end

function load!(encrypted::Ciphertext, context::SEALContext, buffer::DenseVector{UInt8}, length)
in_bytes = Ref{Int64}(0)
retval = ccall((:Ciphertext_Load, libsealc), Clong,
(Ptr{Cvoid}, Ptr{Cvoid}, Ref{UInt8}, UInt64, Ref{Int64}),
encrypted, context, buffer, length, in_bytes)
@check_return_value retval
return Int(in_bytes[])
end
function load!(encrypted::Ciphertext, context::SEALContext, buffer::DenseVector{UInt8})
return load!(encrypted, context, buffer, length(buffer))
end

48 changes: 47 additions & 1 deletion src/encryptionparams.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ See also: [`SEALContext`](@ref)
mutable struct EncryptionParameters <: SEALObject
handle::Ptr{Cvoid}

function EncryptionParameters(scheme::SchemeType.SchemeTypeEnum)
function EncryptionParameters(scheme::SchemeType.SchemeTypeEnum=SchemeType.none)
handleref = Ref{Ptr{Cvoid}}(C_NULL)
retval = ccall((:EncParams_Create1, libsealc), Clong,
(UInt8, Ref{Ptr{Cvoid}}),
Expand Down Expand Up @@ -131,3 +131,49 @@ function parms_id(enc_param::EncryptionParameters)
return parms_id_
end

function save!(buffer::DenseVector{UInt8}, length::Integer,
compr_mode::ComprModeType.ComprModeTypeEnum, enc_param::EncryptionParameters)
out_bytes = Ref{Int64}(0)
retval = ccall((:EncParams_Save, libsealc), Clong,
(Ptr{Cvoid}, Ref{UInt8}, UInt64, UInt8, Ref{Int64}),
enc_param, buffer, length, compr_mode, out_bytes)
@check_return_value retval
return Int(out_bytes[])
end
function save!(buffer::DenseVector{UInt8}, length::Integer, enc_param::EncryptionParameters)
return save!(buffer, length, ComprModeType.default, enc_param)
end
function save!(buffer::DenseVector{UInt8}, enc_param::EncryptionParameters)
return save!(buffer, length(buffer), enc_param)
end

function save_size(compr_mode, enc_param::EncryptionParameters)
result = Ref{Int64}(0)
retval = ccall((:EncParams_SaveSize, libsealc), Clong,
(Ptr{Cvoid}, UInt8, Ref{Int64}),
enc_param, compr_mode, result)
@check_return_value retval
return Int(result[])
end
save_size(enc_param::EncryptionParameters) = save_size(ComprModeType.default, enc_param)

function load!(enc_param::EncryptionParameters, buffer::DenseVector{UInt8}, length)
in_bytes = Ref{Int64}(0)
retval = ccall((:EncParams_Load, libsealc), Clong,
(Ptr{Cvoid}, Ref{UInt8}, UInt64, Ref{Int64}),
enc_param, buffer, length, in_bytes)
@check_return_value retval
return Int(in_bytes[])
end
load!(enc_param::EncryptionParameters, buffer::DenseVector{UInt8}) = load!(enc_param, buffer,
length(buffer))

function Base.:(==)(enc_param1::EncryptionParameters, enc_param2::EncryptionParameters)
result = Ref{UInt8}(0)
retval = ccall((:EncParams_Equals, libsealc), Clong,
(Ptr{Cvoid}, Ptr{Cvoid}, Ref{UInt8}),
enc_param1, enc_param1, result)
@check_return_value retval
return Bool(result[])
end

16 changes: 16 additions & 0 deletions src/encryptor.jl
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,19 @@ function encrypt!(destination::Ciphertext, plain::Plaintext, encryptor::Encrypto
return destination
end

function encrypt_symmetric!(destination::Ciphertext, plain::Plaintext, encryptor::Encryptor)
retval = ccall((:Encryptor_EncryptSymmetric, libsealc), Clong,
(Ptr{Cvoid}, Ptr{Cvoid}, UInt8, Ptr{Cvoid}, Ptr{Cvoid}),
encryptor, plain, false, destination, C_NULL)
@check_return_value retval
return destination
end
function encrypt_symmetric(plain::Plaintext, encryptor::Encryptor)
destination = Ciphertext()
retval = ccall((:Encryptor_EncryptSymmetric, libsealc), Clong,
(Ptr{Cvoid}, Ptr{Cvoid}, UInt8, Ptr{Cvoid}, Ptr{Cvoid}),
encryptor, plain, true, destination, C_NULL)
@check_return_value retval
return destination
end

26 changes: 26 additions & 0 deletions src/plaintext.jl
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,29 @@ function to_string(plain::Plaintext)
# Return as String but without terminating NULL byte
return String(message[1:end-1])
end

function save_size(compr_mode, plain::Plaintext)
result = Ref{Int64}(0)
retval = ccall((:Plaintext_SaveSize, libsealc), Clong,
(Ptr{Cvoid}, UInt8, Ref{Int64}),
plain, compr_mode, result)
@check_return_value retval
return Int(result[])
end
save_size(plain::Plaintext) = save_size(ComprModeType.default, plain)

function save!(buffer::DenseVector{UInt8}, length::Integer,
compr_mode::ComprModeType.ComprModeTypeEnum, plain::Plaintext)
out_bytes = Ref{Int64}(0)
retval = ccall((:Plaintext_Save, libsealc), Clong,
(Ptr{Cvoid}, Ref{UInt8}, UInt64, UInt8, Ref{Int64}),
plain, buffer, length, compr_mode, out_bytes)
@check_return_value retval
return Int(out_bytes[])
end
function save!(buffer::DenseVector{UInt8}, length::Integer, plain::Plaintext)
return save!(buffer, length, ComprModeType.default, plain)
end
function save!(buffer::DenseVector{UInt8}, plain::Plaintext)
return save!(buffer, length(buffer), plain)
end
Loading