(密码学)(crypto)ECC_Crypto(椭圆曲线加密)——python实现

(密码学)(crypto)ECC_Crypto(椭圆曲线加密)——python实现

四月 29, 2020 (Updated: )
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# -*- coding:utf-8 -*-
import random

# 辗转相除求最大公因数
def div_fac( a, b ):
if b != 0:
result = div_fac( b, a % b )
else:
result = a
return result

# 将负数结果转化为正数
def check_neg( a , b ):
while a <= 0:
a += b
return a

# 利用勒让德符号和二次互反律判断平方剩余是否存在
def Leg_Prime( a , p ):
a = a % p
flag = 1 ; a_x = [] ; i = 2 ; tmp = a
while i < tmp ** 0.5:
if tmp % i == 0:
tmp //= i
a_x.append(i)
i = 2
else:
i += 1
else:
a_x.append(tmp)

for i in a_x:
if i == 2:
if p % 8 == 1 or p % 8 == 7:
flag *= 1
else:
flag *= ( -1 )
elif i == -1 or a == p-1:
if p % 4 == 1:
flag *= 1
else:
flag *= ( -1 )
#flag_tmp = ( -1 ) ** (( a - 1 ) * ( p - 1 ) / 4) * Leg_Prime( p % i , i )
elif i == 0:
return 0
else:
flag *= ( ( -1 ) ** (( a - 1 ) * ( p - 1 ) / 4 ) ) * Leg_Prime( p , i )

return flag

# ECC加密中的加法运算实现
def ECC_Add( A , B , p , a):
if A != B:
dx = A[0] - B[0]
dy = A[1] - B[1]
else:
dy = 3 * ( A[0] ** 2 ) + a
dx = 2 * A[1]
if dx == 0 :
return 0
fac = div_fac( dx , dy )
dy //= fac
dx //= fac
tmp = dy % p
check_neg( tmp , p )
while tmp % dx != 0:
tmp += p
k = tmp // dx
C_x = ( k ** 2 - A[0] - B[0] ) % p
check_neg( C_x , p )
C_y = ( k * ( A[0] - C_x ) - A[1] ) % p
check_neg( C_y , p )
return (C_x,C_y)

# 求基点的阶
def Find_Order( G , p , a ):
flag = 1 ; A = G ; B = G
while flag :
flag += 1
A = ECC_Add(A,B,p,a)
if (( A[0] ** 3 + A[0] + 1 ) % p ) == (( A[1] ** 2 ) % p ):
if A[0] == G[0]:
return flag + 1
else:
print("Error!!!")
print("在第 " + str(flag) + " 次运算后结果错误!")
return -1

# 求取公钥
def ECC_PublickeyFind(p,a,G,d):
A = G ; B = G
i = 1
while i < d:
i += 1
A = ECC_Add(A,B,p,a)
if A == 0:
i += 1
A = G
return A

# 将明文嵌入曲线
def ECC_M(m,p,a,b):
M = []
for j in m.encode('utf-8'):
j = j * 30
tmp = 0 ; flag = 0
while tmp < 100:
x = j + tmp
y_2 = ( x ** 3 + a * x + b ) % p
tmp += 1
if Leg_Prime( y_2 , p ) == 1:
for i in range(1,p):
if ( i ** 2 - y_2 ) % p == 0:
M.append(( x , i ))
flag = 1
break
if flag == 1:
break
else:
print("明文某字节在嵌入曲线时 100 次没有得到平方剩余")
exit()
return M

def ECC_encode(M,G,K,r,p,a):
r_G = ECC_PublickeyFind(p,a,G,r)
r_K = ECC_PublickeyFind(p,a,K,r)
C_1 = []
for i in M:
C_1.append(ECC_Add(i,r_K,p,a))
print("C1为:",end='')
for i in C_1:
print(str(i) + ',' ,end='')
else:
print()
print("C2为:" + str(r_G))

def ECC_Encrypt(p,a,b,G,n,d,m):
K = ECC_PublickeyFind(p,a,G,d)
print("公钥为:" + str(K))
M = ECC_M(m,p,a,b)
r = random.randint(1,n-1)
ECC_encode(M,G,K,r,p,a)

def ECC_Decrypt(C1,C2,d,p,a):
C2_tmp = ECC_PublickeyFind(p,a,C2,d)
C2 = (C2_tmp[0],-C2_tmp[1])
for i in C1:
M = ECC_Add(i,C2,p,a)[0] // 30
print(chr(M),end='')
print()

if __name__ == "__main__":
p,a,b,G,n = 4177,1,1,(0,1),28
print("本程序使用曲线方程为:y^2 = x^3 + x + 1")
print("参数 p 选择为 23,基点为 (0,1), n 为 28")
print("为减小计算压力,本程序为ASCII字符集逐字节加密")
d = eval(input("请输入私钥:"))
m = input("请输入要加密的数据:")

ECC_Encrypt(p,a,b,G,n,d,m)

C1 = eval(input("请输入C1:"))
C2 = eval(input("请输入C2:"))

ECC_Decrypt(C1,C2,d,p,a)
隐藏