-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathProtocol_3.py
101 lines (74 loc) · 2.95 KB
/
Protocol_3.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
import numpy as np
from sklearn.datasets import load_diabetes
import phe as paillier
class DH_Endpoint(object):
def __init__(self, public_key1, public_key2, private_key):
self.public_key1 = public_key1
self.public_key2 = public_key2
self.private_key = private_key
self.full_key = None
def generate_partial_key(self):
partial_key = self.public_key1 ** self.private_key
partial_key = partial_key % self.public_key2
return partial_key
def generate_full_key(self, partial_key_r):
full_key = partial_key_r ** self.private_key
full_key = full_key % self.public_key2
self.full_key = full_key
return full_key
def encrypt_message(self, message):
encrypted_message = ""
key = self.full_key
for c in message:
encrypted_message += chr(ord(c) + key)
return encrypted_message
def decrypt_message(self, encrypted_message):
decrypted_message = ""
key = self.full_key
for c in encrypted_message:
decrypted_message += chr(ord(c) - key)
return decrypted_message
class Server:
"""Private key holder. Decrypts the average gradient"""
def __init__(self, key_length):
keypair = paillier.generate_paillier_keypair(n_length=key_length)
self.pubkey, self.privkey = keypair
def decrypt_aggregate(self, input_model, n_clients):
return decrypt_vector(self.privkey, input_model) / n_clients
class Client:
"""Runs linear regression with local data or by gradient steps,
where gradient can be passed in.
Using public key can encrypt locally computed gradients.
"""
def __init__(self, name, X, y, pubkey):
self.name = name
self.pubkey = pubkey
self.X, self.y = X, y
self.weights = np.zeros(X.shape[1])
def fit(self, n_iter, eta=0.01):
"""Linear regression for n_iter"""
for _ in range(n_iter):
gradient = self.compute_gradient()
self.gradient_step(gradient, eta)
def gradient_step(self, gradient, eta=0.01):
"""Update the model with the given gradient"""
self.weights -= eta * gradient
def compute_gradient(self):
"""Compute the gradient of the current model using the training set
"""
delta = self.predict(self.X) - self.y
return delta.dot(self.X) / len(self.X)
def predict(self, X):
"""Score test data"""
return X.dot(self.weights)
def encrypted_gradient(self, sum_to=None):
"""Compute and encrypt gradient.
When `sum_to` is given, sum the encrypted gradient to it, assumed
to be another vector of the same size
"""
gradient = self.compute_gradient()
encrypted_gradient = encrypt_vector(self.pubkey, gradient)
if sum_to is not None:
return sum_encrypted_vectors(sum_to, encrypted_gradient)
else:
return encrypted_gradient