-
Notifications
You must be signed in to change notification settings - Fork 126
/
mov_attack.py
55 lines (45 loc) · 1.61 KB
/
mov_attack.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
import logging
import os
import sys
from math import gcd
from sage.all import GF
path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(os.path.abspath(__file__)))))
if sys.path[1] != path:
sys.path.insert(1, path)
from shared.ecc import get_embedding_degree
def attack(P, R, max_k=6, max_tries=10):
"""
Solves the discrete logarithm problem using the MOV attack.
More information: Harasawa R. et al., "Comparing the MOV and FR Reductions in Elliptic Curve Cryptography" (Section 2)
:param P: the base point
:param R: the point multiplication result
:param max_k: the maximum value of embedding degree to try (default: 6)
:param max_tries: the maximum amount of times to try to find l (default: 10)
:return: l such that l * P == R, or None if l was not found
"""
E = P.curve()
q = E.base_ring().order()
n = P.order()
assert gcd(n, q) == 1, "GCD of base point order and curve base ring order should be 1."
logging.info("Calculating embedding degree...")
k = get_embedding_degree(q, n, max_k)
if k is None:
return None
logging.info(f"Found embedding degree {k}")
Ek = E.base_extend(GF(q ** k))
Pk = Ek(P)
Rk = Ek(R)
for i in range(max_tries):
Q_ = Ek.random_point()
m = Q_.order()
d = gcd(m, n)
Q = (m // d) * Q_
if Q.order() != n:
continue
if (alpha := Pk.weil_pairing(Q, n)) == 1:
continue
beta = Rk.weil_pairing(Q, n)
logging.info(f"Computing {beta}.log({alpha})...")
l = beta.log(alpha)
return int(l)
return None