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
|
import math
def inv_mod(x: int, p: int) -> int:
return pow(x, p-2, p)
def point_add(P, Q, a, p):
if P is None:
return Q
if Q is None:
return P
x1, y1 = P
x2, y2 = Q
if x1 == x2 and (y1 + y2) % p == 0:
return None
if P != Q:
lam = ((y2 - y1) * inv_mod(x2 - x1, p)) % p
else:
lam = ((3 * x1 * x1 + a) * inv_mod(2 * y1, p)) % p
x3 = (lam * lam - x1 - x2) % p
y3 = (lam * (x1 - x3) - y1) % p
return (x3, y3)
def scalar_mul(P, n, a, p):
R = None # 初始结果为无穷远点
Q = P # 临时变量 Q = P, 逐位处理 n
while n > 0:
if n & 1:
R = point_add(R, Q, a, p)
Q = point_add(Q, Q, a, p)
n >>= 1
return R
def dlog_bsgs(P, Q, order_bound, a, p):
m = int(math.ceil(math.sqrt(order_bound)))
table = {}
R = None
for j in range(m):
table[R] = j
R = point_add(R, P, a, p)
mP = scalar_mul(P, m, a, p)
neg_mP = (mP[0], (-mP[1]) % p) if mP is not None else None
S = Q
for i in range(m):
if S in table:
return i * m + table[S]
S = point_add(S, neg_mP, a, p)
return None
def attack_part1():
p1 =
a1 =
b1 =
P1 = ()
cipher = []
bound = 2**20
ns = []
for i in range(3):
ni = dlog_bsgs(P1, cipher[i], bound, a1, p1)
assert ni is not None, "Part1 的 n{} 恢复失败!".format(i)
ns.append(ni)
print("Part1 恢复出的 n 值:", ns)
hex_str = ''.join([hex(x)[2:] for x in ns])
print("拼接后的十六进制字符串:", hex_str)
return hex_str
if __name__ == "__main__":
part11 = attack_part1()
print(part11)
from sage.all import *
from Crypto.Util.number import *
p =
a =
b =
E = EllipticCurve(GF(p),[a,b])
P = E()
Q = E()
print(p== E.order())
def SmartAttack(P,Q,p):
E = P.curve()
Eqp = EllipticCurve(Qp(p, 2), [ ZZ(t) + randint(0,p)*p for t in E.a_invariants() ])
P_Qps = Eqp.lift_x(ZZ(P.xy()[0]), all=True)
for P_Qp in P_Qps:
if GF(p)(P_Qp.xy()[1]) == P.xy()[1]:
break
Q_Qps = Eqp.lift_x(ZZ(Q.xy()[0]), all=True)
for Q_Qp in Q_Qps:
if GF(p)(Q_Qp.xy()[1]) == Q.xy()[1]:
break
p_times_P = p*P_Qp
p_times_Q = p*Q_Qp
x_P,y_P = p_times_P.xy()
x_Q,y_Q = p_times_Q.xy()
phi_P = -(x_P/y_P)
phi_Q = -(x_Q/y_Q)
k = phi_Q/phi_P
return ZZ(k)
m3 = SmartAttack(P,Q,p)
print(m3)
|