def __mul__(self, scalar): """return Multiply by an scalar(such as int, float) """ encode = FixedPointNumber.encode(scalar, self.public_key.n, self.public_key.max_int) plaintext = encode.encoding if plaintext < 0 or plaintext >= self.public_key.n: raise ValueError("Scalar out of bounds: %i" % plaintext) if plaintext >= self.public_key.n - self.public_key.max_int: # Very large plaintext, play a sneaky trick using inverses neg_c = gmpy_math.invert(self.ciphertext(False), self.public_key.nsquare) neg_scalar = self.public_key.n - plaintext ciphertext = gmpy_math.powmod(neg_c, neg_scalar, self.public_key.nsquare) else: ciphertext = gmpy_math.powmod(self.ciphertext(False), plaintext, self.public_key.nsquare) exponent = self.exponent + encode.exponent return PaillierEncryptedNumber(self.public_key, ciphertext, exponent)
def init(self): """ Init self.exponent :return: """ while True: self.exponent = random.randint(2, self.mod_base) if gcd(self.exponent, self.mod_base - 1) == 1: self.exponent_inverse = invert(self.exponent, self.mod_base - 1) break
def invert(self, a): """ :param a: IntegersModuloPrimeElement :return: IntegersModuloPrimeElement """ if type(a) != IntegersModuloPrimeElement: raise TypeError( "Invert only supports IntegersModuloPrimeElement objects") return IntegersModuloPrimeElement(invert(a.val, self.mod))
def __init__(self, mod_base, exponent=None): """ :param exponent: int :param mod_base: int """ super(PohligHellmanCipherKey, self).__init__() self.mod_base = mod_base # p if exponent is not None and gcd(exponent, mod_base - 1) != 1: raise ValueError("In Pohlig, exponent and the totient of the modulo base must be coprimes") self.exponent = exponent # a self.exponent_inverse = None if exponent is None else invert(exponent, mod_base - 1)
def raw_encrypt(self, plaintext, random_value=None): if random_value is not None and random_value != 1: raise NotImplementedError("unsupported in this class, use PaillierPublicKey instead") if not isinstance(plaintext, int): raise TypeError("plaintext should be int, but got: %s" % type(plaintext)) if plaintext >= (self.n - self.max_int) and plaintext < self.n: # Very large plaintext, take a sneaky shortcut using inverses neg_plaintext = self.n - plaintext # = abs(plaintext - nsquare) neg_ciphertext = (self.n * neg_plaintext + 1) % self.nsquare ciphertext = gmpy_math.invert(neg_ciphertext, self.nsquare) else: ciphertext = (self.n * plaintext + 1) % self.nsquare return ciphertext
def __init__(self, public_key, p, q): if not p * q == public_key.n: raise ValueError("given public key does not match the given p and q") if p == q: raise ValueError("p and q have to be different") self.public_key = public_key if q < p: self.p = q self.q = p else: self.p = p self.q = q self.psquare = self.p * self.p self.qsquare = self.q * self.q self.q_inverse = gmpy_math.invert(self.q, self.p) self.hp = self.h_func(self.p, self.psquare) self.hq = self.h_func(self.q, self.qsquare)
def decrypt(self, x_values, y_values): k = len(x_values) assert k == len(set(x_values)), 'x_values points must be distinct' secret = 0 for i in range(k): numerator, denominator = 1, 1 for j in range(k): if i == j: continue # compute a fraction & update the existing numerator + denominator numerator = (numerator * (0 - x_values[j])) denominator = (denominator * (x_values[i] - x_values[j])) # get the polynomial from the numerator + denominator mod inverse lagrange_polynomial = (numerator * gmpy_math.invert(denominator, self.q)) % self.q # multiply the current y & the evaluated polynomial & add it to f(x) secret = (self.q + secret + (y_values[i] * lagrange_polynomial)) % self.q return self.decode(secret)
def raw_encrypt(self, plaintext, random_value=None): """ """ if not isinstance(plaintext, int): raise TypeError("plaintext should be int, but got: %s" % type(plaintext)) if plaintext >= (self.n - self.max_int) and plaintext < self.n: # Very large plaintext, take a sneaky shortcut using inverses neg_plaintext = self.n - plaintext # = abs(plaintext - nsquare) neg_ciphertext = (self.n * neg_plaintext + 1) % self.nsquare ciphertext = gmpy_math.invert(neg_ciphertext, self.nsquare) else: ciphertext = (self.n * plaintext + 1) % self.nsquare ciphertext = self.apply_obfuscator(ciphertext, random_value) return ciphertext
def h_func(self, x, xsquare): """Computes the h-function as defined in Paillier's paper page. """ return gmpy_math.invert( self.l_func(gmpy_math.powmod(self.public_key.g, x - 1, xsquare), x), x)
def mod_inverse(self): return gmpy_math.invert(self.a, self.n)
def mod_inverse(self): a_array_inv = [0 for _ in self.a_array] for i in range(self.key_round): a_array_inv[i] = invert(self.a_array[i], self.n_array[i]) return a_array_inv