from random import randint
from gmpy2 import gcd, powmod, invert, lcm
from Crypto.Util.number import getPrime
L =lambda x, n:(x -1)// n
defpaillier_keygen(bits:int=1024):
p = getPrime(bits //2)
q = getPrime(bits //2)
n = p * q
lam = lcm(p -1, q -1)
g = randint(1, n * n -1)
t = L(powmod(g, lam, n **2), n)while gcd(t, n)!=1:
g = randint(1, n * n -1)
t = L(powmod(g, lam, n **2), n)
mu = invert(t, n)return n, g, lam, mu
defpaillier_encrypt(m:int, n:int, g:int)->int:
r = randint(1, n -1)while gcd(r, n)!=1:
r = randint(1, n -1)
mod = n * n
c = powmod(g, m, mod)* powmod(r, n, mod)% mod
return c
defpaillier_decrypt(c:int, n:int, g:int, lam:int, mu:int)->int:
m = L(powmod(c, lam, n **2), n)* mu % n
return m