forked from data61/MP-SPDZ
-
Notifications
You must be signed in to change notification settings - Fork 0
/
FHE_Keys.h
244 lines (176 loc) · 6.48 KB
/
FHE_Keys.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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
#ifndef _FHE_Keys
#define _FHE_Keys
/* These are standardly generated FHE public and private key pairs */
#include "FHE/Rq_Element.h"
#include "FHE/FHE_Params.h"
#include "FHE/Random_Coins.h"
#include "FHE/Ciphertext.h"
#include "FHE/Plaintext.h"
class FHE_PK;
class Ciphertext;
/**
* BGV secret key.
* The class allows addition.
*/
class FHE_SK
{
Rq_Element sk;
const FHE_Params *params;
bigint pr;
public:
static int size() { return 0; }
const FHE_Params& get_params() const { return *params; }
bigint p() const { return pr; }
// secret key always on lower level
void assign(const Rq_Element& s) { sk=s; sk.lower_level(); }
FHE_SK(const FHE_Params& pms);
FHE_SK(const FHE_Params& pms, const bigint& p)
: sk(pms.FFTD(),evaluation,evaluation) { params=&pms; pr=p; }
FHE_SK(const FHE_PK& pk);
// Rely on default copy constructor/assignment
const Rq_Element& s() const { return sk; }
/// Append to buffer
void pack(octetStream& os, int = -1) const { sk.pack(os); pr.pack(os); }
/// Read from buffer. Assumes parameters are set correctly
void unpack(octetStream& os, int = -1)
{ sk.unpack(os, *params); pr.unpack(os); }
// Assumes Ring and prime of mess have already been set correctly
// Ciphertext c must be at level 0 or an error occurs
// c must have same params as SK
template<class T, class FD, class S>
void decrypt(Plaintext<T, FD, S>& mess,const Ciphertext& c) const;
template <class FD>
Plaintext<typename FD::T, FD, typename FD::S> decrypt(const Ciphertext& c, const FD& FieldD);
/// Decryption for cleartexts modulo prime
Plaintext_<FFT_Data> decrypt(const Ciphertext& c);
template <class FD>
void decrypt_any(Plaintext_<FD>& mess, const Ciphertext& c);
Rq_Element quasi_decrypt(const Ciphertext& c) const;
// Three stage procedure for Distributed Decryption
// - First stage produces my shares
// - Second stage adds in another players shares, do this once for each other player
// - Third stage outputs the message by executing
// mess.set_poly_mod(vv,mod)
// where mod p0 and mess is Plaintext<T,FD,S>
void dist_decrypt_1(vector<bigint>& vv,const Ciphertext& ctx,int player_number,int num_players) const;
void dist_decrypt_2(vector<bigint>& vv,const vector<bigint>& vv1) const;
friend void KeyGen(FHE_PK& PK,FHE_SK& SK,PRNG& G);
/* Add secret keys
* Used for adding distributed keys together
* a,b,c must have same params otherwise an error
*/
FHE_SK operator+(const FHE_SK& x) const { FHE_SK res = *this; res += x; return res; }
FHE_SK& operator+=(const FHE_SK& x);
bool operator!=(const FHE_SK& x) const { return pr != x.pr or sk != x.sk; }
void add(octetStream& os, int = -1)
{ FHE_SK tmp(*this); tmp.unpack(os); *this += tmp; }
void check(const FHE_Params& params, const FHE_PK& pk, const bigint& pr) const;
template<class FD>
void check(const FHE_PK& pk, const FD& FieldD);
bigint get_noise(const Ciphertext& c);
friend ostream& operator<<(ostream& o, const FHE_SK&) { throw not_implemented(); return o; }
};
/**
* BGV public key.
*/
class FHE_PK
{
Rq_Element a0,b0;
Rq_Element Sw_a,Sw_b;
const FHE_Params *params;
bigint pr;
public:
const FHE_Params& get_params() const { return *params; }
bigint p() const { return pr; }
void assign(const Rq_Element& a,const Rq_Element& b,
const Rq_Element& sa = {},const Rq_Element& sb = {}
)
{ a0=a; b0=b; Sw_a=sa; Sw_b=sb; }
FHE_PK(const FHE_Params& pms);
FHE_PK(const FHE_Params& pms, const bigint& p)
: a0(pms.FFTD(),evaluation,evaluation),
b0(pms.FFTD(),evaluation,evaluation),
Sw_a(pms.FFTD(),evaluation,evaluation),
Sw_b(pms.FFTD(),evaluation,evaluation)
{ params=&pms; pr=p; }
FHE_PK(const FHE_Params& pms, int p) :
FHE_PK(pms, bigint(p))
{
}
template<class FD>
FHE_PK(const FHE_Params& pms, const FD& FTD) :
FHE_PK(pms, FTD.get_prime())
{
}
// Rely on default copy constructor/assignment
const Rq_Element& a() const { return a0; }
const Rq_Element& b() const { return b0; }
const Rq_Element& as() const { return Sw_a; }
const Rq_Element& bs() const { return Sw_b; }
// c must have same params as PK and rc
template <class T, class FD, class S>
void encrypt(Ciphertext& c, const Plaintext<T, FD, S>& mess, const Random_Coins& rc) const;
template <class S>
void encrypt(Ciphertext& c, const vector<S>& mess, const Random_Coins& rc) const;
void quasi_encrypt(Ciphertext& c, const Rq_Element& mess, const Random_Coins& rc) const;
template <class FD>
Ciphertext encrypt(const Plaintext<typename FD::T, FD, typename FD::S>& mess, const Random_Coins& rc) const;
/// Encryption
template <class FD>
Ciphertext encrypt(const Plaintext<typename FD::T, FD, typename FD::S>& mess) const;
Ciphertext encrypt(const Rq_Element& mess) const;
friend void KeyGen(FHE_PK& PK,FHE_SK& SK,PRNG& G);
Rq_Element sample_secret_key(PRNG& G);
void KeyGen(Rq_Element& sk, PRNG& G, int noise_boost = 1);
void partial_key_gen(const Rq_Element& sk, const Rq_Element& a, PRNG& G,
int noise_boost = 1);
void check_noise(const FHE_SK& sk) const;
void check_noise(const Rq_Element& x, bool check_modulo = false) const;
/// Append to buffer
void pack(octetStream& o) const;
/// Read from buffer. Assumes parameters are set correctly
void unpack(octetStream& o);
bool operator!=(const FHE_PK& x) const;
void check(const FHE_Params& params, const bigint& pr) const;
};
// PK and SK must have the same params, otherwise an error
void KeyGen(FHE_PK& PK,FHE_SK& SK,PRNG& G);
/**
* BGV key pair
*/
class FHE_KeyPair
{
public:
/// Public key
FHE_PK pk;
/// Secret key
FHE_SK sk;
FHE_KeyPair(const FHE_Params& params, const bigint& pr) :
pk(params, pr), sk(params, pr)
{
}
/// Initialization
FHE_KeyPair(const FHE_Params& params) :
pk(params), sk(params)
{
}
void generate(PRNG& G)
{
KeyGen(pk, sk, G);
}
/// Generate fresh keys
void generate()
{
SeededPRNG G;
generate(G);
}
};
template <class S>
void FHE_PK::encrypt(Ciphertext& c, const vector<S>& mess,
const Random_Coins& rc) const
{
Rq_Element mm((*params).FFTD(),polynomial,polynomial);
mm.from(Iterator<S>(mess));
quasi_encrypt(c, mm, rc);
}
#endif