26
26
Mapping = dict
27
27
28
28
from phe import EncodedNumber
29
- from phe .util import invert , powmod , getprimeover , isqrt
29
+ from phe .util import invert , powmod , mulmod , getprimeover , isqrt
30
30
31
31
# Paillier cryptosystem is based on integer factorisation.
32
32
# 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):
125
125
if self .n - self .max_int <= plaintext < self .n :
126
126
# Very large plaintext, take a sneaky shortcut using inverses
127
127
neg_plaintext = self .n - plaintext # = abs(plaintext - nsquare)
128
+ # avoid using gmpy2's mulmod when a * b < c
128
129
neg_ciphertext = (self .n * neg_plaintext + 1 ) % self .nsquare
129
130
nude_ciphertext = invert (neg_ciphertext , self .nsquare )
130
131
else :
@@ -135,7 +136,7 @@ def raw_encrypt(self, plaintext, r_value=None):
135
136
r = r_value or self .get_random_lt_n ()
136
137
obfuscator = powmod (r , self .n , self .nsquare )
137
138
138
- return (nude_ciphertext * obfuscator ) % self .nsquare
139
+ return mulmod (nude_ciphertext , obfuscator , self .nsquare )
139
140
140
141
def get_random_lt_n (self ):
141
142
"""Return a cryptographically random number less than :attr:`n`"""
@@ -342,8 +343,14 @@ def raw_decrypt(self, ciphertext):
342
343
raise TypeError ('Expected ciphertext to be an int, not: %s' %
343
344
type (ciphertext ))
344
345
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 )
347
354
return self .crt (decrypt_to_p , decrypt_to_q )
348
355
349
356
def h_function (self , x , xsquare ):
@@ -363,7 +370,7 @@ def crt(self, mp, mq):
363
370
mp(int): the solution modulo p.
364
371
mq(int): the solution modulo q.
365
372
"""
366
- u = (mq - mp ) * self .p_inverse % self .q
373
+ u = mulmod (mq - mp , self .p_inverse , self .q )
367
374
return mp + (u * self .p )
368
375
369
376
def __eq__ (self , other ):
@@ -613,7 +620,7 @@ def obfuscate(self):
613
620
"""
614
621
r = self .public_key .get_random_lt_n ()
615
622
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 )
617
624
self .__is_obfuscated = True
618
625
619
626
def _add_scalar (self , scalar ):
@@ -709,7 +716,7 @@ def _raw_add(self, e_a, e_b):
709
716
int: E(a + b), calculated by taking the product of E(a) and
710
717
E(b) modulo :attr:`~PaillierPublicKey.n` ** 2.
711
718
"""
712
- return e_a * e_b % self .public_key .nsquare
719
+ return mulmod ( e_a , e_b , self .public_key .nsquare )
713
720
714
721
def _raw_mul (self , plaintext ):
715
722
"""Returns the integer E(a * plaintext), where E(a) = ciphertext
0 commit comments