def raw_encrypt(self, plaintext, r_value=None): """Paillier encryption of a positive integer plaintext < :attr:`n`. You probably should be using :meth:`encrypt` instead, because it handles positive and negative ints and floats. Args: plaintext (int): a positive integer < :attr:`n` to be Paillier encrypted. Typically this is an encoding of the actual number you want to encrypt. r_value (int): obfuscator for the ciphertext; by default (i.e. r_value is None), a random value is used. Returns: int: Paillier encryption of plaintext. Raises: TypeError: if plaintext is not an int. """ if not isinstance(plaintext, int): raise TypeError('Expected int type plaintext but got: %s' % type(plaintext)) if self.n - self.max_int <= plaintext < self.n: # Very large plaintext, take a sneaky shortcut using inverses neg_plaintext = self.n - plaintext # = abs(plaintext - nsquare) neg_ciphertext = powmod(self.g, neg_plaintext, self.nsquare) nude_ciphertext = invert(neg_ciphertext, self.nsquare) else: nude_ciphertext = powmod(self.g, plaintext, self.nsquare) r = r_value or self.get_random_lt_n() obfuscator = powmod(r, self.n, self.nsquare) return (nude_ciphertext * obfuscator) % self.nsquare
def my__mul__(self, other): """Multiply by an int, float, or EncodedNumber. If `other` is a scalar, it is first encoded to fixed-point precision of `self`""" if isinstance(other, paillier.EncryptedNumber): raise NotImplementedError('Good luck with that...') if isinstance(other, paillier.EncodedNumber): encoding = other else: int_rep = int(other * pow(paillier.EncodedNumber.BASE, -self.exponent)) if abs(int_rep) > self.public_key.max_int: raise ValueError('Integer needs to be within +/- %d but got %d' % (self.public_key.max_int, int_rep)) # Wrap negative numbers by adding n encoding = paillier.EncodedNumber(self.public_key, int_rep % self.public_key.n, self.exponent) product = self._raw_mul(encoding.encoding) exponent = self.exponent + encoding.exponent unscaled_result = paillier.EncryptedNumber(self.public_key, product, exponent) # moving the decimal point to end up having the same number of digits to its right scaling_multiplier = invert(paillier.EncodedNumber.BASE**(-self.exponent), self.public_key.n) scaled_product = unscaled_result._raw_mul(scaling_multiplier) return paillier.EncryptedNumber(self.public_key, scaled_product, self.exponent)
def _raw_mul(self, plaintext): """Returns the integer E(a * plaintext), where E(a) = ciphertext Args: plaintext (int): number by which to multiply the `EncryptedNumber`. *plaintext* is typically an encoding. 0 <= *plaintext* < :attr:`~PaillierPublicKey.n` Returns: int: Encryption of the product of `self` and the scalar encoded in *plaintext*. Raises: TypeError: if *plaintext* is not an int. ValueError: if *plaintext* is not between 0 and :attr:`PaillierPublicKey.n`. """ if not isinstance(plaintext, int): raise TypeError('Expected ciphertext to be int, not %s' % type(plaintext)) if plaintext < 0 or plaintext >= self.public_key.n: raise ValueError('Scalar out of bounds: %i' % plaintext) if self.public_key.n - self.public_key.max_int <= plaintext: # Very large plaintext, play a sneaky trick using inverses neg_c = invert(self.ciphertext(False), self.public_key.nsquare) neg_scalar = self.public_key.n - plaintext return powmod(neg_c, neg_scalar, self.public_key.nsquare) else: return powmod(self.ciphertext(False), plaintext, self.public_key.nsquare)
def raw_decrypt(self, ciphertext): """Decrypt raw ciphertext and return raw plaintext. Args: ciphertext (int): (usually from :meth:`EncryptedNumber.ciphertext()`) that is to be Paillier decrypted. Returns: int: Paillier decryption of ciphertext. This is a positive integer < :attr:`public_key.n`. Raises: TypeError: if ciphertext is not an int. """ if not isinstance(ciphertext, dict): raise TypeError('Expected ciphertext to be a dict, not: %s' % type(ciphertext)) #decrypt_to_p = self.l_function(powmod(ciphertext, self.p-1, self.psquare), self.p) * self.hp % self.p #decrypt_to_q = self.l_function(powmod(ciphertext, self.q-1, self.qsquare), self.q) * self.hq % self.q #return self.crt(decrypt_to_p, decrypt_to_q) t1=invert(ciphertext['A'],self.nsquare) t2=powmod(t1,self.sk,self.nsquare) t3=ciphertext['B'] t4=t3*t2 one=powmod(1,1,self.nsquare) t5=t4 - one t6=t5%self.nsquare m = t6 // self.n return m
def _raw_mul(self, plaintext): """Returns the integer E(a * plaintext), where E(a) = ciphertext Args: plaintext (int): number by which to multiply the `EncryptedNumber`. *plaintext* is typically an encoding. 0 <= *plaintext* < :attr:`~PaillierPublicKey.n` Returns: int: Encryption of the product of `self` and the scalar encoded in *plaintext*. Raises: TypeError: if *plaintext* is not an int. ValueError: if *plaintext* is not between 0 and :attr:`PaillierPublicKey.n`. """ a,b = self, plaintext if not isinstance(plaintext, int): raise TypeError('Expected ciphertext to be int, not %s' % type(plaintext)) if plaintext < 0 or plaintext >= self.public_key.n: raise ValueError('Scalar out of bounds: %i' % plaintext) if self.public_key.n - self.public_key.max_int <= plaintext: # Very large plaintext, play a sneaky trick using inverses neg_c = invert(self.ciphertext, self.public_key.nsquare) neg_scalar = self.public_key.n - plaintext return powmod(neg_c, neg_scalar, self.public_key.nsquare) else: return a.exponentiate(plaintext)
def raw_decrypt(self, ciphertext): if not isinstance(ciphertext, int): raise TypeError('Expected ciphertext to be an int, not: %s' % type(ciphertext)) n = self.n t = self.t SecretKeyShares = self.SecretKeyShares theta = self.theta nFac = math.factorial(n) #c = Ciphertext.ciphertext() c = ciphertext N = self.public_key.n NSquare = N**2 shares = SecretKeyShares.shares degree = SecretKeyShares.degree # NB: Here the reconstruction set is implicity defined, but any # large enough subset of shares will do. reconstruction_shares = { key: shares[key] for key in list(shares.keys())[:degree + 1] } lagrange_interpol_enum = { i: mult_list([j for j in reconstruction_shares.keys() if i != j]) for i in reconstruction_shares.keys() } lagrange_interpol_denom = { i: mult_list([(j - i) for j in reconstruction_shares.keys() if i != j]) for i in reconstruction_shares.keys() } exponents = [ (nFac * lagrange_interpol_enum[i] * reconstruction_shares[i]) // lagrange_interpol_denom[i] for i in reconstruction_shares.keys() ] # Notice that the partial decryption is already raised to the power given # by the Lagrange interpolation coefficient partialDecryptions = [powmod(c, exp, NSquare) for exp in exponents] combinedDecryption = mult_list(partialDecryptions) % NSquare if (combinedDecryption - 1) % N != 0: print("Error, combined decryption minus one not divisible by N") message = ((combinedDecryption - 1) // N * invert(theta, N)) % N return message
def raw_transform(self,encrypted_number): ciphertext = encrypted_number.ciphertext if not isinstance(ciphertext, dict): raise TypeError('Expected ciphertext to be a dict, not: %s' % type(ciphertext)) A = ciphertext['A'] A1 = invert(ciphertext['A'],self.public_key.nsquare) t2 = powmod(A1,self.sk,self.public_key.nsquare) t3 = ciphertext['B'] t4=t3*t2 B=t4%self.public_key.nsquare transformed_cipher = {"A":A,"B":B} print('transformerssssss',transformed_cipher) encrypted_number.ciphertext = transformed_cipher return encrypted_number
def _raw_mul(self, plaintext): if not isinstance(plaintext, int): raise TypeError('Expected ciphertext to be int, not %s' % type(plaintext)) if plaintext < 0 or plaintext >= self.public_key.n: raise ValueError('Scalar out of bounds: %i' % plaintext) if self.public_key.n - self.public_key.max_int <= plaintext: # Very large plaintext, play a sneaky trick using inverses neg_c = invert(self.ciphertext(False), self.public_key.nsquare) neg_scalar = self.public_key.n - plaintext return powmod(neg_c, neg_scalar, self.public_key.nsquare) else: return powmod(self.ciphertext(False), plaintext, self.public_key.nsquare)
def secure_bit_decomposition_server(client, public_key, enc_x, bitlength_m): l_inv2 = paillier.EncodedNumber.encode(public_key, invert(2, public_key.n)) T = enc_x + 0 x_decomp = [] send(client, bitlength_m) for i in range(0, bitlength_m): x_decomp.append(secure_lsb_server(client, public_key, T, i)) Z = T - x_decomp[i] T = Z * l_inv2 if svr_server(client, public_key, enc_x, x_decomp) == 1: return list(reversed(x_decomp)) else: return secure_bit_decomposition_server(client, public_key, enc_x, bitlength_m)
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: #check that p and q are different, otherwise we can't compute p^-1 mod q raise ValueError('p and q have to be different') self.public_key = public_key if q < p: #ensure that p < q. 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.p_inverse = invert(self.p, self.q) self.hp = self.h_function(self.p, self.psquare); self.hq = self.h_function(self.q, self.qsquare);
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: # check that p and q are different, otherwise we can't compute p^-1 mod q raise ValueError('p and q have to be different') self.public_key = public_key if q < p: #ensure that p < q. 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.p_inverse = invert(self.p, self.q) self.hp = self.h_function(self.p, self.psquare) self.hq = self.h_function(self.q, self.qsquare)
def raw_encrypt(self, plaintext, r_value=None): if not isinstance(plaintext, int): raise TypeError('Expected int type plaintext but got: %s' % type(plaintext)) if self.n - self.max_int <= 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 nude_ciphertext = invert(neg_ciphertext, self.nsquare) else: # we chose g = n + 1, so that we can exploit the fact that # (n+1)^plaintext = n*plaintext + 1 mod n^2 nude_ciphertext = (self.n * plaintext + 1) % self.nsquare r = r_value or self.get_random_lt_n() obfuscator = powmod(r, self.n, self.nsquare) return (nude_ciphertext * obfuscator) % self.nsquare
def raw_encrypt(self, plaintext, r_value=None): """Paillier encryption of a positive integer plaintext < :attr:`n`. 一个正整数的加密 You probably should be using :meth:`encrypt` instead, because it handles positive and negative ints and floats. 应该使用方法encrypt加密,因为他处理正负的整数和浮点数 Args: plaintext (int): a positive integer < :attr:`n` to be Paillier encrypted. Typically this is an encoding of the actual number you want to encrypt. plaintext(int)为一个小于n的要加密的实际数字编码 r_value (int): obfuscator for the ciphertext; by default (i.e. r_value is None), a random value is used. 密文模糊处理;默认情况下时(即r_value为None)使用随机值。 Returns: int: Paillier encryption of plaintext. plaintext的Paillier加密 Raises: TypeError: if plaintext is not an int. 异常:plaintext不是整数 """ #异常判断 if not isinstance(plaintext, int): raise TypeError('Expected int type plaintext but got: %s' % type(plaintext)) #加密plaintext if self.n - self.max_int <= 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 nude_ciphertext = invert(neg_ciphertext, self.nsquare) else: # we chose g = n + 1, so that we can exploit the fact that # (n+1)^plaintext = n*plaintext + 1 mod n^2 nude_ciphertext = (self.n * plaintext + 1) % self.nsquare r = r_value or self.get_random_lt_n() obfuscator = powmod(r, self.n, self.nsquare)#使用gmp return (nude_ciphertext * obfuscator) % self.nsquare
def generate_paillier_keypair(private_keyring=None, n_length=DEFAULT_KEYSIZE): """Return a new :class:`PaillierPublicKey` and :class:`PaillierPrivateKey`. Add the private key to *private_keyring* if given. Args: private_keyring (PaillierPrivateKeyring): a :class:`PaillierPrivateKeyring` on which to store the private key. n_length: key size in bits. Returns: tuple: The generated :class:`PaillierPublicKey` and :class:`PaillierPrivateKey` """ p = q = n = None n_len = 0 while n_len != n_length: p = getprimeover(n_length // 2) q = getprimeover(n_length // 2) n = p * q n_len = n.bit_length() # Simpler Paillier variant with g=n+1 results in lambda equal to phi # and mu is phi inverse mod n. g = n + 1 public_key = PaillierPublicKey(g, n) phi_n = (p - 1) * (q - 1) Lambda = phi_n mu = invert(phi_n, n) private_key = PaillierPrivateKey(public_key, Lambda, mu) if private_keyring is not None: private_keyring.add(private_key) return public_key, private_key
def h_function(self, x, xsquare): """Computes the h-function as defined in Paillier's paper page 12, 'Decryption using Chinese-remaindering'. """ return invert(self.l_function(powmod(self.public_key.g, x - 1, xsquare),x), x)
def testInvertNonPrime(self): a = 3 p = 4 self.assertEqual(a * util.invert(a, p) % p, 1)
def testInvert(self): p = 101 for i in range(1, p): iinv = util.invert(i, p) self.assertEqual((iinv * i) % p, 1)