]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 A |
1 | /************************************************************** |
2 | * | |
3 | * ellproj.c | |
4 | * | |
5 | Fast algorithms for fundamental elliptic curve arithmetic, | |
6 | projective format. Such algorithms apply in domains such as: | |
7 | -- factoring | |
8 | -- primality studies (e.g. rigorous primality proofs) | |
9 | -- elliptic curve cryptography (ECC) | |
10 | ||
11 | PROJECTIVE FORMAT | |
12 | ||
13 | Functions are supplied herein for projective format | |
14 | of points. Alternative formats differ in their | |
15 | range of applicability, efficiency, and so on. | |
16 | Primary advantages of the projective format herein are: | |
17 | -- No explicit inversions (until perhaps one such at the end of | |
18 | an elliptic multiply operation) | |
19 | -- Fairly low operation count (~11 muls for point doubling, | |
20 | ~16 muls for point addition) | |
21 | ||
22 | The elliptic curve is over F_p, with p > 3 prime, and Weierstrass | |
23 | parameterization: | |
24 | ||
25 | y^2 = x^3 + a x + b | |
26 | ||
27 | The projective-format coordinates are actually stored in | |
28 | the form {X, Y, Z}, with true x,y | |
29 | coordinates on the curve given by {x,y} = {X/Z^2, Y/Z^3}. | |
30 | The function normalize_proj() performs the | |
31 | transformation from projective->true. | |
32 | (The other direction is trivial, i.e. {x,y} -> {x,y,1} will do.) | |
33 | The basic point multiplication function is | |
34 | ||
35 | ell_mul_proj() | |
36 | ||
37 | which obtains the result k * P for given point P and integer | |
38 | multiplier k. If true {x,y} are required for a multiple, one | |
39 | passes a point P = {X, Y, 1} to ell_mul_proj(), then afterwards | |
40 | calls normalize_proj(), | |
41 | ||
42 | Projective format is an answer to the typical sluggishness of | |
43 | standard elliptic arithmetic, whose explicit inversion in the | |
44 | field is, depending of course on the machinery and programmer, | |
45 | costly. Projective format is thus especially interesting for | |
46 | cryptography. | |
47 | ||
48 | REFERENCES | |
49 | ||
50 | Crandall R and Pomerance C 1998, "Prime numbers: a computational | |
51 | perspective," Springer-Verlag, manuscript | |
52 | ||
53 | Solinas J 1998, IEEE P1363 Annex A (draft standard) | |
54 | ||
55 | LEGAL AND PATENT NOTICE | |
56 | ||
57 | This and related PSI library source code is intended solely for | |
58 | educational and research applications, and should not be used | |
59 | for commercial purposes without explicit permission from PSI | |
60 | (not to mention proper clearance of legal restrictions beyond | |
61 | the purview of PSI). | |
62 | The code herein will not perform cryptography per se, | |
63 | although the number-theoretical algorithms herein -- all of which | |
64 | are in the public domain -- can be used in principle to effect | |
65 | what is known as elliptic curve cryptography (ECC). Note that | |
66 | there are strict constraints on how cryptography may be used, | |
67 | especially in regard to exportability. | |
68 | Therefore one should avoid any casual distribution of actual | |
69 | cryptographic software. Along similar lines, because of various | |
70 | patents, proprietary to Apple Computer, Inc., and perhaps to other | |
71 | organizations, one should not tacitly assume that an ECC scheme is | |
72 | unconstrained. For example,the commercial use of certain fields | |
73 | F_p^k (i.e., fixation of certain primes p) is covered in Apple | |
74 | patents. | |
75 | ||
76 | * Updates: | |
77 | * 3 Apr 98 REC Creation | |
78 | * | |
79 | * c. 1998 Perfectly Scientific, Inc. | |
80 | * All Rights Reserved. | |
81 | * | |
82 | * | |
83 | *************************************************************/ | |
84 | ||
85 | /* include files */ | |
86 | ||
87 | #include <stdio.h> | |
88 | #include <math.h> | |
89 | #include <stdlib.h> | |
90 | #include <time.h> | |
91 | #ifdef _WIN32 | |
92 | ||
93 | #include <process.h> | |
94 | ||
95 | #endif | |
96 | ||
97 | #include <string.h> | |
98 | #include "giants.h" | |
99 | #include "ellproj.h" | |
100 | #include "tools.h" | |
101 | ||
102 | /* global variables */ | |
103 | ||
104 | static giant t0 = NULL, t1 = NULL, t2 = NULL, t3 = NULL, t4 = NULL, | |
105 | t5 = NULL, t6 = NULL, t7 = NULL; | |
106 | ||
107 | /************************************************************** | |
108 | * | |
109 | * Maintenance functions | |
110 | * | |
111 | **************************************************************/ | |
112 | ||
113 | point_proj | |
114 | new_point_proj(int shorts) | |
115 | { | |
116 | point_proj pt; | |
117 | ||
118 | if(t0 == NULL) init_ell_proj(shorts); | |
119 | pt = (point_proj) malloc(sizeof(point_struct_proj)); | |
120 | pt->x = newgiant(shorts); | |
121 | pt->y = newgiant(shorts); | |
122 | pt->z = newgiant(shorts); | |
123 | return(pt); | |
124 | } | |
125 | ||
126 | void | |
127 | free_point_proj(point_proj pt) | |
128 | { | |
129 | free(pt->x); free(pt->y); free(pt->z); | |
130 | free(pt); | |
131 | } | |
132 | ||
133 | void | |
134 | ptop_proj(point_proj pt1, point_proj pt2) | |
135 | { | |
136 | gtog(pt1->x, pt2->x); | |
137 | gtog(pt1->y, pt2->y); | |
138 | gtog(pt1->z, pt2->z); | |
139 | } | |
140 | ||
141 | void | |
142 | init_ell_proj(int shorts) | |
143 | /* Called by new_point_proj(), to set up giant registers. */ | |
144 | { | |
145 | t0 = newgiant(shorts); | |
146 | t1 = newgiant(shorts); | |
147 | t2 = newgiant(shorts); | |
148 | t3 = newgiant(shorts); | |
149 | t4 = newgiant(shorts); | |
150 | t5 = newgiant(shorts); | |
151 | t6 = newgiant(shorts); | |
152 | t7 = newgiant(shorts); | |
153 | } | |
154 | ||
155 | ||
156 | /************************************************************** | |
157 | * | |
158 | * Elliptic curve operations | |
159 | * | |
160 | **************************************************************/ | |
161 | ||
162 | /* Begin projective-format functions for | |
163 | ||
164 | y^2 = x^3 + a x + b. | |
165 | ||
166 | These are useful in elliptic curve cryptography (ECC). | |
167 | A point is kept as a triple {X,Y,Z}, with the true (x,y) | |
168 | coordinates given by | |
169 | ||
170 | {x,y} = {X/Z^2, Y/Z^3} | |
171 | ||
172 | The function normalize_proj() performs the inverse conversion to get | |
173 | the true (x,y) pair. | |
174 | */ | |
175 | ||
176 | void | |
177 | ell_double_proj(point_proj pt, giant a, giant p) | |
178 | /* pt := 2 pt on the curve. */ | |
179 | { | |
180 | giant x = pt->x, y = pt->y, z = pt->z; | |
181 | ||
182 | if(isZero(y) || isZero(z)) { | |
183 | itog(1,x); itog(1,y); itog(0,z); | |
184 | return; | |
185 | } | |
186 | gtog(z,t1); squareg(t1); modg(p, t1); | |
187 | squareg(t1); modg(p, t1); | |
188 | mulg(a, t1); modg(p, t1); /* t1 := a z^4. */ | |
189 | gtog(x, t2); squareg(t2); smulg(3, t2); modg(p, t2); /* t2 := 3x^2. */ | |
190 | addg(t2, t1); modg(p, t1); /* t1 := slope m. */ | |
191 | mulg(y, z); addg(z,z); modg(p, z); /* z := 2 y z. */ | |
192 | gtog(y, t2); squareg(t2); modg(p, t2); /* t2 := y^2. */ | |
193 | gtog(t2, t3); squareg(t3); modg(p, t3); /* t3 := y^4. */ | |
194 | gshiftleft(3, t3); /* t3 := 8 y^4. */ | |
195 | mulg(x, t2); gshiftleft(2, t2); modg(p, t2); /* t2 := 4xy^2. */ | |
196 | gtog(t1, x); squareg(x); modg(p, x); | |
197 | subg(t2, x); subg(t2, x); modg(p, x); /* x done. */ | |
198 | gtog(t1, y); subg(x, t2); mulg(t2, y); subg(t3, y); | |
199 | modg(p, y); | |
200 | } | |
201 | /* | |
202 | elldouble[pt_] := Block[{x,y,z,m,y2,s}, | |
203 | x = pt[[1]]; y = pt[[2]]; z = pt[[3]]; | |
204 | If[(y==0) || (z==0), Return[{1,1,0}]]; | |
205 | m = Mod[3 x^2 + a Mod[Mod[z^2,p]^2,p],p]; | |
206 | z = Mod[2 y z, p]; | |
207 | y2 = Mod[y^2,p]; | |
208 | s = Mod[4 x y2,p]; | |
209 | x = Mod[m^2 - 2s,p]; | |
210 | y = Mod[m(s - x) - 8 y2^2,p]; | |
211 | Return[{x,y,z}]; | |
212 | ]; | |
213 | */ | |
214 | ||
215 | void | |
216 | ell_add_proj(point_proj pt0, point_proj pt1, giant a, giant p) | |
217 | /* pt0 := pt0 + pt1 on the curve. */ | |
218 | { | |
219 | giant x0 = pt0->x, y0 = pt0->y, z0 = pt0->z, | |
220 | x1 = pt1->x, y1 = pt1->y, z1 = pt1->z; | |
221 | ||
222 | if(isZero(z0)) { | |
223 | gtog(x1,x0); gtog(y1,y0); gtog(z1,z0); | |
224 | return; | |
225 | } | |
226 | if(isZero(z1)) return; | |
227 | gtog(x0, t1); gtog(y0,t2); gtog(z0, t3); | |
228 | gtog(x1, t4); gtog(y1, t5); | |
229 | if(!isone(z1)) { | |
230 | gtog(z1, t6); | |
231 | gtog(t6, t7); squareg(t7); modg(p, t7); | |
232 | mulg(t7, t1); modg(p, t1); | |
233 | mulg(t6, t7); modg(p, t7); | |
234 | mulg(t7, t2); modg(p, t2); | |
235 | } | |
236 | gtog(t3, t7); squareg(t7); modg(p, t7); | |
237 | mulg(t7, t4); modg(p, t4); | |
238 | mulg(t3, t7); modg(p, t7); | |
239 | mulg(t7, t5); modg(p, t5); | |
240 | negg(t4); addg(t1, t4); modg(p, t4); | |
241 | negg(t5); addg(t2, t5); modg(p, t5); | |
242 | if(isZero(t4)) { | |
243 | if(isZero(t5)) { | |
244 | ell_double_proj(pt0, a, p); | |
245 | } else { | |
246 | itog(1, x0); itog(1, y0); itog(0, z0); | |
247 | } | |
248 | return; | |
249 | } | |
250 | addg(t1, t1); subg(t4, t1); modg(p, t1); | |
251 | addg(t2, t2); subg(t5, t2); modg(p, t2); | |
252 | if(!isone(z1)) { | |
253 | mulg(t6, t3); modg(p, t3); | |
254 | } | |
255 | mulg(t4, t3); modg(p, t3); | |
256 | gtog(t4, t7); squareg(t7); modg(p, t7); | |
257 | mulg(t7, t4); modg(p, t4); | |
258 | mulg(t1, t7); modg(p, t7); | |
259 | gtog(t5, t1); squareg(t1); modg(p, t1); | |
260 | subg(t7, t1); modg(p, t1); | |
261 | subg(t1, t7); subg(t1, t7); modg(p, t7); | |
262 | mulg(t7, t5); modg(p, t5); | |
263 | mulg(t2, t4); modg(p, t4); | |
264 | gtog(t5, t2); subg(t4,t2); modg(p, t2); | |
265 | if(t2->n[0] & 1) { /* Test if t2 is odd. */ | |
266 | addg(p, t2); | |
267 | } | |
268 | gshiftright(1, t2); | |
269 | gtog(t1, x0); gtog(t2, y0); gtog(t3, z0); | |
270 | } | |
271 | ||
272 | /* | |
273 | elladd[pt0_, pt1_] := Block[ | |
274 | {x0,y0,z0,x1,y1,z1, | |
275 | t1,t2,t3,t4,t5,t6,t7}, | |
276 | x0 = pt0[[1]]; y0 = pt0[[2]]; z0 = pt0[[3]]; | |
277 | x1 = pt1[[1]]; y1 = pt1[[2]]; z1 = pt1[[3]]; | |
278 | If[z0 == 0, Return[pt1]]; | |
279 | If[z1 == 0, Return[pt0]]; | |
280 | ||
281 | t1 = x0; | |
282 | t2 = y0; | |
283 | t3 = z0; | |
284 | t4 = x1; | |
285 | t5 = y1; | |
286 | If[(z1 != 1), | |
287 | t6 = z1; | |
288 | t7 = Mod[t6^2, p]; | |
289 | t1 = Mod[t1 t7, p]; | |
290 | t7 = Mod[t6 t7, p]; | |
291 | t2 = Mod[t2 t7, p]; | |
292 | ]; | |
293 | t7 = Mod[t3^2, p]; | |
294 | t4 = Mod[t4 t7, p]; | |
295 | t7 = Mod[t3 t7, p]; | |
296 | t5 = Mod[t5 t7, p]; | |
297 | t4 = Mod[t1-t4, p]; | |
298 | t5 = Mod[t2 - t5, p]; | |
299 | If[t4 == 0, If[t5 == 0, | |
300 | Return[elldouble[pt0]], | |
301 | Return[{1,1,0}] | |
302 | ] | |
303 | ]; | |
304 | t1 = Mod[2t1 - t4,p]; | |
305 | t2 = Mod[2t2 - t5, p]; | |
306 | If[z1 != 1, t3 = Mod[t3 t6, p]]; | |
307 | t3 = Mod[t3 t4, p]; | |
308 | t7 = Mod[t4^2, p]; | |
309 | t4 = Mod[t4 t7, p]; | |
310 | t7 = Mod[t1 t7, p]; | |
311 | t1 = Mod[t5^2, p]; | |
312 | t1 = Mod[t1-t7, p]; | |
313 | t7 = Mod[t7 - 2t1, p]; | |
314 | t5 = Mod[t5 t7, p]; | |
315 | t4 = Mod[t2 t4, p]; | |
316 | t2 = Mod[t5-t4, p]; | |
317 | If[EvenQ[t2], t2 = t2/2, t2 = (p+t2)/2]; | |
318 | Return[{t1, t2, t3}]; | |
319 | ]; | |
320 | */ | |
321 | ||
322 | void | |
323 | ell_neg_proj(point_proj pt, giant p) | |
324 | /* pt := -pt on the curve. */ | |
325 | { | |
326 | negg(pt->y); modg(p, pt->y); | |
327 | } | |
328 | ||
329 | void | |
330 | ell_sub_proj(point_proj pt0, point_proj pt1, giant a, giant p) | |
331 | /* pt0 := pt0 - pt1 on the curve. */ | |
332 | { | |
333 | ell_neg_proj(pt1, p); | |
334 | ell_add_proj(pt0, pt1,a,p); | |
335 | ell_neg_proj(pt1,p); | |
336 | } | |
337 | ||
338 | void | |
339 | ell_mul_proj(point_proj pt0, point_proj pt1, giant k, giant a, giant p) | |
340 | /* General elliptic multiplication; | |
341 | pt1 := k*pt0 on the curve, | |
342 | with k an arbitrary integer. | |
343 | */ | |
344 | { | |
345 | giant x = pt0->x, y = pt0->y, z = pt0->z, | |
346 | xx = pt1->x, yy = pt1->y, zz = pt1->z; | |
347 | int ksign, hlen, klen, b, hb, kb; | |
348 | ||
349 | if(isZero(k)) { | |
350 | itog(1, xx); | |
351 | itog(1, yy); | |
352 | itog(0, zz); | |
353 | return; | |
354 | } | |
355 | ksign = k->sign; | |
356 | if(ksign < 0) negg(k); | |
357 | gtog(x,xx); gtog(y,yy); gtog(z,zz); | |
358 | gtog(k, t0); addg(t0, t0); addg(k, t0); /* t0 := 3k. */ | |
359 | hlen = bitlen(t0); | |
360 | klen = bitlen(k); | |
361 | for(b = hlen-2; b > 0; b--) { | |
362 | ell_double_proj(pt1,a,p); | |
363 | hb = bitval(t0, b); | |
364 | if(b < klen) kb = bitval(k, b); else kb = 0; | |
365 | if((hb != 0) && (kb == 0)) | |
366 | ell_add_proj(pt1, pt0, a, p); | |
367 | else if((hb == 0) && (kb !=0)) | |
368 | ell_sub_proj(pt1, pt0, a, p); | |
369 | } | |
370 | if(ksign < 0) { | |
371 | ell_neg_proj(pt1, p); | |
372 | k->sign = -k->sign; | |
373 | } | |
374 | } | |
375 | ||
376 | /* | |
377 | elliptic[pt_, k_] := Block[{pt2, hh, kk, hb, kb, lenh, lenk}, | |
378 | If[k==0, Return[{1,1,0}]]; | |
379 | hh = Reverse[bitList[3k]]; | |
380 | kk = Reverse[bitList[k]]; | |
381 | pt2 = pt; | |
382 | lenh = Length[hh]; | |
383 | lenk = Length[kk]; | |
384 | Do[ | |
385 | pt2 = elldouble[pt2]; | |
386 | hb = hh[[b]]; | |
387 | If[b <= lenk, kb = kk[[b]], kb = 0]; | |
388 | If[{hb,kb} == {1,0}, | |
389 | pt2 = elladd[pt2, pt], | |
390 | If[{hb, kb} == {0,1}, | |
391 | pt2 = ellsub[pt2, pt]] | |
392 | ] | |
393 | ,{b, lenh-1, 2,-1} | |
394 | ]; | |
395 | Return[pt2]; | |
396 | ]; | |
397 | */ | |
398 | ||
399 | void | |
400 | normalize_proj(point_proj pt, giant p) | |
401 | /* Obtain actual x,y coords via normalization: | |
402 | {x,y,z} := {x/z^2, y/z^3, 1}. | |
403 | */ | |
404 | ||
405 | { giant x = pt->x, y = pt->y, z = pt->z; | |
406 | ||
407 | if(isZero(z)) { | |
408 | itog(1,x); itog(1,y); | |
409 | return; | |
410 | } | |
411 | binvaux(p, z); gtog(z, t1); | |
412 | squareg(z); modg(p, z); | |
413 | mulg(z, x); modg(p, x); | |
414 | mulg(t1, z); mulg(z, y); modg(p, y); | |
415 | itog(1, z); | |
416 | } | |
417 | ||
418 | /* | |
419 | normalize[pt_] := Block[{z,z2,z3}, | |
420 | If[pt[[3]] == 0, Return[pt]]; | |
421 | z = ellinv[pt[[3]]]; | |
422 | z2 = Mod[z^2,p]; | |
423 | z3 = Mod[z z2,p]; | |
424 | Return[{Mod[pt[[1]] z2, p], Mod[pt[[2]] z3, p], 1}]; | |
425 | ]; | |
426 | */ | |
427 | ||
428 | ||
429 | void | |
430 | find_point_proj(point_proj pt, giant seed, giant a, giant b, giant p) | |
431 | /* Starting with seed, finds a random (projective) point {x,y,1} on curve. | |
432 | */ | |
433 | { giant x = pt->x, y = pt->y, z = pt->z; | |
434 | ||
435 | modg(p, seed); | |
436 | while(1) { | |
437 | gtog(seed, x); | |
438 | squareg(x); modg(p, x); | |
439 | addg(a, x); | |
440 | mulg(seed,x); addg(b, x); | |
441 | modg(p, x); /* x := seed^3 + a seed + b. */ | |
442 | if(sqrtmod(p, x)) break; /* Test if cubic form has root. */ | |
443 | iaddg(1, seed); | |
444 | } | |
445 | gtog(x, y); | |
446 | gtog(seed,x); | |
447 | itog(1, z); | |
448 | } |