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 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 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) ])
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) ])
def decrypt(self, v): """Decrypt a given ciphertext v with given key pair. The plain text is defined: .. math:: Dec(v) = \\frac{L(v^{\\lambda})}{L(g^{\\lambda})} \\mod m Args: v: scalar or vector of ciphertext. Returns: vector of plain texts; even if the input is a scalar, one dimension vector is returned. """ if not isinstance(v, (tuple, list, np.ndarray)): v = [v] X = [ (powmod(int(vi), self.Lambda, self.m2) - 1) % self.m2 // self.pk.m for vi in v ] Y = (self.pk.glambda - 1) % self.m2 // self.pk.m return np.array([(Xi * invert(Y, self.pk.m)) % self.pk.m for Xi in X])
def share(c): """Compute the description share associated with this encryption. """ return (np.array([ powmod(int(ci), int(yi) - self.a + self.b, self.m2) for ci, yi in zip(c, y) ]) * self.pk.encrypt(r)) % self.m2
def test_g(self): """Test :math:`g^{\\lambda}`. """ self.assertEqual( powmod(self.pk.g, self.sk.Lambda, self.pk.m**2), self.pk.glambda)
def test_glambda(self): """Test :math:`(g^{\\lambda})^{m} \\equiv 1 \\mod m^{2}`. """ self.assertEqual(powmod(self.pk.glambda, self.pk.m, self.pk.m**2), 1)
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)