def dec_recompose( enc_wts ): # function to decrypt the aggregated weight vector received from parameter server dec_wts = [] global_aggregate = {} chunks = len(enc_wts) for h in range(chunks): plain_agg = Plaintext() decryptor.decrypt(enc_wts[h], plain_agg) crtbuilder.decompose(plain_agg) dec_wts += [ plain_agg.coeff_at(h) for h in range(plain_agg.coeff_count()) ] for h in range(len(dec_wts)): if dec_wts[h] > int(parms.plain_modulus().value() - 1) / 2: dec_wts[h] = dec_wts[h] - parms.plain_modulus().value() for h in range(len(dec_wts)): dec_wts[h] = float(dec_wts[h]) / (1000 * m) pos_start = 0 for param_tensor in flattened_lengths: pos_end = pos_start + flattened_lengths[param_tensor] global_aggregate.update({ param_tensor: torch.tensor(dec_wts[pos_start:pos_end]).reshape( shapes[param_tensor]) }) pos_start = pos_end return global_aggregate
def decrypt(item): decryptor = simplefhe._decryptor if simplefhe._private_key is None: raise ValueError( 'Private key has not been set. Decryption not possible.') if simplefhe._relin_keys is None: raise ValueError( 'Relinearization keys have not been set. Decryption not possible.') result = Plaintext() decryptor.decrypt(item._ciphertext, result) mode = item._mode if mode['type'] == 'int': if decryptor.invariant_noise_budget(item._ciphertext) == 0: raise ValueError( 'The noise budget has been exhausted.' + ' Try calling `simplefhe.initialize` with a larger `poly_modulus_degree` or a smaller `max_int`.' ) result = result.to_string() result = int(result, 16) if result > mode['modulus'] // 2: result -= mode['modulus'] return result else: decoded = DoubleVector() item._mode['encoder'].decode(result, decoded) return float(decoded[0])
def rotateAdd(ct, length, lowerbound=1): res = Plaintext() while length > lowerbound: length //= 2 oldCt = copy.deepcopy(ct) evaluator.rotate_rows(ct, length, gal_keys) evaluator.add(ct, oldCt) print(length) decryptor.decrypt(ct, res) crtbuilder.decompose(res) #print_matrix([res.coeff_at(i) for i in range(res.coeff_count())]) return [res.coeff_at(i) for i in range(lowerbound)]
def dot_matrix_with_matrix_transpose(self, matrix_a: CipherMatrix, matrix_b: CipherMatrix): result_matrix = CipherMatrix(rows=matrix_a.rows, cols=matrix_a.cols) rows_a = matrix_a.rows cols_b = matrix_b.rows for i in range(rows_a): vector_dot_products = [] zeros = Plaintext() for j in range(cols_b): vector_dot_products += [ self.dot_vector(matrix_a[i], matrix_b[j]) ] if j == 0: zero = DoubleVector() self.encoder.encode(zero, vector_dot_products[j].scale(), zeros) self.evaluator.mod_switch_to_inplace( zeros, vector_dot_products[j].parms_id()) self.evaluator.add_plain(vector_dot_products[j], zeros, result_matrix[i]) else: self.evaluator.rotate_vector_inplace( vector_dot_products[j], -j, self.galois_keys) self.evaluator.add_inplace(result_matrix[i], vector_dot_products[j]) for vec in result_matrix: self.evaluator.relinearize_inplace(vec, self.relin_keys) self.evaluator.rescale_to_next_inplace(vec) return result_matrix
def print_plain(D): # function to print out all elements in a matrix for row in D: for values in row: p = Plaintext() decryptor.decrypt(values, p) print(encoderF.decode(p))
def masking_output(self): spread_mask = generate_random_mask( self.modulus, [self.num_output_batch, self.degree]) self.output_mask_s = torch.zeros(self.num_output_unit).double() pod_vector = uIntVector() pt = Plaintext() for idx_output_batch in range(self.num_output_batch): encoding_tensor = torch.zeros(self.degree, dtype=torch.float) for idx_piece in range(self.num_piece_in_batch): idx_output_unit = self.index_output_batch_to_units( idx_output_batch, idx_piece) if idx_output_unit is False: break padded_span = self.num_elem_in_piece start_piece = idx_piece * padded_span arr = spread_mask[idx_output_batch, start_piece:start_piece + padded_span] encoding_tensor[start_piece:start_piece + padded_span] = arr self.output_mask_s[idx_output_unit] = arr.double().sum() encoding_tensor = pmod(encoding_tensor, self.modulus) pod_vector.from_np(encoding_tensor.numpy().astype(np.uint64)) self.batch_encoder.encode(pod_vector, pt) self.evaluator.add_plain_inplace(self.output_cts[idx_output_batch], pt) self.output_mask_s = pmod(self.output_mask_s, self.modulus)
def print_plain(D): # function to print out all elements in a matrix if (type(D[0]) != list): for element in D: p = Plaintext() decryptor.decrypt(element, p) print(encoderF.decode(p), end=" ") print() else: for row in D: for values in row: p = Plaintext() decryptor.decrypt(values, p) print(encoderF.decode(p), end=" ") print()
def decrypt_ciphertext(self, cipher): plain = Plaintext() self.decryptor.decrypt(cipher, plain) pl = self.encoder.decode(plain) return pl
def compute_with_weight(self, weight_tensor): assert (weight_tensor.shape == self.weight_shape) pod_vector = uIntVector() pt = Plaintext() self.output_cts = encrypt_zeros(self.num_output_batch, self.batch_encoder, self.encryptor, self.degree) for idx_output_batch, idx_input_batch in product( range(self.num_output_batch), range(self.num_input_batch)): encoding_tensor = torch.zeros(self.degree) is_w_changed = False for idx_piece in range(self.num_piece_in_batch): idx_row, idx_col_start, idx_col_end = \ self.index_weight_batch_to_units(idx_output_batch, idx_input_batch, idx_piece) if idx_row is False: continue is_w_changed = True padded_span = self.num_elem_in_piece data_span = idx_col_end - idx_col_start start_piece = idx_piece * padded_span encoding_tensor[start_piece:start_piece + data_span] = weight_tensor[ idx_row, idx_col_start:idx_col_end] if not is_w_changed: continue encoding_tensor = pmod(encoding_tensor, self.modulus) pod_vector.from_np(encoding_tensor.numpy().astype(np.uint64)) self.batch_encoder.encode(pod_vector, pt) sub_dotted = Ciphertext(self.input_cts[idx_input_batch]) self.evaluator.multiply_plain_inplace(sub_dotted, pt) self.evaluator.add_inplace(self.output_cts[idx_output_batch], sub_dotted)
def decrypt_new_grid(self, encrypted_new_grid, dim): ''' Decrypts a homomorphic-encrypted grid by looping through every element, decrypt it and then applying the decoding rules to get the new board state :param encrypted_new_grid: :param dim: :return: ''' new_grid = numpy.zeros(dim*dim, dtype='i').reshape(dim,dim) for i in range(dim): for j in range(dim): plain = Plaintext() encrypted = encrypted_new_grid[dim*i + j] self.decryptor.decrypt(encrypted, plain) value = self.encoder.decode_int32(plain) # transformation / decoding rules if(value <= 0): new_grid[i][j] = 0 elif(value > 0): new_grid[i][j] = 1 return new_grid
def send_enc(): list_params = [] for param_tensor in model.state_dict(): list_params += model.state_dict()[param_tensor].flatten().tolist() length = len(list_params) list_params_int = [0] * length for h in range(length): # Convert float values to integer so that they can be encrypted # length_integer is the maximum number of digits in the integer representation. # The returned value min_prec is the min number of dec places before first non-zero digit in float value. list_params_int[h] = round(list_params[h], 3) * 1000 #length_integer = 3 #list_params_int[h], min_prec = conv_int(list_params[h], length_integer) slot_count = int(crtbuilder.slot_count()) pod_iter = iter(list_params_int) pod_sliced = list( chunk_pad(pod_iter, slot_count, 0) ) # partitions the vector pod_vec into chunks of size equal to the number of batching slots for h in range(len(pod_sliced)): pod_sliced[h] = [ int(pod_sliced[h][j]) for j in range(len(pod_sliced[h])) ] for j in range(len(pod_sliced[h])): if pod_sliced[h][j] < 0: pod_sliced[h][j] = parms.plain_modulus().value( ) + pod_sliced[h][j] comm.send(len(pod_sliced), dest=0, tag=1) for chunk in range(len(pod_sliced)): encrypted_vec = Ciphertext() plain_vector = Plaintext() crtbuilder.compose(list(pod_sliced[chunk]), plain_vector) encryptor.encrypt(plain_vector, encrypted_vec) comm.send(encrypted_vec, dest=0, tag=chunk + 2)
def decrypt(self, encrypted_matrix=None, keygen=None): """ :return: """ if encrypted_matrix is not None: self.encrypted_matrix = encrypted_matrix assert self._encrypted, "No encrypted matrix" del self.matrix shape = self.encrypted_matrix.shape self.matrix = np.empty(shape) if keygen is not None: self._update_cryptors(keygen) for i in range(shape[0]): for j in range(shape[1]): plain_text = Plaintext() self.decryptor.decrypt(self.encrypted_matrix[i, j], plain_text) self.matrix[i, j] = self.encoder.decode(plain_text) self._encrypted = False return np.copy(self.matrix)
def search(): y = np.load('./class_lables.npy') X = np.load('all_descriptors.npy') centroids = pickle.load('./centroids.npy') if len(ENC_CONF) > 0: params = ENC_CONF[0] context = ENC_CONF[1] frac_encoder = ENC_CONF[2] encryptor = ENC_CONF[3] evaluator = ENC_CONF[4] decryptor = ENC_CONF[5] encrypted_matrix = Ciphertext() e1 = encryptor.encrypt(X[56], encrypted_matrix) encrypted_matrix = Ciphertext() e2 = encryptor.encrypt(X[128], encrypted_matrix) encrypted_matrix = Ciphertext() e3 = encryptor.encrypt(X[300], encrypted_matrix) test_query = [e1, e2, e3] y_test = [y[56], y[128], y[300]] encrypted_matrix = Ciphertext() c1 = encryptor.encrypt(centroids[0], encrypted_matrix) encrypted_matrix = Ciphertext() c2 = encryptor.encrypt(centroids[1], encrypted_matrix) encrypted_matrix = Ciphertext() c3 = encryptor.encrypt(centroids[2], encrypted_matrix) encrypted_matrix = Ciphertext() c4 = encryptor.encrypt(centroids[3], encrypted_matrix) centroids_enc = [c1, c2, c3, c4] for i, x in enumerate(test_query): print("Received descriptor A for the person") for j, c in enumerate(centroids_enc): print( "Calculating distance between ciphertext A and Fixed Person from cluster #{}:" .format(j)) time_start = time.time() enc_res = euclidean_dist_enc(evaluator, x, c) time_end = time.time() print("Done. Time: {} miliseconds".format( (str)(1000 * (time_end - time_start)))) print("Encrypted distance result is calculated") plain_result = Plaintext() print("Decrypting result: ") time_start = time.time() decryptor.decrypt(enc_res, plain_result) res = frac_encoder.encode(plain_result) time_end = time.time() print("Decrypted. Time: {} miliseconds".format( (str)(1000 * (time_end - time_start)))) print("Distance between Current and Fixed Person #{}: {:.2f}". format(j, res)) if (res < 0.6): print("🔦Found Match") break time.sleep(4) #delay for 20 sec
def learn(y_data, x_data, evaluator, m_data, b_data, encoder, encryptor, learningRate_e, decryptor): y_data_encoded = encoder.encode(y_data) x_data_encoded = encoder.encode(x_data) m_data_encoded = encoder.encode(m_data) b_data_encoded = encoder.encode(b_data) # Encrypting the values is easy. y_e_data = Ciphertext() x_e_data = Ciphertext() encryptor.encrypt(y_data_encoded, y_e_data) encryptor.encrypt(x_data_encoded, x_e_data) m_e_current = Ciphertext() b_e_current = Ciphertext() encryptor.encrypt(m_data_encoded, m_e_current) encryptor.encrypt(b_data_encoded, b_e_current) # Calculate y_e_predicted = m_e_c*x_e_data _ b_e_c ypred_data = 1.0 ypred_data_encoded = encoder.encode(ypred_data) ypred_e_data = Ciphertext() encryptor.encrypt(ypred_data_encoded, ypred_e_data) evaluator.multiply(ypred_e_data, x_e_data) evaluator.multiply(ypred_e_data, m_e_current) evaluator.add(ypred_e_data, b_e_current) # delta = ypred_e - y_e evaluator.negate(y_e_data) evaluator.add(ypred_e_data, y_e_data) # Update m and b m_e_current = updateM(evaluator, m_e_current, x_e_data, learningRate_e, ypred_e_data) b_e_current = updateB(evaluator, b_e_current, learningRate_e, ypred_e_data) retVals = [] m_learnt = Plaintext() decryptor.decrypt(m_e_current, m_learnt) retVals.append(encoder.decode(m_learnt)) b_learnt = Plaintext() decryptor.decrypt(b_e_current, b_learnt) retVals.append(encoder.decode(b_learnt)) return retVals
def dec(self, cipher_arr): n = len(cipher_arr) arr = np.empty(n, int) for i in range(n): p = Plaintext() self._decryptor.decrypt(cipher_arr[i], p) arr[i] = self._encoder.decode_int64(p) return arr
def encode_float(item: float) -> Plaintext: """Encodes the given float into a plaintext.""" mode = simplefhe._mode encoder = mode['encoder'] scale = mode['default_scale'] output = Plaintext() encoder.encode(item, scale, output) return output
def multiplyDeterminant(M, determinant): p=Plaintext() # need to send user D so that user can send back -1/D either in encrypted form or decrypted form decryptor.decrypt(determinant, p) d= (-1/encoderF.decode(p)) delta=encoderF.encode(d) for i in range(len(M)): for j in range(len(M[0])): evaluator.multiply_plain(M[i][j], delta)
def mat_decrypt(matrix, decryption, encoding): result=np.zeros((matrix.shape[0], matrix.shape[1])).tolist() for i in range(matrix.shape[0]): for j in range(matrix.shape[1]): plain_result = Plaintext() decryption.decrypt(matrix[i][j], plain_result) result[i][j] = (str)(encoding.decode_int32(plain_result)) return np.asarray(result)
def encrypt_zeros(num_batch, batch_encoder, encryptor, degree): cts = [Ciphertext() for i in range(num_batch)] pod_vector = uIntVector() pt = Plaintext() zeros_tensor = np.zeros(degree).astype(np.int64) pod_vector.from_np(zeros_tensor) batch_encoder.encode(pod_vector, pt) for i in range(num_batch): encryptor.encrypt(pt, cts[i]) return cts
def encrypt(self, matrix: np.array): matrix = Matrix.from_numpy_array(array=matrix) cipher_matrix = CipherMatrix(rows=matrix.rows, cols=matrix.cols) for i in range(matrix.rows): encoded_row = Plaintext() self.encoder.encode(matrix[i], self.scale, encoded_row) self.encryptor.encrypt(encoded_row, cipher_matrix[i]) return cipher_matrix
def test_seal_env_running(): n = np.ones((3, 3)) s = SealOps.with_env() m = s.encrypt(n) x = s.get_vector_range(m[0], 1, 2) p = Plaintext() p1 = DoubleVector() s.decryptor.decrypt(x, p) s.encoder.decode(p, p1) print(p1)
def decrypt_matrix(M): M_dec = [] for x in M: m = [] for y in x: p = Plaintext() decryptor.decrypt(y, p) m.append(encoderF.decode(p)) M.append(m) return (M)
def encode_int(item: int) -> Plaintext: """Encodes the given integer into a plaintext.""" modulus = simplefhe._mode['modulus'] if item <= -modulus // 2 or item > modulus // 2: raise ValueError(f'Integer {item} is too large to be represented.' + ' Try increasing `max_int` during initialization.') item = item % modulus item_str = hex(item)[2:] return Plaintext(item_str)
def decrypt(self, cipher_matrix: CipherMatrix) -> Matrix: matrix = Matrix(rows=cipher_matrix.rows, cols=cipher_matrix.cols) for i in range(matrix.rows): row = Vector() encoded_row = Plaintext() self.decryptor.decrypt(cipher_matrix[i], encoded_row) self.encoder.decode(encoded_row, row) matrix[i] = row return matrix
def decompose_plain(slot_count, x, crtbuilder): if type(x) is np.ndarray: DESC_SIZE = x.shape[0] x = x.reshape(1, DESC_SIZE) zeros = np.zeros((1, slot_count), dtype=np.int32) zeros[:x.shape[0], :x.shape[1]] = x pad_matrix = zeros.flatten() print("Decomposed flattened vector", pad_matrix) plain_matrix = Plaintext() crtbuilder.compose(pad_matrix, plain_matrix) return plain_matrix
def get_vector_range(self, vector_a: Ciphertext, i: int, j: int) -> Ciphertext: cipher_range = Ciphertext() one_and_zeros = DoubleVector([0.0 if x < i else 1.0 for x in range(j)]) plain = Plaintext() self.encoder.encode(one_and_zeros, self.scale, plain) self.evaluator.mod_switch_to_inplace(plain, vector_a.parms_id()) self.evaluator.multiply_plain(vector_a, plain, cipher_range) return cipher_range
def encryption(value): # IntegerEncoder with base 2 encoder = IntegerEncoder(context.plain_modulus()) # generate public/private keys keygen = KeyGenerator(context) public_key = keygen.public_key() secret_key = keygen.secret_key() # encrypts public key encryptor = Encryptor(context, public_key) # perform computations on ciphertexts evaluator = Evaluator(context) # decrypts secret key decryptor = Decryptor(context, secret_key) # perform encryptions plaintext = encoder.encode(value) # convert into encrypted ciphertext encrypt = Ciphertext() encryptor.encrypt(plaintext, encrypt) print("Encryption successful!") print("Encrypted ciphertext: " + (str)(value) + " as " + plaintext.to_string()) # noise budget of fresh encryptions print("Noise budget: " + (str)(decryptor.invariant_noise_budget(encrypt)) + " bits") # decrypts result result = Plaintext() decryptor.decrypt(encrypt, result) print("Decryption successful!") print("Plaintext: " + result.to_string()) # decode for original integer print("Original node: " + (str)(encoder.decode_int32(result)) + "\n")
def sumDiagProducts(diagMatrix, ct_vector): template = [0] * len(diagMatrix[0]) plain_matrix = Plaintext() crtbuilder.compose(template, plain_matrix) accumulated = Ciphertext() encryptor.encrypt(plain_matrix, accumulated) for i, row in enumerate(diagMatrix): print("_____________________________") print(i, row) temp = copy.deepcopy(ct_vector) # the last number needs to wrap around! evaluator.rotate_rows(temp, i, gal_keys) decryptor.decrypt(temp, plain_matrix) crtbuilder.decompose(plain_matrix) print_matrix([plain_matrix.coeff_at(i) for i in range(plain_matrix.coeff_count())]) encodedRow = Plaintext() crtbuilder.compose(row, encodedRow) evaluator.multiply_plain(temp, encodedRow) evaluator.add(accumulated, temp) decryptor.decrypt(accumulated, plain_matrix) crtbuilder.decompose(plain_matrix) print([plain_matrix.coeff_at(i) for i in range(4)]) return accumulated
def test2(): img_path = '00001.jpg' img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE) print("Original image dimensions {}".format(img.shape)) sift = cv2.xfeatures2d.SIFT_create() (kps, desc) = sift.detectAndCompute(img, None) desc = preprocessing.normalize(np.array( desc.flatten()[:DESC_SIZE]).reshape(1, DESC_SIZE), norm='l2') descriptor_vec1 = desc descriptor_vec2 = descriptor_vec1 context = config() public_key, secret_key = keygen(context) encoder = IntegerEncoder(context.plain_modulus()) encryptor = Encryptor(context, public_key) crtbuilder = PolyCRTBuilder(context) evaluator = Evaluator(context) decryptor = Decryptor(context, secret_key) slot_count = (int)(crtbuilder.slot_count()) print("slot count {}".format(slot_count)) print("Plaintext shape", descriptor_vec1.shape) plain_matrix = decompose_plain(slot_count, descriptor_vec1, crtbuilder) for i in range(10000): encrypted_matrix = Ciphertext() print("Encrypting: ") time_start = time.time() encryptor.encrypt(plain_matrix, encrypted_matrix) time_end = time.time() print("Done in time {}".format((str)(1000 * (time_end - time_start)))) print("Square:") time_start = time.time() evaluator.square(encrypted_matrix) time_end = time.time() print("Square is done in {} miliseconds".format( (str)(1000 * (time_end - time_start)))) plain_result = Plaintext() print("Decryption plain: ") time_start = time.time() decryptor.decrypt(encrypted_matrix, plain_result) time_end = time.time() print("Decryption is done in {} miliseconds".format( (str)(1000 * (time_end - time_start)))) # print("Plaintext polynomial: {}".format(plain_result.to_string())) # print("Decoded integer: {}".format(encoder.decode_int32(plain_result))) print("Noise budget {} bits".format( decryptor.invariant_noise_budget(encrypted_matrix)))
def multiplyDeterminant(M, determinant): p=Plaintext() plainMul_pool = multiprocessing.Pool(processes=num_cores) # need to send user D so that user can send back -1/D either in encrypted form or decrypted form decryptor.decrypt(determinant, p) d= (-1/encoderF.decode(p)) delta=encoderF.encode(d) del(p) X=[] for i in range(len(M)): X.append(plainMul_pool.starmap(parallel_plainMultiplication, zip(M[i],itertools.repeat(delta)))) plainMul_pool.close() return(X)