void gmersennemod( int n, giant g ) /* g := g (mod 2^n - 1) */ { int the_sign; giant scratch3 = borrowGiant(g->capacity); giant scratch4 = borrowGiant(1); if ((the_sign = gsign(g)) < 0) absg(g); while (bitlen(g) > n) { gtog(g,scratch3); gshiftright(n,scratch3); addg(scratch3,g); gshiftleft(n,scratch3); subg(scratch3,g); } if(isZero(g)) goto out; int_to_giant(1,scratch3); gshiftleft(n,scratch3); int_to_giant(1,scratch4); subg(scratch4,scratch3); if(gcompg(g,scratch3) >= 0) subg(scratch3,g); if (the_sign < 0) { g->sign = -g->sign; addg(scratch3,g); } out: returnGiant(scratch3); returnGiant(scratch4); }
static void numer_plus(giant x1, giant x2, giant res, curveParams *par) /* Numerator algebra. res = (x1 x2 + a)(x1 + x2) + 2(c x1 x2 + b). */ { giant t1; giant t2; PROF_START; t1 = borrowGiant(par->maxDigits); t2 = borrowGiant(par->maxDigits); gtog(x1, t1); mulg(x2, t1); feemod(par, t1); gtog(x2, t2); addg(x1, t2); feemod(par, t2); gtog(t1, res); if(!isZero(par->a)) addg(par->a, res); mulg(t2, res); feemod(par, res); if(par->curveType == FCT_Weierstrass) { // i.e., isZero(par->c) int_to_giant(0, t1); } else { mulg(par->c, t1); feemod(par, t1); } if(!isZero(par->b)) addg(par->b, t1); gshiftleft(1, t1); addg(t1, res); feemod(par, res); returnGiant(t1); returnGiant(t2); PROF_END(numerPlusTime); }
void make_recip(giant d, giant r) /* r becomes the steady-state reciprocal * 2^(2b)/d, where b = bit-length of d-1. */ { int b; giant tmp, tmp2; if (isZero(d) || (d->sign < 0)) { exit(SIGN); } tmp = popg(); tmp2 = popg(); itog(1, r); subg(r, d); b = bitlen(d); addg(r, d); gshiftleft(b, r); gtog(r, tmp2); while (1) { gtog(r, tmp); squareg(tmp); gshiftright(b, tmp); mulg(d, tmp); gshiftright(b, tmp); addg(r, r); subg(tmp, r); if (gcompg(r, tmp2) <= 0) break; gtog(r, tmp2); } itog(1, tmp); gshiftleft(2 * b, tmp); gtog(r, tmp2); mulg(d, tmp2); subg(tmp2, tmp); itog(1, tmp2); while (tmp->sign < 0) { subg(tmp2, r); addg(d, tmp); } pushg(2); }
void ellDoubleProj(pointProj pt, curveParams *cp) /* pt := 2 pt on the curve. */ { giant x = pt->x, y = pt->y, z = pt->z; giant t1; giant t2; giant t3; if(isZero(y) || isZero(z)) { int_to_giant(1,x); int_to_giant(1,y); int_to_giant(0,z); return; } t1 = borrowGiant(cp->maxDigits); t2 = borrowGiant(cp->maxDigits); t3 = borrowGiant(cp->maxDigits); if((cp->a->sign >= 0) || (cp->a->n[0] != 3)) { /* Path prior to Apr2001. */ gtog(z,t1); gsquare(t1); feemod(cp, t1); gsquare(t1); feemod(cp, t1); mulg(cp->a, t1); feemod(cp, t1); /* t1 := a z^4. */ gtog(x, t2); gsquare(t2); feemod(cp, t2); smulg(3, t2); /* t2 := 3x^2. */ addg(t2, t1); feemod(cp, t1); /* t1 := slope m. */ } else { /* New optimization for a = -3 (post Apr 2001). */ gtog(z, t1); gsquare(t1); feemod(cp, t1); /* t1 := z^2. */ gtog(x, t2); subg(t1, t2); /* t2 := x-z^2. */ addg(x, t1); smulg(3, t1); /* t1 := 3(x+z^2). */ mulg(t2, t1); feemod(cp, t1); /* t1 := slope m. */ } mulg(y, z); addg(z,z); feemod(cp, z); /* z := 2 y z. */ gtog(y, t2); gsquare(t2); feemod(cp, t2); /* t2 := y^2. */ gtog(t2, t3); gsquare(t3); feemod(cp, t3); /* t3 := y^4. */ gshiftleft(3, t3); /* t3 := 8 y^4. */ mulg(x, t2); gshiftleft(2, t2); feemod(cp, t2); /* t2 := 4xy^2. */ gtog(t1, x); gsquare(x); feemod(cp, x); subg(t2, x); subg(t2, x); feemod(cp, x); /* x done. */ gtog(t1, y); subg(x, t2); mulg(t2, y); subg(t3, y); feemod(cp, y); returnGiant(t1); returnGiant(t2); returnGiant(t3); }
void make_base_prim(curveParams *cp) /* Jams cp->basePrime with 2^q-k. Assumes valid maxDigits, q, k. */ { giant tmp = borrowGiant(cp->maxDigits); CKASSERT(cp->primeType != FPT_General); int_to_giant(1, cp->basePrime); gshiftleft((int)cp->q, cp->basePrime); int_to_giant(cp->k, tmp); subg(tmp, cp->basePrime); returnGiant(tmp); }
static void bdivg(giant v, giant u) /* u becomes greatest power of two not exceeding u/v. */ { int diff = bitlen(u) - bitlen(v); giant scratch7; if (diff<0) { int_to_giant(0,u); return; } scratch7 = borrowGiant(u->capacity); gtog(v, scratch7); gshiftleft(diff,scratch7); if(gcompg(u,scratch7) < 0) diff--; if(diff<0) { int_to_giant(0,u); returnGiant(scratch7); return; } int_to_giant(1,u); gshiftleft(diff,u); returnGiant(scratch7); }
static void numer_times(giant x1, giant z1, giant x2, giant z2, giant res, curveParams *par) /* Numerator algebra. res := (x1 x2 - a z1 z2)^2 - 4 b(x1 z2 + x2 z1 + c z1 z2) z1 z2 */ { giant t1; giant t2; giant t3; giant t4; PROF_START; t1 = borrowGiant(par->maxDigits); t2 = borrowGiant(par->maxDigits); t3 = borrowGiant(par->maxDigits); t4 = borrowGiant(par->maxDigits); gtog(x1, t1); mulg(x2, t1); feemod(par, t1); gtog(z1, t2); mulg(z2, t2); feemod(par, t2); gtog(t1, res); if(!isZero(par->a)) { gtog(par->a, t3); mulg(t2, t3); feemod(par, t3); subg(t3, res); } gsquare(res); feemod(par, res); if(isZero(par->b)) goto done; if(par->curveType != FCT_Weierstrass) { // i.e., !isZero(par->c) gtog(par->c, t3); mulg(t2, t3); feemod(par, t3); } else int_to_giant(0, t3); gtog(z1, t4); mulg(x2, t4); feemod(par, t4); addg(t4, t3); gtog(x1, t4); mulg(z2, t4); feemod(par, t4); addg(t4, t3); mulg(par->b, t3); feemod(par, t3); mulg(t2, t3); gshiftleft(2, t3); feemod(par, t3); subg(t3, res); feemod(par, res); done: returnGiant(t1); returnGiant(t2); returnGiant(t3); returnGiant(t4); PROF_END(numerTimesTime); }
int signature_compare(giant p0x, giant p1x, giant p2x, curveParams *par) /* Returns non-zero iff p0x cannot be the x-coordinate of the sum of two points whose respective x-coordinates are p1x, p2x. */ { int ret = 0; giant t1; giant t2; giant t3; giant t4; giant t5; PROF_START; t1 = borrowGiant(par->maxDigits); t2 = borrowGiant(par->maxDigits); t3 = borrowGiant(par->maxDigits); t4 = borrowGiant(par->maxDigits); t5 = borrowGiant(par->maxDigits); if(gcompg(p1x, p2x) == 0) { int_to_giant(1, t1); numer_double(p1x, t1, t2, par); denom_double(p1x, t1, t3, par); mulg(p0x, t3); subg(t3, t2); feemod(par, t2); } else { numer_plus(p1x, p2x, t1, par); gshiftleft(1, t1); feemod(par, t1); int_to_giant(1, t3); numer_times(p1x, t3, p2x, t3, t2, par); int_to_giant(1, t4); int_to_giant(1, t5); denom_times(p1x, t4 , p2x, t5, t3, par); /* Now we require t3 x0^2 - t1 x0 + t2 == 0. */ mulg(p0x, t3); feemod(par, t3); subg(t1, t3); mulg(p0x, t3); feemod(par, t3); addg(t3, t2); feemod(par, t2); } if(!isZero(t2)) ret = SIGNATURE_INVALID; returnGiant(t1); returnGiant(t2); returnGiant(t3); returnGiant(t4); returnGiant(t5); PROF_END(sigCompTime); return(ret); }
void gshiftright(int bits, giant g) /* shift g right bits bits. Equivalent to g = g/2^bits. */ { register int j, size = abs(g->sign); register unsigned int carry; int words = bits >> 4; int remain = bits & 15, cremain = (16 - remain); if (bits == 0) return; if (isZero(g)) return; if (bits < 0) { gshiftleft(-bits, g); return; } if (words >= size) { g->sign = 0; return; } if (remain == 0) { memmove(g->n, g->n + words, (size - words) * sizeof(short)); g->sign += (g->sign < 0) ? (words) : (-words); } else { size -= words; if (size) { for (j = 0;j < size - 1;++j) { carry = g->n[j + words + 1] << cremain; g->n[j] = (unsigned short)((g->n[j + words] >> remain) | carry); } g->n[size - 1] = (unsigned short)(g->n[size - 1 + words] >> remain); } if (g->n[size - 1] == 0) --size; if (g->sign > 0) g->sign = size; else g->sign = -size; } }
static void numer_double(giant x, giant z, giant res, curveParams *par) /* Numerator algebra. res := (x^2 - a z^2)^2 - 4 b (2 x + c z) z^3. */ { giant t1; giant t2; PROF_START; t1 = borrowGiant(par->maxDigits); t2 = borrowGiant(par->maxDigits); gtog(x, t1); gsquare(t1); feemod(par, t1); gtog(z, res); gsquare(res); feemod(par, res); gtog(res, t2); if(!isZero(par->a) ) { if(!isone(par->a)) { /* Speedup - REC 17 Jan 1997. */ mulg(par->a, res); feemod(par, res); } subg(res, t1); feemod(par, t1); } gsquare(t1); feemod(par, t1); /* t1 := (x^2 - a z^2)^2. */ if(isZero(par->b)) { /* Speedup - REC 17 Jan 1997. */ gtog(t1, res); goto done; } if(par->curveType != FCT_Weierstrass) { // i.e., !isZero(par->c) // Speedup - REC 17 Jan 1997. gtog(z, res); mulg(par->c, res); feemod(par, res); } else { int_to_giant(0, res); } addg(x, res); addg(x, res); mulg(par->b, res); feemod(par, res); gshiftleft(2, res); mulg(z, res); feemod(par, res); mulg(t2, res); feemod(par, res); negg(res); addg(t1, res); feemod(par, res); done: returnGiant(t1); returnGiant(t2); PROF_END(numerDoubleTime); }
static void denom_double(giant x, giant z, giant res, curveParams *par) /* Denominator algebra. res = 4 z (x^3 + c x^2 z + a x z^2 + b z^3). */ { giant t1; giant t2; PROF_START; t1 = borrowGiant(par->maxDigits); t2 = borrowGiant(par->maxDigits); gtog(x, res); gtog(z, t1); if(par->curveType != FCT_Weierstrass) { // i.e., !isZero(par->c) gtog(par->c, t2); mulg(t1, t2); feemod(par, t2); addg(t2, res); } mulg(x, res); feemod(par, res); gsquare(t1); feemod(par, t1); if(!isZero(par->a)) { gtog(t1, t2); mulg(par->a, t2); feemod(par, t2); addg(t2, res); } mulg(x, res); feemod(par, res); if(!isZero(par->b)) { mulg(z, t1); feemod(par, t1); mulg(par->b, t1); feemod(par, t1); addg(t1, res); } mulg(z, res); gshiftleft(2, res); feemod(par, res); returnGiant(t1); returnGiant(t2); PROF_END(denomDoubleTime); }
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; }
static void ell_even(giant x1, giant z1, giant x2, giant z2, curveParams *par) { giant t1; giant t2; giant t3; EPROF_START; t1 = borrowGiant(par->maxDigits); t2 = borrowGiant(par->maxDigits); t3 = borrowGiant(par->maxDigits); if(par->curveType == FCT_Montgomery) { /* Begin Montgomery OPT: 10 Jan 98 REC. */ gtog(x1, t1); gsquare(t1); feemod(par, t1); /* t1 := x1^2. */ gtog(z1, t2); gsquare(t2); feemod(par, t2); /* t2 := z1^2. */ gtog(x1, t3); mulg(z1, t3); feemod(par, t3); gtog(t3, z2); mulg(par->c, z2); feemod(par, z2); addg(t1, z2); addg(t2, z2); mulg(t3, z2); gshiftleft(2, z2); feemod(par, z2); /* z2 := 4 x1 z1 (x1^2 + c x1 z1 + z1^2). */ gtog(t1, x2); subg(t2, x2); gsquare(x2); feemod(par, x2); /* x2 := (x1^2 - z1^2)^2. */ /* End OPT: 10 Jan 98 REC. */ } else if((par->curveType == FCT_Weierstrass) && isZero(par->a)) { /* Begin Atkin3 OPT: 9 Jan 98 REC. */ gtog(x1, t1); gsquare(t1); feemod(par, t1); mulg(x1, t1); feemod(par, t1); /* t1 := x^3. */ gtog(z1, t2); gsquare(t2); feemod(par, t2); mulg(z1, t2); feemod(par, t2); /* t2 := z1^3 */ mulg(par->b, t2); feemod(par, t2); /* t2 := b z1^3. */ gtog(t1, t3); addg(t2, t3); /* t3 := x^3 + b z1^3 */ mulg(z1, t3); feemod(par, t3); /* t3 *= z1 * = z1 ( x^3 + b z1^3 ) */ gshiftleft(2, t3); feemod(par, t3); /* t3 = 4 z1 (x1^3 + b z1^3) */ gshiftleft(3, t2); /* t2 = 8 b z1^3 */ subg(t2, t1); /* t1 = x^3 - 8 b z1^3 */ mulg(x1, t1); feemod(par, t1); /* t1 = x1 (x1^3 - 8 b z1^3) */ gtog(t3, z2); gtog(t1, x2); /* End OPT: 9 Jan 98 REC. */ } else { numer_double(x1, z1, t1, par); denom_double(x1, z1, t2, par); gtog(t1, x2); gtog(t2, z2); } returnGiant(t1); returnGiant(t2); returnGiant(t3); EPROF_END(ellEvenTime); EPROF_INCR(numEllEvens); /* printf("ell_even end\n"); printf(" x1 : "); printGiant(x1); printf(" z1 : "); printGiant(z1); printf(" x2 : "); printGiant(x2); printf(" z2 : "); printGiant(z2); */ }