Skip to content
This repository was archived by the owner on Aug 18, 2020. It is now read-only.

Commit 2eb4566

Browse files
committed
changes with savefile
1 parent 23cacd7 commit 2eb4566

File tree

8 files changed

+185
-22
lines changed

8 files changed

+185
-22
lines changed

Diff for: .gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.idea/

Diff for: SEAL/configure

100644100755
File mode changed.

Diff for: SEAL/seal/ciphertext.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,13 @@ namespace seal
112112
stream.write(reinterpret_cast<const char*>(ciphertext_array_.get()), size_ * poly_coeff_count_ * coeff_mod_count_ * bytes_per_uint64);
113113
}
114114

115+
void Ciphertext::python_save(std::string &path) const
116+
{
117+
std::ofstream out(path);
118+
save(out);
119+
out.close();
120+
}
121+
115122
void Ciphertext::load(istream &stream)
116123
{
117124
stream.read(reinterpret_cast<char*>(&hash_block_), sizeof(EncryptionParameters::hash_block_type));
@@ -129,6 +136,13 @@ namespace seal
129136
stream.read(reinterpret_cast<char*>(ciphertext_array_.get()), size_ * poly_coeff_count_ * coeff_mod_count_ * bytes_per_uint64);
130137
}
131138

139+
void Ciphertext::python_load(std::string &path)
140+
{
141+
std::ifstream in(path);
142+
load(in);
143+
in.close();
144+
}
145+
132146
void Ciphertext::resize(int size, int poly_coeff_count, int coeff_mod_count, const MemoryPoolHandle &pool)
133147
{
134148
if (size < 2)

Diff for: SEAL/seal/ciphertext.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <string>
44
#include <iostream>
5+
#include <fstream>
56
#include "seal/util/uintcore.h"
67
#include "seal/encryptionparams.h"
78
#include "seal/memorypoolhandle.h"
@@ -485,15 +486,15 @@ namespace seal
485486
@see load() to load a saved ciphertext.
486487
*/
487488
void save(std::ostream &stream) const;
488-
489+
void python_save(std::string &path) const;
489490
/**
490491
Loads a ciphertext from an input stream overwriting the current ciphertext.
491492
492493
@param[in] stream The stream to load the ciphertext from
493494
@see save() to save a ciphertext.
494495
*/
495496
void load(std::istream &stream);
496-
497+
void python_load(std::string &path);
497498
/**
498499
Returns a constant reference to the hash block.
499500

Diff for: SEALPython/wrapper.cpp

+7-1
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,12 @@ PYBIND11_MODULE(seal, m) {
160160
"Allocates enough memory to accommodate the backing array of a ciphertext with given capacity")
161161
.def("reserve", (void (Ciphertext::*)(const EncryptionParameters &, int, const MemoryPoolHandle &)) &Ciphertext::reserve,
162162
"Allocates enough memory to accommodate the backing array of a ciphertext with given capacity")
163-
.def("size", &Ciphertext::size, "Returns the capacity of the allocation");
163+
.def("size", &Ciphertext::size, "Returns the capacity of the allocation")
164+
.def("python_save", (void (Ciphertext::*)(std::string &)) &Ciphertext::python_save,
165+
"Saves Ciphertext object to file given filepath")
166+
.def("python_load", (void (Ciphertext::*)(std::string &)) &Ciphertext::python_load,
167+
"Loads Ciphertext object from file given filepath");
168+
164169

165170
py::class_<Decryptor>(m, "Decryptor")
166171
.def(py::init<const SEALContext &, const SecretKey &>())
@@ -463,4 +468,5 @@ PYBIND11_MODULE(seal, m) {
463468

464469
m.def("coeff_modulus_128", &coeff_modulus_128, "Returns the default coefficients modulus for a given polynomial modulus degree.");
465470
m.def("dbc_max", &dbc_max, "Return dbc max value.");
471+
466472
}

Diff for: SEALPythonExamples/examples.py

+158-17
Original file line numberDiff line numberDiff line change
@@ -1539,24 +1539,165 @@ def performance_test_mt(th_index, lock, pool):
15391539
th_vector[i].join()
15401540

15411541

1542+
1543+
def save_example():
1544+
1545+
print_example_banner("Example: Basics I");
1546+
1547+
1548+
parms = EncryptionParameters()
1549+
1550+
# We first set the polynomial modulus. This must be a power-of-2 cyclotomic
1551+
# polynomial, i.e. a polynomial of the form "1x^(power-of-2) + 1". The polynomial
1552+
# modulus should be thought of mainly affecting the security level of the scheme;
1553+
# larger polynomial modulus makes the scheme more secure. At the same time, it
1554+
# makes ciphertext sizes larger, and consequently all operations slower.
1555+
# Recommended degrees for poly_modulus are 1024, 2048, 4096, 8192, 16384, 32768,
1556+
# but it is also possible to go beyond this. Since we perform only a very small
1557+
# computation in this example, it suffices to use a very small polynomial modulus
1558+
parms.set_poly_modulus("1x^2048 + 1")
1559+
1560+
1561+
parms.set_coeff_modulus(seal.coeff_modulus_128(2048))
1562+
1563+
# The plaintext modulus can be any positive integer, even though here we take
1564+
# it to be a power of two. In fact, in many cases one might instead want it to
1565+
# be a prime number; we will see this in example_batching(). The plaintext
1566+
# modulus determines the size of the plaintext data type, but it also affects
1567+
# the noise budget in a freshly encrypted ciphertext, and the consumption of
1568+
# the noise budget in homomorphic multiplication. Thus, it is essential to try
1569+
# to keep the plaintext data type as small as possible for good performance.
1570+
# The noise budget in a freshly encrypted ciphertext is
1571+
1572+
# ~ log2(coeff_modulus/plain_modulus) (bits)
1573+
1574+
# and the noise budget consumption in a homomorphic multiplication is of the
1575+
# form log2(plain_modulus) + (other terms).
1576+
parms.set_plain_modulus(1 << 8)
1577+
1578+
# Now that all parameters are set, we are ready to construct a SEALContext
1579+
# object. This is a heavy class that checks the validity and properties of
1580+
# the parameters we just set, and performs and stores several important
1581+
# pre-computations.
1582+
context = SEALContext(parms)
1583+
1584+
# Print the parameters that we have chosen
1585+
print_parameters(context);
1586+
1587+
1588+
encoder = IntegerEncoder(context.plain_modulus())
1589+
1590+
# We are now ready to generate the secret and public keys. For this purpose we need
1591+
# an instance of the KeyGenerator class. Constructing a KeyGenerator automatically
1592+
# generates the public and secret key, which can then be read to local variables.
1593+
# To create a fresh pair of keys one can call KeyGenerator::generate() at any time.
1594+
keygen = KeyGenerator(context)
1595+
public_key = keygen.public_key()
1596+
secret_key = keygen.secret_key()
1597+
1598+
# To be able to encrypt, we need to construct an instance of Encryptor. Note that
1599+
# the Encryptor only requires the public key.
1600+
encryptor = Encryptor(context, public_key)
1601+
1602+
# Computations on the ciphertexts are performed with the Evaluator class.
1603+
evaluator = Evaluator(context)
1604+
1605+
# We will of course want to decrypt our results to verify that everything worked,
1606+
# so we need to also construct an instance of Decryptor. Note that the Decryptor
1607+
# requires the secret key.
1608+
decryptor = Decryptor(context, secret_key)
1609+
1610+
# We start by encoding two integers as plaintext polynomials.
1611+
value1 = 5;
1612+
plain1 = encoder.encode(value1);
1613+
print("Encoded " + (str)(value1) + " as polynomial " + plain1.to_string() + " (plain1)")
1614+
1615+
value2 = -7;
1616+
plain2 = encoder.encode(value2);
1617+
print("Encoded " + (str)(value2) + " as polynomial " + plain2.to_string() + " (plain2)")
1618+
1619+
# Encrypting the values is easy.
1620+
encrypted1 = Ciphertext()
1621+
encrypted2 = Ciphertext()
1622+
print("Encrypting plain1: ")
1623+
encryptor.encrypt(plain1, encrypted1)
1624+
print("Done (encrypted1)")
1625+
1626+
encrypted1.save()
1627+
1628+
print("Encrypting plain2: ")
1629+
encryptor.encrypt(plain2, encrypted2)
1630+
print("Done (encrypted2)")
1631+
1632+
# To illustrate the concept of noise budget, we print the budgets in the fresh
1633+
# encryptions.
1634+
print("Noise budget in encrypted1: " + (str)(decryptor.invariant_noise_budget(encrypted1)) + " bits")
1635+
print("Noise budget in encrypted2: " + (str)(decryptor.invariant_noise_budget(encrypted2)) + " bits")
1636+
1637+
# As a simple example, we compute (-encrypted1 + encrypted2) * encrypted2.
1638+
1639+
# Negation is a unary operation.
1640+
evaluator.negate(encrypted1)
1641+
1642+
# Negation does not consume any noise budget.
1643+
print("Noise budget in -encrypted1: " + (str)(decryptor.invariant_noise_budget(encrypted1)) + " bits")
1644+
1645+
# Addition can be done in-place (overwriting the first argument with the result,
1646+
# or alternatively a three-argument overload with a separate destination variable
1647+
# can be used. The in-place variants are always more efficient. Here we overwrite
1648+
# encrypted1 with the sum.
1649+
evaluator.add(encrypted1, encrypted2)
1650+
1651+
# It is instructive to think that addition sets the noise budget to the minimum
1652+
# of the input noise budgets. In this case both inputs had roughly the same
1653+
# budget going on, and the output (in encrypted1) has just slightly lower budget.
1654+
# Depending on probabilistic effects, the noise growth consumption may or may
1655+
# not be visible when measured in whole bits.
1656+
print("Noise budget in -encrypted1 + encrypted2: " + (str)(decryptor.invariant_noise_budget(encrypted1)) + " bits")
1657+
1658+
# Finally multiply with encrypted2. Again, we use the in-place version of the
1659+
# function, overwriting encrypted1 with the product.
1660+
evaluator.multiply(encrypted1, encrypted2)
1661+
1662+
# Multiplication consumes a lot of noise budget. This is clearly seen in the
1663+
# print-out. The user can change the plain_modulus to see its effect on the
1664+
# rate of noise budget consumption.
1665+
print("Noise budget in (-encrypted1 + encrypted2) * encrypted2: " + (str)(decryptor.invariant_noise_budget(encrypted1)) + " bits")
1666+
1667+
# Now we decrypt and decode our result.
1668+
plain_result = Plaintext()
1669+
print("Decrypting result: ")
1670+
decryptor.decrypt(encrypted1, plain_result)
1671+
print("Done")
1672+
1673+
# Print the result plaintext polynomial.
1674+
print("Plaintext polynomial: " + plain_result.to_string())
1675+
1676+
# Decode to obtain an integer result.
1677+
print("Decoded integer: " + (str)(encoder.decode_int32(plain_result)))
1678+
1679+
1680+
15421681
def main():
1543-
# Example: Basics I
1544-
example_basics_i()
1545-
# Example: Basics II
1546-
example_basics_ii()
1547-
# Example: Weighted Average
1548-
example_weighted_average()
1549-
# Example: Batching using CRT
1550-
example_batching()
1551-
# Example: Parameter Selection
1552-
example_parameter_selection()
1553-
# Example: Performance (Single Thread)
1554-
example_performance_st()
1555-
# Example: Performance (Multi Thread)
1556-
th_count = ((int)(input('Thread count: ')))
1557-
if th_count > 0: example_performance_mt(th_count)
1558-
else: print('Invalid thread count.')
1559-
# Wait for ENTER before closing screen.
1682+
# # Example: Basics I
1683+
# example_basics_i()
1684+
# # Example: Basics II
1685+
# example_basics_ii()
1686+
# # Example: Weighted Average
1687+
# example_weighted_average()
1688+
# # Example: Batching using CRT
1689+
# example_batching()
1690+
# # Example: Parameter Selection
1691+
# example_parameter_selection()
1692+
# # Example: Performance (Single Thread)
1693+
# example_performance_st()
1694+
# # Example: Performance (Multi Thread)
1695+
# th_count = ((int)(input('Thread count: ')))
1696+
# if th_count > 0: example_performance_mt(th_count)
1697+
# else: print('Invalid thread count.')
1698+
# # Wait for ENTER before closing screen.
1699+
1700+
save_example()
15601701
input('Press ENTER to exit')
15611702

15621703
def print_example_banner(title, ch='*', length=78):

Diff for: build-docker.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
#!/bin/bash
2-
docker build -t seal -f Dockerfile .
2+
docker build -t seal-save -f Dockerfile .

Diff for: run-docker.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
#!/bin/bash
22
# docker run -it seal bash
33
# docker run -it seal ./bin/sealexamples
4-
docker run -it seal python3 SEALPythonExamples/examples.py
4+
docker run -it seal-io python3 SEALPythonExamples/examples.py

0 commit comments

Comments
 (0)