1 // @file simple-integers-serial-bgvrns.cpp - Simple example for BGVrns (integer
2 // arithmetic) with serialization.
3 // Refer to the simple-real-numbers-serial file for an example of how to use
4 // this in a "client-server" setup
5 // @author TPOC: contact@palisade-crypto.org
6 //
7 // @copyright Copyright (c) 2019, New Jersey Institute of Technology (NJIT))
8 // All rights reserved.
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are met:
11 // 1. Redistributions of source code must retain the above copyright notice,
12 // this list of conditions and the following disclaimer.
13 // 2. Redistributions in binary form must reproduce the above copyright notice,
14 // this list of conditions and the following disclaimer in the documentation
15 // and/or other materials provided with the distribution. THIS SOFTWARE IS
16 // PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
17 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 // EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
20 // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27 #include "palisade.h"
28
29 // header files needed for serialization
30 #include "ciphertext-ser.h"
31 #include "cryptocontext-ser.h"
32 #include "pubkeylp-ser.h"
33 #include "scheme/bgvrns/bgvrns-ser.h"
34
35 using namespace lbcrypto;
36
37 const std::string DATAFOLDER = "demoData";
38
main()39 int main() {
40 std::cout << "This program requres the subdirectory `" << DATAFOLDER
41 << "' to exist, otherwise you will get "
42 << "an error writing serializations." << std::endl;
43
44 // Sample Program: Step 1 - Set CryptoContext
45
46 // Set the main parameters
47 int plaintextModulus = 65537;
48 double sigma = 3.2;
49 SecurityLevel securityLevel = HEStd_128_classic;
50 uint32_t depth = 2;
51
52 // Instantiate the crypto context
53 CryptoContext<DCRTPoly> cryptoContext =
54 CryptoContextFactory<DCRTPoly>::genCryptoContextBGVrns(
55 depth, plaintextModulus, securityLevel, sigma, depth, OPTIMIZED, BV);
56
57 // Enable features that you wish to use
58 cryptoContext->Enable(ENCRYPTION);
59 cryptoContext->Enable(SHE);
60 cryptoContext->Enable(LEVELEDSHE);
61
62 std::cout << "\nThe cryptocontext has been generated." << std::endl;
63
64 // Serialize cryptocontext
65 if (!Serial::SerializeToFile(DATAFOLDER + "/cryptocontext.txt", cryptoContext,
66 SerType::BINARY)) {
67 std::cerr << "Error writing serialization of the crypto context to "
68 "cryptocontext.txt"
69 << std::endl;
70 return 1;
71 }
72 std::cout << "The cryptocontext has been serialized." << std::endl;
73
74 // Sample Program: Step 2 - Key Generation
75
76 // Initialize Public Key Containers
77 LPKeyPair<DCRTPoly> keyPair;
78
79 // Generate a public/private key pair
80 keyPair = cryptoContext->KeyGen();
81
82 std::cout << "The key pair has been generated." << std::endl;
83
84 // Serialize the public key
85 if (!Serial::SerializeToFile(DATAFOLDER + "/key-public.txt",
86 keyPair.publicKey, SerType::BINARY)) {
87 std::cerr << "Error writing serialization of public key to key-public.txt"
88 << std::endl;
89 return 1;
90 }
91 std::cout << "The public key has been serialized." << std::endl;
92
93 // Serialize the secret key
94 if (!Serial::SerializeToFile(DATAFOLDER + "/key-private.txt",
95 keyPair.secretKey, SerType::BINARY)) {
96 std::cerr << "Error writing serialization of private key to key-private.txt"
97 << std::endl;
98 return 1;
99 }
100 std::cout << "The secret key has been serialized." << std::endl;
101
102 // Generate the relinearization key
103 cryptoContext->EvalMultKeyGen(keyPair.secretKey);
104
105 std::cout << "The eval mult keys have been generated." << std::endl;
106
107 // Serialize the relinearization (evaluation) key for homomorphic
108 // multiplication
109 std::ofstream emkeyfile(DATAFOLDER + "/" + "key-eval-mult.txt",
110 std::ios::out | std::ios::binary);
111 if (emkeyfile.is_open()) {
112 if (cryptoContext->SerializeEvalMultKey(emkeyfile, SerType::BINARY) == false) {
113 std::cerr << "Error writing serialization of the eval mult keys to "
114 "key-eval-mult.txt"
115 << std::endl;
116 return 1;
117 }
118 std::cout << "The eval mult keys have been serialized." << std::endl;
119
120 emkeyfile.close();
121 } else {
122 std::cerr << "Error serializing eval mult keys" << std::endl;
123 return 1;
124 }
125
126 // Generate the rotation evaluation keys
127 cryptoContext->EvalAtIndexKeyGen(keyPair.secretKey, {1, 2, -1, -2});
128
129 std::cout << "The rotation keys have been generated." << std::endl;
130
131 // Serialize the rotation keyhs
132 std::ofstream erkeyfile(DATAFOLDER + "/" + "key-eval-rot.txt",
133 std::ios::out | std::ios::binary);
134 if (erkeyfile.is_open()) {
135 if (cryptoContext->SerializeEvalAutomorphismKey(erkeyfile, SerType::BINARY) == false) {
136 std::cerr << "Error writing serialization of the eval rotation keys to "
137 "key-eval-rot.txt"
138 << std::endl;
139 return 1;
140 }
141 std::cout << "The eval rotation keys have been serialized." << std::endl;
142
143 erkeyfile.close();
144 } else {
145 std::cerr << "Error serializing eval rotation keys" << std::endl;
146 return 1;
147 }
148
149 // Sample Program: Step 3: Encryption
150
151 // First plaintext vector is encoded
152 std::vector<int64_t> vectorOfInts1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
153 Plaintext plaintext1 = cryptoContext->MakePackedPlaintext(vectorOfInts1);
154 // Second plaintext vector is encoded
155 std::vector<int64_t> vectorOfInts2 = {3, 2, 1, 4, 5, 6, 7, 8, 9, 10, 11, 12};
156 Plaintext plaintext2 = cryptoContext->MakePackedPlaintext(vectorOfInts2);
157 // Third plaintext vector is encoded
158 std::vector<int64_t> vectorOfInts3 = {1, 2, 5, 2, 5, 6, 7, 8, 9, 10, 11, 12};
159 Plaintext plaintext3 = cryptoContext->MakePackedPlaintext(vectorOfInts3);
160
161 std::cout << "Plaintext #1: " << plaintext1 << std::endl;
162 std::cout << "Plaintext #2: " << plaintext2 << std::endl;
163 std::cout << "Plaintext #3: " << plaintext3 << std::endl;
164
165 // The encoded vectors are encrypted
166 auto ciphertext1 = cryptoContext->Encrypt(keyPair.publicKey, plaintext1);
167 auto ciphertext2 = cryptoContext->Encrypt(keyPair.publicKey, plaintext2);
168 auto ciphertext3 = cryptoContext->Encrypt(keyPair.publicKey, plaintext3);
169
170 std::cout << "The plaintexts have been encrypted." << std::endl;
171
172 if (!Serial::SerializeToFile(DATAFOLDER + "/" + "ciphertext1.txt",
173 ciphertext1, SerType::BINARY)) {
174 std::cerr
175 << "Error writing serialization of ciphertext 1 to ciphertext1.txt"
176 << std::endl;
177 return 1;
178 }
179 std::cout << "The first ciphertext has been serialized." << std::endl;
180
181 if (!Serial::SerializeToFile(DATAFOLDER + "/" + "ciphertext2.txt",
182 ciphertext2, SerType::BINARY)) {
183 std::cerr
184 << "Error writing serialization of ciphertext 2 to ciphertext2.txt"
185 << std::endl;
186 return 1;
187 }
188 std::cout << "The second ciphertext has been serialized." << std::endl;
189
190 if (!Serial::SerializeToFile(DATAFOLDER + "/" + "ciphertext3.txt",
191 ciphertext1, SerType::BINARY)) {
192 std::cerr
193 << "Error writing serialization of ciphertext 3 to ciphertext3.txt"
194 << std::endl;
195 return 1;
196 }
197 std::cout << "The third ciphertext has been serialized." << std::endl;
198
199
200 // Sample Program: Step 4 - Evaluation
201
202 // PALISADE maintains an internal map of CryptoContext objects which are
203 // indexed by a tag and the tag is applied to both the CryptoContext and some
204 // of the keys. When deserializing a context, PALISADE checks for the tag and
205 // if it finds it in the CryptoContext map, it will return the stored version.
206 // Hence, we need to clear the context and clear the keys.
207 cryptoContext->ClearEvalMultKeys();
208 cryptoContext->ClearEvalAutomorphismKeys();
209 lbcrypto::CryptoContextFactory<lbcrypto::DCRTPoly>::ReleaseAllContexts();
210
211 // Deserialize the crypto context
212 CryptoContext<DCRTPoly> cc;
213 if (!Serial::DeserializeFromFile(DATAFOLDER + "/cryptocontext.txt", cc,
214 SerType::BINARY)) {
215 std::cerr << "I cannot read serialization from "
216 << DATAFOLDER + "/cryptocontext.txt" << std::endl;
217 return 1;
218 }
219 std::cout << "The cryptocontext has been deserialized." << std::endl;
220
221 LPPublicKey<DCRTPoly> pk;
222 if (Serial::DeserializeFromFile(DATAFOLDER + "/key-public.txt", pk,
223 SerType::BINARY) == false) {
224 std::cerr << "Could not read public key" << std::endl;
225 return 1;
226 }
227 std::cout << "The public key has been deserialized." << std::endl;
228
229 std::ifstream emkeys(DATAFOLDER + "/key-eval-mult.txt",
230 std::ios::in | std::ios::binary);
231 if (!emkeys.is_open()) {
232 std::cerr << "I cannot read serialization from "
233 << DATAFOLDER + "/key-eval-mult.txt" << std::endl;
234 return 1;
235 }
236 if (cc->DeserializeEvalMultKey(emkeys, SerType::BINARY) == false) {
237 std::cerr << "Could not deserialize the eval mult key file" << std::endl;
238 return 1;
239 }
240 std::cout << "Deserialized the eval mult keys." << std::endl;
241
242 std::ifstream erkeys(DATAFOLDER + "/key-eval-rot.txt",
243 std::ios::in | std::ios::binary);
244 if (!erkeys.is_open()) {
245 std::cerr << "I cannot read serialization from "
246 << DATAFOLDER + "/key-eval-rot.txt" << std::endl;
247 return 1;
248 }
249 if (cc->DeserializeEvalAutomorphismKey(erkeys, SerType::BINARY) == false) {
250 std::cerr << "Could not deserialize the eval rotation key file"
251 << std::endl;
252 return 1;
253 }
254 std::cout << "Deserialized the eval rotation keys." << std::endl;
255
256 //deserializing ciphertexts
257 Ciphertext<DCRTPoly> ct1;
258 if (Serial::DeserializeFromFile(DATAFOLDER + "/ciphertext1.txt", ct1,
259 SerType::BINARY) == false) {
260 std::cerr << "Could not read the ciphertext" << std::endl;
261 return 1;
262 }
263 std::cout << "The first ciphertext has been deserialized." << std::endl;
264
265 Ciphertext<DCRTPoly> ct2;
266 if (Serial::DeserializeFromFile(DATAFOLDER + "/ciphertext1.txt", ct2,
267 SerType::BINARY) == false) {
268 std::cerr << "Could not read the ciphertext" << std::endl;
269 return 1;
270 }
271 std::cout << "The second ciphertext has been deserialized." << std::endl;
272
273 Ciphertext<DCRTPoly> ct3;
274 if (Serial::DeserializeFromFile(DATAFOLDER + "/ciphertext1.txt", ct3,
275 SerType::BINARY) == false) {
276 std::cerr << "Could not read the ciphertext" << std::endl;
277 return 1;
278 }
279 std::cout << "The third ciphertext has been deserialized." << std::endl;
280
281 // Homomorphic additions
282 auto ciphertextAdd12 = cc->EvalAdd(ct1, ct2);//iphertext2);
283 auto ciphertextAddResult = cc->EvalAdd(ciphertextAdd12, ct3);//iphertext3);
284
285 // Homomorphic multiplications
286 auto ciphertextMul12 = cc->EvalMult(ct1, ct2);//iphertext2);
287 auto ciphertextMultResult = cc->EvalMult(ciphertextMul12, ct3);//iphertext3);
288
289 // Homomorphic rotations
290 auto ciphertextRot1 = cc->EvalAtIndex(ct1, 1);
291 auto ciphertextRot2 = cc->EvalAtIndex(ct1, 2);
292 auto ciphertextRot3 = cc->EvalAtIndex(ct1, -1);
293 auto ciphertextRot4 = cc->EvalAtIndex(ct1, -2);
294
295 // Sample Program: Step 5 - Decryption
296
297 LPPrivateKey<DCRTPoly> sk;
298 if (Serial::DeserializeFromFile(DATAFOLDER + "/key-private.txt", sk,
299 SerType::BINARY) == false) {
300 std::cerr << "Could not read secret key" << std::endl;
301 return 1;
302 }
303 std::cout << "The secret key has been deserialized." << std::endl;
304
305 // Decrypt the result of additions
306 Plaintext plaintextAddResult;
307 cc->Decrypt(sk, ciphertextAddResult, &plaintextAddResult);
308
309 // Decrypt the result of multiplications
310 Plaintext plaintextMultResult;
311 cc->Decrypt(sk, ciphertextMultResult, &plaintextMultResult);
312
313 // Decrypt the result of rotations
314 Plaintext plaintextRot1;
315 cc->Decrypt(sk, ciphertextRot1, &plaintextRot1);
316 Plaintext plaintextRot2;
317 cc->Decrypt(sk, ciphertextRot2, &plaintextRot2);
318 Plaintext plaintextRot3;
319 cc->Decrypt(sk, ciphertextRot3, &plaintextRot3);
320 Plaintext plaintextRot4;
321 cc->Decrypt(sk, ciphertextRot4, &plaintextRot4);
322
323 // Shows only the same number of elements as in the original plaintext vector
324 // By default it will show all coefficients in the BFV-encoded polynomial
325 plaintextRot1->SetLength(vectorOfInts1.size());
326 plaintextRot2->SetLength(vectorOfInts1.size());
327 plaintextRot3->SetLength(vectorOfInts1.size());
328 plaintextRot4->SetLength(vectorOfInts1.size());
329
330 // Output results
331 std::cout << "\nResults of homomorphic computations" << std::endl;
332 std::cout << "#1 + #2 + #3: " << plaintextAddResult << std::endl;
333 std::cout << "#1 * #2 * #3: " << plaintextMultResult << std::endl;
334 std::cout << "Left rotation of #1 by 1: " << plaintextRot1 << std::endl;
335 std::cout << "Left rotation of #1 by 2: " << plaintextRot2 << std::endl;
336 std::cout << "Right rotation of #1 by 1: " << plaintextRot3 << std::endl;
337 std::cout << "Right rotation of #1 by 2: " << plaintextRot4 << std::endl;
338
339 return 0;
340 }
341