PALISADE Lattice Crypto Library  1.11.9
A lattice crypto library for software engineers by software engineers.
lwecore.h
1 // @file lwecore.h - Main Classes for Boolean circuit FHE.
2 // @author TPOC: contact@palisade-crypto.org
3 //
4 // @copyright Copyright (c) 2019, Duality Technologies Inc.
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 #ifndef BINFHE_LWECORE_H
25 #define BINFHE_LWECORE_H
26 
27 #include <string>
28 #include <utility>
29 #include <vector>
30 
31 #include "math/backend.h"
32 #include "math/discretegaussiangenerator.h"
33 #include "utils/serializable.h"
34 
35 namespace lbcrypto {
36 
37 typedef int64_t LWEPlaintext;
38 
42 class LWECryptoParams : public Serializable {
43  public:
44  LWECryptoParams() : m_n(0), m_N(0), m_q(0), m_Q(0), m_qKS(0), m_baseKS(0) {}
45 
57  explicit LWECryptoParams(uint32_t n, uint32_t N, const NativeInteger &q,
58  const NativeInteger &Q, const NativeInteger &qKS, double std, uint32_t baseKS)
59  : m_n(n), m_N(N), m_q(q), m_Q(Q), m_qKS(qKS), m_baseKS(baseKS) {
60  m_dgg.SetStd(std);
61 
62  if (Q.GetMSB() > MAX_MODULUS_SIZE) {
63  std::string errMsg =
64  "ERROR: Maximum size of Q supported for FHEW is 60 bits.";
65  PALISADE_THROW(config_error, errMsg);
66  }
67 
68  PreCompute();
69  }
70 
74  void PreCompute() {
75  // Number of digits in representing numbers mod Q
76  uint32_t digitCount = (uint32_t)std::ceil(
77  log(m_qKS.ConvertToDouble()) / log(static_cast<double>(m_baseKS)));
78  // Populate digits
79  NativeInteger value = 1;
80  for (uint32_t i = 0; i < digitCount; i++) {
81  m_digitsKS.push_back(value);
82  value *= m_baseKS;
83  }
84  }
85 
86  explicit LWECryptoParams(const LWECryptoParams &rhs) {
87  this->m_n = rhs.m_n;
88  this->m_N = rhs.m_N;
89  this->m_q = rhs.m_q;
90  this->m_Q = rhs.m_Q;
91  this->m_qKS = rhs.m_qKS;
92  this->m_baseKS = rhs.m_baseKS;
93  this->m_digitsKS = rhs.m_digitsKS;
94  this->m_dgg.SetStd(rhs.m_dgg.GetStd());
95  }
96 
97  explicit LWECryptoParams(const LWECryptoParams &&rhs) {
98  this->m_n = std::move(rhs.m_n);
99  this->m_N = std::move(rhs.m_N);
100  this->m_q = std::move(rhs.m_q);
101  this->m_Q = std::move(rhs.m_Q);
102  this->m_qKS = std::move(rhs.m_qKS);
103  this->m_baseKS = std::move(rhs.m_baseKS);
104  this->m_digitsKS = std::move(rhs.m_digitsKS);
105  this->m_dgg.SetStd(rhs.m_dgg.GetStd());
106  }
107 
108  const LWECryptoParams &operator=(const LWECryptoParams &rhs) {
109  this->m_n = rhs.m_n;
110  this->m_N = rhs.m_N;
111  this->m_q = rhs.m_q;
112  this->m_Q = rhs.m_Q;
113  this->m_qKS = rhs.m_qKS;
114  this->m_baseKS = rhs.m_baseKS;
115  this->m_digitsKS = rhs.m_digitsKS;
116  this->m_dgg.SetStd(rhs.m_dgg.GetStd());
117  return *this;
118  }
119 
120  const LWECryptoParams &operator=(const LWECryptoParams &&rhs) {
121  this->m_n = std::move(rhs.m_n);
122  this->m_N = std::move(rhs.m_N);
123  this->m_q = std::move(rhs.m_q);
124  this->m_Q = std::move(rhs.m_Q);
125  this->m_qKS = std::move(rhs.m_qKS);
126  this->m_baseKS = std::move(rhs.m_baseKS);
127  this->m_digitsKS = std::move(rhs.m_digitsKS);
128  this->m_dgg.SetStd(rhs.m_dgg.GetStd());
129  return *this;
130  }
131 
132  uint32_t Getn() const { return m_n; }
133 
134  uint32_t GetN() const { return m_N; }
135 
136  const NativeInteger &Getq() const { return m_q; }
137 
138  const NativeInteger &GetQ() const { return m_Q; }
139 
140  const NativeInteger &GetqKS() const { return m_qKS; }
141 
142  uint32_t GetBaseKS() const { return m_baseKS; }
143 
144  const std::vector<NativeInteger> &GetDigitsKS() const { return m_digitsKS; }
145 
146  const DiscreteGaussianGeneratorImpl<NativeVector> &GetDgg() const {
147  return m_dgg;
148  }
149 
150  bool operator==(const LWECryptoParams &other) const {
151  return m_n == other.m_n && m_N == other.m_N && m_q == other.m_q &&
152  m_Q == other.m_Q && m_dgg.GetStd() == other.m_dgg.GetStd() &&
153  m_baseKS == other.m_baseKS && m_digitsKS == other.m_digitsKS;
154  }
155 
156  bool operator!=(const LWECryptoParams &other) const {
157  return !(*this == other);
158  }
159 
160  template <class Archive>
161  void save(Archive &ar, std::uint32_t const version) const {
162  ar(::cereal::make_nvp("n", m_n));
163  ar(::cereal::make_nvp("N", m_N));
164  ar(::cereal::make_nvp("q", m_q));
165  ar(::cereal::make_nvp("Q", m_Q));
166  ar(::cereal::make_nvp("qSK", m_qKS));
167  ar(::cereal::make_nvp("sigma", m_dgg.GetStd()));
168  ar(::cereal::make_nvp("bKS", m_baseKS));
169  }
170 
171  template <class Archive>
172  void load(Archive &ar, std::uint32_t const version) {
173  if (version > SerializedVersion()) {
174  PALISADE_THROW(deserialize_error,
175  "serialized object version " + std::to_string(version) +
176  " is from a later version of the library");
177  }
178 
179  ar(::cereal::make_nvp("n", m_n));
180  ar(::cereal::make_nvp("N", m_N));
181  ar(::cereal::make_nvp("q", m_q));
182  ar(::cereal::make_nvp("Q", m_Q));
183  ar(::cereal::make_nvp("qSK", m_qKS));
184  double sigma;
185  ar(::cereal::make_nvp("sigma", sigma));
186  this->m_dgg.SetStd(sigma);
187  ar(::cereal::make_nvp("bKS", m_baseKS));
188 
189  this->PreCompute();
190  }
191 
192  std::string SerializedObjectName() const { return "LWECryptoParams"; }
193  static uint32_t SerializedVersion() { return 1; }
194 
195  private:
196  // lattice parameter for the additive LWE scheme
197  uint32_t m_n;
198  // ring dimension for RingGSW/RingLWE scheme
199  uint32_t m_N;
200  // modulus for the additive LWE scheme
201  NativeInteger m_q;
202  // modulus for the RingGSW/RingLWE scheme
203  NativeInteger m_Q;
204  // modulus for key-switching
205  NativeInteger m_qKS;
206  // Error distribution generator
208  // Base used in key switching
209  uint32_t m_baseKS;
210  // Powers of m_baseKS
211  std::vector<NativeInteger> m_digitsKS;
212 };
213 
219  public:
220  LWECiphertextImpl() {}
221 
222  explicit LWECiphertextImpl(const NativeVector &&a, const NativeInteger &b)
223  : m_a(std::move(a)), m_b(b) {}
224 
225  explicit LWECiphertextImpl(const NativeVector &a, const NativeInteger &b)
226  : m_a(a), m_b(b) {}
227 
229  : m_a(std::move(a)), m_b(b) {}
230 
231  explicit LWECiphertextImpl(const LWECiphertextImpl &rhs) {
232  this->m_a = rhs.m_a;
233  this->m_b = rhs.m_b;
234  }
235 
236  explicit LWECiphertextImpl(const LWECiphertextImpl &&rhs) {
237  this->m_a = std::move(rhs.m_a);
238  this->m_b = std::move(rhs.m_b);
239  }
240 
241  const LWECiphertextImpl &operator=(const LWECiphertextImpl &rhs) {
242  this->m_a = rhs.m_a;
243  this->m_b = rhs.m_b;
244  return *this;
245  }
246 
247  const LWECiphertextImpl &operator=(const LWECiphertextImpl &&rhs) {
248  this->m_a = std::move(rhs.m_a);
249  this->m_b = std::move(rhs.m_b);
250  return *this;
251  }
252 
253  const NativeVector &GetA() const { return m_a; }
254 
255  const NativeInteger &GetA(std::size_t i) const { return m_a[i]; }
256 
257  const NativeInteger &GetB() const { return m_b; }
258 
259  void SetA(const NativeVector &a) { m_a = a; }
260 
261  void SetB(const NativeInteger &b) { m_b = b; }
262 
263  bool operator==(const LWECiphertextImpl &other) const {
264  return m_a == other.m_a && m_b == other.m_b;
265  }
266 
267  bool operator!=(const LWECiphertextImpl &other) const {
268  return !(*this == other);
269  }
270 
271  template <class Archive>
272  void save(Archive &ar, std::uint32_t const version) const {
273  ar(::cereal::make_nvp("a", m_a));
274  ar(::cereal::make_nvp("b", m_b));
275  }
276 
277  template <class Archive>
278  void load(Archive &ar, std::uint32_t const version) {
279  if (version > SerializedVersion()) {
280  PALISADE_THROW(deserialize_error,
281  "serialized object version " + std::to_string(version) +
282  " is from a later version of the library");
283  }
284 
285  ar(::cereal::make_nvp("a", m_a));
286  ar(::cereal::make_nvp("b", m_b));
287  }
288 
289  std::string SerializedObjectName() const { return "LWECiphertext"; }
290  static uint32_t SerializedVersion() { return 1; }
291 
292  private:
293  NativeVector m_a;
294  NativeInteger m_b;
295 };
296 
301  public:
302  LWEPrivateKeyImpl() {}
303 
304  explicit LWEPrivateKeyImpl(const NativeVector &s) : m_s(s) {}
305 
306  explicit LWEPrivateKeyImpl(const LWEPrivateKeyImpl &rhs) {
307  this->m_s = rhs.m_s;
308  }
309 
310  explicit LWEPrivateKeyImpl(const LWEPrivateKeyImpl &&rhs) {
311  this->m_s = std::move(rhs.m_s);
312  }
313 
314  const LWEPrivateKeyImpl &operator=(const LWEPrivateKeyImpl &rhs) {
315  this->m_s = rhs.m_s;
316  return *this;
317  }
318 
319  const LWEPrivateKeyImpl &operator=(const LWEPrivateKeyImpl &&rhs) {
320  this->m_s = std::move(rhs.m_s);
321  return *this;
322  }
323 
324  const NativeVector &GetElement() const { return m_s; }
325 
326  void SetElement(const NativeVector &s) { m_s = s; }
327 
328  bool operator==(const LWEPrivateKeyImpl &other) const {
329  return m_s == other.m_s;
330  }
331 
332  bool operator!=(const LWEPrivateKeyImpl &other) const {
333  return !(*this == other);
334  }
335 
336  template <class Archive>
337  void save(Archive &ar, std::uint32_t const version) const {
338  ar(::cereal::make_nvp("s", m_s));
339  }
340 
341  template <class Archive>
342  void load(Archive &ar, std::uint32_t const version) {
343  if (version > SerializedVersion()) {
344  PALISADE_THROW(deserialize_error,
345  "serialized object version " + std::to_string(version) +
346  " is from a later version of the library");
347  }
348 
349  ar(::cereal::make_nvp("s", m_s));
350  }
351 
352  std::string SerializedObjectName() const { return "LWEPrivateKey"; }
353  static uint32_t SerializedVersion() { return 1; }
354 
355  private:
356  NativeVector m_s;
357 };
358 
363  public:
364  LWESwitchingKey() {}
365 
366  explicit LWESwitchingKey(
367  const std::vector<std::vector<std::vector<LWECiphertextImpl>>> &key)
368  : m_key(key) {}
369 
370  explicit LWESwitchingKey(const LWESwitchingKey &rhs) {
371  this->m_key = rhs.m_key;
372  }
373 
374  explicit LWESwitchingKey(const LWESwitchingKey &&rhs) {
375  this->m_key = std::move(rhs.m_key);
376  }
377 
378  const LWESwitchingKey &operator=(const LWESwitchingKey &rhs) {
379  this->m_key = rhs.m_key;
380  return *this;
381  }
382 
383  const LWESwitchingKey &operator=(const LWESwitchingKey &&rhs) {
384  this->m_key = std::move(rhs.m_key);
385  return *this;
386  }
387 
388  const std::vector<std::vector<std::vector<LWECiphertextImpl>>> &GetElements()
389  const {
390  return m_key;
391  }
392 
393  void SetElements(
394  const std::vector<std::vector<std::vector<LWECiphertextImpl>>> &key) {
395  m_key = key;
396  }
397 
398  bool operator==(const LWESwitchingKey &other) const {
399  return m_key == other.m_key;
400  }
401 
402  bool operator!=(const LWESwitchingKey &other) const {
403  return !(*this == other);
404  }
405 
406  template <class Archive>
407  void save(Archive &ar, std::uint32_t const version) const {
408  ar(::cereal::make_nvp("k", m_key));
409  }
410 
411  template <class Archive>
412  void load(Archive &ar, std::uint32_t const version) {
413  if (version > SerializedVersion()) {
414  PALISADE_THROW(deserialize_error,
415  "serialized object version " + std::to_string(version) +
416  " is from a later version of the library");
417  }
418 
419  ar(::cereal::make_nvp("k", m_key));
420  }
421 
422  std::string SerializedObjectName() const { return "LWEPrivateKey"; }
423  static uint32_t SerializedVersion() { return 1; }
424 
425  private:
426  std::vector<std::vector<std::vector<LWECiphertextImpl>>> m_key;
427 };
428 
429 } // namespace lbcrypto
430 
431 #endif
LWECryptoParams(uint32_t n, uint32_t N, const NativeInteger &q, const NativeInteger &Q, const NativeInteger &qKS, double std, uint32_t baseKS)
Definition: lwecore.h:57
Base class for PALISADE serialization.
Definition: serializable.h:76
void PreCompute()
Definition: lwecore.h:74
Class that stores all parameters for the LWE scheme.
Definition: lwecore.h:42
usint GetMSB() const
Definition: ubintnat.h:1932
Definition: stl_allocator.h:124
Class that stores a LWE scheme ciphertext; composed of a vector "a" and integer "b".
Definition: lwecore.h:218
Definition: exception.h:147
Class that stores the LWE scheme switching key.
Definition: lwecore.h:362
Definition: mubintvecnat.h:102
Class that stores the LWE scheme secret key; contains a vector.
Definition: lwecore.h:300
The class for Discrete Gaussion Distribution generator.
Definition: discretegaussiangenerator.h:73
Definition: binfhecontext.h:36
Main class for big integers represented as an array of native (primitive) unsigned integers...
Definition: backend.h:60
Definition: exception.h:107
double ConvertToDouble() const
Definition: ubintnat.h:1899