p = 424243
Fp = GF(p)
A = 323
E = EllipticCurve(Fp, [0, A, 0, 1, 0])
E
Elliptic Curve defined by y^2 = x^3 + 323*x^2 + x over Finite Field of size 424243
# Define the generator
P = E(308951, 234702)
P
(308951 : 234702 : 1)
# Define the point for which we want to find the discrete logarithm
Q = E(125565, 39963)
Q
(125565 : 39963 : 1)
# Let's compute the solution, so we can use it to check what we are doing later on
solution = P.discrete_log(Q)
solution
57
n = 2^5 * 5 # number of points (in the subgroup) on the curve
n
160
# Here, we have to compute the discrete logarithm base 2^5
# Hence, we have p_i = 2
p_i = 2
Q_i = Q
a_ijminus1 = 0
n_i = n/p_i
# The image of P in the subgroup of order 2
R_i = n_i * P
R_i
(0 : 0 : 1)
for
-loop, iteration 0¶j = 0
n_i = n/(p_i^(j+1))
Q_i = Q_i - (a_ijminus1*p_i^(j-1))*P
# The target for 2^0
Q_i
(125565 : 39963 : 1)
S_i = n_i*Q_i
S_i, R_i
((0 : 0 : 1), (0 : 0 : 1))
At this point, we need to solve the discrete logarithm $S_i=a_{2,0}R_i$. Filling in the points we just obtained, we get $$(0,0) = a_{2,0} (0,0)$$ Clearly, this holds when $a_{2,0}=1$.
# To check our results, we perform the following computation
a_ijminus1 = R_i.discrete_log(S_i)
a_ijminus1
1
# As a sanity check, let us compute the correct result from the already-computed discrete logarithm.
Mod(solution, 2^1)
1
for
-loop, iteration 1¶j = 1
n_i = n/(p_i^(j+1))
Q_i = Q_i - (a_ijminus1*p_i^(j-1))*P
# The target for 2^1
Q_i
(338173 : 375090 : 1)
S_i = n_i*Q_i
S_i, R_i
((0 : 1 : 0), (0 : 0 : 1))
At this point, we need to solve the discrete logarithm $S_i=a_{2,1}R_i$. Filling in the points we just obtained, we get $$P_\infty = a_{2,1} (0,0)$$ Clearly, this holds when $a_{2,1}=0$.
# To check our results, we perform the following computation
a_ijminus1 = R_i.discrete_log(S_i)
a_ijminus1
0
for
-loop, iteration 2¶j = 2
n_i = n/(p_i^(j+1))
Q_i = Q_i - (a_ijminus1*p_i^(j-1))*P
# The target for 2^2
Q_i
(338173 : 375090 : 1)
S_i = n_i*Q_i
S_i, R_i
((0 : 1 : 0), (0 : 0 : 1))
At this point, we need to solve the discrete logarithm $S_i=a_{2,2}R_i$. Filling in the points we just obtained, we get $$P_\infty = a_{2,2} (0,0)$$ Clearly, this holds when $a_{2,2}=0$.
# To check our results, we perform the following computation
a_ijminus1 = R_i.discrete_log(S_i)
a_ijminus1
0
for
-loop, iteration 3¶j = 3
n_i = n/(p_i^(j+1))
Q_i = Q_i - (a_ijminus1*p_i^(j-1))*P
# The target for 2^3
Q_i
(338173 : 375090 : 1)
S_i = n_i*Q_i
S_i, R_i
((0 : 0 : 1), (0 : 0 : 1))
At this point, we need to solve the discrete logarithm $S_i=a_{2,3}R_i$. Filling in the points we just obtained, we get $$(0,0) = a_{2,3} (0,0)$$ Clearly, this holds when $a_{2,3}=1$.
# To check our results, we perform the following computation
a_ijminus1 = R_i.discrete_log(S_i)
a_ijminus1
1
for
-loop, iteration 4¶j = 4
n_i = n/(p_i^(j+1))
Q_i = Q_i - (a_ijminus1*p_i^(j-1))*P
# The target for 2^4
Q_i
(339160 : 133756 : 1)
S_i = n_i*Q_i
S_i, R_i
((0 : 0 : 1), (0 : 0 : 1))
At this point, we need to solve the discrete logarithm $S_i=a_{2,4}R_i$. Filling in the points we just obtained, we get $$(0,0) = a_{2,4} (0,0)$$ Clearly, this holds when $a_{2,4}=1$.
# To check our results, we perform the following computation
a_ijminus1 = R_i.discrete_log(S_i)
a_ijminus1
1
# Our intermediate results were
a2_0 = 1
a2_1 = 0
a2_2 = 0
a2_3 = 1
a2_4 = 1
# Our final result is
a_2 = a2_0 + a2_1*2 + a2_2*2^2 + a2_3*2^3 + a2_4*2^4
a_2
25
# As a sanity check, let us compute the correct result from the already-computed discrete logarithm.
Mod(solution, 2^5)
25
# To verify our result, we compute (a_2)*(n/2^5)*P, and check whether this is equal to (n/2^5)*Q.
a_2 * (n/2^5)*P, (n/2^5)*Q, a_2 * (n/2^5)*P == (n/2^5)*Q
((146249 : 144755 : 1), (146249 : 144755 : 1), True)
# Here, we have to compute the discrete logarithm base 5
# Hence, we have p_i = 5
p_i = 5
Q_i = Q
a_ijminus1 = 0
n_i = n/p_i
R_i = n_i * P
# The image of P in the subgroup of order 5
R_i
(80722 : 1884 : 1)
for
-loop, iteration 0¶j = 0
n_i = n/(p_i^(j+1))
Q_i = Q_i - (a_ijminus1*p_i^(j-1))*P
# The target for 5
Q_i
(125565 : 39963 : 1)
S_i = n_i*Q_i
S_i, R_i
((405809 : 261409 : 1), (80722 : 1884 : 1))
for i in range(5):
print(str(i)+ "*R_i gives", str(i*R_i))
0*R_i gives (0 : 1 : 0) 1*R_i gives (80722 : 1884 : 1) 2*R_i gives (405809 : 261409 : 1) 3*R_i gives (405809 : 162834 : 1) 4*R_i gives (80722 : 422359 : 1)
At this point, we need to solve the discrete logarithm $S_i=a_{5,0}R_i$. Filling in the points we just obtained, we get $$(0,0) = a_{5,0} (0,0)$$ Clearly, this holds when $a_{5,0}=1$.
# To check our results, we perform the following computation
a_ijminus1 = R_i.discrete_log(S_i)
a_ijminus1
2
# As a sanity check, let us compute the correct result from the already-computed discrete logarithm.
Mod(solution, 5)
2
a_5 = a_ijminus1
# To verify our result, we compute (a_2)*(n/5)*P, and check whether this is equal to (n/5)*Q.
a_5 * (n/5)*P, (n/5)*Q, a_5 * (n/5)*P == (n/5)*Q
((405809 : 261409 : 1), (405809 : 261409 : 1), True)
a = CRT([25, 2], [2^5, 5])
a
57
# To verify our result, we compute a*P, and check whether this is equal to Q.
a*P, Q, a*P == Q
((125565 : 39963 : 1), (125565 : 39963 : 1), True)