Let us walk on the 3-isogeny graph
Loading...
Searching...
No Matches
isogeny_walks_3_fp.c
Go to the documentation of this file.
1//
2// 3-isogeny chain calculations via radical computations (over Fp)
3//
4#include <stdio.h>
5#include "isogeny_walks.h"
6#include "utilities.h"
7
8static void print_fp(const fp_t input, char* s){
9 fp_t aux;
10 fp_from_mont(aux, input);
11 printf("%s = 0x", s);
12 for(int i = FIELD_64BITS_WORDS -1; i >= 0; i--){
13 printf("%016lX", aux[i]);
14 }
15 printf(";\n");
16}
17
18void isogeny_walks_get_points_3_fp(fp_t *output, const fp_t *input_A){
19 fp_t A_times_one_third, A_squared, C_squared;
20 fp_t t, r, s, u, aux, tmp, y;
21 fp_t s0, s1, s2, s0_squared, v;
22
23 // input_A[0] is A
24 // input_A[1] is C
25 // A_times_one_third = A * one_third # M𝒸
26 fp_mul(A_times_one_third, ONE_THIRD, input_A[0]);
27 // A_squared = A**2 # S
28 fp_sqr(A_squared, input_A[0]);
29 // C_squared = C**2 # S
30 fp_sqr(C_squared, input_A[1]);
31
32 // t = (3 * C_squared - A_squared) * one_ninth # M𝒸 + 3A
33 fp_add(t, C_squared, C_squared);
34 fp_add(t, t, C_squared);
35 fp_sub(t, t, A_squared);
36 fp_mul(t, ONE_NINTH, t);
37
38 // r = 16 * (A_squared * A) * one_by_27 # M + M𝒸 + 4A
39 fp_mul(r, A_squared, input_A[0]);
40 fp_mul(r, ONE_BY_27, r);
41 fp_add(r, r, r);
42 fp_add(r, r, r);
43 fp_add(r, r, r);
44 fp_add(r, r, r);
45
46 // s = 8 * A_times_one_third # 3A
47 fp_add(s, A_times_one_third, A_times_one_third);
48 fp_add(s, s, s);
49 fp_add(s, s, s);
50
51 // u = r - s * C_squared # M + A
52 fp_mul(u, s, C_squared);
53 fp_sub(u, r, u);
54
55 // aux = 2*C_squared**2 # S + A
56 fp_sqr(aux, C_squared);
57 fp_add(aux, aux, aux);
58 // y = 4 * C_squared # 2A
59 fp_add(y, C_squared, C_squared);
60 fp_add(y, y, y);
61 // y = y - A_squared # A
62 fp_sub(y, y, A_squared);
63 // y = aux * y # M
64 fp_mul(y, aux, y);
65
66 // y = t + one_third * setup['curt'](y) # M𝒸 + A + E (TOTAL = S + M + Mc + 5A + E)
67 fp_curt(y, y);
68 fp_mul(y, y, ONE_THIRD);
69 fp_add(y, y, t);
70
71 // r = 2 * y # A
72 fp_add(r, y, y);
73 // s = 6 * t # 3A
74 fp_add(s, t, t);
75 fp_add(t, s, s);
76 fp_add(s, s, t);
77
78 // s0 = setup['sqrt'](r - s) # A + E
79 fp_sub(s0, r, s);
80 fp_sqrt(s0, s0);
81
82 // s0_squared = s0**2 # S
83 fp_sqr(s0_squared, s0);
84 // v = -(r + s) # 2A
85 fp_add(v, r, s);
86 fp_neg(v, v);
87
88 fp_mul(tmp, v, s0_squared); // # M
89 fp_mul(u, u, s0); // # M
90 // s1 = setup['sqrt'](tmp + u) # A + E
91 fp_add(t, tmp, u);
92 fp_sqrt(s1, t);
93 // s2 = setup['sqrt'](tmp - u) # A + E
94 fp_sub(s, tmp, u);
95 fp_sqrt(s2, s);
96
97 // Test to know if s1 and s2 are square roots # 2S
98 fp_sqr(tmp, s1);
99 fp_sqr(aux, s2);
100 uint8_t test_s1 = fp_is_equal(tmp, t);
101 uint8_t test_s2 = fp_is_equal(aux, s);
102
103 // Compute z # 4Mc + 5A
104 fp_sub(t, s1, s0_squared);
105 fp_mul(t, t, ONE_HALF);
106 fp_neg(s1, s1);
107 fp_sub(r, s1, s0_squared);
108 fp_mul(r, r, ONE_HALF);
109
110 fp_add(s, s2, s0_squared);
111 fp_mul(s, s, ONE_HALF);
112 fp_sub(u, s0_squared, s2);
113 fp_mul(u, u, ONE_HALF);
114
115 // Select z in constant time
116 fp_cset(output[0], t, -test_s1);
117 fp_cset(output[1], r, -test_s1);
118 fp_cset(output[0], s, -test_s2);
119 fp_cset(output[1], u, -test_s2);
120
121 // Compute num and den # 2M + 2A
122 fp_mul(output[2], s0, input_A[1]);
123 fp_mul(aux, s0, A_times_one_third);
124 fp_sub(output[0], output[0], aux);
125 fp_sub(output[1], output[1], aux);
126
127 // # 2S + 7M + 2A
128 fp_sqr(r, output[0]); // x**2
129 fp_sqr(s, output[2]); // den**2
130 fp_mul(v, input_A[1], output[0]); // C*x
131 fp_mul(t, output[2], input_A[0]); // A*den
132 fp_mul(u, v, s); // C*x*den**2
133 fp_mul(aux, s, output[2]); // den**3
134 fp_mul(aux, aux, input_A[1]); // C*den**3
135 fp_add(t, t, v); // C*x + A*den
136 fp_mul(t, t, r); // x**2 * (C*x + A*den)
137 fp_add(t, t, u); // (x**2 * (C*x + A*den)) + C*x * den**2
138 fp_mul(t, t, aux);
139
140 uint64_t test_sqr = (uint64_t)!fp_is_square(t);// # E
141 fp_cswap(output[0], output[1], -test_sqr);
142}
143
144void isogeny_walks_to_montgomery_model_3_fp(fp_t *output_A, const fp_t *input_t){
145 fp_t r_squared, s_squared, r_cubed;
146 fp_t aux, alpha_cubed, alpha, rd;
147
148 // input_t[0] is r
149 // input_t[1] is s
150 // r_squared = r**2
151 fp_sqr(r_squared, input_t[0]);
152 // s_squared = s**2
153 fp_sqr(s_squared, input_t[1]);
154 // r_cubed = r_squared * r
155 fp_mul(r_cubed, r_squared, input_t[0]);
156 // s_cubed = s_squared * s
157 fp_mul(output_A[1], s_squared, input_t[1]);
158 // aux = r * s_squared
159 fp_mul(aux, s_squared, input_t[0]);
160
161 // alpha_cubed = r * (r_squared - s_squared)
162 fp_sub(alpha_cubed, r_squared, s_squared);
163 fp_mul(alpha_cubed, alpha_cubed, input_t[0]);
164 // alpha = setup['curt'](alpha_cubed)
165 fp_curt(alpha, alpha_cubed);
166
167 // Goal rd = 3 * (r * alpha**2 + r_squared * alpha + r_cubed) - s_sqr * alpha - 2 * aux
168 //rd = (r * alpha**2 + r_squared * alpha + r_cubed)
169 fp_mul(rd, input_t[0], alpha);
170 fp_add(rd, rd, r_squared);
171 fp_mul(rd, rd, alpha);
172 fp_add(rd, rd, r_cubed);
173 // rd = 3 * (r * alpha**2 + r_squared * alpha + r_cubed)
174 fp_add(r_squared, rd, rd);
175 fp_add(rd, rd, r_squared);
176 // rd = 3 * (r * alpha**2 + r_squared * alpha + r_cubed) - s_sqr * alpha - 2 * aux
177 fp_sub(rd, rd, aux);
178 fp_sub(rd, rd, aux);
179 fp_mul(r_squared, s_squared, alpha);
180 fp_sub(output_A[0], rd, r_squared);
181}
182
183void isogeny_to_montgomery(fp_t output_A, const fp_t *input_t){
184 fp_t r_squared, r_at_four, s_squared, s_at_four;
185 fp_t num, den, aux;
186
187 // input_t[0] is r
188 // input_t[1] is s
189 fp_sqr(r_squared, input_t[0]);
190 fp_sqr(s_squared, input_t[1]);
191 fp_sqr(r_at_four, r_squared);
192 fp_sqr(s_at_four, s_squared);
193
194 // num = -3 * r_at_four - 6 * r_squared * s_squared + s_at_four
195 fp_add(aux, r_squared, r_squared);
196 fp_mul(num, aux, s_squared);
197 fp_add(num, num, r_at_four);
198 fp_sub(s_at_four, s_at_four, num);
199 fp_sub(s_at_four, s_at_four, num);
200 fp_sub(num, s_at_four, num);
201
202 // den = 4 * r_squared * r * s
203 fp_add(aux, aux, aux);
204 fp_mul(den, aux, input_t[0]);
205 fp_mul(den, den, input_t[1]);
206 fp_inv(den, den);
207 fp_mul(output_A, den, num);
208}
209
210#define TOP_BIT (8*sizeof(int)-1)
211
212static int absolute_value(int a){
213 int y = a >> TOP_BIT;
214 return (a + y) ^ y;
215}
216
217void isogeny_walks_3_fp(fp_t output_A, const fp_t input_A, int input_length){
218 fp_t aux[2], num_den[3];
219
220 fp_copy(aux[0], input_A);
221 fp_set_to_one(aux[1]);
222
223 isogeny_walks_get_points_3_fp(num_den, aux);
224
225 uint64_t sign = (input_length >> TOP_BIT) & 1;
226 fp_cset(aux[0], num_den[0], -sign);
227 fp_cset(aux[0], num_den[1], sign-1);
228 fp_copy(aux[1], num_den[2]);
229
230 int input_length_abs = absolute_value(input_length);
231 for(int i = 0; i < input_length_abs; i++){
232 fp_t t[2] = {0};
233 uint64_t d = constant_time_is_lessthan_u64(i, input_length_abs);
235 fp_cset(aux[0], t[0], -d);
236 fp_cset(aux[1], t[1], -d);
237 }
238 isogeny_to_montgomery(output_A, aux);
239}
void isogeny_walks_get_points_3_fp(fp_t *output, const fp_t *input_A)
#define TOP_BIT
void isogeny_walks_3_fp(fp_t output_A, const fp_t input_A, int input_length)
void isogeny_to_montgomery(fp_t output_A, const fp_t *input_t)
void isogeny_walks_to_montgomery_model_3_fp(fp_t *output_A, const fp_t *input_t)
#define fp_sqr
Definition fp-gmp.h:73
#define fp_sub
Definition fp-gmp.h:67
#define fp_mul
Definition fp-gmp.h:70
#define fp_inv
Definition fp-gmp.h:88
#define fp_add
Definition fp-gmp.h:64
#define fp_copy
Definition fp-gmp.h:79
#define fp_cswap
Definition fp-gmp.h:82
void fp_curt(fp_t output, const fp_t input)
Definition fp.c:189
void fp_neg(fp_t output, const fp_t input)
Definition fp.c:9
uint8_t fp_is_equal(const fp_t input_a, const fp_t input_b)
Definition fp.c:122
void fp_cset(fp_t output, const fp_t input, uint64_t input_mask)
Definition fp.c:28
void fp_from_mont(fp_t output, const fp_t input)
Definition fp.c:104
void fp_set_to_one(fp_t input_output)
Definition fp.c:14
void fp_sqrt(fp_t output, const fp_t input)
Definition fp.c:168
uint8_t fp_is_square(const fp_t input)
Definition fp.c:148
uint64_t fp_t[FIELD_64BITS_WORDS]
Definition fp.h:12
num
#define FIELD_64BITS_WORDS
Definition p254.h:9
for i
f a
Definition to_model.m:12
uint64_t constant_time_is_lessthan_u64(uint64_t x, uint64_t y)
Definition utilities.c:58