2626 Mapping = dict
2727
2828from phe import EncodedNumber
29- from phe .util import invert , powmod , getprimeover , isqrt
29+ from phe .util import invert , powmod , mulmod , getprimeover , isqrt
3030
3131# Paillier cryptosystem is based on integer factorisation.
3232# The default is chosen to give a minimum of 128 bits of security.
@@ -125,6 +125,7 @@ def raw_encrypt(self, plaintext, r_value=None):
125125 if self .n - self .max_int <= plaintext < self .n :
126126 # Very large plaintext, take a sneaky shortcut using inverses
127127 neg_plaintext = self .n - plaintext # = abs(plaintext - nsquare)
128+ # avoid using gmpy2's mulmod when a * b < c
128129 neg_ciphertext = (self .n * neg_plaintext + 1 ) % self .nsquare
129130 nude_ciphertext = invert (neg_ciphertext , self .nsquare )
130131 else :
@@ -135,7 +136,7 @@ def raw_encrypt(self, plaintext, r_value=None):
135136 r = r_value or self .get_random_lt_n ()
136137 obfuscator = powmod (r , self .n , self .nsquare )
137138
138- return (nude_ciphertext * obfuscator ) % self .nsquare
139+ return mulmod (nude_ciphertext , obfuscator , self .nsquare )
139140
140141 def get_random_lt_n (self ):
141142 """Return a cryptographically random number less than :attr:`n`"""
@@ -342,8 +343,14 @@ def raw_decrypt(self, ciphertext):
342343 raise TypeError ('Expected ciphertext to be an int, not: %s' %
343344 type (ciphertext ))
344345
345- decrypt_to_p = self .l_function (powmod (ciphertext , self .p - 1 , self .psquare ), self .p ) * self .hp % self .p
346- decrypt_to_q = self .l_function (powmod (ciphertext , self .q - 1 , self .qsquare ), self .q ) * self .hq % self .q
346+ decrypt_to_p = mulmod (
347+ self .l_function (powmod (ciphertext , self .p - 1 , self .psquare ), self .p ),
348+ self .hp ,
349+ self .p )
350+ decrypt_to_q = mulmod (
351+ self .l_function (powmod (ciphertext , self .q - 1 , self .qsquare ), self .q ),
352+ self .hq ,
353+ self .q )
347354 return self .crt (decrypt_to_p , decrypt_to_q )
348355
349356 def h_function (self , x , xsquare ):
@@ -363,7 +370,7 @@ def crt(self, mp, mq):
363370 mp(int): the solution modulo p.
364371 mq(int): the solution modulo q.
365372 """
366- u = (mq - mp ) * self .p_inverse % self .q
373+ u = mulmod (mq - mp , self .p_inverse , self .q )
367374 return mp + (u * self .p )
368375
369376 def __eq__ (self , other ):
@@ -613,7 +620,7 @@ def obfuscate(self):
613620 """
614621 r = self .public_key .get_random_lt_n ()
615622 r_pow_n = powmod (r , self .public_key .n , self .public_key .nsquare )
616- self .__ciphertext = self .__ciphertext * r_pow_n % self .public_key .nsquare
623+ self .__ciphertext = mulmod ( self .__ciphertext , r_pow_n , self .public_key .nsquare )
617624 self .__is_obfuscated = True
618625
619626 def _add_scalar (self , scalar ):
@@ -709,7 +716,7 @@ def _raw_add(self, e_a, e_b):
709716 int: E(a + b), calculated by taking the product of E(a) and
710717 E(b) modulo :attr:`~PaillierPublicKey.n` ** 2.
711718 """
712- return e_a * e_b % self .public_key .nsquare
719+ return mulmod ( e_a , e_b , self .public_key .nsquare )
713720
714721 def _raw_mul (self , plaintext ):
715722 """Returns the integer E(a * plaintext), where E(a) = ciphertext
0 commit comments