-
Notifications
You must be signed in to change notification settings - Fork 1
/
old_vhe.py
145 lines (116 loc) · 3.94 KB
/
old_vhe.py
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
from utils.numTh import *
import decimal
decimal.getcontext().prec = 60
class OldVHE:
def __init__(self, l, bound, stdev, q, w):
self.l = l
self.bound = bound
self.stdev = stdev
self.q = q
self.w = w
def setCoeffs(self, array):
tarray = array.flatten()
for i in range(len(tarray)):
tarray[i] = tarray[i] % self.q
if tarray[i] > self.q / 2:
tarray[i] = tarray[i] - self.q
tarray = tarray.reshape(array.shape)
return tarray
def setCoeffs_(self, array):
tarray = array.flatten()
for i in range(len(tarray)):
tarray[i] = tarray[i] % self.q
tarray = tarray.reshape(array.shape)
return tarray
def get_random_matrix(self, row, col, bound=None):
if bound == None:
bound = self.bound
R = np.random.randint(-bound, bound, (row, col))
R = R.astype(np.object)
return R
# returns S
def get_secret_key(self, T):
rows, cols = T.shape
I = np.eye(cols, dtype=np.int64)
return np.hstack((I, T)), I
# returns c*
def get_bit_vector(self, c):
result = np.array([bin(int(elem)).replace('b', '').zfill(self.l)[::-1] for elem in c])
ans = np.zeros((self.l * len(c)), np.int)
for i, string in enumerate(result):
string = list(string)
negate = 1
if string[-1] == "-":
string[-1] = '0'
negate = -1
for j, char in enumerate(string):
ans[i * self.l + j] = int(char) * negate
return ans
# finds c* then returns Mc*
def key_switch(self, M, c):
cstar = self.get_bit_vector(c)
c_ = np.dot(M, cstar)
c_ = self.setCoeffs(c_)
return c_
# returns S*w
def get_bit_matrix(self, S):
powers = np.array([2 ** x for x in range(self.l)])
result = np.array([np.array([powers * int(elem) for elem in row]) for row in S])
result = result.reshape(result.shape[0], result.shape[1] * result.shape[2])
return result
def key_switch_matrix(self, S, T):
t_rows, t_cols = T.shape
s_star = self.get_bit_matrix(S)
s_rows, s_cols = s_star.shape
A = self.get_random_matrix(t_cols, s_cols, pow(2, 31))
E = gauss_sample(s_rows * s_cols, self.stdev)
E = E.reshape((s_rows, s_cols))
E = E.astype(np.object)
M = np.vstack((s_star + E - np.matmul(T, A), A))
return M
def get_public_key(self, S, T):
M = self.key_switch_matrix(S, T)
return M
def encrypt(self, M, x):
x = x.astype(np.object)
sc = x * self.w
return self.key_switch(M, sc)
def decrypt(self, S, c):
sc = np.dot(S, c)
for i in range(len(sc)):
sc[i] = int(round(decimal.Decimal(sc[i]) / decimal.Decimal(self.w)))
sc = self.setCoeffs(sc)
return sc
def encrypt_image(self, img, M):
H, W, _ = img.shape
eimg = np.zeros((H, W, 2 * N), np.object)
for y in range(H):
for x in range(W):
t = img[y, x].tolist()
t.insert(0, 0)
t = np.asarray(t)
t = t.astype(np.object)
eimg[y, x] = self.encrypt(M, t)
return eimg
def decrypt_image(self, eimg, S):
H, W, _ = eimg.shape
img = np.zeros((H, W, 3), np.uint8)
for y in range(H):
for x in range(W):
img[y, x] = self.decrypt(S, eimg[y, x])[1:4]
return img
if __name__ == "__main__":
N = 4
stdev = 3.2
w = pow(2, 30)
bound = 100
l = 100
q = pow(2, 50)
v = OldVHE(l, bound, stdev, q, w)
T = v.get_random_matrix(N, N)
S, I = v.get_secret_key(T)
# print("secret kry: \n", S)
M = v.get_public_key(I, T)
p = np.array((15,-2200,-31000,-7), np.object)
cp = v.encrypt(M, p)
print(v.decrypt(S, cp))