def Enc_localData(self): """ Protocol-Vertical Step2(local computation) :param self.X, self.Y: training dataset. X = (n,d) matrix, Y = n vector :param magnitude: parameter for data representation(if we use at most "l" fractional digits, then magnitude = 10**l) :return self.enc_A, self.enc_b: Enc(A), Enc(b) :return self.labEnc_Xi, self.labEnc_Yi : labEnc(X), labEnc(Y) """ # convert a data representation domain(real -> Integer) # R => Z<l+r> => Z<N> Xi = (self.Xi * self.magnitude).astype(int) # compute Enc(Ai) Xi_trans = np.transpose(Xi) Ai = np.matmul(Xi_trans, Xi).astype(int).tolist() enc_Ai = [] for index, line in enumerate(Ai): enc_Ai.append([0] * index + [ self.mpk.encrypt(space_mapping(item, self.mpk.n)) for item in line[index:] ]) # compute labEnc(Xi) Xi = Xi.tolist() labEnc_Xi = [[ self.mpk.labEncrypt(self.seed, (h_index + w_index * self.num_instances), Xi_item) for Xi_item, w_index in zip(Xi_line, range(self.num_features)) ] for Xi_line, h_index in zip(Xi, range(self.num_instances))] # Enc() if self.Yi is None: enc_bi = None labEnc_Yi = None else: #Enc(bi) = Enc(Xi_trans, Yi) Yi = (self.Yi * self.magnitude).astype(int) bi = np.matmul(Xi_trans, Yi).astype(int).tolist() enc_bi = [ self.mpk.encrypt(space_mapping(item, self.mpk.n)) for item in bi ] Yi = Yi.tolist() labEnc_Yi = [ self.mpk.labEncrypt(self.seed, index, Yi_item) for Yi_item, index in zip(Yi, range(self.num_instances)) ] # return self.enc_Ai = enc_Ai self.enc_bi = enc_bi self.labEnc_Xi = labEnc_Xi self.labEnc_Yi = labEnc_Yi
def compute_merged_mask(self, enc_seed_i, num_instances, num_features): """ Protocol-Vertical Step1(set up) - receive upk_i[Enc(seed_i)], label information[num_instances, num_features] from DataOweners - compute B'=Enc(sum(b_i*b_j), c'=Enc(sum(bi*b_0)) :param enc_seed_i : upk_i :param num_instances, num_features : label information :return enc_mask_A, enc_mask_b: B', c' denoted in the paper """ seed_i = self.msk.decrypt(enc_seed_i) mask_X_i = [[ PRF(seed_i, h_index + w_index * num_instances, self.mpk.n) for w_index in range(num_features) ] for h_index in range(num_instances)] # compute B'[i,j] enc_mask_A = None t_mask_X_i = transpose(mask_X_i) if len(self.list_mask_X) != 0: for mask_X_j in self.list_mask_X: submask = [[ self.mpk.encrypt( space_mapping(sum(map(operator.mul, vector1, vector2)), self.mpk.n)) for vector1 in t_mask_X_i ] for vector2 in transpose(mask_X_j)] if enc_mask_A is None: enc_mask_A = submask else: enc_mask_A += submask self.list_mask_X.append(mask_X_i) # compute c'[i] enc_mask_b = None if self.mask_Y is None: #self.mask_Y = [PRF(seed_i, index, self.mpk.n) for index in range(num_instances)] self.mask_Y = t_mask_X_i[0] else: enc_mask_b = [ self.mpk.encrypt( space_mapping(sum(map(operator.mul, vector1, self.mask_Y)), self.mpk.n)) for vector1 in t_mask_X_i ] return enc_mask_A, enc_mask_b
def protocol_ridge_step2(self, enc_C, enc_d): """ Protocol-ridge_version1 Step2(masked model computation) - receive Enc(C), Enc(d) from MLE and decrypt them - compute w_tilda and determinant of C(=A*R) :param enc_C: Enc(C) = Enc(A*R) received from MLE :param enc_d: Enc(d) = Enc(b + Ar) received from MLE :return w_tilda: inverse(C)*d mod N """ # decrypt Enc(C) and Enc(d) dec_C = [] for line in enc_C: dec_C.append([self.msk.decrypt(x) for x in line]) dec_d = [self.msk.decrypt(y) for y in enc_d] # compute w_tilda( = inverse(C)*d) using gaussian Elimination algorithm temp = [dec_C[index] + [dec_d[index]] for index in range(len(dec_C))] w_tilda = gaussElimination(temp, self.mpk.n) for index, item in enumerate(w_tilda): w_tilda[index] = space_mapping(item, self.mpk.n) return w_tilda
def labDecrypt(self, cipher): if isinstance(cipher, LabEncDataType1): return space_mapping(cipher.hm + self.decrypt(cipher.enc_mask), self.public_key.n) else: print("cipher data type error in labDecrypt()") assert False
def __mul__(self, other): # other should be one of (int, type1)LabEncDataType1 if isinstance(other, LabEncDataType1): return other.enc_mask * self.hm + self.enc_mask * other.hm + space_mapping( self.hm * other.hm, self.enc_mask.public_key.n) elif isinstance(other, int): return LabEncDataType1(self.hm * other, self.enc_mask * other) else: print("type(other) :", type(other)) assert False, "Datatype(other) error during LabEncData multiplication"
def labEncrypt(self, seed, label, plain): # compute mask[b](b belong to Z(n)) mask = PRF(seed, label, self.n) # hidden message = plain - b mod pk.n, hidden_message = space_mapping(plain - mask, self.n) # enc_mask = Enc(b) enc_mask = self.encrypt(mask) return LabEncDataType1(hidden_message, enc_mask)
def computeEnc_Ab(self): """ Protocol-Horizontal Step2(local computation) :param X, Y: training dataset. X = (n,d) matrix, Y = n vector :param magnitude: parameter for data representation(if we use at most "l" fractional digits, then magnitude = 10**l) :return enc_A: encrypted trans(X)*X :return enc_b: encrypted trans(X)*Y """ # convert a data representation domain(real -> Integer) # R => Z<l+r> => Z<N> X = (self.X * self.magnitude).astype(int) Y = (self.Y * self.magnitude).astype(int).tolist() X_trans = np.transpose(X).tolist() num_instances = self.X.shape[0] num_features = self.X.shape[1] # compute A = trans(X)*X, encrypt A self.enc_A = [] for index in range(num_features): # To improve efficiency, compute a triangular matrix of A # Because A_ij = A_ji self.enc_A.append([0] * index + [ self.pk.encrypt(x) for x in [ space_mapping(sum(map(mul, X_trans[index], X_trans[j])), self.pk.n) for j in range(index, num_features) ] ]) # compute b = trans(X)*Y, encrypt b self.enc_b = [ self.pk.encrypt(b) for b in [ space_mapping(sum(map(mul, X_trans[i], Y)), self.pk.n) for i in range(num_features) ] ]
def protocol_ridge_step3(self, w_tilda): """ Protocol-ridge Step3(model reconstruction) - receive w_tilda and det(C) and compute w* :param w_tilda: inverse(C)*d mod N :return w_star: Estimated coefficients for the linear regression problem computed by the suggested protocol(version1) """ # compute w_dash = R*w_tilda - r w_dash = [] for index in range(len(w_tilda)): w_dash.append(space_mapping((sum(map(mul, self.R[index], w_tilda)) - self.r[index]) , self.mpk.n)) # rational reconstruction w_star = rationalRecon(w_dash, self.mpk.n) w_star = np.asarray(w_star) return w_star