Skip to content

Commit 9ebbc61

Browse files
authored
Merge pull request #3 from wfus/homo
Homo
2 parents 4b32719 + 6899f61 commit 9ebbc61

File tree

6 files changed

+418
-351
lines changed

6 files changed

+418
-351
lines changed

.vscode/settings.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"files.associations": {
3+
"algorithm": "cpp",
4+
"random": "cpp"
5+
}
6+
}

homo/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ all : raymond dct encode test
1111

1212

1313
raymond : raymond.cpp
14-
$(CXX) $(CXXFLAGS) $(LDFLAGS) raymond.cpp $(addprefix -I,$(INCLUDE_DIR)) $(addprefix -L,$(LIB_DIR)) -lseal -o $(BIN_DIR)/raymond
14+
$(CXX) $(CXXFLAGS) $(LDFLAGS) fhe_image.h raymond.cpp $(addprefix -I,$(INCLUDE_DIR)) $(addprefix -L,$(LIB_DIR)) -lseal -o $(BIN_DIR)/raymond
1515

1616
dct : dct.cpp
1717
@-mkdir -p $(dir $@)

homo/fhe_image.h

Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,285 @@
1+
#ifndef FHE_IMAGE_H
2+
#define FHE_IMAGE_H
3+
4+
#include <iostream>
5+
#include <iomanip>
6+
#include <vector>
7+
#include <string>
8+
#include <chrono>
9+
#include <random>
10+
#include <thread>
11+
#include <mutex>
12+
#include <random>
13+
#include <limits>
14+
#include <fstream>
15+
#include <cmath>
16+
17+
18+
#include "seal/seal.h"
19+
using namespace seal;
20+
21+
22+
const int BLOCK_SIZE = 8;
23+
std::vector<std::vector<double>> split_image_eight_block(std::vector<double> im, int w, int h) {
24+
std::vector<std::vector<double>> lst;
25+
for (int i = 0; i < w; i += BLOCK_SIZE) {
26+
for (int j = 0; j < h; j += BLOCK_SIZE) {
27+
std::vector<double> new_lst;
28+
for (int k = 0; k < BLOCK_SIZE; k++)
29+
for (int l = 0; l < BLOCK_SIZE; l++) {
30+
int index = (j+k)*w + i + l;
31+
new_lst.push_back(im[index]);
32+
}
33+
lst.push_back(new_lst);
34+
}
35+
}
36+
return lst;
37+
}
38+
39+
void print_image(std::vector<double> &im, int w, int h) {
40+
std::cout << "Printing Image dim: (" << w << "," << h << ")" << std::endl;
41+
for (int i = 0; i < im.size(); i++) {
42+
std::cout << std::setw(11) << im[i] << " ";
43+
if ((i + 1) % w == 0) std::cout << std::endl;
44+
}
45+
}
46+
47+
48+
void print_blocks(std::vector<std::vector<double>> &blocks) {
49+
for (int a = 0; a < blocks.size(); a++) {
50+
std::cout << "Printing block " << a << std::endl;
51+
for (int i = 0; i < blocks[a].size(); i++) {
52+
std::cout << std::setw(11) << blocks[a][i] << " ";
53+
if ((i + 1) % BLOCK_SIZE == 0) std::cout << std::endl;
54+
}
55+
std::cout << "---------------" << std::endl;
56+
}
57+
}
58+
59+
std::vector<double> read_image(std::string fname) {
60+
int w, h;
61+
std::vector<double> im;
62+
std::ifstream myfile;
63+
64+
myfile.open(fname.c_str());
65+
myfile >> w;
66+
myfile >> h;
67+
std::cout << "Read in " << fname << "with dimensions: " << w << " x " << h << std::endl;
68+
69+
float tmp;
70+
for (int i = 0; i < w*h; i++) {
71+
myfile >> tmp;
72+
im.push_back(tmp);
73+
}
74+
return im;
75+
}
76+
77+
78+
/* Recieves a 8x8 box of pixels, in ciphertext form.
79+
* Data should be laid out in a 64 element vector with
80+
* rows first then columns
81+
*/
82+
void encrypted_dct(std::vector<Ciphertext> &data,
83+
Evaluator &evaluator,
84+
FractionalEncoder &encoder,
85+
Encryptor &encryptor) {
86+
Ciphertext z1, z2, z3, z4, z5;
87+
Ciphertext tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp10, tmp11, tmp12, tmp13;
88+
Ciphertext tmp14;
89+
Ciphertext cons1;
90+
int curr_index = 0;
91+
for (int c = 0; c < BLOCK_SIZE; c++) {
92+
Ciphertext boaz1(data[curr_index+0]); evaluator.add(boaz1, data[curr_index+7]); tmp0 = boaz1;
93+
Ciphertext boaz2(data[curr_index+0]); evaluator.sub(boaz2, data[curr_index+7]); tmp7 = boaz2;
94+
Ciphertext boaz3(data[curr_index+1]); evaluator.add(boaz3, data[curr_index+6]); tmp1 = boaz3;
95+
Ciphertext boaz4(data[curr_index+1]); evaluator.sub(boaz4, data[curr_index+6]); tmp6 = boaz4;
96+
Ciphertext boaz5(data[curr_index+2]); evaluator.add(boaz5, data[curr_index+5]); tmp2 = boaz5;
97+
Ciphertext boaz6(data[curr_index+2]); evaluator.sub(boaz6, data[curr_index+5]); tmp5 = boaz6;
98+
Ciphertext boaz7(data[curr_index+3]); evaluator.add(boaz7, data[curr_index+4]); tmp3 = boaz7;
99+
Ciphertext boaz8(data[curr_index+3]); evaluator.sub(boaz8, data[curr_index+4]); tmp4 = boaz8;
100+
Ciphertext boaz9(tmp0); evaluator.add(boaz9, tmp3); tmp10 = boaz9;
101+
Ciphertext boaz10(tmp0); evaluator.sub(boaz10, tmp3); tmp13 = boaz10;
102+
Ciphertext boaz11(tmp1); evaluator.add(boaz11, tmp2); tmp11 = boaz11;
103+
Ciphertext boaz12(tmp1); evaluator.sub(boaz12, tmp2); tmp12 = boaz12;
104+
Ciphertext boaz13(tmp10); evaluator.add(boaz13, tmp11); data[curr_index+0] = boaz13;
105+
Ciphertext boaz14(tmp10); evaluator.sub(boaz14, tmp11); data[curr_index+4] = boaz14;
106+
Ciphertext boaz15(tmp12); evaluator.add(boaz15, tmp13); Ciphertext boaz16(boaz15); evaluator.multiply_plain(boaz16, encoder.encode(0.541196100)); z1 = boaz16;
107+
Ciphertext boaz17(tmp13); evaluator.multiply_plain(boaz17, encoder.encode(0.765366865)); Ciphertext boaz18(z1); evaluator.add(boaz18, boaz17); data[curr_index+2] = boaz18;
108+
Ciphertext boaz19(tmp12); evaluator.multiply_plain(boaz19, encoder.encode(-1.847759065)); Ciphertext boaz20(z1); evaluator.add(boaz20, boaz19); data[curr_index+6] = boaz20;
109+
Ciphertext boaz21(tmp4); evaluator.add(boaz21, tmp7); z1 = boaz21;
110+
Ciphertext boaz22(tmp5); evaluator.add(boaz22, tmp6); z2 = boaz22;
111+
Ciphertext boaz23(tmp4); evaluator.add(boaz23, tmp6); z3 = boaz23;
112+
Ciphertext boaz24(tmp5); evaluator.add(boaz24, tmp7); z4 = boaz24;
113+
Ciphertext boaz25(z3); evaluator.add(boaz25, z4); Ciphertext boaz26(boaz25); evaluator.multiply_plain(boaz26, encoder.encode(1.175875602)); z5 = boaz26;
114+
Ciphertext boaz27(tmp4); evaluator.multiply_plain(boaz27, encoder.encode(0.298631336)); tmp4 = boaz27;
115+
Ciphertext boaz28(tmp5); evaluator.multiply_plain(boaz28, encoder.encode(2.053119869)); tmp5 = boaz28;
116+
Ciphertext boaz29(tmp6); evaluator.multiply_plain(boaz29, encoder.encode(3.072711026)); tmp6 = boaz29;
117+
Ciphertext boaz30(tmp7); evaluator.multiply_plain(boaz30, encoder.encode(1.501321110)); tmp7 = boaz30;
118+
Ciphertext boaz31(z1); evaluator.multiply_plain(boaz31, encoder.encode(-0.899976223)); z1 = boaz31;
119+
Ciphertext boaz32(z2); evaluator.multiply_plain(boaz32, encoder.encode(-2.562915447)); z2 = boaz32;
120+
Ciphertext boaz33(z3); evaluator.multiply_plain(boaz33, encoder.encode(-1.961570560)); z3 = boaz33;
121+
Ciphertext boaz34(z4); evaluator.multiply_plain(boaz34, encoder.encode(-0.390180644)); z4 = boaz34;
122+
Ciphertext boaz35(z3); evaluator.add(boaz35, z5); z3 = boaz35;
123+
Ciphertext boaz36(z4); evaluator.add(boaz36, z5); z4 = boaz36;
124+
Ciphertext boaz37(tmp4); evaluator.add(boaz37, z1); Ciphertext boaz38(boaz37); evaluator.add(boaz38, z3); data[curr_index+7] = boaz38;
125+
Ciphertext boaz39(tmp5); evaluator.add(boaz39, z2); Ciphertext boaz40(boaz39); evaluator.add(boaz40, z4); data[curr_index+5] = boaz40;
126+
Ciphertext boaz41(tmp6); evaluator.add(boaz41, z2); Ciphertext boaz42(boaz41); evaluator.add(boaz42, z3); data[curr_index+3] = boaz42;
127+
Ciphertext boaz43(tmp7); evaluator.add(boaz43, z1); Ciphertext boaz44(boaz43); evaluator.add(boaz44, z4); data[curr_index+1] = boaz44;
128+
curr_index += BLOCK_SIZE;
129+
}
130+
curr_index = 0;
131+
for (int c = 0; c < BLOCK_SIZE; c++) {
132+
Ciphertext boaz45(data[curr_index+0]); evaluator.add(boaz45, data[curr_index+56]); tmp0 = boaz45;
133+
Ciphertext boaz46(data[curr_index+0]); evaluator.sub(boaz46, data[curr_index+56]); tmp7 = boaz46;
134+
Ciphertext boaz47(data[curr_index+8]); evaluator.add(boaz47, data[curr_index+48]); tmp1 = boaz47;
135+
Ciphertext boaz48(data[curr_index+8]); evaluator.sub(boaz48, data[curr_index+48]); tmp6 = boaz48;
136+
Ciphertext boaz49(data[curr_index+16]); evaluator.add(boaz49, data[curr_index+40]); tmp2 = boaz49;
137+
Ciphertext boaz50(data[curr_index+16]); evaluator.sub(boaz50, data[curr_index+40]); tmp5 = boaz50;
138+
Ciphertext boaz51(data[curr_index+24]); evaluator.add(boaz51, data[curr_index+32]); tmp3 = boaz51;
139+
Ciphertext boaz52(data[curr_index+24]); evaluator.sub(boaz52, data[curr_index+32]); tmp4 = boaz52;
140+
Ciphertext boaz53(tmp0); evaluator.add(boaz53, tmp3); tmp10 = boaz53;
141+
Ciphertext boaz54(tmp0); evaluator.sub(boaz54, tmp3); tmp13 = boaz54;
142+
Ciphertext boaz55(tmp1); evaluator.add(boaz55, tmp2); tmp11 = boaz55;
143+
Ciphertext boaz56(tmp1); evaluator.sub(boaz56, tmp2); tmp12 = boaz56;
144+
Ciphertext boaz57(tmp10); evaluator.add(boaz57, tmp11); Ciphertext boaz58(boaz57); evaluator.multiply_plain(boaz58, encoder.encode(0.125)); data[curr_index+0] = boaz58;
145+
Ciphertext boaz59(tmp10); evaluator.sub(boaz59, tmp11); Ciphertext boaz60(boaz59); evaluator.multiply_plain(boaz60, encoder.encode(0.125)); data[curr_index+32] = boaz60;
146+
Ciphertext boaz61(tmp12); evaluator.add(boaz61, tmp13); Ciphertext boaz62(boaz61); evaluator.multiply_plain(boaz62, encoder.encode(0.541196100)); z1 = boaz62;
147+
Ciphertext boaz63(tmp13); evaluator.multiply_plain(boaz63, encoder.encode(0.765366865)); Ciphertext boaz64(z1); evaluator.add(boaz64, boaz63); Ciphertext boaz65(boaz64); evaluator.multiply_plain(boaz65, encoder.encode(0.125)); data[curr_index+16] = boaz65;
148+
Ciphertext boaz66(tmp12); evaluator.multiply_plain(boaz66, encoder.encode(-1.847759065)); Ciphertext boaz67(z1); evaluator.add(boaz67, boaz66); Ciphertext boaz68(boaz67); evaluator.multiply_plain(boaz68, encoder.encode(0.125)); data[curr_index+48] = boaz68;
149+
Ciphertext boaz69(tmp4); evaluator.add(boaz69, tmp7); z1 = boaz69;
150+
Ciphertext boaz70(tmp5); evaluator.add(boaz70, tmp6); z2 = boaz70;
151+
Ciphertext boaz71(tmp4); evaluator.add(boaz71, tmp6); z3 = boaz71;
152+
Ciphertext boaz72(tmp5); evaluator.add(boaz72, tmp7); z4 = boaz72;
153+
Ciphertext boaz73(z3); evaluator.add(boaz73, z4); Ciphertext boaz74(boaz73); evaluator.multiply_plain(boaz74, encoder.encode(1.175875602)); z5 = boaz74;
154+
Ciphertext boaz75(tmp4); evaluator.multiply_plain(boaz75, encoder.encode(0.298631336)); tmp4 = boaz75;
155+
Ciphertext boaz76(tmp5); evaluator.multiply_plain(boaz76, encoder.encode(2.053119869)); tmp5 = boaz76;
156+
Ciphertext boaz77(tmp6); evaluator.multiply_plain(boaz77, encoder.encode(3.072711026)); tmp6 = boaz77;
157+
Ciphertext boaz78(tmp7); evaluator.multiply_plain(boaz78, encoder.encode(1.501321110)); tmp7 = boaz78;
158+
Ciphertext boaz79(z1); evaluator.multiply_plain(boaz79, encoder.encode(-0.899976223)); z1 = boaz79;
159+
Ciphertext boaz80(z2); evaluator.multiply_plain(boaz80, encoder.encode(-2.562915447)); z2 = boaz80;
160+
Ciphertext boaz81(z3); evaluator.multiply_plain(boaz81, encoder.encode(-1.961570560)); z3 = boaz81;
161+
Ciphertext boaz82(z4); evaluator.multiply_plain(boaz82, encoder.encode(-0.390180644)); z4 = boaz82;
162+
Ciphertext boaz83(z3); evaluator.add(boaz83, z5); z3 = boaz83;
163+
Ciphertext boaz84(z4); evaluator.add(boaz84, z5); z4 = boaz84;
164+
Ciphertext boaz85(tmp4); evaluator.add(boaz85, z1); Ciphertext boaz86(boaz85); evaluator.add(boaz86, z3); Ciphertext boaz87(boaz86); evaluator.multiply_plain(boaz87, encoder.encode(0.125)); data[curr_index+56] = boaz87;
165+
Ciphertext boaz88(tmp5); evaluator.add(boaz88, z2); Ciphertext boaz89(boaz88); evaluator.add(boaz89, z4); Ciphertext boaz90(boaz89); evaluator.multiply_plain(boaz90, encoder.encode(0.125)); data[curr_index+40] = boaz90;
166+
Ciphertext boaz91(tmp6); evaluator.add(boaz91, z2); Ciphertext boaz92(boaz91); evaluator.add(boaz92, z3); Ciphertext boaz93(boaz92); evaluator.multiply_plain(boaz93, encoder.encode(0.125)); data[curr_index+24] = boaz93;
167+
Ciphertext boaz94(tmp7); evaluator.add(boaz94, z1); Ciphertext boaz95(boaz94); evaluator.add(boaz95, z4); Ciphertext boaz96(boaz95); evaluator.multiply_plain(boaz96, encoder.encode(0.125)); data[curr_index+8]= boaz96;
168+
curr_index++;
169+
}
170+
return;
171+
}
172+
173+
/* Recieves a 8x8 box of pixels, in ciphertext form.
174+
* Data should be laid out in a 64 element vector with
175+
* rows first then columns. Divides each element by quant
176+
*/
177+
inline void quantize_fhe(std::vector<Ciphertext> &data,
178+
const std::vector<double> &quant,
179+
Evaluator &evaluator,
180+
FractionalEncoder &encoder,
181+
Encryptor &encryptor) {
182+
for (int i = 0; i < 64; i++) {
183+
evaluator.multiply_plain(data[i], encoder.encode(1/quant[i]));
184+
}
185+
}
186+
187+
188+
189+
190+
191+
// Forward DCT, regular no encryption
192+
inline void dct(double *data) {
193+
double z1, z2, z3, z4, z5, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp10, tmp11, tmp12, tmp13, *data_ptr;
194+
data_ptr = data;
195+
for (int c=0; c < 8; c++) {
196+
tmp0 = data_ptr[0] + data_ptr[7];
197+
tmp7 = data_ptr[0] - data_ptr[7];
198+
tmp1 = data_ptr[1] + data_ptr[6];
199+
tmp6 = data_ptr[1] - data_ptr[6];
200+
tmp2 = data_ptr[2] + data_ptr[5];
201+
tmp5 = data_ptr[2] - data_ptr[5];
202+
tmp3 = data_ptr[3] + data_ptr[4];
203+
tmp4 = data_ptr[3] - data_ptr[4];
204+
tmp10 = tmp0 + tmp3;
205+
tmp13 = tmp0 - tmp3;
206+
tmp11 = tmp1 + tmp2;
207+
tmp12 = tmp1 - tmp2;
208+
data_ptr[0] = tmp10 + tmp11;
209+
data_ptr[4] = tmp10 - tmp11;
210+
z1 = (tmp12 + tmp13) * 0.541196100;
211+
data_ptr[2] = z1 + tmp13 * 0.765366865;
212+
data_ptr[6] = z1 + tmp12 * - 1.847759065;
213+
z1 = tmp4 + tmp7;
214+
z2 = tmp5 + tmp6;
215+
z3 = tmp4 + tmp6;
216+
z4 = tmp5 + tmp7;
217+
z5 = (z3 + z4) * 1.175875602;
218+
tmp4 *= 0.298631336;
219+
tmp5 *= 2.053119869;
220+
tmp6 *= 3.072711026;
221+
tmp7 *= 1.501321110;
222+
z1 *= -0.899976223;
223+
z2 *= -2.562915447;
224+
z3 *= -1.961570560;
225+
z4 *= -0.390180644;
226+
z3 += z5;
227+
z4 += z5;
228+
data_ptr[7] = tmp4 + z1 + z3;
229+
data_ptr[5] = tmp5 + z2 + z4;
230+
data_ptr[3] = tmp6 + z2 + z3;
231+
data_ptr[1] = tmp7 + z1 + z4;
232+
data_ptr += 8;
233+
}
234+
235+
data_ptr = data;
236+
237+
for (int c=0; c < 8; c++) {
238+
tmp0 = data_ptr[8*0] + data_ptr[8*7];
239+
tmp7 = data_ptr[8*0] - data_ptr[8*7];
240+
tmp1 = data_ptr[8*1] + data_ptr[8*6];
241+
tmp6 = data_ptr[8*1] - data_ptr[8*6];
242+
tmp2 = data_ptr[8*2] + data_ptr[8*5];
243+
tmp5 = data_ptr[8*2] - data_ptr[8*5];
244+
tmp3 = data_ptr[8*3] + data_ptr[8*4];
245+
tmp4 = data_ptr[8*3] - data_ptr[8*4];
246+
tmp10 = tmp0 + tmp3;
247+
tmp13 = tmp0 - tmp3;
248+
tmp11 = tmp1 + tmp2;
249+
tmp12 = tmp1 - tmp2;
250+
data_ptr[8*0] = (tmp10 + tmp11) / 8.0;
251+
data_ptr[8*4] = (tmp10 - tmp11) / 8.0;
252+
z1 = (tmp12 + tmp13) * 0.541196100;
253+
data_ptr[8*2] = (z1 + tmp13 * 0.765366865) / 8.0;
254+
data_ptr[8*6] = (z1 + tmp12 * -1.847759065) / 8.0;
255+
z1 = tmp4 + tmp7;
256+
z2 = tmp5 + tmp6;
257+
z3 = tmp4 + tmp6;
258+
z4 = tmp5 + tmp7;
259+
z5 = (z3 + z4) * 1.175875602;
260+
tmp4 *= 0.298631336;
261+
tmp5 *= 2.053119869;
262+
tmp6 *= 3.072711026;
263+
tmp7 *= 1.501321110;
264+
z1 *= -0.899976223;
265+
z2 *= -2.562915447;
266+
z3 *= -1.961570560;
267+
z4 *= -0.390180644;
268+
z3 += z5;
269+
z4 += z5;
270+
data_ptr[8*7] = (tmp4 + z1 + z3) / 8.0;
271+
data_ptr[8*5] = (tmp5 + z2 + z4) / 8.0;
272+
data_ptr[8*3] = (tmp6 + z2 + z3) / 8.0;
273+
data_ptr[8*1] = (tmp7 + z1 + z4) / 8.0;
274+
data_ptr++;
275+
}
276+
}
277+
278+
279+
void dct_blocks(std::vector<std::vector<double>> &blocks) {
280+
for (int a = 0; a < blocks.size(); a++) {
281+
dct(&blocks[a][0]);
282+
}
283+
}
284+
285+
#endif

0 commit comments

Comments
 (0)