forked from FudanMPL/Garnet
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCiphertext.h
executable file
·137 lines (102 loc) · 4.93 KB
/
Ciphertext.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#ifndef _Ciphertext
#define _Ciphertext
#include "FHE/FHE_Keys.h"
#include "FHE/Random_Coins.h"
#include "FHE/Plaintext.h"
class FHE_PK;
class Ciphertext;
// Forward declare the friend functions
template<class T,class FD,class S> void mul(Ciphertext& ans,const Plaintext<T,FD,S>& a,const Ciphertext& c);
template<class T,class FD,class S> void mul(Ciphertext& ans,const Ciphertext& c,const Plaintext<T,FD,S>& a);
void add(Ciphertext& ans,const Ciphertext& c0,const Ciphertext& c1);
void mul(Ciphertext& ans,const Ciphertext& c0,const Ciphertext& c1,const FHE_PK& pk);
/**
* BGV ciphertext.
* The class allows adding two ciphertexts as well as adding a plaintext and
* a ciphertext via operator overloading. The multiplication of two ciphertexts
* requires the public key and thus needs a separate function.
*/
class Ciphertext
{
Rq_Element cc0,cc1;
const FHE_Params *params;
// identifier for debugging
word pk_id;
public:
static int size() { return 0; }
const FHE_Params& get_params() const { return *params; }
Ciphertext(const FHE_Params& p)
: cc0(p.FFTD(),evaluation,evaluation),
cc1(p.FFTD(),evaluation,evaluation), pk_id(0) { params=&p; }
Ciphertext(const FHE_PK &pk);
Ciphertext(const Rq_Element& a0, const Rq_Element& a1, const Ciphertext& C) :
Ciphertext(C.get_params())
{
set(a0, a1, C.get_pk_id());
}
// Rely on default copy assignment/constructor
word get_pk_id() const { return pk_id; }
void set(const Rq_Element& a0, const Rq_Element& a1, word pk_id)
{ cc0=a0; cc1=a1; this->pk_id = pk_id; }
void set(const Rq_Element& a0, const Rq_Element& a1, const FHE_PK& pk);
const Rq_Element& c0() const { return cc0; }
const Rq_Element& c1() const { return cc1; }
void assign_zero() { cc0.assign_zero(); cc1.assign_zero(); pk_id = 0; }
// Scale down an element from level 1 to level 0, if at level 0 do nothing
void Scale(const bigint& p) { cc0.Scale(p); cc1.Scale(p); }
void Scale();
// Throws error if ans,c0,c1 etc have different params settings
// - Thus programmer needs to ensure this rather than this being done
// automatically. This saves some time in space initialization
friend void add(Ciphertext& ans,const Ciphertext& c0,const Ciphertext& c1);
friend void sub(Ciphertext& ans,const Ciphertext& c0,const Ciphertext& c1);
friend void mul(Ciphertext& ans,const Ciphertext& c0,const Ciphertext& c1,const FHE_PK& pk);
template<class T,class FD,class S> friend void mul(Ciphertext& ans,const Plaintext<T,FD,S>& a,const Ciphertext& c);
template<class T,class FD,class S> friend void mul(Ciphertext& ans,const Ciphertext& c,const Plaintext<T,FD,S>& a)
{ ::mul(ans,a,c); }
void mul(const Ciphertext& c, const Rq_Element& a);
template<class FD>
void mul(const Ciphertext& c, const Plaintext_<FD>& a) { ::mul(*this, c, a); }
template<class FD>
Ciphertext operator+(const Plaintext_<FD>& other) { Ciphertext res = *this; res += other; return res; }
template<class FD>
Ciphertext& operator+=(const Plaintext_<FD>& other) { cc0 += other.get_poly(); return *this; }
bool operator==(const Ciphertext& c) { return pk_id == c.pk_id && cc0.equals(c.cc0) && cc1.equals(c.cc1); }
bool operator!=(const Ciphertext& c) { return !(*this == c); }
Ciphertext operator+(const Ciphertext& other) const
{ Ciphertext res(*params); ::add(res, *this, other); return res; }
template <class FD>
Ciphertext operator*(const Plaintext_<FD>& other) const
{ Ciphertext res(*params); ::mul(res, *this, other); return res; }
Ciphertext& operator+=(const Ciphertext& other) { ::add(*this, *this, other); return *this; }
template <class FD>
Ciphertext& operator*=(const Plaintext_<FD>& other) { ::mul(*this, *this, other); return *this; }
/**
* Ciphertext multiplication.
* @param pk public key
* @param x second ciphertext
* @returns product ciphertext
*/
Ciphertext mul(const FHE_PK& pk, const Ciphertext& x) const
{ Ciphertext res(*params); ::mul(res, *this, x, pk); return res; }
Ciphertext mul_by_X_i(int i, const FHE_PK&) const
{
return {cc0.mul_by_X_i(i), cc1.mul_by_X_i(i), *this};
}
/// Re-randomize for circuit privacy.
void rerandomize(const FHE_PK& pk);
int level() const { return cc0.level(); }
/// Append to buffer
void pack(octetStream& o) const
{ cc0.pack(o); cc1.pack(o); o.store(pk_id); }
/// Read from buffer. Assumes parameters are set correctly
void unpack(octetStream& o)
{ cc0.unpack(o, *params); cc1.unpack(o, *params); o.get(pk_id); }
void output(ostream& s) const
{ cc0.output(s); cc1.output(s); s.write((char*)&pk_id, sizeof(pk_id)); }
void input(istream& s)
{ cc0.input(s); cc1.input(s); s.read((char*)&pk_id, sizeof(pk_id)); }
void add(octetStream& os);
size_t report_size(ReportType type) const { return cc0.report_size(type) + cc1.report_size(type); }
};
#endif