void reverse_subg(giant a, giant b) /* b := a - b; requires b, a non-negative and a >= b. */ { int j, size = a->sign; unsigned int k; k = 0; for (j = 0; j < b->sign; ++j) { k += 0xffff - b->n[j] + a->n[j]; b->n[j] = (unsigned short)(k & 0xffff); k >>= 16; } for (j = b->sign; j < size; ++j) { k += 0xffff + a->n[j]; b->n[j] = (unsigned short)(k & 0xffff); k >>= 16; } b->sign = size; /* REC, 21 Apr 1996. */ if (b->n[0] == 0xffff) iaddg(1, b); else ++b->n[0]; while (!b->n[--size]); b->sign = size + 1; }
/* * Completely rewritten in CryptKit-18, 13 Jan 1997, for new IEEE-style * curveParameters. */ int which_curve(giant x, curveParams *par) /* Returns (+-1) depending on whether x is on curve (+-)y^2 = x^3 + c x^2 + a x + b. */ { giant t1; giant t2; giant t3; int result; PROF_START; t1 = borrowGiant(par->maxDigits); t2 = borrowGiant(par->maxDigits); t3 = borrowGiant(par->maxDigits); /* First, set t2:= x^3 + c x^2 + a x + b. */ gtog(x, t2); addg(par->c, t2); mulg(x, t2); addg(par->a, t2); /* t2 := x^2 + c x + a. */ feemod(par, t2); mulg(x, t2); addg(par->b, t2); feemod(par, t2); /* Next, test whether t2 is a square. */ gtog(t2, t1); make_base(par, t3); iaddg(1, t3); gshiftright(1, t3); /* t3 = (p+1)/2. */ feepowermodg(par, t1, t3); /* t1 := t2^((p+1)/2) (mod p). */ if(gcompg(t1, t2) == 0) result = CURVE_PLUS; else result = CURVE_MINUS; returnGiant(t1); returnGiant(t2); returnGiant(t3); PROF_END(whichCurveTime); return result; }
void normal_subg(giant a, giant b) /* b := b - a; requires b, a non-negative and b >= a. */ { int j, size = b->sign; unsigned int k; if (a->sign == 0) return; k = 0; for (j = 0; j < a->sign; ++j) { k += 0xffff - a->n[j] + b->n[j]; b->n[j] = (unsigned short)(k & 0xffff); k >>= 16; } for (j = a->sign; j < size; ++j) { k += 0xffff + b->n[j]; b->n[j] = (unsigned short)(k & 0xffff); k >>= 16; } if (b->n[0] == 0xffff) iaddg(1, b); else ++b->n[0]; while ((size-- > 0) && (b->n[size] == 0)); b->sign = (b->n[size] == 0) ? 0 : size + 1; }
main(int argc, char **argv) { giant p = newgiant(CM_SHORTS); giant u = newgiant(CM_SHORTS); giant v = newgiant(CM_SHORTS); giant g[6]; giant plus_order = newgiant(CM_SHORTS); giant minus_order = newgiant(CM_SHORTS); giant a = newgiant(CM_SHORTS); giant b = newgiant(CM_SHORTS); int d, dc, olen, k; init_tools(CM_SHORTS); /* Basic algorithms. */ printf("Give base prime p:\n"); fflush(stdout); gin(p); for(dc=0; dc < 6; dc++) g[dc] = newgiant(CM_SHORTS); for(dc = 0; dc < DCOUNT; dc++) { d = disc12[dc]; /* Next, seek representation 4N = u^2 + |d| v^2. */ if(cornacchia4(p, d, u, v) == 0) continue; /* Here, (u,v) give the quadratic representation of 4p. */ printf("D: %d\n", d); fflush(stdout); gtog(u, g[0]); switch(d) { case -3: olen = 3; /* Six orders: p + 1 +- g[0,1,2]. */ gtog(u, g[1]); gtog(v, g[2]); addg(g[2], g[2]); addg(v, g[2]); /* g[2] := 3v. */ addg(g[2], g[1]); gshiftright(1, g[1]); /* g[1] = (u + 3v)/2. */ subg(u, g[2]); gshiftright(1, g[2]); absg(g[2]); /* g[2] = |u-3v|/2. */ break; case -4: olen = 2; /* Four orders: p + 1 +- g[0,1]. */ gtog(v, g[1]); addg(g[1], g[1]); /* g[1] = 2v. */ break; default: olen = 1; /* Two orders: p + 1 +- g[0]. */ } for(k=0; k < olen; k++) { gtog(p, plus_order); iaddg(1, plus_order); gtog(p, minus_order); iaddg(1, minus_order); addg(g[k], plus_order); subg(g[k], minus_order); printf("curve orders: \n"); printf("(%d) ", prime_probable(plus_order)); gout(plus_order); printf("(%d) ", prime_probable(minus_order)); gout(minus_order); } } }
/* * New optimzation of curveOrderJustify using known reciprocal, 11 June 1997. * g is set to be within [2, curveOrder-2]. */ static void curveOrderJustifyWithRecip(giant g, giant curveOrder, giant recip) { giant tmp; CKASSERT(!isZero(curveOrder)); modg_via_recip(curveOrder, recip, g); // g now in [0, curveOrder-1] if(isZero(g)) { /* * First degenerate case - (g == 0) : set g := 2 */ dbgLog(("curveOrderJustify: case 1\n")); int_to_giant(2, g); return; } if(isone(g)) { /* * Second case - (g == 1) : set g := 2 */ dbgLog(("curveOrderJustify: case 2\n")); int_to_giant(2, g); return; } tmp = borrowGiant(g->capacity); gtog(g, tmp); iaddg(1, tmp); if(gcompg(tmp, curveOrder) == 0) { /* * Third degenerate case - (g == (curveOrder-1)) : set g -= 1 */ dbgLog(("curveOrderJustify: case 3\n")); int_to_giant(1, tmp); subg(tmp, g); } returnGiant(tmp); return; }
void findPointProj(pointProj pt, giant seed, curveParams *cp) /* Starting with seed, finds a random (projective) point {x,y,1} on curve. */ { giant x = pt->x, y = pt->y, z = pt->z; CKASSERT(cp->curveType == FCT_Weierstrass); feemod(cp, seed); while(1) { gtog(seed, x); gsquare(x); feemod(cp, x); // x := seed^2 addg(cp->a, x); // x := seed^2 + a mulg(seed,x); // x := seed^3 + a*seed addg(cp->b, x); feemod(cp, x); // x := seed^3 + a seed + b. /* test cubic form for having root. */ if(sqrtmod(x, cp)) break; iaddg(1, seed); } gtog(x, y); gtog(seed,x); int_to_giant(1, z); }
void main( void ) { giant x = newgiant(INFINITY), y = newgiant(INFINITY), p = newgiant(INFINITY), r = newgiant(100); int j; printf("Give two integers x, y on separate lines:\n"); gin(x); gin(y); gtog(y, p); /* p := y */ mulg(x, p); printf("y * x = "); gout(p); gtog(y, p); subg(x, p); printf("y - x = "); gout(p); gtog(y, p); addg(x, p); printf("y + x = "); gout(p); gtog(y, p); divg(x, p); printf("y div x = "); gout(p); gtog(y, p); modg(x, p); printf("y mod x = "); gout(p); gtog(y, p); gcdg(x, p); printf("GCD(x, y) = "); gout(p); /* Next, test which of x, y is greater. */ if (gcompg(x, y) < 0 ) printf("y is greater\n"); else if (gcompg(x,y) == 0) printf("x, y equal\n"); else printf("x is greater\n"); /* Next, we see how a giant struct is comprised. * We make a random, bipolar number of about 100 * digits in base 65536. */ for (j=0; j < 100; j++) { /* Fill 100 digits randomly. */ r->n[j] = (unsigned short)rand(); } r->sign = 100 * (1 - 2*(rand()%2)); /* Next, don't forget to check for leading zero digits, * even though such are unlikely. */ j = abs(r->sign) - 1; while ((r->n[j] == 0) && (j > 0)) { --j; } r->sign = (j+1) * ((r->sign > 0) ? 1: -1); printf("The random number: "); gout(r); /* Next, compare a large-FFT multiply with a standard, * grammar-school multiply. */ itog(1, x); gshiftleft(65536, x); iaddg(1, x); itog(5, y); gshiftleft(30000, y); itog(1, p); subg(p, y); /* Now we multiply (2^65536 + 1)*(5*(2^30000) - 1). */ gtog(y, p); mulg(x, p); /* Actually invokes FFT method because bit lengths of x, y are sufficiently large. */ printf("High digit of (2^65536 + 1)*(5*(2^30000) - 1) via FFT mul: %d\n", (int) p->n[abs(p->sign)-1]); fflush(stdout); gtog(y, p); grammarmulg(x, p); /* Grammar-school method. */ printf("High digit via grammar-school mul: %d\n", (int) p->n[abs(p->sign)-1]); fflush(stdout); /* Next, perform Fermat test for pseudoprimality. */ printf("Give prime candidate p:\n"); gin(p); gtog(p, y); itog(1, x); subg(x, y); itog(2, x); powermodg(x, y, p); if (isone(x)) printf("p is probably prime.\n"); else printf("p is composite.\n"); }
static int sqrtmod(giant x, curveParams *cp) /* If Sqrt[x] (mod p) exists, function returns 1, else 0. In either case x is modified, but if 1 is returned, x:= Sqrt[x] (mod p). */ { int rtn; giant t0 = borrowGiant(cp->maxDigits); giant t1 = borrowGiant(cp->maxDigits); giant t2 = borrowGiant(cp->maxDigits); giant t3 = borrowGiant(cp->maxDigits); giant t4 = borrowGiant(cp->maxDigits); giant p = cp->basePrime; feemod(cp, x); /* Justify the argument. */ gtog(x, t0); /* Store x for eventual validity check on square root. */ if((p->n[0] & 3) == 3) { /* The case p = 3 (mod 4). */ gtog(p, t1); iaddg(1, t1); gshiftright(2, t1); powermodg(x, t1, cp); goto resolve; } /* Next, handle case p = 5 (mod 8). */ if((p->n[0] & 7) == 5) { gtog(p, t1); int_to_giant(1, t2); subg(t2, t1); gshiftright(2, t1); gtog(x, t2); powermodg(t2, t1, cp); /* t2 := x^((p-1)/4) % p. */ iaddg(1, t1); gshiftright(1, t1); /* t1 := (p+3)/8. */ if(isone(t2)) { powermodg(x, t1, cp); /* x^((p+3)/8) is root. */ goto resolve; } else { int_to_giant(1, t2); subg(t2, t1); /* t1 := (p-5)/8. */ gshiftleft(2,x); powermodg(x, t1, cp); mulg(t0, x); addg(x, x); feemod(cp, x); /* 2x (4x)^((p-5)/8. */ goto resolve; } } /* Next, handle tougher case: p = 1 (mod 8). */ int_to_giant(2, t1); while(1) { /* Find appropriate nonresidue. */ gtog(t1, t2); gsquare(t2); subg(x, t2); feemod(cp, t2); if(jacobi_symbol(t2, cp) == -1) break; iaddg(1, t1); } /* t2 is now w^2 in F_p^2. */ int_to_giant(1, t3); gtog(p, t4); iaddg(1, t4); gshiftright(1, t4); powFp2(t1, t3, t2, t4, cp); gtog(t1, x); resolve: gtog(x,t1); gsquare(t1); feemod(cp, t1); if(gcompg(t0, t1) == 0) { rtn = 1; /* Success. */ } else { rtn = 0; /* no square root */ } returnGiant(t0); returnGiant(t1); returnGiant(t2); returnGiant(t3); returnGiant(t4); return rtn; }
/* * Completely rewritten in CryptKit-18, 13 Jan 1997, for new IEEE-style * curveParameters. */ void elliptic_add(giant x1, giant x2, giant x3, curveParams *par, int s) { /* Addition algorithm for x3 = x1 + x2 on the curve, with sign ambiguity s. From theory, we know that if {x1,1} and {x2,1} are on a curve, then their elliptic sum (x1,1} + {x2,1} = {x3,1} must have x3 as one of two values: x3 = U/2 + s*Sqrt[U^2/4 - V] where sign s = +-1, and U,V are functions of x1,x2. Tho present function is called a maximum of twice, to settle which of +- is s. When a call is made, it is guaranteed already that x1, x2 both lie on the same curve (+- curve); i.e., which curve (+-) is not connected at all with sign s of the x3 relation. */ giant cur_n; giant t1; giant t2; giant t3; giant t4; giant t5; PROF_START; cur_n = borrowGiant(par->maxDigits); t1 = borrowGiant(par->maxDigits); t2 = borrowGiant(par->maxDigits); t3 = borrowGiant(par->maxDigits); t4 = borrowGiant(par->maxDigits); t5 = borrowGiant(par->maxDigits); if(gcompg(x1, x2)==0) { int_to_giant(1, t1); numer_double(x1, t1, x3, par); denom_double(x1, t1, t2, par); binvg_cp(par, t2); mulg(t2, x3); feemod(par, x3); goto out; } numer_plus(x1, x2, t1, par); int_to_giant(1, t3); numer_times(x1, t3, x2, t3, t2, par); int_to_giant(1, t4); int_to_giant(1, t5); denom_times(x1, t4, x2, t5, t3, par); binvg_cp(par, t3); mulg(t3, t1); feemod(par, t1); /* t1 := U/2. */ mulg(t3, t2); feemod(par, t2); /* t2 := V. */ /* Now x3 will be t1 +- Sqrt[t1^2 - t2]. */ gtog(t1, t4); gsquare(t4); feemod(par, t4); subg(t2, t4); make_base(par, cur_n); iaddg(1, cur_n); gshiftright(2, cur_n); /* cur_n := (p+1)/4. */ feepowermodg(par, t4, cur_n); /* t4 := t2^((p+1)/4) (mod p). */ gtog(t1, x3); if(s != SIGN_PLUS) negg(t4); addg(t4, x3); feemod(par, x3); out: returnGiant(cur_n); returnGiant(t1); returnGiant(t2); returnGiant(t3); returnGiant(t4); returnGiant(t5); PROF_END(ellAddTime); }