Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
241818 views
1
#include <stdlib.h>
2
#include <stdio.h>
3
#include <string.h>
4
#include <math.h>
5
#include <time.h>
6
#include "gmp.h"
7
#include "mpzutil.h"
8
#include "ffwrapper.h"
9
#include "ffext.h"
10
#include "ffpoly.h"
11
#include "hecurve.h"
12
#include "cstd.h"
13
14
/*
15
Copyright 2007 Andrew V. Sutherland
16
17
This file is part of smalljac.
18
19
smalljac is free software: you can redistribute it and/or modify
20
it under the terms of the GNU General Public License as published by
21
the Free Software Foundation, either version 2 of the License, or
22
(at your option) any later version.
23
24
smalljac is distributed in the hope that it will be useful,
25
but WITHOUT ANY WARRANTY; without even the implied warranty of
26
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27
GNU General Public License for more details.
28
29
You should have received a copy of the GNU General Public License
30
along with smalljac. If not, see <http://www.gnu.org/licenses/>.
31
*/
32
33
/*
34
General module for hyperelliptic curve group operations.
35
Fast genus specific group operations for the common cases
36
are in hecurve1.c, hecurve2.c, and hecurve3.c. This module
37
handles everything else. It also includes a non-genus specific
38
implementation of Cantor's algorithm.
39
*/
40
41
static char buf[4096];
42
43
#if HECURVE_GENUS == 1
44
#define _deg_u(u) (_ff_nonzero(u[1])?0:1)
45
#define _deg_v(v) (_ff_nonzero(v[0])?0:-1)
46
#define _hecurve_set_zero(u,v) {_ff_set_zero(u[0]);_ff_set_zero(v[0]);}
47
#endif
48
#if HECURVE_GENUS == 2
49
#define _deg_u(u) (_ff_nonzero(u[2])?2:(_ff_nonzero(u[1])?1:0))
50
#define _deg_v(v) (_ff_nonzero(v[1])?1:(_ff_nonzero(v[0])?0:-1))
51
#define _hecurve_set_zero(u,v) {_ff_set_zero(u[2]);_ff_set_zero(u[1]);_ff_set_zero(u[0]);_ff_set_zero(v[1]);_ff_set_zero(v[0]);}
52
#endif
53
#if HECURVE_GENUS == 3
54
#define _deg_u(u) (_ff_nonzero(u[3])?3:(_ff_nonzero(u[2])?2:(_ff_nonzero(u[1])?1:0)))
55
#define _deg_v(v) (_ff_nonzero(v[2])?2:(_ff_nonzero(v[1])?1:(_ff_nonzero(v[0])?0:-1)))
56
#define _hecurve_set_zero(u,v) {_ff_set_zero(u[3]);_ff_set_zero(u[2]);_ff_set_zero(u[1]);_ff_set_zero(u[0]);_ff_set_zero(v[2]);_ff_set_zero(v[1]);_ff_set_zero(v[0]);}
57
#endif
58
59
60
#define _dbg_print_uv(s,u,v) if ( dbg_level >= DEBUG_LEVEL ) { printf (s); hecurve_print(u,v); }
61
62
// The make functions are independent of genus
63
void hecurve_make_2 (ff_t u[3], ff_t v[2], ff_t x1, ff_t y1, ff_t x2, ff_t y2);
64
void hecurve_make_3 (ff_t u[4], ff_t v[3], ff_t x1, ff_t y1, ff_t x2, ff_t y2, ff_t x3, ff_t y3);
65
66
// needed to double pts in random
67
void hecurve_g2_square_1 (ff_t u[3], ff_t v[2], ff_t u0, ff_t v0, ff_t f[6]);
68
69
// note that caller must clear higher coefficients of u and v
70
static inline void hecurve_make_1 (ff_t u[2], ff_t v[1], ff_t x1, ff_t y1)
71
{
72
_ff_set_one(u[1]); // this also works in genus 1 Jacobian coords (z=u[1]=1)
73
_ff_neg(u[0],x1);
74
_ff_set(v[0],y1);
75
}
76
77
void hecurve_setup (mpz_t p)
78
{
79
#if HECURVE_VERIFY
80
err_printf ("HECURVE VERIFY IS ON\n");
81
#endif
82
ff_setup (p);
83
}
84
85
86
void hecurve_print (ff_t u[HECURVE_GENUS+1], ff_t v[HECURVE_GENUS])
87
{ hecurve_sprint(buf, u, v); out_printf ("%s\n", buf); }
88
89
90
int hecurve_sprint (char *s, ff_t u[HECURVE_GENUS+1], ff_t v[HECURVE_GENUS])
91
{
92
#if HECURVE_GENUS==3
93
if ( _ff_nonzero(u[3]) ) {
94
if ( _ff_one(u[3]) ) {
95
return gmp_sprintf (s, "(x^3 + %Zd*x^2 + %Zd*x + %Zd, %Zd*x^2 + %Zd*x + %Zd)",
96
_ff_wrap_mpz(u[2],0),_ff_wrap_mpz(u[1],1), _ff_wrap_mpz(u[0],2), _ff_wrap_mpz(v[2],3), _ff_wrap_mpz(v[1],4), _ff_wrap_mpz(v[0],5));
97
} else {
98
err_printf ("Warning, non-monic u in hecurve_sprint\n");
99
return gmp_sprintf (s, "(%Zd*x^2 + %Zd*x + %Zd, %Zd*x + %Zd)",
100
_ff_wrap_mpz(u[3],0),_ff_wrap_mpz(u[2],1),_ff_wrap_mpz(u[1],2), _ff_wrap_mpz(u[0],3), _ff_wrap_mpz(v[2],4),_ff_wrap_mpz(v[1],5), _ff_wrap_mpz(v[0],6));
101
}
102
}
103
#endif
104
#if HECURVE_GENUS >= 2
105
if ( _ff_nonzero(u[2]) ) {
106
#if HECURVE_GENUS == 3
107
if ( _ff_nonzero(v[2]) ) err_printf ("Warning, deg v == deg u detected in hecurve_sprint, v[2] = %Zd\n", _ff_wrap_mpz(v[2],0));
108
#endif
109
if ( _ff_one(u[2]) ) {
110
return gmp_sprintf (s, "(x^2 + %Zd*x + %Zd, %Zd*x + %Zd)",
111
_ff_wrap_mpz(u[1],1), _ff_wrap_mpz(u[0],2), _ff_wrap_mpz(v[1],3), _ff_wrap_mpz(v[0],4));
112
} else {
113
err_printf ("Warning, non-monic u in hecurve_sprint\n");
114
return gmp_sprintf (s, "(%Zd*x^2 + %Zd*x + %Zd, %Zd*x + %Zd)",
115
_ff_wrap_mpz(u[2],0),_ff_wrap_mpz(u[1],1), _ff_wrap_mpz(u[0],2), _ff_wrap_mpz(v[1],3), _ff_wrap_mpz(v[0],4));
116
}
117
} else if ( _ff_nonzero(u[1]) ) {
118
if ( _ff_nonzero(v[1]) ) err_printf ("Warning, deg v == deg u = 1 detected in hecurve_sprint, v = %Zdx+%Zd\n", _ff_wrap_mpz(v[1],0),_ff_wrap_mpz(v[0],1));
119
if ( _ff_one(u[1]) ) {
120
return gmp_sprintf (s, "(x + %Zd, %Zd)", _ff_wrap_mpz(u[0],0), _ff_wrap_mpz(v[0],1));
121
} else {
122
err_printf ("Warning, non-monic u in hecurve_sprint\n");
123
return gmp_sprintf (s, "(%Zdx + %Zd, %Zd)", _ff_wrap_mpz(u[1],0), _ff_wrap_mpz(u[0],1), _ff_wrap_mpz(v[0],2));
124
}
125
} else if ( _ff_nonzero(u[0]) ) {
126
if ( _ff_nonzero(v[1]) || _ff_nonzero(v[0]) ) err_printf ("Warning, deg v >= deg u = 0 detected in hecurve_sprint, v = %Zdx+%Zd\n", _ff_wrap_mpz(v[1],0),_ff_wrap_mpz(v[0],1));
127
if ( _ff_one(u[0]) ) {
128
return gmp_sprintf (s, "(1, 0)");
129
} else {
130
err_printf ("Warning, non-monic u in hecurve_sprint\n");
131
return gmp_sprintf (s, "(%Zd, 0)", _ff_wrap_mpz(u[0],0));
132
}
133
} else {
134
err_printf ("u is zero in hecurve_sprint!\n"); exit (0);
135
}
136
#else
137
if ( ! _ff_zero(u[1]) && ! _ff_one(u[1]) ) { printf ("non-monic u in hecurve print, lc=%d(raw=%u,one=%u(\n", _ff_get_ui(u[1]),u[1],_ff_mont_R); exit(0); }
138
if ( _hecurve_is_identity(u,v) ) {
139
return gmp_sprintf (s, "(1, 0)");
140
} else {
141
return gmp_sprintf(s, "(x + %Zd, %Zd)", _ff_wrap_mpz(u[0],1), _ff_wrap_mpz(v[0],2));
142
}
143
#endif
144
}
145
146
147
int hecurve_verify (ff_t u[HECURVE_GENUS+1], ff_t v[HECURVE_GENUS], ff_t f[HECURVE_DEGREE+1])
148
{
149
_ff_t_declare t[2*HECURVE_GENUS-1], g[HECURVE_DEGREE+1], x, y, z;
150
int i, d_u, d_v, d_t, d_g;
151
152
if ( ! _ff_one (f[HECURVE_DEGREE]) ) { err_printf ("Invalid f polynomial in hecurve_verify, not monic degree %d\n", HECURVE_DEGREE); exit (0); }
153
if ( ! u ) { err_printf ("Null pointer in hecurve_verification!\n"); return 0; }
154
155
#if HECURVE_GENUS == 1
156
if ( _ff_zero(u[1]) ) {
157
if ( _ff_zero(v[0]) && _ff_zero(u[0]) ) return 1;
158
out_printf ("hecurve verification failed - invalid identity element in genus 1\n");
159
return 0;
160
}
161
if ( ! _ff_one(u[1]) ) { out_printf ("hecurve verification failed - non-affine point in genus 1, u[1]=%d\n", _ff_get_ui(u[1])); return 0; }
162
_ff_neg (x, u[0]);
163
ff_poly_eval (&y, f, HECURVE_DEGREE, &x);
164
+ff_square (z, v[0]);
165
if ( ! _ff_equal (y,z) ) {
166
out_printf ("hecurve verification failed for element:\n "); hecurve_print(u,v);
167
out_printf ("point not on curve\n");
168
return 0;
169
}
170
return 1;
171
#endif
172
173
d_u = _deg_u(u);
174
if ( d_u == 0 ) {
175
if ( ! _hecurve_is_identity(u,v) ) {
176
out_printf ("hecurve verification failed for element:\n "); hecurve_print(u,v);
177
out_printf ("degree of u is zero, but (u,v) is not the identity.\n");
178
return 0;
179
}
180
return 1;
181
}
182
if ( ! _ff_one(u[d_u]) ) {
183
out_printf ("hecurve verification failed for element:\n "); hecurve_print(u,v);
184
out_printf ("u is not monic.\n");
185
printf ("d_u = %d, u[d_u] = %d (raw) %Zd\n", d_u, u[d_u], _ff_wrap_mpz(u[d_u], 0));
186
return 0;
187
}
188
d_v = _deg_v(v);
189
ff_poly_mult (t, &d_t, v, d_v, v, d_v); // t = v^2
190
ff_poly_sub (g, &d_g, f, HECURVE_DEGREE, t, d_t); // g = f-v^2
191
ff_poly_mod (t, &d_t, g, d_g, u, d_u);
192
if ( d_t >= 0 ) {
193
out_printf ("hecurve verification failed for element: \n "); hecurve_print (u,v);
194
out_printf ("f-v^2 mod u = "); ff_poly_print (t, d_t);
195
out_printf("degree u = %d, degree v = %d\n", d_u, d_v);
196
out_printf("f-v^2 = "); ff_poly_print(g,d_g);
197
return 0;
198
}
199
return 1;
200
}
201
202
203
int hecurve_random_point (ff_t px[1], ff_t py[1], ff_t f[HECURVE_DEGREE+1])
204
{
205
_ff_t_declare x, y, z, t;
206
int i;
207
#if INIT_REQUIRED
208
static int init;
209
if ( ! init ) { _ff_init(x); _ff_init(y); _ff_init(z); _ff_init(t); init = 1; }
210
#endif
211
i = 0;
212
do {
213
if ( i++ > HECURVE_RANDOM_POINT_RETRIES ) return 0; // it is possible for very small p that there are no rational points on the curve other than the point at infinity
214
_ff_random(x);
215
/// dbg_printf ("Random x = %Zd in F_%Zd\n",_ff_wrap_mpz(x,0), _ff_mpz_p);
216
ff_poly_eval (&y, f, HECURVE_DEGREE, &x);
217
/// dbg_printf ("y^2 = f(%Zd) = %Zd mod %Zd, computing square root\n",_ff_wrap_mpz(x,0),_ff_wrap_mpz(y,1), _ff_mpz_p);
218
} while ( ! ff_sqrt (&z, &y) );
219
if ( ui_randomb(1) ) ff_negate (z); // flip square root 50% of the time
220
/// dbg_printf ("Found square root %Zd\n", _ff_wrap_mpz(z,0));
221
_ff_set(px[0],x);
222
_ff_set(py[0],z);
223
#if ! HECURVE_FAST
224
if ( dbg_level >= 2 ) {
225
ff_poly_sprint (buf, f, HECURVE_DEGREE);
226
dbg_printf ("Random Point (%Zd,%Zd) on y^2 = %s over F_%Zd\n",_ff_wrap_mpz(px[0],0), _ff_wrap_mpz(py[0],1), buf, _ff_mpz_p);
227
}
228
#endif
229
return 1;
230
}
231
232
void hecurve_random (ff_t u[HECURVE_GENUS+1], ff_t v[HECURVE_GENUS], ff_t f[HECURVE_DEGREE+1])
233
{
234
_ff_t_declare x1, y1, x2, y2, x3, y3;
235
_ff_t_declare alpha[3], beta[3];
236
#if HECURVE_GENUS == 3
237
_ff_t_declare alpha_p[3], beta_p[3], temp1[3], temp2[3], temp3[3];
238
_ff_t_declare_reg gamma, delta, b, c, d, D;
239
#endif
240
register unsigned long t;
241
unsigned bits;
242
int r;
243
244
#if HECURVE_GENUS == 1
245
if ( ! hecurve_random_point(&x1,&y1, f) ) { _hecurve_set_identity(u,v); return; }
246
hecurve_make_1 (u,v,x1,y1);
247
#if HECURVE_VERIFY
248
if ( ! hecurve_verify (u, v, f) ) {
249
err_printf ("Verification failed in hecurve_random!\n");
250
err_printf ("P1 = (%Zd,%Zd)\n", _ff_wrap_mpz(x1,0), _ff_wrap_mpz(y1,1));
251
}
252
#endif
253
#if ! HECURVE_FAST
254
if ( dbg_level >= 2 ) { printf ("Random element: "); hecurve_print (u, v); }
255
#endif
256
return;
257
#endif
258
259
#if HECURVE_GENUS == 2
260
#if HECURVE_RANDOM == 1
261
do {
262
_ff_random(u[2]);
263
if ( _ff_zero(u[2]) ) { // use weight one divisor with probability 1/p
264
_hecurve_set_zero(u,v);
265
if ( ! hecurve_random_point(&x1,&y1, f) ) { _hecurve_set_identity(u,v); return; }
266
hecurve_make_1 (u, v, x1, y1);
267
break;
268
}
269
_ff_set_one(u[2]);
270
_ff_random(u[1]);
271
_ff_random(u[0]);
272
bits = (unsigned) ui_randomm(4);
273
} while ( ! hecurve_unbits (v,u,bits,f) );
274
#else
275
#if HECURVE_RANDOM == 2
276
_hecurve_set_zero (u, v);
277
// Flip a coin to decide how to split u(x)
278
if ( ui_randomb(1) ) {
279
// u will be reducible. pick two points on the curve
280
if ( ! hecurve_random_point (&x1, &y1, f) ) { _hecurve_set_identity(u,v); return; } // identity return only happens for curves with no rational pts
281
if ( ! hecurve_random_point (&x2, &y2, f) ) { _hecurve_set_identity(u,v); return; }
282
if ( _ff_equal(x1,x2) ) {
283
if ( _ff_equal(y1,y2) ) {
284
// if the points are identical, double the pt, unless it has 2-torsion
285
if ( _ff_zero(y1) ) {
286
hecurve_make_1 (u, v, x1, y1); // for 2-torsion points don't double (means we never return identity here)
287
// puts ("singleton 2-torsion");
288
} else {
289
ff_negate(x1); // for single pt divisor, u(x)=x-x1 so u0=-x1
290
hecurve_g2_square_1 (u, v, x1, y1, f);
291
// puts ("double pt");
292
}
293
} else {
294
// Treat the case of a pt and its opposite by just making a divisor with 1 pt.
295
// This will occur with probability \approx 1/p, which is right ratio
296
hecurve_make_1 (u, v, x1, y1);
297
// puts ("singleton non-torsion");
298
}
299
} else {
300
hecurve_make_2 (u, v, x1, y1, x2, y2);
301
// puts ("pair of pts");
302
}
303
} else {
304
// make u irreducible by picking a root alpha of degree 2 over F_p and setting u(x)=(x-alpha)(x-phi(alpha))
305
// where phi is the frobenius map. If alpha = a_0+a_1z \in F_p[z]/(z^2-nr), then phi(alpha) = a_0-a_1z
306
// note that if beta^2 = f(alpha) then phi(beta)^2 = f(phi(alpha)), so the divisor necessarily contains the
307
// two points (alpha,+/-beta) and (phi(alpha),+/-phi(beta)). The signs must match, otherwise v(x) won't be rational.
308
for(;;) {
309
do { _ff_random(alpha[1]); } while ( _ff_zero(alpha[1]) );
310
_ff_random(alpha[0]);
311
//printf ("alpha=%ldz+%ld\n", _ff_get_ui(alpha[1]), _ff_get_ui(alpha[0]));
312
ff2_poly_eval(beta, f, HECURVE_DEGREE, alpha);
313
if ( ! ff2_sqrt(beta, beta) ) continue;
314
if ( ui_randomb(1) ) ff2_negate (beta); // flip square root 50% of the time
315
//printf ("beta=%ldz+%ld\n", _ff_get_ui(beta[1]), _ff_get_ui(beta[0]));
316
_ff_set_one(u[2]);
317
_ff_add(x1,alpha[0],alpha[0]);
318
_ff_neg(u[1],x1);
319
_ff_square(x1,alpha[0]);
320
_ff_square(x2,alpha[1]);
321
_ff_mult(x3,x2,_ff_nr);
322
_ff_sub(u[0],x1,x3);
323
_ff_invert(x1,alpha[1]);
324
_ff_mult(v[1],x1,beta[1]);
325
_ff_mult(x2,alpha[0],v[1]);
326
_ff_sub(v[0],beta[0],x2);
327
// cost to get (u,v) from (alpha,beta) is I+5M+4A, counting squares as mults and subs/negs as additions.
328
// puts ("2 non-rational conjugates");
329
break;
330
}
331
}
332
333
#else
334
_hecurve_set_zero (u, v);
335
if ( ! hecurve_random_point (&x1, &y1, f) ) { _hecurve_set_identity(u,v); return; }
336
if ( ! hecurve_random_point (&x2, &y2, f) ) { _hecurve_set_identity(u,v); return; }
337
if ( _ff_equal(x1,x2) ) {
338
hecurve_make_1 (u, v, x1, y1);
339
} else {
340
hecurve_make_2 (u, v, x1, y1, x2, y2);
341
}
342
#endif
343
#endif
344
#endif
345
#if HECURVE_GENUS == 3
346
_hecurve_set_zero (u, v);
347
#if HECURVE_RANDOM == 2
348
349
// Flip a 6-sided coin to decide how to split u(x)
350
retry3:
351
r = ui_randomm(6);
352
if ( !r ) {
353
// with probabilty 1/6, split u completely
354
for(;;) {
355
_hecurve_set_zero (u, v);
356
// u will be split completely. pick three points on the curve
357
if ( ! hecurve_random_point (&x1, &y1, f) ) goto retry3; // only happens for curves with no rational pts
358
if ( ! hecurve_random_point (&x2, &y2, f) ) goto retry3;
359
if ( ! hecurve_random_point (&x3, &y3, f) ) goto retry3;
360
if ( _ff_equal(x1,x2) ) {
361
if ( _ff_equal(x1,x3) || ! _ff_equal(y1,y2) ) {
362
// If all three x values are equal, let P=(x1,y1) and we create P, 2P, or 3P with equal probabilities
363
// Each case should have probability 1/p^3, however the probability we have reached this point with a particular P is (1/6)*(4/p^3) = 2/(3p^3)
364
// and we really want it to be 3/p^3. To fix things up, we include some of the cases where (x1,y1) and (x2,y2) are opposite points
365
if ( ! _ff_equal(y1,y2) ) {
366
r = ui_randomm(3*_ff_p);
367
if ( r >= 7 ) continue;
368
// we get here with probability 7/(3p^3), which added to 2/(3p^3) (all three x values equal) gives the desired 3/p^3.
369
}
370
r = ui_randomm(3);
371
switch (r) {
372
case 0:
373
hecurve_make_1 (u, v, x1, y1);
374
// puts ("single point");
375
break;
376
case 1:
377
hecurve_make_1 (u, v, x1, y1);
378
hecurve_g3_square (u, v, u, v, f, 0);
379
// puts ("double point");
380
break;
381
case 2:
382
hecurve_make_1 (u, v, x1, y1);
383
hecurve_g3_square (alpha, beta, u, v, f, 0);
384
hecurve_g3_compose (u, v, alpha, beta, u, v, f, 0);
385
// puts ("triple point");
386
}
387
} else {
388
// we have two copies of a pt and a third distinct pt
389
_hecurve_set_zero(alpha,beta);
390
hecurve_make_2 (alpha, beta, x1, y1, x3, y3); // compose distinct pts
391
hecurve_make_1 (u, v, x2, y2); // make one of the dups singleton
392
hecurve_compose (u, v, alpha, beta, u, v, f, 0); // put it all together
393
// puts ("2+1 point");
394
}
395
} else if ( _ff_equal (x1, x3) || _ff_equal(x2,x3) ) {
396
// points 1 and 2 are distinct, but 3 is a duplicate or an opposite
397
// We have handled all cases except 2 distinct rational points, which we handle here if (x1,y1)==(x3,y3)
398
// otherwise we retry in order to avoid overweighting
399
if (! (_ff_equal(x1,x3) && _ff_equal(y1,y3)) ) continue;
400
hecurve_make_2 (u, v, x1, y1, x2, y2);
401
// puts ("2 distinct rational points");
402
} else {
403
hecurve_make_3 (u, v, x1, y1, x2, y2, x3, y3); // usual case
404
// puts ("3 distinct rational points");
405
}
406
break;
407
}
408
} else if ( r < 4 ) {
409
// with probability 1/2, split u(x) into a linear and a quadratic, in general,
410
// but with probaility 1/p (within 1/2) don't include a linear factor (or if there are none)
411
if ( ! ui_randomm(_ff_p+1) || ! hecurve_random_point (&x1, &y1, f) ) {
412
// this is an exact duplicate of the genus 2 code above
413
for(;;) {
414
do { _ff_random(alpha[1]); } while ( _ff_zero(alpha[1]) );
415
_ff_random(alpha[0]);
416
//printf ("alpha=%ldz+%ld\n", _ff_get_ui(alpha[1]), _ff_get_ui(alpha[0]));
417
ff2_poly_eval(beta, f, HECURVE_DEGREE, alpha);
418
if ( ! ff2_sqrt(beta, beta) ) continue;
419
if ( ui_randomb(1) ) ff2_negate (beta); // flip square root 50% of the time
420
//printf ("beta=%ldz+%ld\n", _ff_get_ui(beta[1]), _ff_get_ui(beta[0]));
421
_ff_set_one(u[2]);
422
_ff_add(x1,alpha[0],alpha[0]);
423
_ff_neg(u[1],x1);
424
_ff_square(x1,alpha[0]);
425
_ff_square(x2,alpha[1]);
426
_ff_mult(x3,x2,_ff_nr);
427
_ff_sub(u[0],x1,x3);
428
_ff_invert(x1,alpha[1]);
429
_ff_mult(v[1],x1,beta[1]);
430
_ff_mult(x2,alpha[0],v[1]);
431
_ff_sub(v[0],beta[0],x2);
432
// cost to get (u,v) from (alpha,beta) is I+5M+4A, counting squares as mults and subs/negs as additions.
433
// puts ("2 non-rational conjugates");
434
break;
435
}
436
} else {
437
// split u(x) into a linear and a quadratic
438
//printf("x1=%ld, y1=%ld, s=%ld, p=%ld\n", _ff_get_ui(x1), _ff_get_ui(y1), _ff_get_ui(_ff_nr), _ff_p);
439
for(;;) {
440
do { _ff_random(alpha[1]); } while ( _ff_zero(alpha[1]) );
441
_ff_random(alpha[0]);
442
//printf ("alpha=%ldz+%ld\n", _ff_get_ui(alpha[1]), _ff_get_ui(alpha[0]));
443
ff2_poly_eval(beta, f, HECURVE_DEGREE, alpha);
444
if ( ! ff2_sqrt(beta, beta) ) continue;
445
if ( ui_randomb(1) ) ff2_negate (beta); // flip square root 50% of the time
446
//printf ("beta=%ldz+%ld\n", _ff_get_ui(beta[1]), _ff_get_ui(beta[0]));
447
_ff_add(b,alpha[0],alpha[0]);
448
ff_negate(b); // b = -tr(alpha) is coeff of x in quadratic factor
449
//printf("b=%ld\n", _ff_get_ui(b));
450
_ff_square(c,alpha[0]);
451
_ff_square(y2,alpha[1]);
452
_ff_mult(x2,y2,_ff_nr);
453
_ff_add(d,c,x2); // d = a0^2+s*a1^2 used below to compute delta
454
_ff_subfrom(c,x2); // c = N(alpha) is const. coeff in quadratic factor
455
//printf("c=%ld\n", _ff_get_ui(c));
456
_ff_mult(D,b,x1);
457
_ff_set_one(u[3]); // u[3] = 1
458
_ff_sub(u[2],b,x1); // u[2] = b-x1
459
_ff_sub(u[1],c,D); // u[1] = c-bx1
460
_ff_mult(y3,c,x1);
461
_ff_neg(u[0],y3); // u[0] = -cx1
462
_ff_square(x2,x1);
463
_ff_addto(D,x2);
464
_ff_addto(D,c);
465
ff_mult(y3,D,alpha[1]);
466
//printf("D=%ld\n", _ff_get_ui(D));
467
ff_invert(D,y3); // D = 2z/ [(x1^2+bx1+c)(alpha-phi(alpha))] note the 2's all cancel
468
_ff_mult(gamma,alpha[1],beta[0]);
469
_ff_mult(delta,alpha[0],gamma);
470
_ff_mult(y3,beta[1],alpha[0]);
471
_ff_subfrom(gamma,y3); // gamma = alpha*phi(beta), only need gamma[1]
472
//printf("gamma=%ld\n", _ff_get_ui(gamma));
473
_ff_x2(delta);
474
_ff_mult(y3,beta[1],d);
475
_ff_subfrom(delta,y3); // delta = alpha^2*phi(beta) only need delta[1]
476
//printf("delta=%ld\n", _ff_get_ui(delta));
477
ff_mult(y1,alpha[1],y1); // all use of y1 from here on out will include the factor alpha[1]=(alpha-phi(alpha))/2
478
_ff_sub(y2,y1,gamma);
479
_ff_mult(y3,beta[1],x1);
480
_ff_subfrom(y2,y3);
481
_ff_mult(v[2],D,y2); // v[2] = [alpha1*y1 - gamma1 - beta1*x1] / D
482
_ff_mult(y2,x2,beta[1]);
483
_ff_addto(y2,delta);
484
_ff_mult(y3,b,y1);
485
_ff_addto(y2,y3);
486
_ff_mult(v[1],D,y2); // v[1] = [alpha1*y1*b + delta1+ beta1*x1^2] / D
487
_ff_mult(y2,c,y1);
488
_ff_mult(y3,x1,delta);
489
_ff_subfrom(y2,y3);
490
_ff_mult(y3,gamma,x2);
491
_ff_addto(y2,y3);
492
_ff_mult(v[0],D,y2); // v[0] = [alpha1*y1*c - delta1*x1 + gamm1*x1^2] / D
493
// Cost to get (u,v) from (alpha,beta) is I+21M+18A
494
// puts ("2,1 non-rational conjugates and rational pt");
495
break;
496
}
497
}
498
// construct quadratic factor as in genus 2 case above.
499
} else {
500
// with probability 1/3 make u(x) irreducible
501
for(;;) {
502
do { ff3_random(alpha); } while ( _ff_zero(alpha[1]) && _ff_zero(alpha[2]) );
503
//printf ("alpha=%ldz^2+%ldz+%ld\n", _ff_get_ui(alpha[2]), _ff_get_ui(alpha[1]), _ff_get_ui(alpha[0]));
504
ff3_poly_eval(beta, f, HECURVE_DEGREE, alpha);
505
//printf ("f(alpha)=%ldz^2+%ldz+%ld\n", _ff_get_ui( beta[2]), _ff_get_ui( beta[1]), _ff_get_ui( beta[0]));
506
if ( ! ff3_sqrt(beta, beta) ) continue;
507
if ( ui_randomb(1) ) ff3_negate (beta); // flip square root 50% of the time
508
//printf ("beta=%ldz^2+%ldz+%ld\n", _ff_get_ui( beta[2]), _ff_get_ui( beta[1]), _ff_get_ui( beta[0]));
509
ff3_exp_p(alpha_p,alpha);
510
ff3_mult(temp1,alpha,alpha_p);
511
ff3_trace(&x1,alpha);
512
ff3_norm(&x2,alpha);
513
_ff_set_one(u[3]); // u[3] = 1
514
_ff_neg(u[2],x1); // u[2]=-tr(alpha)
515
ff3_trace(u+1,temp1); // u[1]=tr(alpha^(p+1))
516
_ff_neg(u[0],x2); // u[0]=-norm(alpha)
517
ff3_mult(temp2,temp1,alpha_p); // temp2=alpha^(2p+1)
518
ff3_mult(temp1,temp1,alpha); // temp1=alpha^(p+2)
519
ff3_trace(&x1,temp2);
520
ff3_trace(&x2,temp1);
521
_ff_sub(x3,x1,x2);
522
ff_invert(D,x3); // D = 1 / [(alpha-alpha^p)(alpha^p-alpha^(p^2))(alpha^(p^2)-alpha)]
523
ff3_exp_p(beta_p,beta);
524
ff3_exp_p(beta,beta_p); // beta now set to beta^2 (we don't need beta anymore)
525
ff3_mult(temp3,temp2,beta);
526
ff3_trace(&x1,temp3);
527
ff3_mult(temp3,temp1,beta);
528
ff3_trace(&x2,temp3);
529
_ff_sub(x3,x1,x2);
530
_ff_mult(v[0],D,x3); // v[0] = D * [tr(alpha^(2p+1)*beta^(p^2)) - tr(alpha^(p+2)*beta^(p^2))]
531
ff3_square(temp1,alpha);
532
ff3_mult(temp2,temp1,beta);
533
ff3_trace(&x1,temp2);
534
ff3_mult(temp3,temp1,beta_p);
535
ff3_trace(&x2,temp3);
536
_ff_sub(x3,x1,x2);
537
_ff_mult(v[1],D,x3); // v[1] = D * [tr(alpha^2*(beta^(p^2)) - tr(alpha^2*beta^p)]
538
ff3_mult(temp2,alpha,beta_p);
539
ff3_trace(&x1,temp2);
540
ff3_mult(temp3,alpha,beta);
541
ff3_trace(&x2,temp3);
542
_ff_sub(x3,x1,x2);
543
_ff_mult(v[2],D,x3); // v[2] = D * [tr(alpha*beta^p) = tr(alpha*beta^(p^2))]
544
// puts ("3 non-rational conjugates");
545
break;
546
}
547
}
548
#else
549
if ( ! hecurve_random_point (&x1, &y1, f) ) { _hecurve_set_identity(u,v); return; }
550
if ( ! hecurve_random_point (&x2, &y2, f) ) { _hecurve_set_identity(u,v); return; }
551
if ( ! hecurve_random_point (&x3, &y3, f) ) { _hecurve_set_identity(u,v); return; }
552
if ( _ff_equal(x1,x2) ) {
553
if ( _ff_equal (x1,x3) ) {
554
hecurve_make_1 (u, v, x1, y1);
555
} else {
556
hecurve_make_2 (u, v, x1, y1, x3, y3);
557
}
558
} else {
559
if ( _ff_equal(x1,x3) || _ff_equal(x2,x3) ) {
560
hecurve_make_2 (u, v, x1, y1, x2, y2);
561
} else {
562
hecurve_make_3 (u, v, x1, y1, x2, y2, x3, y3); // usual case
563
}
564
}
565
#endif
566
#endif
567
#if ! HECURVE_FAST
568
if ( dbg_level >= 2 ) { printf ("Random element: "); hecurve_print (u, v); }
569
#endif
570
#if HECURVE_VERIFY
571
if ( ! hecurve_verify (u, v, f) ) {
572
err_printf ("Verification failed in hecurve_random!\n");
573
#if HECURVE_GENUS == 3
574
err_printf ("P1 = (%Zd,%Zd), P2 = (%Zd,%Zd), P3 = (%Zd,%Zd)\n",
575
_ff_wrap_mpz(x1,0), _ff_wrap_mpz(y1,1), _ff_wrap_mpz(x2,2), _ff_wrap_mpz(y2,3), _ff_wrap_mpz(x3,4), _ff_wrap_mpz(y3,5));
576
#else
577
err_printf ("P1 = (%Zd,%Zd), P2 = (%Zd,%Zd)\n", _ff_wrap_mpz(x1,0), _ff_wrap_mpz(y1,1), _ff_wrap_mpz(x2,2), _ff_wrap_mpz(y2,3));
578
#endif
579
exit (0);
580
}
581
#endif
582
}
583
584
// See formulas on p.307 of [HECHECC]
585
void hecurve_make_3 (ff_t u[4], ff_t v[3], ff_t x1, ff_t y1, ff_t x2, ff_t y2, ff_t x3, ff_t y3)
586
{
587
_ff_t_declare_reg s1, s2, s3, t1, t2, t3, t, w, z;
588
#if ! HECURVE_FAST
589
if ( _ff_equal(x1,x2) ) { err_printf ("Call to hecurve_make_3 with x1 = x2!\n"); exit (0); }
590
if ( _ff_equal(x2,x3) ) { err_printf ("Call to hecurve_make_3 with x2 = x3!\n"); exit (0); }
591
if ( _ff_equal(x3,x1) ) { err_printf ("Call to hecurve_make_3 with x3 = x1!\n"); exit (0); }
592
#endif
593
// Construct u(x) = (x-x1)(x-x2)(x-x3) with roots x1, x2, and x3 then construct v(x) so that v(x_i) = y_i ensuring u|v^2-f (note h =0)
594
_ff_set_one(u[3]); // u[3] = 1
595
_ff_sub(t1,x1,x2); // t1=x1-x2
596
_ff_sub(t2,x2,x3); // t2=x2-x3
597
_ff_sub(t3,x3,x1); // t3=x3-x1
598
_ff_mult(t,t1,t2);
599
_ff_mult(z,t,t3);
600
_ff_invert(z,z);
601
ff_negate(z); // z = -1/[(x1-x2)(x2-x3)(x3-x1)]
602
ff_mult(t1,t1,y3); // t1=(x1-x2)y3
603
ff_mult(t2,t2,y1); // t2=(x2-x3)y1
604
ff_mult(t3,t3,y2); // t3=(x3-x1)y2
605
_ff_add(t,t1,t2);
606
_ff_addto(t,t3);
607
ff_mult(v[2],z,t); // v[2] = -[(x1-x2)y3+(x2-x3)y1+(x3-x1)y2]/[(x1-x2)(x2-x3)(x3-x1)]
608
_ff_add(s1,x1,x2); // s1=x1+x2
609
_ff_add(s2,x2,x3); // s2=x2+x3
610
_ff_add(s3,x3,x1); // s3=x3+x1
611
_ff_add(t,s1,x3);
612
_ff_neg(u[2],t); // u[2] = -(x1+x2+x3)
613
_ff_mult(t,s1,t1);
614
_ff_mult(w,s2,t2);
615
_ff_addto(t,w);
616
_ff_mult(w,s3,t3);
617
_ff_addto(t,w);
618
ff_negate(t);
619
ff_mult(v[1],z,t); // v[1] = [(x1-x2)(x1+x2)y3+(x2-x3)(x2+x3)y1+(x3-x1)(x3+x1)y2]/[(x1-x2)(x2-x3)(x3-x1)]
620
_ff_mult(s1,x1,x2); // s1=x1x2
621
_ff_mult(s2,x2,x3); // s2=x2x3
622
_ff_mult(s3,x3,x1); // s3=x3x1
623
_ff_mult(t,s1,x3);
624
_ff_neg(u[0],t); // u[0] = -x1x2x3
625
_ff_add(t,s1,s2);
626
_ff_add(u[1],t,s3); // u[1] = x1x2+x2x3+x3x1
627
_ff_mult(t,s1,t1);
628
_ff_mult(w,s2,t2);
629
_ff_addto(t,w);
630
_ff_mult(w,s3,t3);
631
_ff_addto(t,w);
632
_ff_mult(v[0],z,t); // v[0] = -[x1x2(x1-x2)y3+x2x3(x2-x3)y1)+x3x1(x3-x1)y2]/[(x1-x2)(x2-x3)(x3-x1)]
633
// Total cost is I+18M+16A (counting negations and subtractions as additions)
634
}
635
636
637
// note this function is not genus specific, however caller is responsible for zeroing higher degree coefficients
638
void hecurve_make_2 (ff_t u[3], ff_t v[2], ff_t x1, ff_t y1, ff_t x2, ff_t y2)
639
{
640
_ff_t_declare_reg t1, t2, t3;
641
#if ! HECURVE_FAST
642
if ( _ff_equal(x1,x2) ) { err_printf ("Call to hecurve_make_2 with x1 = x2!\n"); exit (0); }
643
#endif
644
// Construct u(x) = (x-x_1)(x-x_2) has roots x1 and x2 then construct v(x) so that v(x_i) = y_i ensuring u|v^2-f (note h =0)
645
_ff_set_one(u[2]); // u[2] = 1
646
_ff_add(t1,x1,x2);
647
_ff_neg(u[1],t1); // u[1] = -(x1+x2)
648
_ff_mult(u[0],x1,x2);
649
_ff_sub(t1,x1,x2);
650
_ff_invert(t1,t1); // t1 = 1/(x1-x2)
651
_ff_sub(t2,y1,y2);
652
_ff_mult(v[1],t2,t1); // v1 = (y1-y1)/(x1-x2)
653
_ff_mult(t3,x1,y2);
654
_ff_mult(t2,x2,y1);
655
_ff_subfrom(t3,t2);
656
_ff_mult(v[0],t3,t1); // v0 = (x1y2-x2y1)/(x1-x2)
657
// total cost is I+5M+5A (counting subtractions and negations as additions)
658
}
659
660
/*
661
Basic implementation of Cantor's algorithm. Not optimized in the least - only intended for use
662
in exceptional cases. These generally are quite infrequent, however for very small p this
663
algorithm sees heavy use (in fact, smalljac typically runs faster with p > 1000 than p < 1000 for this reason).
664
665
Based on Algorithm 14.7 of [HECHECC].
666
*/
667
void hecurve_compose_cantor (ff_t u[HECURVE_GENUS+1], ff_t v[HECURVE_GENUS],
668
ff_t u1[HECURVE_GENUS+1], ff_t v1[HECURVE_GENUS],
669
ff_t u2[HECURVE_GENUS+1], ff_t v2[HECURVE_GENUS], ff_t f[HECURVE_DEGREE+1])
670
{
671
_ff_t_declare d1[HECURVE_GENUS+1], e1[HECURVE_GENUS+1], e2[HECURVE_GENUS+1];
672
_ff_t_declare d[HECURVE_GENUS], c1[HECURVE_GENUS], c2[HECURVE_GENUS];
673
_ff_t_declare s1[POLY_MAX_DEGREE+1], s2[POLY_MAX_DEGREE+1], s3[POLY_MAX_DEGREE+1];
674
_ff_t_declare q[POLY_MAX_DEGREE+1], r[POLY_MAX_DEGREE+1], s[POLY_MAX_DEGREE+1], t[POLY_MAX_DEGREE+1];
675
int i, d_d1, d_e1, d_e2, d_d, d_c1, d_c2, d_s, d_t, d_s1, d_s2, d_s3, d_u1, d_u2, d_v1, d_v2, d_q, d_r, d_f, d_u, d_v;
676
677
// assume no initialization of ff_t's is required - too much of a hassle
678
#if FF_MPZ
679
err_printf ("Cantor's algorithm not supported for MPZ field implementation\n");
680
exit (0);
681
#endif
682
683
// out_printf ("Cantor composition:\n");
684
// out_printf (" (u1,v1) = "); hecurve_print (u1,v1);
685
// out_printf (" (u2,v2) = "); hecurve_print (u2,v2);
686
687
#if HECURVE_VERIFY
688
if ( ! hecurve_verify (u1, v1, f) ) { err_printf ("hecurve_compose_cantor: invalid input\n"); exit (0); }
689
if ( ! hecurve_verify (u2, v2, f) ) { err_printf ("hecurve_compose_cantor: invalid input\n"); exit (0); }
690
#endif
691
692
d_u1 = _deg_u(u1); d_u2 = _deg_u(u2); d_v1 = _deg_v(v1); d_v2 = _deg_v(v2); d_f = HECURVE_DEGREE;
693
694
_poly_gcdext (d1, e1, e2, u1, u2);
695
_poly_add (t, v1, v2);
696
_poly_gcdext (d, c1, c2, d1, t);
697
_poly_mult(s1,c1,e1); _poly_mult(s2,c1,e2); _poly_set(s3,c2);
698
_poly_mult (q, u1, u2);
699
_poly_mult (t, d, d);
700
_poly_div (s, r, q, t); // s = u1u2/d^2 (s = u)
701
if ( d_r != -1 ) { err_printf ("Inexact division in Cantor's algorithm, r = "); _poly_print(r); exit (0); }
702
_poly_mult (r, u1, v2);
703
_poly_mult (t, r, s1);
704
_poly_mult (r, u2, v1);
705
_poly_mult (q, r, s2);
706
_poly_addto (t, q);
707
_poly_mult (r, v1, v2);
708
_poly_addto (r, f);
709
_poly_mult (q, r, s3);
710
_poly_addto (t, q);
711
_poly_div (q, r, t, d);
712
if ( d_r != -1 ) { err_printf ("Inexact division in Cantor's algorithm, r = "); _poly_print(r); exit (0); }
713
_poly_mod (t, q, s); // t = (s1u1v1+s2u2v1+s3(v1v2+f))/d mod u
714
do {
715
_poly_mult (s3, t, t);
716
_poly_sub (s2, f, s3);
717
_poly_div (s1, r, s2, s); // s1 = (f-v^2)/u (s1 = u')
718
_poly_set (s, s1);
719
_poly_mod (s2, t, s1);
720
_poly_neg (t, s2);
721
} while ( d_s > HECURVE_GENUS );
722
_poly_monic (u, s);
723
_poly_set (v, t);
724
for ( i = d_u+1 ; i <= HECURVE_GENUS ; i++ ) _ff_set_zero(u[i]);
725
for ( i = d_v+1 ; i < HECURVE_GENUS ; i++ ) _ff_set_zero(v[i]);
726
#if HECURVE_VERIFY
727
if ( ! hecurve_verify (u, v, f) ) {
728
err_printf ("hecurve_compose_cantor output verification failed for inputs:\n");
729
err_printf (" "); hecurve_print(u1,v1);
730
err_printf (" "); hecurve_print(u2,v2);
731
err_printf ("note that inputs have been modified if output overlapped.\n");
732
exit (0);
733
}
734
#endif
735
}
736
737
/*
738
compression/decompression currently only supported for genus 1 and 2. Note that
739
decompression is used for random element generation.
740
741
See p. 312 of [HECHECC] for a description of compression in genus 2.
742
*/
743
744
745
#if HECURVE_GENUS <= 2
746
747
unsigned hecurve_bits (ff_t u[3], ff_t v[2], ff_t f[6])
748
{
749
_ff_t_declare_reg s0, t1, t2;
750
register unsigned long bits;
751
#if HECURVE_GENUS == 1
752
return ( _ff_parity(v[0]) ? 1 : 0 );
753
#endif
754
755
// In genus 2, compute low order bit of s0 and low order bit of v0 (or v1 when v0 = 0)
756
757
_ff_square (t1, u[1]);
758
_ff_add(t2, u[0], u[0]);
759
_ff_subfrom (t2, t1);
760
_ff_mult (t1, t2, u[1]);
761
_ff_square (s0, v[1]);
762
_ff_subfrom (s0, t1);
763
#if ! HECURVE_SPARSE
764
if ( _ff_nonzero(f[3]) ) {
765
_ff_mult (t1, f[3], u[1]);
766
_ff_addto (s0, t1);
767
}
768
if ( _ff_nonzero(f[2]) ) _ff_subfrom (s0, f[2]);
769
#endif
770
bits = _ff_parity(s0);
771
if ( v[0] ) {
772
if ( _ff_parity(v[0]) ) bits |= 0x2;
773
} else {
774
if ( _ff_parity(v[1]) ) bits |= 0x2;
775
}
776
return bits;
777
}
778
779
780
// Used for genus 2 decompression and random element generation - attempts to reconstruct v from u and 2 bits
781
// No comparable support exists in genus 3 - decompression is much more difficult for g > 2
782
// This code needs to handle f4 != 0, since it may get used over F_5
783
int hecurve_unbits (ff_t v[2], ff_t u[3], unsigned bits, ff_t f[6])
784
{
785
_ff_t_declare_reg s, A, B, a, b, c, t0, t1, t2,w1,w2,w3,w4;
786
_ff_t_declare T0, T1;
787
788
#if HECURVE_GENUS == 1
789
_ff_square (t1, u[0]);
790
_ff_addto (t1, f[1]);
791
_ff_sub (T0, f[0], t1);
792
if ( ! ff_sqrt(v,&T0) ) { /*dbg_printf ("unbits: sqrt(f0-f1+u0^2) = sqrt(%Zd) failed\n", _ff_wrap_mpz(t0,0)); */ return 0; }
793
if ( (bits&0x1) != _ff_parity(v[0]) ) ff_negate(v[0]);
794
return 1;
795
#endif
796
797
_ff_square(w1,u[1]); // save w1 = u[1]^2
798
_ff_add(t1,u[0],u[0]);
799
_ff_add(w4,t1,t1); // save w4 = 4u[0]
800
_ff_subfrom(t1,w1);
801
_ff_mult(w2,u[1],t1); // save w2 = u[1](2u[0]-u[1]^2)
802
_ff_sub(t1,u[0],w1);
803
_ff_mult(w3,u[0],t1); // save w3 = u[0](u[0]-u[1]^2)
804
#if ! HECURVE_SPARSE
805
if ( _ff_nonzero(f[3]) ) {
806
_ff_mult(t1,f[3],u[1]);
807
_ff_sub(A,f[2],t1);
808
_ff_addto(A,w2);
809
_ff_mult(t1,f[3],u[0]);
810
_ff_sub(B,f[1],t1);
811
_ff_addto(B,w3);
812
} else {
813
_ff_add(A,w2,f[2]);
814
_ff_add(B,w3,f[1]);
815
}
816
if ( _ff_nonzero(f[4]) ) {
817
_ff_sub(t1,u[0],w1);
818
ff_mult(t1,t1,f[4]);
819
_ff_subfrom(A,t1);
820
_ff_mult(t1,u[0],u[1]);
821
ff_mult(t1,t1,f[4]);
822
_ff_addto(B,t1);
823
}
824
#else
825
_ff_set(A,w2);
826
_ff_add(B,f[1],w3);
827
#endif
828
// (14.5) on p. 312 is: (s+A)x^2 + (u[1]s+B)x + (u[0]s+f[0]) which must have discriminant 0 (note s = s0)
829
// this implies (u[1]s+B)^2 - 4(s+A)(u[0]s+f[0]) = 0
830
// thus (u[1]^2-4u[0])s^2 + (2Bu[1]-4(Au[0]+f[0]))s + (B^2-4Af[0]) = as^2 + bs + c = 0
831
// we now compute a, b, and c
832
_ff_sub(a,w1,w4); // a = u[1]^2-4u[0]
833
_ff_multadd (t0, A, u[0], f[0]);
834
_ff_x2(t0); _ff_x2(t0);
835
_ff_mult(t1,B,u[1]);
836
_ff_add(b,t1,t1);
837
_ff_subfrom(b,t0); // b = 2Bu[1] - 4(Au[0]+f[0])
838
_ff_square(c,B);
839
_ff_mult(t0,A,f[0]);
840
_ff_x2(t0); _ff_x2(t0);
841
_ff_subfrom(c,t0); // c = B^2 - 4Af[0]
842
if ( _ff_zero(a) ) {
843
if ( _ff_zero(b) ) { /*dbg_printf ("unbits: a=b=0\n"); */ return 0; }
844
_ff_invert(t0,b);
845
_ff_neg(t1,c);
846
_ff_mult(s,t0,t1);
847
} else {
848
_ff_mult(t0,a,c);
849
_ff_add(t1,t0,t0); _ff_x2(t1);
850
_ff_square(T0,b);
851
_ff_subfrom(T0,t1);
852
if ( ! ff_sqrt(&T1,&T0) ) { /*dbg_printf ("unbits: sqrt(b^2-4ac) = sqrt(%Zd) failed\n", _ff_wrap_mpz(t1,0));*/ return 0; }
853
_ff_add(t0,a,a);
854
ff_invert(t0,t0);
855
_ff_sub(s,T1,b);
856
ff_mult(s,s,t0); // s = (-b + sqrt(b^2-4ac))/2a
857
if ( bits&0x1 != _ff_parity(s) ) { // 50/50 chance here
858
_ff_neg(s,T1);
859
_ff_subfrom(s,b);
860
ff_mult(s,s,t0);
861
}
862
}
863
// we have s, now we use (14.6), (14.7), and (14.8) on p.312 of HHECC to compute v[0] and v[1]
864
// First use (14.6) to compute v0 = sqrt(u0s0+f0)
865
_ff_multadd(T0,s,u[0],f[0]);
866
if ( ! ff_sqrt(v,&T0) ) { /*dbg_printf ("unbits: sqrt(u[1]s0+f[0]) = sqrt(%Zd) failed\n", _ff_wrap_mpz(t0, 0));*/ return 0; }
867
if ( _ff_zero(v[0]) ) {
868
// use (14.8) to calculate v[1] when v[0] is zero - note that 14.8 is just v[1]^2 = s+A where A was computed above
869
_ff_add(T0,s,A);
870
if ( ! ff_sqrt(v+1,&T0) ) { /*dbg_printf ("unbits: sqrt(s0+f[2]-f[3]u[1]+u[1](2u[0]-u[1]^2) = sqrt(%Zd) failed\n", _ff_wrap_mpz(t0,0));*/ return 0; }
871
if ( ((bits&0x2)>>1) != _ff_parity(v[1]) ) ff_negate(v[1]);
872
} else {
873
// got v[0], set sign appropriately and use (14.7) to calculuate v[1] = (u[1]s+B)/(2v[0]) where B was computed above
874
if ( ((bits&0x2)>>1) != _ff_parity(v[0]) ) ff_negate(v[0]);
875
_ff_add(t0,v[0],v[0]);
876
ff_invert(t0,t0);
877
_ff_multadd(t1,u[1],s,B);
878
_ff_mult(v[1],t0,t1);
879
}
880
return 1;
881
}
882
883
#endif
884
885
886