基于离散对数的公钥加密

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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import random                   
from Crypto.Util import number

def GenPara(bitlen):
q = number.getPrime(bitlen-1)
while(not number.isPrime(2 * q + 1)):
q = number.getPrime(bitlen-1)
p = 2 * q + 1 # generate safe prime p = 2 \* q + 1
g = random.randint(0, p-1)
while(fastPowMod(g, 2, p) == 1 or fastPowMod(g, q, p) == 1):
g = random.randint(0, p-1) # generate the primitive element g
return p, q, g



def fastPowMod(b,n,m): # 快速模幂
b = b % m
a = 1
while (n):
if n & 1:
a = (a * b) % m
n>>=1
b = (b * b) % m
return a

def GenKey(p, g):
x = random.randint(1, p-1)
y = fastPowMod(g, x, p)
return x, y

def Enc(m, p, g, y):
k = random.randint(1, p-2)
u = fastPowMod(g, k, p)
v = fastPowMod(y, k, p)* m % p
return [u, v]


def Dec(c, p, x):
u = c[0]
v = c[1]
return fastPowMod(u,p-1-x,p)* v % p

def Round1(x1, p, g):
return fastPowMod(g, x1, p)

def Round2(x2, p, g):
return fastPowMod(g, x2, p)

def FinalRound(x1, y1, x2, y2, p):
return fastPowMod(y2, x1, p) , fastPowMod(y1, x2, p)



if __name__ == '__main__':
[p, q, g] = GenPara(256)
print("p = %d\ng = %d" %(p, g))
print("\nElgamal: ")
[x, y] = GenKey(p, g)
print("\nx = %d\ny = %d" %(x, y))
m = random.randint(0, p-1)
print("\nm = %d" %m)
c = Enc(m, p, g, y)
print("\nc = %s" %c)
m_dec = Dec(c, p, x)
print("\nm_dec = %d" %m_dec)
print(m == m_dec)

print("\nDH key exchange: ")
x1 = random.randint(1, p-1)
print("\nAlice chooses x1 = %d" %x1)
y1 = Round1(x1, p, g)
print("\nAlice sends %d to Bob" %y1)
x2 = random.randint(1, p-1)
print("\nBob chooses x2 = %d" %x2)
y2 = Round2(x2, p, g)
print("\nBob sends %d to Alice" %y2)
print("\nAlice and Bob agree with the same key: ")
[z1, z2] = FinalRound(x1, y1, x2, y2, p)
print("%d\n%d" %(z1,z2))
print(z1 == z2)