self.XtX[i][j] += xs[i] * xs[j] def dump(self) -> dict: """Export the regression coefficients.""" output = {} for i in range(self.dimension): output[f'XtY-{i}'] = self.XtY[i] for j in range(self.dimension): output[f'XtX-{i}-{j}'] = self.XtX[i][j] return output #### Process the client's encrypted data #### regression = LinearRegression(3) N_DATAPOINTS = 50 for i in range(N_DATAPOINTS): # Load the ith datapoint xs = [] y = load_encrypted_value(f'inputs/y-{i}.dat') for j in range(3): xs.append(load_encrypted_value(f'inputs/x{j}-{i}.dat')) # Update regression regression.update(xs, y) print(f'Procesed datapoint {i+1} of {N_DATAPOINTS}') # Dump regression coefficients coefficients = regression.dump() for name, value in coefficients.items(): value.save(f'outputs/{name}.dat')
from simplefhe import load_public_key, load_relin_keys, display_config, load_encrypted_value # The private key never leaves the client. load_public_key('keys/public.key') load_relin_keys('keys/relin.key') display_config() # Process values on server. def f(x): return x**3 - 3*x + 1 for i in range(4): # Load encrypted value sent from client value = load_encrypted_value(f'inputs/{i}.dat') # simplefhe seamlessly translates all arithmetic to # FHE encrypted operations. # We never gain access to the unencrypted information. result = f(value) # Send encrypted result back to client result.save(f'outputs/{i}.dat') print(f'[SERVER] Processed entry {i}: inputs/{i}.dat -> outputs/{i}.dat')
from simplefhe import (load_private_key, load_relin_keys, display_config, decrypt, load_encrypted_value) # Note: this is the only step at which the private key is used! load_private_key('keys/private.key') load_relin_keys('keys/relin.key') display_config() # Decrypt results from the server (client-side) sensitive_data = [-30, -5, 17, 28] for i, entry in enumerate(sensitive_data): encrypted = load_encrypted_value(f'outputs/{i}.dat') result = decrypt(encrypted) print(f'[CLIENT] Result for {entry}: {result}')
# Client-side script to decrypt the server's results import numpy as np from simplefhe import (initialize, decrypt, load_encrypted_value, load_private_key, load_relin_keys) # Initialization and keys initialize('float') load_private_key('keys/private.key') load_relin_keys('keys/relin.key') # Decrypt server's results XtX = np.zeros(shape=[3, 3]) XtY = np.zeros(shape=3) for i in range(3): XtY[i] = decrypt(load_encrypted_value(f'outputs/XtY-{i}.dat')) for j in range(3): XtX[i, j] = decrypt(load_encrypted_value(f'outputs/XtX-{i}-{j}.dat')) # Some post-processing coefficients = np.linalg.inv(XtX) @ XtY # Display results GROUND_TRUTH = [3.2, -1.7, 0.8] for i, pair in enumerate(zip(GROUND_TRUTH, coefficients)): a, b = pair print(f'Coefficient {i}: Expected {a:.4f}, Computed {b:.4f}')