-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathECC.py
234 lines (189 loc) · 5.91 KB
/
ECC.py
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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
import math
import random
from typing import *
def get_inverse(fenmu, p):
for i in range(1, p):
if (i*fenmu) % p == 1:
return i
return -1
def get_np(x1, y1, x2, y2, a, p):
"""
获取n*p,每次+p,直到求解阶数np=-p
"""
flag = 1 # 用于判断斜率k的正负
# 计算斜率k(当两点相同)
if x1 == x2 and y1 == y2:
fenzi = 3 * (x1 ** 2) + a
fenmu = 2 * y1 # 计算分母
# 计算斜率k(当两点不同)
else:
fenzi = y2 - y1
fenmu = x2 - x1
if fenzi * fenmu < 0:
flag = 0
fenzi = abs(fenzi)
fenmu = abs(fenmu)
# 分子分母约分
gcd_value = math.gcd(fenzi, fenmu)
fenzi = fenzi // gcd_value
fenmu = fenmu // gcd_value
# 求分母的逆元
inverse_fenmu = get_inverse(fenmu, p)
k = (fenzi * inverse_fenmu)
# 如果斜率k为负
if flag == 0:
k = -k
k = k % p
# 计算x3,y3 P+Q
x3 = (k ** 2 - x1 - x2) % p
y3 = (k * (x1 - x3) - y1) % p
return x3, y3
def get_rank(x0, y0, a, b, p):
"""
计算椭圆曲线的阶
"""
x1 = x0 # -p的x坐标
y1 = (-1*y0) % p # -p的y坐标
temp_x = x0
temp_y = y0
n = 1
while True:
n += 1
# 递归加(选择使用加法,较为简单)
p_x, p_y = get_np(temp_x, temp_y, x0, y0, a, p)
# 如果 == -p,那么阶数+1,结束
if p_x == x1 and p_y == y1:
return n+1
temp_x = p_x
temp_y = p_y
def get_param(x0, a, b, p):
"""
计算p与-p
"""
y0 = -1
for i in range(p):
# 查看椭圆曲线上是否存在x为该值的点
if pow(i, 2, p) == (x0**3 + a*x0 + b) % p:
y0 = i
break
# 没有时
if y0 == -1:
return False
# 有p(x0,y0),计算-p(x1,y1)
x1 = x0
y1 = (-1*y0) % p
return x0, y0, x1, y1
def get_graph(a, b, p) -> List[List[int]]:
"""
输出椭圆曲线散点图\n
返回list[column][row]
"""
x_y = []
# 初始化二维数组
for i in range(p):
x_y.append(['-' for i in range(p)])
for i in range(p):
val = get_param(i, a, b, p) # 椭圆曲线上的点
if(val != False):
x0, y0, x1, y1 = val
x_y[x0][y0] = 1
x_y[x1][y1] = 1
print("椭圆曲线的散列图为:")
for i in range(p): # i= 0-> p-1
temp = p-1-i # 倒序
# 格式化输出1/2位数,y坐标轴
if temp >= 10:
print(temp, end=" ")
else:
print(temp, end=" ")
# 输出具体坐标的值,一行
for j in range(p):
print(x_y[j][temp], end=" ")
print("") # 换行
# 输出 x 坐标轴
print(" ", end="")
for i in range(p):
if i >= 10:
print(i, end=" ")
else:
print(i, end=" ")
print('\n')
return x_y
def get_kG(x, y, privatekey, a, p):
"""
计算nG
"""
temp_x = x
temp_y = y
while privatekey != 1:
# k次相加得K=kG,输出坐标
temp_x, temp_y = get_np(temp_x, temp_y, x, y, a, p)
privatekey -= 1
return temp_x, temp_y
def ecc_main():
while True:
a = int(input("请输入椭圆曲线参数a:"))
b = int(input("请输入椭圆曲线参数b:"))
p = int(input("请输入椭圆曲线参数p(p为素数):"))
# 条件判断
if (4*(a**3)+27*(b**2)) % p == 0:
print("参数有误,请重新输入\n")
else:
break
# 输出椭圆曲线散点图
get_graph(a, b, p)
# 选点作为G点
print("在如上坐标系中选一个值为G的坐标")
G_x = int(input("user1:请输入选取的x坐标值:"))
G_y = int(input("user1:请输入选取的y坐标值:"))
# 获取椭圆曲线的阶
n = get_rank(G_x, G_y, a, b, p)
# user1生成私钥k
key = int(input("user1:请输入私钥小key(<{}):".format(n)))
# user1生成公钥K
K_x, K_y = get_kG(G_x, G_y, key, a, p)
# user2拿到user1的公钥K,Ep(a,b)阶n,加密需要加密的明文数据
# 加密准备
r = int(input("user2:请输入一个整数r(<{})用于求rG和rK:".format(n)))
rG_x, rG_y = get_kG(G_x, G_y, r, a, p)
rK_x, rK_y = get_kG(K_x, K_y, r, a, p)
# 加密
plain_text = input("user2:请输入需要加密的字符串:")
plain_text = plain_text.strip().encode()
c = []
print("密文为:", end="")
for i in plain_text:
num = i
cipher_text = num*rK_x
c.append([rG_x, rG_y, cipher_text])
print("(({},{}),{})".format(rG_x, rG_y, cipher_text), end=" ")
# user1 知道 kG_x,kG_y,key,求解kQ_x,kQ_y,plain_text = cipher_text/kQ_x
print("\nuser1解密得到明文:", end="")
d = bytearray()
for i in c:
decrypto_text_x, decrypto_text_y = get_kG(
i[0], i[1], key, a, p)
d.append(i[2]//decrypto_text_x)
#print(chr(i[2]//decrypto_text_x), end="")
print(d.decode())
def decrypt(text, k, a, p):
ret = bytearray()
for i in text:
decrypto_text_x, decrypto_text_y = get_kG(
i[0][0], i[0][1], k, a, p)
ret.append(i[1]//decrypto_text_x)
return bytes(ret)
def encrypt(text, K_x, K_y, G_x, G_y, a, p, n, k):
rs = [i for i in range(n)]
rs.remove(k)
r = random.choice(rs)
c = []
rG_x, rG_y = get_kG(G_x, G_y, r, a, p)
rK_x, rK_y = get_kG(K_x, K_y, r, a, p)
for i in text:
num = i
cipher_text = num*rK_x
c.append([(rG_x, rG_y), cipher_text])
return c
if __name__ == "__main__":
ecc_main()