Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
jack4818
GitHub Repository: jack4818/Castryck-Decru-SageMath
Path: blob/main/sandwich_attack.sage
323 views
1
"""
2
This file demonstrates how to run an isogeny diamond attack
3
in the case when 2^(a-alpha) - k*3^b = u^2+v^2
4
where k is either a sum of squares, or a small smooth or prime integer.
5
6
This specific form is used by Damien Robert in the dimension 4 attack
7
(https://eprint.iacr.org/2022/1038.pdf)
8
9
This is notably possible in the SIKEp217 challenge and in the
10
(withdrawn) SIKEp964 parameter set.
11
12
There are 2 possible diagrams for this attack:
13
- the second auxiliary isogeny can be constructed from EB (always
14
possible), in which case we sandwich the secret isogeny
15
between the auxiliary isogenies.
16
Preferably k is a smooth integer here
17
18
phi aux2 (deg k)
19
Estart ---> EB ------> EB'
20
| | |
21
| | |
22
|aux=u+iv | |
23
| | |
24
v v v
25
C ------> CB ------> CB'
26
27
- or it can be realized as an endomorphism of E_start
28
(preferably k is a sum of squares)
29
30
aux2 (deg k)
31
Estart ---> Estart ------> EB'
32
| | |
33
| | |
34
|aux=u+iv | |
35
| | |
36
v v v
37
Estart ---> Estart ------> CB'
38
"""
39
40
# Python imports
41
import time
42
from itertools import product
43
44
# Local Imports
45
from helpers import supersingular_gens, fast_log3
46
from richelot_aux import Does22ChainSplit, Pushing3Chain
47
48
# Load Sage Files
49
load('speedup.sage')
50
51
# TODO: implement the first strategy (when k is not a sum of squares).
52
53
def SandwichAttack(E_start, P2, Q2, EB, PB, QB, two_i, k, alp):
54
"Implementation of the second strategy (endomorphism of degree k)"
55
56
tim = time.time()
57
58
# FIXME: a, b are magically in global scope
59
# Might be precomputed if *really* required
60
v, u = two_squares(2^(a-alp) - k*3^b)
61
vk, uk = two_squares(k)
62
63
# aux1 = u + i*v
64
# aux2 = uk+ i*vk
65
# aux2inv = (uk - i * vk) / k
66
67
# Need to twist 2-torsion and 3-torsion
68
kinv2 = pow(k, -1, 2^a)
69
kinv3 = pow(k, -1, 3^b)
70
71
def aux(P, kinv):
72
# Beware, we are given 2i, so swap coordinates depending on
73
# parity.
74
if vk % 2 == 0:
75
x = uk*P - (vk//2)*two_i(P)
76
else:
77
x = vk*P - (uk//2)*two_i(P)
78
x *= kinv
79
if v % 2 == 0:
80
return u*x + (v//2)*two_i(x)
81
else:
82
return v*x + (u//2)*two_i(x)
83
84
P_c = aux(P2, kinv2)
85
Q_c = aux(Q2, kinv2)
86
# FIXME: P3 and Q3 are magically in scope
87
P3_c = aux(P3, kinv3)
88
Q3_c = aux(Q3, kinv3)
89
90
chain, (E1, E2) = Does22ChainSplit(E_start, EB,
91
2^alp*P_c, 2^alp*Q_c, 2^alp*PB, 2^alp*QB, a-alp)
92
93
# Evaluate quotient map
94
if E1.j_invariant() == E_start.j_invariant():
95
index = 1
96
CB = E2
97
else:
98
index = 0
99
CB = E1
100
def C_to_CB(x):
101
pt = (x, None)
102
for c in chain:
103
pt = c(pt)
104
return pt[index]
105
106
P3_CB = C_to_CB(P3_c)
107
Q3_CB = C_to_CB(Q3_c)
108
109
print("Computed image of 3-adic torsion in split factor C_B")
110
Z3 = Zmod(3^b)
111
G1_CB, G2_CB = supersingular_gens(CB)
112
G1_CB3 = ((p+1) / 3^b) * G1_CB
113
G2_CB3 = ((p+1) / 3^b) * G2_CB
114
w = G1_CB3.weil_pairing(G2_CB3, 3^b)
115
116
sk = None
117
for G in (G1_CB3, G2_CB3):
118
xP = fast_log3(P3_CB.weil_pairing(G, 3^b), w)
119
xQ = fast_log3(Q3_CB.weil_pairing(G, 3^b), w)
120
if xQ % 3 != 0:
121
sk = int(-Z3(xP) / Z3(xQ))
122
break
123
124
if sk is not None:
125
# Sanity check
126
bobscurve, _ = Pushing3Chain(E_start, P3 + sk*Q3, b)
127
found = bobscurve.j_invariant() == EB.j_invariant()
128
129
print(f"Bob's secret key revealed as: {sk}")
130
print(f"In ternary, this is: {Integer(sk).digits(base=3)}")
131
print(f"Altogether this took {time.time() - tim} seconds.")
132
return sk
133
else:
134
print("Something went wrong.")
135
print(f"Altogether this took {time.time() - tim} seconds.")
136
return None
137
138