1 // @file bfvrns.cpp - Example of basic SHE operations. 2 // @author TPOC: contact@palisade-crypto.org 3 // 4 // @copyright Copyright (c) 2019, New Jersey Institute of Technology (NJIT)) 5 // All rights reserved. 6 // Redistribution and use in source and binary forms, with or without 7 // modification, are permitted provided that the following conditions are met: 8 // 1. Redistributions of source code must retain the above copyright notice, 9 // this list of conditions and the following disclaimer. 10 // 2. Redistributions in binary form must reproduce the above copyright notice, 11 // this list of conditions and the following disclaimer in the documentation 12 // and/or other materials provided with the distribution. THIS SOFTWARE IS 13 // PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 14 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 15 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 16 // EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 17 // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 // 24 // @section DESCRIPTION 25 // Demo software for BFV multiparty operations. 26 27 #include <chrono> 28 #include <fstream> 29 #include <iostream> 30 #include <iterator> 31 32 #include "palisade.h" 33 34 using namespace std; 35 using namespace lbcrypto; 36 37 int main(int argc, char *argv[]) { 38 //////////////////////////////////////////////////////////// 39 // Set-up of parameters 40 //////////////////////////////////////////////////////////// 41 42 std::cout << "\nThis code demonstrates the use of the BFVrns scheme for " 43 "basic homomorphic encryption operations. " 44 << std::endl; 45 std::cout 46 << "This code shows how to auto-generate parameters during run-time " 47 "based on desired plaintext moduli and security levels. " 48 << std::endl; 49 std::cout << "In this demonstration we use three input plaintext and show " 50 "how to both add them together and multiply them together. " 51 << std::endl; 52 53 // Generate parameters. 54 double diff, start, finish; 55 56 int plaintextModulus = 256; 57 double sigma = 4; 58 double rootHermiteFactor = 1.006; 59 60 // Set Crypto Parameters 61 CryptoContext<DCRTPoly> cryptoContext = 62 CryptoContextFactory<DCRTPoly>::genCryptoContextBFVrns( 63 plaintextModulus, rootHermiteFactor, sigma, 0, 5, 0, OPTIMIZED, 6); 64 65 // enable features that you wish to use 66 cryptoContext->Enable(ENCRYPTION); 67 cryptoContext->Enable(SHE); 68 69 std::cout << "p = " 70 << cryptoContext->GetCryptoParameters()->GetPlaintextModulus() 71 << std::endl; 72 std::cout << "n = " 73 << cryptoContext->GetCryptoParameters() 74 ->GetElementParams() 75 ->GetCyclotomicOrder() / 76 2 77 << std::endl; 78 std::cout << "log2 q = " 79 << log2(cryptoContext->GetCryptoParameters() 80 ->GetElementParams() 81 ->GetModulus() 82 .ConvertToDouble()) 83 << std::endl; 84 85 // Initialize Public Key Containers 86 LPKeyPair<DCRTPoly> keyPair; 87 88 //////////////////////////////////////////////////////////// 89 // Perform Key Generation Operation 90 //////////////////////////////////////////////////////////// 91 92 std::cout << "Running key generation (used for source data)..." << std::endl; 93 94 start = currentDateTime(); 95 96 keyPair = cryptoContext->KeyGen(); 97 98 // Create evaluation key vector to be used in keyswitching 99 cryptoContext->EvalMultKeysGen(keyPair.secretKey); 100 101 finish = currentDateTime(); 102 diff = finish - start; 103 cout << "Key generation time: " 104 << "\t" << diff << " ms" << endl; 105 106 if (!keyPair.good()) { 107 std::cout << "Key generation failed!" << std::endl; 108 exit(1); 109 } 110 111 //////////////////////////////////////////////////////////// 112 // Encode source data 113 //////////////////////////////////////////////////////////// 114 115 std::vector<int64_t> vectorOfInts1 = {5, 4, 3, 2, 1, 0, 5, 4, 3, 2, 1, 0}; 116 std::vector<int64_t> vectorOfInts2 = {2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 117 std::vector<int64_t> vectorOfInts3 = {2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 118 std::vector<int64_t> vectorOfInts4 = {2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 119 std::vector<int64_t> vectorOfInts5 = {2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 120 std::vector<int64_t> vectorOfInts6 = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 121 122 Plaintext plaintext1 = cryptoContext->MakeCoefPackedPlaintext(vectorOfInts1); 123 Plaintext plaintext2 = cryptoContext->MakeCoefPackedPlaintext(vectorOfInts2); 124 Plaintext plaintext3 = cryptoContext->MakeCoefPackedPlaintext(vectorOfInts3); 125 Plaintext plaintext4 = cryptoContext->MakeCoefPackedPlaintext(vectorOfInts4); 126 Plaintext plaintext5 = cryptoContext->MakeCoefPackedPlaintext(vectorOfInts5); 127 Plaintext plaintext6 = cryptoContext->MakeCoefPackedPlaintext(vectorOfInts6); 128 129 //////////////////////////////////////////////////////////// 130 // Encryption 131 //////////////////////////////////////////////////////////// 132 133 Ciphertext<DCRTPoly> ciphertext1; 134 Ciphertext<DCRTPoly> ciphertext2; 135 Ciphertext<DCRTPoly> ciphertext3; 136 Ciphertext<DCRTPoly> ciphertext4; 137 Ciphertext<DCRTPoly> ciphertext5; 138 Ciphertext<DCRTPoly> ciphertext6; 139 140 start = currentDateTime(); 141 142 ciphertext1 = cryptoContext->Encrypt(keyPair.publicKey, plaintext1); 143 ciphertext2 = cryptoContext->Encrypt(keyPair.publicKey, plaintext2); 144 ciphertext3 = cryptoContext->Encrypt(keyPair.publicKey, plaintext3); 145 ciphertext4 = cryptoContext->Encrypt(keyPair.publicKey, plaintext4); 146 ciphertext5 = cryptoContext->Encrypt(keyPair.publicKey, plaintext5); 147 ciphertext6 = cryptoContext->Encrypt(keyPair.publicKey, plaintext6); 148 149 finish = currentDateTime(); 150 diff = finish - start; 151 cout << "Encryption time: " 152 << "\t" << diff << " ms" << endl; 153 154 //////////////////////////////////////////////////////////// 155 // Decryption of Ciphertext 156 //////////////////////////////////////////////////////////// 157 158 Plaintext plaintext1Dec; 159 Plaintext plaintext2Dec; 160 Plaintext plaintext3Dec; 161 Plaintext plaintext4Dec; 162 Plaintext plaintext5Dec; 163 Plaintext plaintext6Dec; 164 165 start = currentDateTime(); 166 167 cryptoContext->Decrypt(keyPair.secretKey, ciphertext1, &plaintext1Dec); 168 cryptoContext->Decrypt(keyPair.secretKey, ciphertext2, &plaintext2Dec); 169 cryptoContext->Decrypt(keyPair.secretKey, ciphertext3, &plaintext3Dec); 170 cryptoContext->Decrypt(keyPair.secretKey, ciphertext4, &plaintext4Dec); 171 cryptoContext->Decrypt(keyPair.secretKey, ciphertext5, &plaintext5Dec); 172 cryptoContext->Decrypt(keyPair.secretKey, ciphertext6, &plaintext6Dec); 173 174 finish = currentDateTime(); 175 diff = finish - start; 176 cout << "Decryption time: " 177 << "\t" << diff << " ms" << endl; 178 179 cout << "\n Original Plaintext: \n"; 180 cout << *plaintext1 << endl; 181 cout << *plaintext2 << endl; 182 cout << *plaintext3 << endl; 183 cout << *plaintext4 << endl; 184 cout << *plaintext5 << endl; 185 cout << *plaintext6 << endl; 186 187 cout << "\n Resulting Decryption of Ciphertext: \n"; 188 cout << *plaintext1Dec << endl; 189 cout << *plaintext2Dec << endl; 190 cout << *plaintext3Dec << endl; 191 cout << *plaintext4Dec << endl; 192 cout << *plaintext5Dec << endl; 193 cout << *plaintext6Dec << endl; 194 195 cout << "\n"; 196 197 //////////////////////////////////////////////////////////// 198 // EvalMult Operation 199 //////////////////////////////////////////////////////////// 200 201 Ciphertext<DCRTPoly> ciphertextMul12; 202 Ciphertext<DCRTPoly> ciphertextMul123; 203 Ciphertext<DCRTPoly> ciphertextMul1234; 204 Ciphertext<DCRTPoly> ciphertextMul12345; 205 Ciphertext<DCRTPoly> ciphertextMul123456; 206 207 start = currentDateTime(); 208 // Perform consecutive multiplications and do a keyswtiching at the end. 209 ciphertextMul12 = cryptoContext->EvalMultNoRelin(ciphertext1, ciphertext2); 210 ciphertextMul123 = 211 cryptoContext->EvalMultNoRelin(ciphertextMul12, ciphertext3); 212 ciphertextMul1234 = 213 cryptoContext->EvalMultNoRelin(ciphertextMul123, ciphertext4); 214 ciphertextMul12345 = 215 cryptoContext->EvalMultNoRelin(ciphertextMul1234, ciphertext5); 216 ciphertextMul123456 = 217 cryptoContext->EvalMultAndRelinearize(ciphertextMul12345, ciphertext6); 218 219 finish = currentDateTime(); 220 diff = finish - start; 221 cout << "EvalMult time: " 222 << "\t" << diff << " ms" << endl; 223 224 //////////////////////////////////////////////////////////// 225 // Decryption after Accumulation Operation on Re-Encrypted Data 226 //////////////////////////////////////////////////////////// 227 228 Plaintext plaintextMul1; 229 Plaintext plaintextMul2; 230 Plaintext plaintextMul3; 231 Plaintext plaintextMul4; 232 Plaintext plaintextMul5; 233 234 start = currentDateTime(); 235 236 cryptoContext->Decrypt(keyPair.secretKey, ciphertextMul12, &plaintextMul1); 237 cryptoContext->Decrypt(keyPair.secretKey, ciphertextMul123, &plaintextMul2); 238 cryptoContext->Decrypt(keyPair.secretKey, ciphertextMul1234, &plaintextMul3); 239 cryptoContext->Decrypt(keyPair.secretKey, ciphertextMul12345, &plaintextMul4); 240 cryptoContext->Decrypt(keyPair.secretKey, ciphertextMul123456, 241 &plaintextMul5); 242 243 finish = currentDateTime(); 244 diff = finish - start; 245 246 // std::cin.get(); 247 248 cout << "\n Original Plaintext: \n"; 249 cout << *plaintext1 << endl; 250 cout << *plaintext2 << endl; 251 cout << *plaintext3 << endl; 252 cout << *plaintext4 << endl; 253 cout << *plaintext5 << endl; 254 cout << *plaintext6 << endl; 255 256 cout << "\n Resulting Plaintext (after polynomial multiplication): \n"; 257 cout << *plaintextMul1 << endl; 258 cout << *plaintextMul2 << endl; 259 cout << *plaintextMul3 << endl; 260 cout << *plaintextMul4 << endl; 261 cout << *plaintextMul5 << endl; 262 263 cout << "\n"; 264 265 //////////////////////////////////////////////////////////// 266 // EvalAdd Operation 267 //////////////////////////////////////////////////////////// 268 269 Ciphertext<DCRTPoly> ciphertextAdd12; 270 Ciphertext<DCRTPoly> ciphertextAdd123; 271 272 start = currentDateTime(); 273 274 ciphertextAdd12 = cryptoContext->EvalAdd(ciphertextMul12, ciphertextMul12345); 275 ciphertextAdd123 = cryptoContext->EvalAdd(ciphertextAdd12, ciphertextMul123); 276 277 finish = currentDateTime(); 278 diff = finish - start; 279 cout << "EvalAdd time: " 280 << "\t" << diff << " ms" << endl; 281 282 //////////////////////////////////////////////////////////// 283 // Decryption after Accumulation Operation 284 //////////////////////////////////////////////////////////// 285 286 Plaintext plaintextAdd1; 287 Plaintext plaintextAdd2; 288 289 start = currentDateTime(); 290 291 cryptoContext->Decrypt(keyPair.secretKey, ciphertextAdd12, &plaintextAdd1); 292 cryptoContext->Decrypt(keyPair.secretKey, ciphertextAdd123, &plaintextAdd2); 293 294 finish = currentDateTime(); 295 diff = finish - start; 296 297 cout << "\n Original Plaintext: \n"; 298 cout << *plaintextMul1 << endl; 299 cout << *plaintextMul4 << endl; 300 cout << *plaintextMul5 << endl; 301 302 cout << "\n Resulting Added Plaintext: \n"; 303 cout << *plaintextAdd1 << endl; 304 cout << *plaintextAdd2 << endl; 305 306 cout << "\n"; 307 308 //////////////////////////////////////////////////////////// 309 // Done 310 //////////////////////////////////////////////////////////// 311 Ciphertext<DCRTPoly> ciphertextMul1234567; 312 vector<Ciphertext<DCRTPoly>> cipherTextList; 313 314 cipherTextList.push_back(ciphertext1); 315 cipherTextList.push_back(ciphertext2); 316 cipherTextList.push_back(ciphertext3); 317 cipherTextList.push_back(ciphertext4); 318 cipherTextList.push_back(ciphertext5); 319 320 ciphertextMul1234567 = cryptoContext->EvalMultMany(cipherTextList); 321 322 Plaintext plaintextMul7; 323 cryptoContext->Decrypt(keyPair.secretKey, ciphertextMul1234567, 324 &plaintextMul7); 325 326 cout << *plaintextMul7 << endl; 327 328 std::cout << "Execution Completed." << std::endl; 329 330 return 0; 331 } 332