def test_vector(self): """Test Encrypt-Sum-Squad with vectors. """ data = [ np.array([random_m(self.pk.m) for _ in range(20)]) for _ in range(len(self.cks)) ] R = [ np.array([random_m(self.pk.m) for _ in range(20)]) for _ in range(len(self.cks)) ] C = [] T = [] for ck, d, r in zip(self.cks, data, R): cu, t = ck.encrypt_sum_squared(d, r) C.append(cu) T.append(t) c = self.sk.aggregate_sum_squared(C) cp = self.sk.aggregate_sum_squared2([t(c) for t in T]) res = self.sk.decrypt(cp) sum_of_values = sum(data) ans = (sum_of_values**2 + sum(R)) % self.pk.m for v, d in zip(res, ans): self.assertEqual(v, d)
def generate_keypair(m_length=2048): """Generate a key pair. """ p = q = m = None while not m or gcd(m, (p - 1) * (q - 1)) != 1: m_len = 0 while m_len < m_length: p = getprimeover(m_length // 2) q = getprimeover(m_length // 2) if p == q: continue m = p * q m_len = m.bit_length() beta = random_m(m) Lambda = beta * lcm(p - 1, q - 1) a = random_m(m) b = random_m(m) m2 = m**2 g = (powmod(1 + m, a, m2) * powmod(b, m, m2)) % m2 pk = PublicKey(m, g, powmod(g, Lambda, m2)) sk = PrivateKey(pk, Lambda) return sk, pk
def encrypt(self, v): """Encrypt a given number v. The ciphertext of v is defined: .. math:: Enc(v) = g^{v} r^{m} \\mod m^{2} Args: v: scalar or vector to be encrypted. Returns: vector of ciphertexts; even if the input is a scalar, one dimension vector is returned. """ if not isinstance(v, np.ndarray): if not isinstance(v, (tuple, list)): v = np.array([v]) else: v = np.array(v) r = [random_m(self.m) for _ in range(len(v))] m2 = self.m2 return np.array([ (powmod(self.g, int(vi), m2) * powmod(ri, self.m, m2)) % m2 for vi, ri in zip(v, r) ])
def test_vector_without_randomness(self): """Test Encrypt-Noisy-Sum for vectors without randomness. """ data = [ np.array([random_m(self.pk.m) for _ in range(20)]) for _ in range(len(self.cks)) ] Y = [] Yt = [] X = [] T = [] logging.info("Step1: calling encrypt_noisy_sum") for c, v in zip(self.cks, data): R = [np.array([0 for _ in range(len(v))]) for _ in range(5)] y, y_t, x, t = c.encrypt_noisy_sum(v, 0, R) Y.append(y) Yt.append(y_t) X.append(x) T.append(t) logging.info("Step2: aggregate_noisy_sum") cy = self.sk.aggregate_noisy_sum(Y) logging.info("Step3: aggregate_noisy_sum2") cp = self.sk.aggregate_noisy_sum2([ [t[i](c) for i, c in enumerate(cy)] + [x] for t, x in zip(Yt, X) ]) logging.info("Step4: decrypt_sum") res = self.sk.decrypt_sum([t(cp) for t in T]) for v, d in zip(res, sum(data) % self.pk.m): self.assertEqual(v, d)
def generate_user_keys(self, n): """Generate the given number of user's key. """ Lambda_u = [] a = [random_m(self.pk.m // n) for _ in range(n)] b = [] for _ in range(n - 1): Lambda_u.append(random_m(self.pk.m // n)) b.append(random_m(self.pk.m // n)) # Sum of Lambda_u must be equal to Lambda. Lambda_u.append(self.Lambda - sum(Lambda_u)) # Sum of a must be remembered. self.a = sum(a) % self.m2 # Sum of b must be equal to 0, i.e. m*2 b.append(self.m2 - sum(b)) return [ ClientKey(self.pk, Lambda_u, au, bu) for Lambda_u, au, bu in zip(Lambda_u, a, b) ]
def test_with_zeros(self): """Test Encrypt-Sum-Squared with 0. """ R = [random_m(self.pk.m) for _ in range(len(self.cks))] C = [] T = [] for ck, r in zip(self.cks, R): cu, t = ck.encrypt_sum_squared(0, r) C.append(cu) T.append(t) c = self.sk.aggregate_sum_squared(C) cp = self.sk.aggregate_sum_squared2([t(c) for t in T]) res = self.sk.decrypt(cp) self.assertEqual(res, sum(R) % self.pk.m)
def encrypt_sum(self, v, r=None): """Encrypt a given value. """ if not isinstance(v, np.ndarray): if not isinstance(v, (tuple, list)): v = np.array([v]) else: v = np.array(v) if r is None: r = np.array([random_m(self.pk.m) for _ in range(len(v))]) e = self.pk.encrypt(v + r) def share(c): """Compute a decryption share. """ return np.array([ powmod(int(ci), self.Lambda_u, self.m2) * powmod(self.pk.glambda, -int(ri), self.m2) for ci, ri in zip(c, r) ]) return e, share
def encrypt_noisy_sum(self, v, sigma, R=None): """Encrypt a given number for Encrypt-Noisy-Sum. """ if not isinstance(v, np.ndarray): if not isinstance(v, (tuple, list)): v = np.array([v]) else: v = np.array(v) if not R: R = [ np.array([random_m(self.pk.m) for _ in range(len(v))]) for _ in range(5) ] r = (R[0] + R[1] + (self.m2 - R[2]) + (self.m2 - R[3]) + R[4]) % self.m2 enc_y = [] enc_y_t = [] for i in range(4): y = [self._gauss(0, sigma) for _ in range(len(v))] c, t = self.encrypt_sum_squared(y, R[i]) enc_y.append(c) enc_y_t.append(t) enc_x, _ = self.encrypt_sum(v, R[4]) def share(c): """Compute the description share associated with this encryption. """ return np.array([ powmod(int(ci), self.Lambda_u, self.m2) * powmod( self.pk.glambda, -int(ri), self.m2) for ci, ri in zip(c, r) ]) return enc_y, enc_y_t, enc_x, share
def test(self): """Test Encrypt-Sum-Squared. """ R = [random_m(self.servicer.pk.m) for _ in range(2)] self.run_encrypt_sum_squad(R)
def test_propertyof_m_and_lambda(self): """Test :math:`b^{m\\lambda} \\equiv 1 \\mod m^{2}`. """ b = random_m(self.pk.m) self.assertEqual( powmod(b, self.pk.m * self.sk.Lambda, self.pk.m**2), 1)
def test(self): """Test Encrypt-Sum-Squared. """ R = [random_m(self.pk.m) for _ in range(len(self.cks))] self.run_encrypt_sum_squad(R)