def setPoints(self, folder, n, m, p, d, T, A, B, C, W, V, F): self.n = n self.m = m self.p = p self.T = T self.d = d x0 = np.loadtxt("Data/" + folder + "/x0.txt", delimiter=',', dtype=float) xr = np.loadtxt("Data/" + folder + "/xr.txt", delimiter=',', dtype=float) ur = np.loadtxt("Data/" + folder + "/ur.txt", delimiter=',', dtype=float) x0 = x0.reshape(n) xr = xr.reshape(n) ur = ur.reshape(m) self.x = x0 self.x_series = np.zeros((n, T + 1)) self.x_series[:, 0] = x0 self.xr = xr self.ur = ur self.xf = util_fpv.vfp(x0) self.xrf = util_fpv.vfp(xr) self.urf = util_fpv.vfp(ur) self.A = A self.B = B self.C = C self.W = W self.V = V self.F = F
def computeProducts(self): lf = DEFAULT_PRECISION # Compute LCA encrypted prod_LCA = Mult3Matrix(self.enc_L, self.enc_C, self.enc_A, self.enc_bLC, self.enc_bLA, self.enc_bCA) self.enc_LCA = prod_LCA # Compute Gamma2 = (I-LC)BK = BK - LCBK = Gamma3*K enc_Gamma2 = np.dot(self.enc_Gamma3, self.enc_K) rGamma2 = [[ gmpy2.mpz_urandomb(gmpy2.random_state(), self.l + lf + self.sigma) for i in range(self.n) ] for j in range(self.n)] self.rGamma2 = util_fpv.vfp(rGamma2, -lf) # Compute Gamma = (I-LC)(A+BK) = A + BK - LCA - LCBK, they have different precisions enc_Gamma = ( np.dot(self.enc_A, 2**(2 * lf) * np.eye(self.n, dtype=object)) - prod_LCA + np.dot(enc_Gamma2, 2**lf * np.eye(self.n, dtype=object))) rGamma = [[ gmpy2.mpz_urandomb(gmpy2.random_state(), self.l + 2 * lf + self.sigma) for i in range(self.n) ] for j in range(self.n)] self.rGamma = util_fpv.vfp(rGamma, -2 * lf) return enc_Gamma + rGamma, enc_Gamma2 + rGamma2
def refresh_Gamma1_2(self, blinded_Gamma, blinded_Gamma2): lf = DEFAULT_PRECISION old_bGamma = ( np.dot(self.bGamma3K, 2**lf * np.eye(self.n, dtype=object)) - self.bLCA) Gammar = util_fpv.von_dec(self.privkey, blinded_Gamma) + old_bGamma new_Gamma = util_fpv.von_enc(self.pubkey, util_fpv.vfp(Gammar, -2 * lf), self.bGamma) Gammar2 = util_fpv.von_dec(self.privkey, blinded_Gamma2, self.bGamma3K) new_Gamma2 = util_fpv.von_enc(self.pubkey, util_fpv.vfp(Gammar2, -lf), self.bGamma2) return new_Gamma, new_Gamma2
def refresh_xk(self, blinded_xk, k): bxkr = self.bxkr[:, k - 1] # xkr = util_fpv.von_dec(self.privkey,blinded_xk)+bxkr # print('act x%d: '%(k+1), util_fpv.vfp(xkr,-2*DEFAULT_PRECISION)'') ## if Gref is not a full LabHE encryption, but rather [[Gref - bGref]], then perform # bxk = bxkr + self.bGref xkr = util_fpv.von_dec(self.privkey, blinded_xk, bxkr) return util_fpv.von_enc(self.pubkey, util_fpv.vfp(xkr, -DEFAULT_PRECISION), self.bx[:, k])
def refresh_Gamma3(self, blinded_Gamma3): lf = DEFAULT_PRECISION old_bGamma3 = self.bLCB * (-1) Gammar3 = util_fpv.von_dec(self.privkey, blinded_Gamma3) + old_bGamma3 new_Gamma3 = util_fpv.von_enc(self.pubkey, util_fpv.vfp(Gammar3, -2 * lf), self.bGamma3) return new_Gamma3
def generateRandomness(self): n = self.n m = self.m T = self.T state = gmpy2.random_state() rk = [ gmpy2.mpz_urandomb(state, self.l + self.sigma) for i in range(n * T) ] self.rk = rk self.rkf = util_fpv.vfp(rk, -DEFAULT_PRECISION)
def getMeasurement(self, k): z = np.add( np.dot(self.C, self.x), np.random.multivariate_normal([0] * self.p, self.V, tol=1e-6)) # z = np.dot(self.C,self.x) # no noise # z = np.array(z, dtype=object) self.z = z # print("Measurement z%d: "%(k+1),["%.5f"% i for i in z]) enc_bz = [item[k] for item in self.enc_bz] enc_z = util_fpv.von_enc(self.pubkey, util_fpv.vfp(z), self.bz[:, k], enc_bz) return enc_z
def encryptMatrices(self, flag): pubkey = self.pubkey self.enc_A = util_fpv.von_enc(pubkey, self.Af, self.bA, self.enc_bA) # print('A: ',util_fpv.retrieve_fp_matrix(util_fpv.on_dec_mat(privkey,enc_A,act.bA))) self.enc_C = util_fpv.von_enc(pubkey, self.Cf, self.bC, self.enc_bC) # print('C: ',util_fpv.retrieve_fp_matrix(util_fpv.on_dec_mat(privkey,enc_C,act.bC))) self.enc_L = util_fpv.von_enc(pubkey, self.Lf, self.bL, self.enc_bL) # print('L: ',util_fpv.retrieve_fp_matrix(util_fpv.on_dec_mat(privkey,enc_L,act.bL))) self.enc_B = util_fpv.von_enc(pubkey, self.Bf, self.bB, self.enc_bB) # print('B: ',util_fpv.retrieve_fp_matrix(util_fpv.on_dec_mat(privkey,enc_B,act.bB))) self.enc_K = util_fpv.von_enc(pubkey, self.Kf, self.bK, self.enc_bK) if flag == 0: self.enc_Gamma = util_fpv.von_enc(pubkey, util_fpv.vfp(self.Gamma), self.bGamma, self.enc_bGamma) self.enc_Gamma2 = util_fpv.von_enc(pubkey, util_fpv.vfp(self.Gamma2), self.bGamma2, self.enc_bGamma2) self.enc_Gamma3 = util_fpv.von_enc(pubkey, util_fpv.vfp(self.Gamma3), self.bGamma3, self.enc_bGamma3)
def closedLoop(self, u, k): # print("Last input: ", ["%.5f"% i for i in u]) # with np.errstate(invalid='ignore'): # np.warnings.filterwarnings('ignore') x = np.add( np.dot(self.A, self.x), np.dot(self.B, u), np.dot( self.F, np.random.multivariate_normal([0] * self.d, self.W, tol=1e-6))) # x = np.dot(self.A,self.x) + np.dot(self.B,u) # no noise self.x = x self.x_series[:, k] = x self.xf = util_fpv.vfp(x)
def computeGamma3(self): lf = DEFAULT_PRECISION # Compute LCB encrypted prod_LCB = Mult3Matrix(self.enc_L, self.enc_C, self.enc_B, self.enc_bLC, self.enc_bLB, self.enc_bCB) self.enc_LCB = prod_LCB # Compute Gamma3 = (I-LC)B = B - LCB, they have different precisions enc_Gamma3 = np.dot( self.enc_B, 2**(2 * lf) * np.eye(self.m, dtype=object)) - prod_LCB rGamma3 = [[ gmpy2.mpz_urandomb(gmpy2.random_state(), self.l + 2 * lf + self.sigma) for i in range(self.m) ] for j in range(self.n)] self.rGamma3 = util_fpv.vfp(rGamma3, -2 * lf) return enc_Gamma3 + rGamma3
def main(): """ Run instances of encrypted LQG with Labeled Homomorphic Encryption.""" flag = 0 # The Setup computes gives the gain matrices Gamma to the cloud if flag = 0, otherwise, the cloud and actuator compute their encryption verbose = 0 # Print values of variables if verbose = 1, does nothing otherwise # folder = 'building_1_room' # folder = 'Random_instance_5_1' folder = 'building_2_rooms' # folder = 'Random_instance_25_5' # folder = 'Random_instance_50_10' # folder = 'Random_instance_75_15' # folder = 'Random_instance_100_20' # folder = 'Random_instance_125_25' lf = DEFAULT_PRECISION T = 100 setup = Client.Client() usk_setup = setup.usk setup.Plant(T,folder) n = setup.n; m = setup.m; p = setup.p; d = setup.d A = setup.Af; B = setup.Bf; C = setup.Cf K = setup.Kf; L = setup.Lf W = setup.Wf; V = setup.Vf; F = setup.F client = Client.Client() usk_client = client.usk client.setPoints(folder,n,m,p,d,T,setup.A,setup.B,setup.C,setup.W,setup.V,setup.F) x0 = client.xf; xr = client.xr; ur = client.ur xrf = client.xrf; urf = client.urf plaintext_x_series = np.zeros((n,T)) act = Actuator.Actuator(usk_setup,usk_client) privkey = act.privkey msk = privkey.msk; upk = privkey.upk pubkey = act.pubkey client.getPubkey(pubkey) setup.getPubkey(pubkey) start = time.time() setup.genLabelsSetup(flag) time_off_setup = time.time() - start print('Offline time for setup: ', "%.5f" % (time_off_setup), ' sec') start = time.time() client.genLabels() time_off_clients = time.time() - start print('Offline time for clients: ', "%.5f" % (time_off_clients), ' sec') start = time.time() cloud = Cloud.Cloud(act.pubkey,n,m,p,T) cloud.generateRandomness() time_off_cloud = time.time() - start print('Offline time for cloud: ', "%.5f" % (time_off_cloud), ' sec') start = time.time() act.genLabels(n,m,p,T,flag) if flag == 1: act.genProgramSecrets() time_off_act = time.time() - start print('Offline time for actuator: ', "%.5f" % (time_off_act), ' sec') start = time.time() setup.encryptMatrices(flag) time_in_setup = time.time() - start print('Online time to compute constants for setup: ', "%.5f" % (time_in_setup), ' sec') start = time.time() client.encryptSetPoints() time_in_clients = time.time() - start print('Online time to compute constants for clients: ', "%.5f" % (time_in_clients), ' sec') if flag == 1: start = time.time() cloud.getCoeff(setup.enc_A,setup.enc_B,setup.enc_C,setup.enc_L,setup.enc_K,client.enc_xr,client.enc_ur) cloud.getProgramSecrets(act.enc_bLC,act.enc_bLA,act.enc_bCA,act.enc_bLB,act.enc_bCB) blinded_enc_Gamma3 = cloud.computeGamma3() # The actuator needs to refresh Gamma3 start_act = time.time() blinded_enc_Gamma3 = act.refresh_Gamma3(blinded_enc_Gamma3) time_in_act = time.time() - start_act cloud.getGamma3(blinded_enc_Gamma3) blinded_enc_Gamma, blinded_enc_Gamma2 = cloud.computeProducts() # The actuator needs to refresh Gamma, Gamma2, Gamma3 start_act = time.time() blinded_enc_Gamma, blinded_enc_Gamma2 = act.refresh_Gamma1_2(blinded_enc_Gamma, blinded_enc_Gamma2) time_in_act = time.time() - start_act + time_in_act print('Online time to compute constants for actuator: ', "%.5f" % (time_in_act), ' sec') cloud.getGamma1_2(blinded_enc_Gamma, blinded_enc_Gamma2) cloud.computeConstants() time_in_cloud = time.time() - start - time_in_act print('Online time to compute constants for cloud: ', "%.5f" % (time_in_cloud), ' sec') if flag == 0: Gamma = setup.Gamma; Gamma2 = setup.Gamma2; Gamma3 = setup.Gamma3 enc_Gamma = setup.enc_Gamma; enc_Gamma2 = setup.enc_Gamma2; enc_Gamma3 = setup.enc_Gamma3 else: Gamma = np.dot(np.eye(n, dtype = object) - np.dot(setup.L,setup.C),setup.A + np.dot(setup.B,setup.K)) Gamma2 = np.dot(np.eye(n, dtype = object) - np.dot(setup.L,setup.C),np.dot(setup.B,setup.K)) Gamma3 = np.dot(np.eye(n, dtype = object) - np.dot(setup.L,setup.C),setup.B) enc_Gamma = util_fpv.von_enc(pubkey,util_fpv.vfp(Gamma),act.bGamma,act.enc_bGamma) enc_Gamma2 = util_fpv.von_enc(pubkey,util_fpv.vfp(Gamma2),act.bGamma2,act.enc_bGamma2) enc_Gamma3 = util_fpv.von_enc(pubkey,util_fpv.vfp(Gamma3),act.bGamma3,act.enc_bGamma3) Gref = np.dot(Gamma3, client.ur) - np.dot(Gamma2, client.xr) Gref_2 = 2**lf*Gref uref = ur - np.dot(setup.K, client.xr) uref_2 = np.dot(uref,2**lf*np.eye(m,dtype = object)) cloud.enc_Gamma = enc_Gamma cloud.enc_Gamma2 = enc_Gamma2 cloud.enc_Gamma3 = enc_Gamma3 if flag == 0: time_in_act = 0 start = time.time() cloud.getCoeff(setup.enc_A,setup.enc_B,setup.enc_C,setup.enc_L,setup.enc_K,client.enc_xr,client.enc_ur) cloud.computeConstants() time_in_cloud = time.time() - start print('Online time to compute constants for cloud: ', "%.5f" % (time_in_cloud), ' sec') if verbose == 1: hat_x = np.zeros((n,T+1)) enc_x0 = util_fpv.von_enc(pubkey,x0,act.bx[:,0],util_fpv.vencrypt(pubkey.Pai_key,act.bx[:,0])) print('x0: ',util_fpv.vretrieve_fp(util_fpv.von_dec(privkey,enc_x0, util_fpv.vencrypt(pubkey.Pai_key,act.bx[:,0])))) start = time.time() k = 0 cloud.xk = client.enc_x0 enc_u0 = cloud.computeInput() u0 = act.getInput(enc_u0,k) if verbose == 1: plaintext_xk = client.x plaintext_x_series[:,k] = plaintext_xk hat_x[:,k] = util_fpv.vretrieve_fp(util_fpv.von_dec(privkey,cloud.xk,act.bx[:,k])) print('decrypted x%d: '%k, ["%.5f"% i for i in hat_x[:,k]]) print('decrypted u%d: '%k, ["%.5f"% i for i in u0]) print('u0: ', ["%.5f"% i for i in np.dot(setup.K,client.x) + uref]) # Get next state and measurement client.closedLoop(u0,k+1) enc_zk = client.getMeasurement(k) # The measurement time is k+1 but the labels are generated for k if verbose == 1: plaintext_zk = client.z print('z1: ', ["%.5f"% i for i in plaintext_zk]) print('decrypted z%d: '%(k+1), ["%.5f"% i for i in util_fpv.vretrieve_fp(util_fpv.von_dec(privkey,enc_zk))]) print('Online time for iteration %d: '%k, "%.5f" % (time.time() - start), ' sec') time_act = np.zeros((T-1,1)) time_cloud = np.zeros((T-1,1)) time_client = np.zeros((T-1,1)) # Start the control loop for k in range(1,T): start_it = time.time() blinded_xk = cloud.computeEstimate(cloud.xk,enc_zk) start_act = time.time() enc_xk2 = act.refresh_xk(blinded_xk,k) end_act = time.time()-start_act cloud.getEstimate(enc_xk2) # get xk if verbose == 1: hat_x[:,k] = util_fpv.vretrieve_fp(util_fpv.von_dec(privkey,cloud.xk,act.bx[:,k])) print('decrypted x%d: '%k, ["%.5f"% i for i in hat_x[:,k]]) plaintext_xk = np.dot(Gamma,plaintext_xk)+np.dot(setup.L,plaintext_zk)+Gref plaintext_x_series[:,k] = plaintext_xk print('x%d: '%k, ["%.5f"% i for i in plaintext_xk]) enc_uk = cloud.computeInput() start_act = time.time() uk = act.getInput(enc_uk,k) # get uk time_act[k-1] = end_act + time.time() - start_act if verbose == 1: print('decrypted u%d: '%k, uk) print('u%d: '%k, ["%.5f"% i for i in np.dot(setup.K,plaintext_xk)+uref]) client.closedLoop(uk,k+1) start_cl = time.time() enc_zk = client.getMeasurement(k) # get zk+1 time_client[k-1] = time.time() - start_cl if verbose == 1: plaintext_zk = client.z plaintext_zk = util_fpv.vretrieve_fp(util_fpv.von_dec(privkey,enc_zk, util_fpv.vencrypt(pubkey.Pai_key,act.bz[:,k]))) print('z%d: '%(k+1), ["%.5f"% i for i in plaintext_zk]) time_cloud[k-1] = time.time() - start_it - time_act[k-1] - time_client[k-1] print('Total online time for %d iterations: '%T, "%.5f" % (time.time() - start), ' sec') print('Mean online time for client for one iteration: ', " %.5f" % np.mean(time_client), ' sec') print('Mean online time for actuator for one iteration: ', " %.5f" % np.mean(time_act), ' sec') print('Mean online time for cloud for one iteration: ', " %.5f" % np.mean(time_cloud), ' sec') # print("%.5f, %.5f MB" % (memory_usage_resource(),memory_usage_psutil())) with open(os.path.abspath('results_'+str(DEFAULT_KEYSIZE)+'_'+str(DEFAULT_PRECISION)+'.txt'),'a+') as f: f.write("%d, %d, %d, flag %d\n " % (n,m,T,flag)); f.write("Offline time:\n setup: %.5f, client: %.5f, cloud: %.5f, actuator %.5f\n" % (time_off_setup, time_off_clients, time_off_cloud, time_off_act)) f.write("Initialization time:\n setup: %.5f, client: %.5f, cloud: %.5f, actuator %.5f\n" % (time_in_setup, time_in_clients, time_in_cloud, time_in_act)) f.write("Online time 1 iter:\n client: %.5f, cloud: %.5f, actuator %.5f\n" % (np.mean(time_client), np.mean(time_act), np.mean(time_cloud))) if folder == 'building_2_rooms' and verbose == 1: # evenly sampled time at 440s intervals Ts = 420 t = Ts*np.arange(0., T) fig, ax = plt.subplots(figsize=(16,8)) for i in range(int(n/2)): ax.plot(t, hat_x[i,:-1], 'C'+str(i), linewidth=2) ax.plot(t, hat_x[int(n/2)+i,:-1], 'C'+str(int(n/2)+i)+'--', linewidth=2) # ax.plot(t, plaintext_x_series[i,:],'C'+str(i)+'--',linewidth=2) ax.set(xlabel='Time (s)', ylabel='State x', title='Evolution of the estimates') ax.grid() plt.legend(('$\hat x_1$', '$\hat x_6$', '$\hat x_2$', '$\hat x_7$', '$\hat x_3$', '$\hat x_8$', '$\hat x_4$', '$\hat x_9$', '$\hat x_5$', '$\hat x_{10}$'), loc='lower right', shadow=True) fig.savefig("Figures/estimates.png") fig.show() fig2, ax = plt.subplots(figsize=(16,8)) t = Ts*np.arange(0., T) for i in range(int(n/2)): ax.plot(t, client.x_series[i,:-1], 'C'+str(i), linewidth=2) ax.plot(t, client.x_series[int(n/2)+i,:-1], 'C'+str(int(n/2)+i)+'--', linewidth=2) # ax.plot(t, plaintext_x_series[i,:],'C'+str(i)+'--',linewidth=2) ax.set(xlabel='Time (s)', ylabel='State x', title='Evolution of the true states') ax.grid() plt.legend(('$x_1$', '$x_6$', '$x_2$', '$x_7$', '$x_3$', '$x_8$', '$x_4$', '$x_9$', '$x_5$', '$x_{10}$'), loc='lower right', shadow=True) fig.savefig("Figures/states.png") plt.show()
def Plant(self, T, folder, A=None, B=None, C=None, F=None, K=None, L=None, x0=None, z1=None, W=None, V=None): self.T = T if A is None: # the vectors are read as rows regardless if they are columns or not A = np.loadtxt("Data/" + folder + "/A.txt", delimiter=',', dtype=float) B = np.loadtxt("Data/" + folder + "/B.txt", delimiter=',', dtype=float) C = np.loadtxt("Data/" + folder + "/C.txt", delimiter=',', dtype=float) F = np.loadtxt("Data/" + folder + "/F.txt", delimiter=',', dtype=float) K = np.loadtxt("Data/" + folder + "/K.txt", delimiter=',', dtype=float) L = np.loadtxt("Data/" + folder + "/L.txt", delimiter=',', dtype=float) W = np.loadtxt("Data/" + folder + "/W.txt", delimiter=',', dtype=float) V = np.loadtxt("Data/" + folder + "/V.txt", delimiter=',', dtype=float) size = np.shape(A) if len(size) == 2: self.n = size[0] if len(size) == 0: self.n == 1 size = np.shape(B) if self.n == 1: if len(size) == 0: self.m = 1 else: self.m = size else: if len(size) == 2: self.m = size[1] else: if len(size) == 1: self.m = 1 size = np.shape(C) if self.n == 1: if len(size) == 0: self.p = 1 else: self.p = size else: if len(size) == 2: self.p = size[0] else: if len(size) == 1: self.p = 1 A = A.reshape(self.n, self.n) B = B.reshape(self.n, self.m) C = C.reshape(self.p, self.n) K = K.reshape(self.m, self.n) L = L.reshape(self.n, self.p) self.d, d = np.shape(W) self.A = A self.B = B self.C = C self.F = F self.K = K self.L = L self.W = W self.V = V self.Af = util_fpv.vfp(A) self.Bf = util_fpv.vfp(B) self.Cf = util_fpv.vfp(C) self.Kf = util_fpv.vfp(K) self.Lf = util_fpv.vfp(L) self.Wf = util_fpv.vfp(W) self.Vf = util_fpv.vfp(V)