15 #include "seal/seal.h"
22 std::vector<seal::Plaintext> encodeVector(
const std::vector<std::vector<std::int64_t>> &vec);
23 std::vector<seal::Ciphertext> encryptVector(
const std::vector<seal::Plaintext> &encoded_vec);
24 std::vector<seal::Ciphertext> eltwiseadd(
const std::vector<seal::Plaintext> &A,
25 const std::vector<seal::Ciphertext> &B);
26 std::vector<seal::Plaintext> decryptResult(
const std::vector<seal::Ciphertext> &encrypted_result);
27 std::vector<std::vector<int64_t>> decodeResult(
const std::vector<seal::Plaintext> &encoded_result);
33 SealBFVContext(
int poly_modulus_degree)
35 seal::EncryptionParameters parms{ seal::scheme_type::bfv };
36 parms.set_poly_modulus_degree(poly_modulus_degree);
37 parms.set_coeff_modulus(seal::CoeffModulus::Create(poly_modulus_degree, { 60, 60 }));
38 parms.set_plain_modulus(seal::PlainModulus::Batching(poly_modulus_degree, 20));
39 m_p_seal_context.reset(
40 new seal::SEALContext(parms,
true, seal::sec_level_type::tc128));
41 m_p_keygen = std::make_unique<seal::KeyGenerator>(context());
43 m_p_keygen->create_public_key(m_public_key);
44 m_secret_key = m_p_keygen->secret_key();
46 m_p_encryptor = std::make_unique<seal::Encryptor>(context(), m_public_key);
47 m_p_evaluator = std::make_unique<seal::Evaluator>(context());
48 m_p_decryptor = std::make_unique<seal::Decryptor>(context(), m_secret_key);
49 m_p_batch_encoder = std::make_unique<seal::BatchEncoder>(context());
52 seal::BatchEncoder &encoder() {
return *m_p_batch_encoder; }
53 seal::Evaluator &evaluator() {
return *m_p_evaluator; }
54 seal::Decryptor &decryptor() {
return *m_p_decryptor; }
55 const seal::Encryptor &encryptor()
const {
return *m_p_encryptor; }
56 const seal::PublicKey &public_key()
const {
return m_public_key; }
57 const seal::SecretKey &secret_key()
const {
return m_secret_key; }
58 seal::SEALContext &context() {
return *m_p_seal_context; }
61 std::shared_ptr<seal::SEALContext> m_p_seal_context;
62 std::unique_ptr<seal::KeyGenerator> m_p_keygen;
63 seal::PublicKey m_public_key;
64 seal::SecretKey m_secret_key;
65 std::unique_ptr<seal::Encryptor> m_p_encryptor;
66 std::unique_ptr<seal::Evaluator> m_p_evaluator;
67 std::unique_ptr<seal::Decryptor> m_p_decryptor;
68 std::unique_ptr<seal::BatchEncoder> m_p_batch_encoder;
71 std::size_t m_vector_size;
72 std::shared_ptr<SealBFVContext> m_p_context;
74 SealBFVContext &context() {
return *m_p_context; }
80 throw std::invalid_argument(
"vector_size");
81 m_vector_size = vector_size;
82 m_p_context = std::make_shared<SealBFVContext>(8192);
85 std::vector<seal::Plaintext> Workload::encodeVector(
const std::vector<std::vector<std::int64_t>> &vec)
87 std::vector<seal::Plaintext> retval(vec.size());
89 for (std::size_t i = 0; i < vec.size(); ++i)
91 assert(vec[i].size() <= context().encoder().slot_count());
92 context().encoder().encode(vec[i], retval[i]);
97 std::vector<seal::Ciphertext> Workload::encryptVector(
const std::vector<seal::Plaintext> &encoded_vec)
99 std::vector<seal::Ciphertext> retval(encoded_vec.size());
100 for (std::size_t i = 0; i < encoded_vec.size(); i++)
101 context().encryptor().encrypt(encoded_vec[i], retval[i]);
105 std::vector<seal::Ciphertext> Workload::eltwiseadd(
const std::vector<seal::Plaintext> &A,
106 const std::vector<seal::Ciphertext> &B)
108 std::vector<seal::Ciphertext> retval(A.size() * B.size());
115 for (std::size_t A_i = 0; A_i < A.size(); ++A_i)
116 for (std::size_t B_i = 0; B_i < B.size(); ++B_i)
118 seal::Ciphertext &retval_item = retval[A_i * B.size() + B_i];
119 context().evaluator().add_plain(B[B_i], A[A_i], retval_item);
125 std::vector<seal::Plaintext> Workload::decryptResult(
const std::vector<seal::Ciphertext> &encrypted_result)
127 std::vector<seal::Plaintext> retval(encrypted_result.size());
128 for (std::size_t i = 0; i < encrypted_result.size(); i++)
129 context().decryptor().decrypt(encrypted_result[i], retval[i]);
133 std::vector<std::vector<int64_t>> Workload::decodeResult(
const std::vector<seal::Plaintext> &encoded_result)
135 std::vector<std::vector<int64_t>> retval(encoded_result.size());
136 for (std::size_t i = 0; i < encoded_result.size(); ++i)
138 context().encoder().decode(encoded_result[i], retval[i]);
139 retval[i].resize(m_vector_size);
149 static const std::size_t VectorSize = 400;
150 static const std::size_t DimensionA = 2;
151 static const std::size_t DimensionB = 5;
154 std::vector<std::vector<std::int64_t>> A(DimensionA, std::vector<std::int64_t>(VectorSize));
155 std::vector<std::vector<std::int64_t>> B(DimensionB, std::vector<std::int64_t>(VectorSize));
158 std::random_device rd;
159 std::mt19937 gen(rd());
160 std::uniform_int_distribution<> distrib(-100, 100);
162 for (std::size_t i = 0; i < A.size(); ++i)
163 for (std::size_t j = 0; j < A[i].size(); ++j)
164 A[i][j] = distrib(gen);
165 for (std::size_t i = 0; i < B.size(); ++i)
166 for (std::size_t j = 0; j < B[i].size(); ++j)
167 B[i][j] = distrib(gen);
173 std::shared_ptr<Workload> p_workload =
174 std::make_shared<Workload>(VectorSize);
178 std::vector<std::vector<std::int64_t>> result =
179 workload.decodeResult(
180 workload.decryptResult(
181 workload.eltwiseadd(workload.encodeVector(A),
182 workload.encryptVector(workload.encodeVector(B)))));
190 std::vector<std::vector<std::int64_t>> exp_out(DimensionA * DimensionB, std::vector<std::int64_t>(VectorSize));
191 assert(exp_out.size() == result.size());
194 std::size_t result_i = 0;
195 for (std::size_t A_i = 0; A_i < A.size(); ++A_i)
196 for (std::size_t B_i = 0; B_i < B.size(); ++B_i)
198 for (std::size_t i = 0; i < VectorSize; ++i)
199 exp_out[result_i][i] = A[A_i][i] + B[B_i][i];
203 if (result == exp_out)
204 std::cout <<
"OK" << std::endl;
206 std::cout <<
"Fail" << std::endl;
Workload
Defines all possible workloads.
int main(int argc, char **argv)