forked from asanso/CryptoWithSageMath
-
Notifications
You must be signed in to change notification settings - Fork 1
/
paillier.sage
executable file
·59 lines (51 loc) · 1.15 KB
/
paillier.sage
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# Paillier keygen, simple version with g = n + 1
# Output:
# public key (n, g), private key (lmd, mu)
# `n` is integer
# `g` in Z_{n^2}*
# `lmd` is integer
# `mu` is in Z_n
#
def paillier_keygen_simple(bits):
p = random_prime(2^bits)
q = random_prime(2^bits)
n = p * q
Zn = IntegerModRing(n)
Zn2 = IntegerModRing(n^2)
g = Zn2(n + 1)
lmd = (p - 1) * (q - 1)
mu = Zn(lmd)^-1
return ((n, g), (lmd, mu))
# Paillier Encryption
# input:
# plaintext `m` is integer in [0, n-1]
# output:
# ciphertext `c` in Z_{n^2}*
#
def paillier_encrypt(m, pk):
(n, g) = pk
Zn2 = IntegerModRing(n^2)
r = Zn2(randint(0, n))
c = g^m * r^n
return c
# L(u) = (u - 1)/n
# m = (L((c^lambda) mod n^2) * u) mod n
# c in Z_{n^2}
#
def paillier_decrypt(c, sk):
((n, g), (lmd, mu)) = sk
Zn = IntegerModRing(n)
c = Zn((Integer(c^lmd) - 1) / n) * mu
return c
def paillier_ciphertext_add(c1, c2, pk):
(n, g) = pk
Zn2 = IntegerModRing(n^2)
r = Zn2(randint(0, n))
return c1 * c2 * r^n
def paillier_ciphertext_scalar_mul(a, c, pk):
return c^a;
def paillier_ciphertext_linear(a, c1, b, c2, pk):
(n, g) = pk
Zn2 = IntegerModRing(n^2)
r = Zn2(randint(0, n))
return (c1^a) * (c2^b) * r^n