1 /* Copyright (C) 2020 IBM Corp.
2  * This program is Licensed under the Apache License, Version 2.0
3  * (the "License"); you may not use this file except in compliance
4  * with the License. You may obtain a copy of the License at
5  *   http://www.apache.org/licenses/LICENSE-2.0
6  * Unless required by applicable law or agreed to in writing, software
7  * distributed under the License is distributed on an "AS IS" BASIS,
8  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9  * See the License for the specific language governing permissions and
10  * limitations under the License. See accompanying LICENSE file.
11  */
12 
13 #ifndef COMMON_H
14 #define COMMON_H
15 
16 #include <iostream>
17 #include <fstream>
18 
19 #include <helib/helib.h>
20 
stripExtension(const std::string & s)21 std::string stripExtension(const std::string& s)
22 {
23   std::size_t dotPos = s.find_last_of(".");
24   return (dotPos == std::string::npos) ? s : s.substr(0, dotPos);
25 }
26 
readline(std::istream & is)27 std::string readline(std::istream& is)
28 {
29   std::string s;
30   getline(is, s);
31   return s;
32 }
33 
readKeyBinary(std::istream & keyFile,helib::PubKey & pk)34 void readKeyBinary(std::istream& keyFile, helib::PubKey& pk)
35 {
36   helib::readPubKeyBinary(keyFile, pk);
37 }
38 
readKeyBinary(std::istream & keyFile,helib::SecKey & sk)39 void readKeyBinary(std::istream& keyFile, helib::SecKey& sk)
40 {
41   helib::readSecKeyBinary(keyFile, sk);
42 }
43 
44 template <typename T1, typename T2>
45 using uniq_pair = std::pair<std::unique_ptr<T1>, std::unique_ptr<T2>>;
46 
47 template <typename KEY>
loadContextAndKey(const std::string & keyFilePath)48 uniq_pair<helib::Context, KEY> loadContextAndKey(const std::string& keyFilePath)
49 {
50   std::ifstream keyFile(keyFilePath, std::ios::binary);
51   if (!keyFile.is_open())
52     throw std::runtime_error("Cannot open Public Key file '" + keyFilePath +
53                              "'.");
54 
55   unsigned long m, p, r;
56   std::vector<long> gens, ords;
57 
58   helib::readContextBaseBinary(keyFile, m, p, r, gens, ords);
59   std::unique_ptr<helib::Context> contextp =
60       std::make_unique<helib::Context>(m, p, r, gens, ords);
61   helib::readContextBinary(keyFile, *contextp);
62 
63   std::unique_ptr<KEY> keyp = std::make_unique<KEY>(*contextp);
64   readKeyBinary(keyFile, *keyp);
65 
66   return {std::move(contextp), std::move(keyp)};
67 }
68 
estimateCtxtSize(const helib::Context & context,long offset)69 inline long estimateCtxtSize(const helib::Context& context, long offset)
70 {
71   // Return in bytes.
72 
73   // We assume that the size of each element in the DCRT is BINIO_64BIT
74 
75   // sizeof(BINIO_EYE_CTXT_BEGIN) = 4;
76   // BINIO_32BIT = 4
77   // sizeof(long) = BINIO_64BIT = 8
78   // xdouble = s * sizeof(long) = 2 * BINIO_64BIT = 16
79 
80   // We assume that primeSet after encryption is context.ctxtPrimes
81   // We assume we have exactly 2 parts after encryption
82   // We assume that the DCRT prime set is the same as the ctxt one
83 
84   long size = 0;
85 
86   size += 4;
87 
88   // Begin Ctxt metadata
89   // 64 = header_size = ptxtSpace (long) + intFactor (long) + ptxtMag (xdouble)
90   //                    + ratFactor (xdouble) + noiseBound (xdouble)
91   size += 64;
92 
93   // primeSet.write(str);
94   // size of set (long) + each prime (long)
95   size += 8 + context.ctxtPrimes.card() * 8;
96 
97   // Begin Ctxt content size
98   // write_raw_vector(str, parts);
99   // Size of the parts vector (long)
100   size += 8;
101 
102   long part_size = 0;
103   // Begin CtxtPart size
104 
105   // skHandle.write(str);
106   // powerOfS (long) + powerOfX (long) + secretKeyID (long)
107   part_size += 24;
108 
109   // Begin DCRT size computation
110 
111   // this->DoubleCRT::write(str);
112   // map.getIndexSet().write(str);
113   // size of set (long) + each prime (long)
114   part_size += 8 + context.ctxtPrimes.card() * 8;
115 
116   // DCRT data write as write_ntl_vec_long(str, map[i]);
117   // For each prime in the ctxt modulus chain
118   //    size of DCRT column (long) + size of each element (long) +
119   //    size of all the slots (column in DCRT) (PhiM long elements)
120   long dcrt_size =
121       (8 + 8 * context.zMStar.getPhiM()) * context.ctxtPrimes.card();
122 
123   part_size += dcrt_size;
124 
125   // End DCRT size
126   // End CtxtPart size
127 
128   size += 2 * part_size; // 2 * because we assumed 2 parts
129   // End Ctxt content size
130 
131   // End eye-catcher
132   size += 4;
133 
134   return size + offset;
135 }
136 
137 #endif // COMMON_H
138