Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
241818 views
1
#include <stdlib.h>
2
#include <stdio.h>
3
#include <math.h>
4
#include <memory.h>
5
#include "gmp.h"
6
#include "mpzutil.h"
7
#include "hecurve.h"
8
#include "ffwrapper.h"
9
#include "cstd.h"
10
11
/*
12
Copyright 2007 Andrew V. Sutherland
13
14
This file is part of smalljac.
15
16
smalljac is free software: you can redistribute it and/or modify
17
it under the terms of the GNU General Public License as published by
18
the Free Software Foundation, either version 2 of the License, or
19
(at your option) any later version.
20
21
smalljac is distributed in the hope that it will be useful,
22
but WITHOUT ANY WARRANTY; without even the implied warranty of
23
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24
GNU General Public License for more details.
25
26
You should have received a copy of the GNU General Public License
27
along with smalljac. If not, see <http://www.gnu.org/licenses/>.
28
*/
29
30
/*
31
This module implements generic Jacobian group operation in genus 1, i.e.
32
point addition (and doubling) on elliptic curves.
33
34
For consistency with higher genera we use a Mumford representation,
35
the point (x,y) is represented by u(z) = z-x and v(z) = y.
36
Thus x = -u[0] and y = v[0]. The identity has u(z) = 1 and v(z) = 0.
37
(*** note the sign difference on x and u[0] ***)
38
39
There is minimal overhead in doing this . u[1] is, in fact, never accessed
40
and need not be allocated.
41
42
We use an affine representation, as elsewhere, so that we can benefit
43
from parallel operation, which is achieved via the ctx parameter. If
44
ctx is non-null and a field inversion is required, the functions will fill
45
ctx with the entry to be inverted along with other state information and
46
return 0 to the caller. The caller should (eventually) perform the required
47
inversion (along with a bunch of others) and call back to finish the operation.
48
*/
49
50
#define _dbg_print_uv(s,u,v) if ( dbg_level >= 2 ) { printf (s); hecurve_print(u,v); }
51
52
int hecurve_g1_compose (ff_t u[HECURVE_GENUS+1], ff_t v[HECURVE_GENUS], ff_t u1[HECURVE_GENUS+1],
53
ff_t v1[HECURVE_GENUS], ff_t u2[HECURVE_GENUS+1],
54
ff_t v2[HECURVE_GENUS+1], ff_t f[HECURVE_DEGREE+1], hecurve_ctx_t *ctx)
55
{
56
_ff_t_declare_reg m, t1, t2;
57
#ifdef FF_INIT_REQUIRED
58
static int init;
59
60
if ( ! init ) { _ff_init (m); _ff_init (t1); _ff_init (t2); init = 1; }
61
#endif
62
63
#if ! HECURVE_FAST
64
_dbg_print_uv ("Genus 1 Compose A: ", u1, v1);
65
_dbg_print_uv ("Genus 1 Compose B: ", u2, v2);
66
#endif
67
#if HECURVE_VERIFY
68
if ( ! hecurve_verify (u1, v1, f) ) { err_printf ("hecurve_compose_g1 input verification failed for input: "); hecurve_print(u1,v1); exit (0); }
69
if ( ! hecurve_verify (u2, v2, f) ) { err_printf ("hecurve_compose_g1 input verification failed for input: "); hecurve_print(u2,v2); exit (0); }
70
#endif
71
72
if ( _hecurve_is_identity (u1,v2) ) { _hecurve_set(u,v,u2,v2); return 1; }
73
if ( _hecurve_is_identity (u2,v2) ) { _hecurve_set(u,v,u1,v1); return 1; }
74
75
if ( ctx && ctx->state ) {
76
if ( ctx->state == 1 ) {
77
// get invert result and restore saved variables
78
_ff_set (t2, ctx->invert); // inverted value of t1 = x1-x2 = u2[0]-u1[0]
79
goto hecurve_g1_compose_inverted;
80
} else if ( ctx->state == 2 ) {
81
// state 2 indicates square completing
82
return hecurve_g1_square (u, v, u1, v1, f, ctx);
83
}
84
}
85
86
_ff_sub (t1, u2[0], u1[0]);
87
if ( _ff_zero(t1) ) {
88
if ( _ff_equal(v1[0],v2[0]) ) {
89
return hecurve_g1_square (u, v, u1, v1, f, ctx);
90
} else {
91
_hecurve_set_identity (u,v);
92
return 1;
93
}
94
}
95
96
if ( ctx && ! ctx->state ) {
97
_ff_set (ctx->invert, t1); // return to let caller invert
98
ctx->state = 1;
99
return 0;
100
}
101
_ff_invert(t2,t1);
102
103
hecurve_g1_compose_inverted: // caller returns here after inverting - we have t2 = 1/(x1-x2) = 1/(u2[0]-u1[0])
104
105
_ff_sub (t1,v1[0],v2[0]);
106
_ff_mult (m,t1,t2);
107
_ff_square (t1,m);
108
_ff_add (t2,u1[0],u2[0]);
109
_ff_addto (t2,t1);
110
_ff_neg (t1,t2); // t1 = -x3 = -(m^2+u1[0]+u2[0]) = -(m^2-x1-x2)
111
_ff_sub (t2, t1, u1[0]);
112
_ff_set_one (u[1]);
113
_ff_set (u[0], t1); // must wait to set u[0] until here due to possible overlap with u1 or u2
114
_ff_mult (t1, t2, m);
115
_ff_subfrom (t1, v1[0]);
116
_ff_set (v[0], t1);
117
#if ! HECURVE_FAST
118
_dbg_print_uv ("Genus 1 Compose Result: ", u, v);
119
#endif
120
#if HECURVE_VERIFY
121
if ( ! hecurve_verify (u, v, f) ) {
122
err_printf ("hecurve_compose output verification failed for inputs:\n");
123
err_printf (" "); hecurve_print(u1,v1);
124
err_printf (" "); hecurve_print(u2,v2);
125
err_printf ("note that inputs have been modified if output overlapped input.\n");
126
exit (0);
127
}
128
#endif
129
return 1;
130
}
131
132
133
int hecurve_g1_square (ff_t u[HECURVE_GENUS+1], ff_t v[HECURVE_GENUS],
134
ff_t u1[HECURVE_GENUS+1], ff_t v1[HECURVE_GENUS], ff_t f[HECURVE_DEGREE+1], hecurve_ctx_t *ctx)
135
{
136
_ff_t_declare_reg m, t1, t2;
137
#ifdef FF_INIT_REQUIRED
138
static int init;
139
140
if ( ! init ) { _ff_init (m); _ff_init (t1); _ff_init (t2); init = 1; }
141
#endif
142
143
#if HECURVE_VERIFY
144
if ( ! hecurve_verify (u1, v1, f) ) { err_printf ("hecurve_square_g1 input verification failed for input: "); hecurve_print(u1,v1); exit (0); }
145
#endif
146
147
if ( ctx && ctx->state == 2 ) {
148
// get invert result and restore saved variables
149
_ff_set (t2, ctx->invert); // inverted value of t1 = x1-x2 = u2[0]-u1[0]
150
goto hecurve_g1_square_inverted;
151
}
152
153
#if ! HECURVE_FAST
154
_dbg_print_uv ("Genus 1 Square: ", u1, v1);
155
#endif
156
157
if ( _hecurve_2tor (u1,v1) ) { _hecurve_set_identity (u,v); return 1; }
158
159
_ff_add (t1, v1[0], v1[0]);
160
if ( ctx && ! ctx->state ) {
161
_ff_set (ctx->invert, t1);
162
ctx->state = 2;
163
return 0;
164
}
165
_ff_invert (t2,t1);
166
167
hecurve_g1_square_inverted: // caller returns here after inverting - t2 = 1/(2y1) = 1/(2v1[0])
168
_ff_square (t1, u1[0]);
169
_ff_add (m, t1, t1);
170
_ff_addto (t1, m);
171
_ff_addto (t1, f[1]);
172
_ff_mult (m, t1, t2); // m = (3x1^2 + f1)/2y1 = 3(u1[0]^2 + f1)/(2v1[0])
173
_ff_square (t1,m);
174
_ff_add (t2,u1[0],u1[0]);
175
_ff_addto (t2,t1);
176
_ff_neg (t1, t2);
177
_ff_sub (t2,t1,u1[0]);
178
ff_mult (t2, t2, m);
179
_ff_subfrom (t2, v1[0]);
180
_ff_set_one (u[1]);
181
_ff_set (u[0], t1); // note that we must wait until here to set u[0] due to possible overlap with u1 or u2
182
_ff_set (v[0], t2);
183
#if ! HECURVE_FAST
184
_dbg_print_uv ("Genus 1 square Result: ", u, v);
185
#endif
186
#if HECURVE_VERIFY
187
if ( ! hecurve_verify (u, v, f) ) {
188
err_printf ("hecurve_square output verification failed for input:\n");
189
err_printf (" "); hecurve_print(u1,v1);
190
err_printf ("note that inputs have been modified if output overlapped input.\n");
191
exit (0);
192
}
193
#endif
194
return 1;
195
}
196
197