void encrypt(int msg/*To be extended to other types !*/){ // generate r between 0 and n-1 inclusive unsigned long int m = msg; gmp_randstate_t state; gmp_randinit_mt (state); // initiallize state with Mersenne Twister which is basically fast one ! mpz_urandomm(r, state, n); //66666666666666666666666666666666666 //mpz_init_set_str(r,"23",10); //6666666666666666666666666666666666 gmp_printf ("\nr = %Zd\n", r); mpz_powm_ui(tmpI, g/*base*/, m/*exp*/, nn/*mod*/); // tmp = base^exp modulo mod gmp_printf ("\ng^m = %Zd\n", tmpI); mpz_powm(tmpII, r/*base*/, n/*exp*/, nn/*mod*/); // tmp = base^exp modulo mod gmp_printf ("\nr^n = %Zd\n", tmpII); // Remember : a.b mod n = ((a mod n).(b mod n)) mod n mpz_mul(c, tmpI, tmpII); mpz_mod(c, c, nn); gmp_printf ("\nc = %Zd\n", c); }
static void zp_square(element_ptr c, element_ptr a) { /* mpz_mul(c->data, a->data, a->data); mpz_mod(c->data, c->data, c->field->order); */ mpz_powm_ui((mpz_ptr)c->data, (mpz_ptr)a->data, 2, c->field->order); /* const mpz_ptr prime = c->field->order; const size_t t = prime->_mp_size; const mpz_ptr p = a->data; const mpz_ptr r = c->data; mp_limb_t tmp[2 * t]; mp_limb_t qp[t + 1]; mpn_mul_n(tmp, p->_mp_d, p->_mp_d, t); mpn_tdiv_qr(qp, r->_mp_d, 0, tmp, 2 * t, prime->_mp_d, t); */ }
static int millerrabin (mpz_srcptr n, mpz_srcptr nm1, mpz_ptr x, mpz_ptr y, mpz_srcptr q, unsigned long int k) { unsigned long int i; mpz_powm (y, x, q, n); if (mpz_cmp_ui (y, 1L) == 0 || mpz_cmp (y, nm1) == 0) return 1; for (i = 1; i < k; i++) { mpz_powm_ui (y, y, 2L, n); if (mpz_cmp (y, nm1) == 0) return 1; if (mpz_cmp_ui (y, 1L) == 0) return 0; } return 0; }
void SRPCalcS(LPNLS nls, char *result) { mpz_t temp, s, v, a; mpz_init2(a, 256); mpz_init2(v, 256); mpz_init(temp); mpz_init(s); mpz_import(a, 32, -1, 1, 0, 0, nls->A); mpz_import(v, 32, -1, 1, 0, 0, nls->V); mpz_powm_ui(temp, v, SRPCalcU(nls->B), N); mpz_mul(temp, a, temp); mpz_powm(s, temp, nls->b_src, N); mpz_export(result, (size_t *)0, -1, 1, 0, 0, s); mpz_clear(temp); mpz_clear(s); mpz_clear(v); mpz_clear(a); }
string bbs(int N) { mpz_t A, B, r, n, tmp; mpz_init(tmp); mpz_init(n); mpz_init(r); mpz_init(A); mpz_init(B); mpz_set_str(A, "32372334488362947019304797379371153325410700999", 10); mpz_set_str(B, "541528607341564832259551", 10); mpz_mul(n, A, B); mpz_set_ui(r, rand() % 100000 + 1); string res; while (N) { mpz_powm_ui(r, r, 2, n); mpz_mod_ui(tmp, r, 2); res += to_string(mpz_get_ui(tmp)); N--; } return res; }
int miller_rabin_pass(mpz_t a, mpz_t n) { int i, s, result; mpz_t a_to_power, d, n_minus_one; mpz_init(n_minus_one); mpz_sub_ui(n_minus_one, n, 1); s = 0; mpz_init_set(d, n_minus_one); while (mpz_even_p(d)) { mpz_fdiv_q_2exp(d, d, 1); s++; } mpz_init(a_to_power); mpz_powm(a_to_power, a, d, n); if (mpz_cmp_ui(a_to_power, 1) == 0) { result=PROBABLE_PRIME; goto exit; } for(i=0; i < s-1; i++) { if (mpz_cmp(a_to_power, n_minus_one) == 0) { result=PROBABLE_PRIME; goto exit; } mpz_powm_ui (a_to_power, a_to_power, 2, n); } if (mpz_cmp(a_to_power, n_minus_one) == 0) { result=PROBABLE_PRIME; goto exit; } result = COMPOSITE; exit: mpz_clear(a_to_power); mpz_clear(d); mpz_clear(n_minus_one); return result; }
/* * isprime : is this number prime ? * this use the Miller-Rabin method. The algorithm can be found at Wikipedia * return 1 (yes) and 0 (no) */ int isprime(mpz_t p) { gmp_randstate_t st; /* random init stat */ mpz_t a, d, tmp, x; int i, ret, j; unsigned long s; ret = 1; /* * ensure that p is odd and greater than 3 */ if (mpz_cmp_ui(p, 3) <= 0 || !mpz_tstbit(p, 0)) return 0; /* * put p in the 2^s.d form */ mpz_init(d); mpz_sub_ui(d, p, 1); /* d = p-1 */ s = 0; do { s++; mpz_divexact_ui(d, d, 2); } while (mpz_divisible_ui_p(d, 2)); /* * now we have p as 2^s.d */ gmp_randinit_default(st); gmp_randseed_ui(st, time(NULL)); mpz_init(a); mpz_init(x); mpz_init(tmp); mpz_sub_ui(tmp, p, 1); /* tmp = p - 1 */ for (i = 0; i < ACCURACY; i++) { /* * generate a as 2 <= a <= n-2 */ do { mpz_urandomm(a, st, tmp); /* a will be between 0 and * tmp-1 * inclusive */ } while (mpz_cmp_ui(a, 2) < 0); mpz_powm(x, a, d, p); /* do x = a^d mod p */ /* * if x == 1 or x == p-1 */ if (!mpz_cmp_ui(x, 1) || !mpz_cmp(x, tmp)) continue; for (j = 1; j < s; j++) { mpz_powm_ui(x, x, 2, p); /* do x = x^2 mod p */ if (!mpz_cmp_ui(x, 1) || !mpz_cmp(x, tmp)) /* x == 1 */ break; } if (mpz_cmp(x, tmp) || !mpz_cmp_ui(x, 1)) { /* x != p-1 */ ret = 0; break; } } /* * Free Ressources */ gmp_randclear(st); mpz_clear(a); mpz_clear(d); mpz_clear(tmp); return ret; }
// get some bytes (taken from gmpbbs.c) void rndbbs_randbytes(PGM_CTX *pgm_ctx, char *retbuf, size_t nbytes) #define FUNC_NAME "rndbbs_randbytes" { char *urandom_buffer = NULL; RNDBBS *bbs; // pick up handy ptr bbs = &pgm_ctx->rndbbs; if ( bbs->xor_urandom ) { if ( (urandom_buffer = (char *) malloc(nbytes)) == NULL) { perror(FUNC_NAME ": malloc"); return; } { int i; int j; unsigned int r; r = nrand48(pgm_ctx->xsubi); for ( j = 0, i = 0 ; i < nbytes ; i++ ) { if ( j > 3 ) { j = 0; r = nrand48(pgm_ctx->xsubi); } urandom_buffer [ i ] = (unsigned char)r; r >>= 8; j += 1; } } #if 0 if ( _urandread(urandom_buffer, nbytes) != nbytes ) { perror(FUNC_NAME ": _urandread: continuting..."); bbs->xor_urandom = 0; } #endif } memset(retbuf, 0, nbytes); if (!bbs->improved) { /* basic implementation without improvements (only keep parity) */ { int i; for (i=0;i<nbytes;i++) { int j; /* we keep the parity (least significant bit) of each x_n */ for (j=7;j>=0;j--) { /* x[n+1] = x[n]^2 (mod blumint) */ mpz_powm_ui(bbs->x, bbs->x, 2, bbs->blumint); /* mpz_fdiv_ui(bbs->x, 2) == mpz_tstbit(bbs->x, 0) */ retbuf[i] |= (mpz_tstbit(bbs->x, 0) << j); } if (bbs->xor_urandom) retbuf[i] ^= urandom_buffer[i]; } if ( urandom_buffer != NULL ) free(urandom_buffer); return; } } else { /* improved implementation (keep log2(log2(blumint)) bits of x[i]) */ unsigned int loglogblum = log(1.0*bbs->key_bitlen)/log(2.0); unsigned int byte=0, bit=0, i; for (;;) { //printf("%s: calculating x[n+1], loglogblum = %d\n", //__FUNCTION__,loglogblum); /* x[n+1] = x[n]^2 (mod blumint) */ mpz_powm_ui(bbs->x, bbs->x, 2, bbs->blumint); for (i=0;i<loglogblum;i++) { if (byte == nbytes) { if ( urandom_buffer != NULL ) free(urandom_buffer); return; } /* get the ith bit of x */ retbuf[byte] |= (mpz_tstbit(bbs->x, i) << (7-bit) ); if (bit == 7) { if (bbs->xor_urandom) retbuf[byte] ^= urandom_buffer[byte]; byte++; bit=0; } else { bit++; } } } } }
/* See: * (1) Kaltofen, Valente, Yui 1989 * (2) Valente 1992 (Thesis) * (3) Konstantinou, Stamatiou, and Zaroliagis (CHES 2002) * This code is performing table 1 of reference 3. */ static void weber_root_to_hilbert_root(mpz_t r, mpz_t N, long D) { mpz_t A, t; if (D < 0) D = -D; D = ((D % 4) == 0) ? D/4 : D; if ( (D % 8) == 0 ) return; mpz_init(A); mpz_init(t); switch (D % 8) { case 1: if ((D % 3) != 0) mpz_powm_ui(t, r, 12, N); else mpz_powm_ui(t, r, 4, N); mpz_mul_ui(A, t, 64); mpz_sub_ui(t, A, 16); break; case 2: case 6: if ((D % 3) != 0) mpz_powm_ui(t, r, 12, N); else mpz_powm_ui(t, r, 4, N); mpz_mul_ui(A, t, 64); mpz_add_ui(t, A, 16); break; case 5: if ((D % 3) != 0) mpz_powm_ui(t, r, 6, N); else mpz_powm_ui(t, r, 2, N); mpz_mul_ui(A, t, 64); mpz_sub_ui(t, A, 16); break; case 7: if (!mpz_invert(t, r, N)) mpz_set_ui(t, 0); if ((D % 3) != 0) mpz_powm_ui(A, t, 24, N); else mpz_powm_ui(A, t, 8, N); mpz_sub_ui(t, A, 16); break; /* Results in degree 3x Hilbert, so typically not used */ case 3: if (!mpz_invert(t, r, N)) mpz_set_ui(t, 0); if ((D % 3) != 0) { mpz_powm_ui(t, t, 24, N); mpz_mul_2exp(A, t, 12); } else { mpz_powm_ui(t, t, 8, N); mpz_mul_2exp(A, t, 4); } mpz_sub_ui(t, A, 16); break; default: break; } /* r = t^3 / A */ mpz_powm_ui(t, t, 3, N); if ( ! mpz_divmod(r, t, A, N, r) ) mpz_set_ui(r, 0); mpz_clear(A); mpz_clear(t); }
void paillier_keygen( int modulusbits, int decryptServers, int thresholdServers, paillier_pubkey_t** pub, paillier_partialkey_t*** partKeys, paillier_get_rand_t get_rand ) { mpz_t p1; mpz_t q1; mpz_t p; mpz_t q; mpz_t m; mpz_t nm; mpz_t nSquare; mpz_t mInversToN; mpz_t d; mpz_t r; mpz_t gcdRN; mpz_t vExp; mpz_t * a; mpz_t * shares; mpz_t * viarray; gmp_randstate_t rand; /* allocate the new key structures */ *pub = (paillier_pubkey_t*) malloc(sizeof(paillier_pubkey_t)); *partKeys = (paillier_partialkey_t**) malloc(sizeof(paillier_partialkey_t*) * decryptServers); /* initialize our integers */ mpz_init((*pub)->n); mpz_init((*pub)->n_squared); mpz_init((*pub)->n_plusone); mpz_init((*pub)->delta); mpz_init((*pub)->combineSharesConstant); mpz_init((*pub)->v); mpz_init(m); mpz_init(nm); mpz_init(nSquare); mpz_init(mInversToN); mpz_init(d); mpz_init(r); mpz_init(gcdRN); mpz_init(vExp); /* pick random (modulusbits/2)-bit primes p and q */ init_rand(rand, get_rand, modulusbits / 8 + 1); do { genSafePrimes(&p1,&p,modulusbits,rand); do genSafePrimes(&q1,&q,modulusbits,rand); while( mpz_cmp(p,q)==0 || mpz_cmp(p,q1)==0 || mpz_cmp(q,p1)==0 || mpz_cmp(q1,p1)==0 ); /* compute the public modulus n = p q */ mpz_mul((*pub)->n, p, q); mpz_mul(m, p1, q1); } while( !mpz_tstbit((*pub)->n, modulusbits - 1) ); (*pub)->bits = modulusbits; (*pub)->decryptServers = decryptServers; (*pub)->threshold = thresholdServers; (*pub)->complete(); // We decide on some s>0, thus the plaintext space will be Zn^s // for now we set s=1 mpz_mul(nm, (*pub)->n, m); mpz_mul(nSquare, (*pub)->n, (*pub)->n); // next d need to be chosen such that // d=0 mod m and d=1 mod n, using Chinese remainder thm // we can find d using Chinese remainder thm // note that $d=(m. (m^-1 mod n))$ int errorCode = mpz_invert(mInversToN,m,(*pub)->n); if (errorCode == 0) { throw std::runtime_error("Inverse of m mod n not found!"); } mpz_mul(d,m,mInversToN); //a[0] is equal to d //a[i] is the random number used for generating the polynomial //between 0... n^s*m-1, for 0 < i < thresholdServers a = (mpz_t*) malloc(sizeof(mpz_t) * thresholdServers); mpz_init(a[0]); mpz_set(a[0], d); for (int i = 1; i < thresholdServers; ++i) { mpz_init(a[i]); mpz_urandomm(a[i], rand, nm); } //We need to generate v //Although v needs to be the generator of the squares in Z^*_{n^2} //I will use a heuristic which gives a generator with high prob. //get a random element r such that gcd(r,nSquare) is one //set v=r*r mod nSquare. This heuristic is used in the Victor Shoup //threshold signature paper. do { mpz_urandomb(r, rand, 4*modulusbits); mpz_gcd(gcdRN, r, (*pub)->n); } while( !mpz_cmp_ui(gcdRN, 1)==0 ); // we can now set v to r*r mod nSquare mpz_powm_ui((*pub)->v, r, 2, nSquare); //This array holds the resulting keys shares = (mpz_t*) malloc(sizeof(mpz_t) * decryptServers); viarray = (mpz_t*) malloc(sizeof(mpz_t) * decryptServers); for (int i = 0; i < decryptServers; ++i) { mpz_init(shares[i]); mpz_init(viarray[i]); // The secret share of the i'th authority will be s_i=f(i) for 1<=i<=l paillier_polynomial_point_t *polynPoint = evaluatePolynomial(a, thresholdServers, i+1, nm); mpz_set(shares[i], polynPoint->p); paillier_freepolynomialpoint(polynPoint); //for each decryption server a verication key v_i=v^(delta*s_i) mod n^(s+1) mpz_mul(vExp, (*pub)->delta, shares[i]); mpz_powm(viarray[i], (*pub)->v, vExp, nSquare); } /* Set key structures */ (*pub)->verificationKeys = (paillier_verificationkey_t**) malloc(sizeof(paillier_verificationkey_t) * decryptServers); for (int i = 0; i < decryptServers; ++i) { int id = i+1; paillier_verificationkey_t* verKey = (paillier_verificationkey_t*) malloc(sizeof(paillier_verificationkey_t)); mpz_init(verKey->v); verKey->id=id; mpz_set(verKey->v, viarray[i]); (*pub)->verificationKeys[i]=verKey; paillier_partialkey_t* share = (paillier_partialkey_t*) malloc(sizeof(paillier_partialkey_t)); mpz_init(share->s); share->id=id; mpz_set(share->s, shares[i]); (*partKeys)[i]=share; } /* clear temporary integers and randstate */ mpz_clear(p); mpz_clear(q); mpz_clear(p1); mpz_clear(q1); mpz_clear(m); mpz_clear(nm); mpz_clear(nSquare); mpz_clear(mInversToN); mpz_clear(d); mpz_clear(r); mpz_clear(gcdRN); mpz_clear(vExp); gmp_randclear(rand); for (int i = 0; i < thresholdServers; ++i) { mpz_clear(a[i]); } free(a); for (int i = 0; i < decryptServers; ++i) { mpz_clear(shares[i]); mpz_clear(viarray[i]); } free(shares); free(viarray); }
static int mpfr_rem1 (mpfr_ptr rem, long *quo, mpfr_rnd_t rnd_q, mpfr_srcptr x, mpfr_srcptr y, mpfr_rnd_t rnd) { mpfr_exp_t ex, ey; int compare, inex, q_is_odd, sign, signx = MPFR_SIGN (x); mpz_t mx, my, r; int tiny = 0; MPFR_ASSERTD (rnd_q == MPFR_RNDN || rnd_q == MPFR_RNDZ); if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x) || MPFR_IS_SINGULAR (y))) { if (MPFR_IS_NAN (x) || MPFR_IS_NAN (y) || MPFR_IS_INF (x) || MPFR_IS_ZERO (y)) { /* for remquo, quo is undefined */ MPFR_SET_NAN (rem); MPFR_RET_NAN; } else /* either y is Inf and x is 0 or non-special, or x is 0 and y is non-special, in both cases the quotient is zero. */ { if (quo) *quo = 0; return mpfr_set (rem, x, rnd); } } /* now neither x nor y is NaN, Inf or zero */ mpz_init (mx); mpz_init (my); mpz_init (r); ex = mpfr_get_z_2exp (mx, x); /* x = mx*2^ex */ ey = mpfr_get_z_2exp (my, y); /* y = my*2^ey */ /* to get rid of sign problems, we compute it separately: quo(-x,-y) = quo(x,y), rem(-x,-y) = -rem(x,y) quo(-x,y) = -quo(x,y), rem(-x,y) = -rem(x,y) thus quo = sign(x/y)*quo(|x|,|y|), rem = sign(x)*rem(|x|,|y|) */ sign = (signx == MPFR_SIGN (y)) ? 1 : -1; mpz_abs (mx, mx); mpz_abs (my, my); q_is_odd = 0; /* divide my by 2^k if possible to make operations mod my easier */ { unsigned long k = mpz_scan1 (my, 0); ey += k; mpz_fdiv_q_2exp (my, my, k); } if (ex <= ey) { /* q = x/y = mx/(my*2^(ey-ex)) */ /* First detect cases where q=0, to avoid creating a huge number my*2^(ey-ex): if sx = mpz_sizeinbase (mx, 2) and sy = mpz_sizeinbase (my, 2), we have x < 2^(ex + sx) and y >= 2^(ey + sy - 1), thus if ex + sx <= ey + sy - 1 the quotient is 0 */ if (ex + (mpfr_exp_t) mpz_sizeinbase (mx, 2) < ey + (mpfr_exp_t) mpz_sizeinbase (my, 2)) { tiny = 1; mpz_set (r, mx); mpz_set_ui (mx, 0); } else { mpz_mul_2exp (my, my, ey - ex); /* divide mx by my*2^(ey-ex) */ /* since mx > 0 and my > 0, we can use mpz_tdiv_qr in all cases */ mpz_tdiv_qr (mx, r, mx, my); /* 0 <= |r| <= |my|, r has the same sign as mx */ } if (rnd_q == MPFR_RNDN) q_is_odd = mpz_tstbit (mx, 0); if (quo) /* mx is the quotient */ { mpz_tdiv_r_2exp (mx, mx, WANTED_BITS); *quo = mpz_get_si (mx); } } else /* ex > ey */ { if (quo) /* remquo case */ /* for remquo, to get the low WANTED_BITS more bits of the quotient, we first compute R = X mod Y*2^WANTED_BITS, where X and Y are defined below. Then the low WANTED_BITS of the quotient are floor(R/Y). */ mpz_mul_2exp (my, my, WANTED_BITS); /* 2^WANTED_BITS*Y */ else if (rnd_q == MPFR_RNDN) /* remainder case */ /* Let X = mx*2^(ex-ey) and Y = my. Then both X and Y are integers. Assume X = R mod Y, then x = X*2^ey = R*2^ey mod (Y*2^ey=y). To be able to perform the rounding, we need the least significant bit of the quotient, i.e., one more bit in the remainder, which is obtained by dividing by 2Y. */ mpz_mul_2exp (my, my, 1); /* 2Y */ mpz_set_ui (r, 2); mpz_powm_ui (r, r, ex - ey, my); /* 2^(ex-ey) mod my */ mpz_mul (r, r, mx); mpz_mod (r, r, my); if (quo) /* now 0 <= r < 2^WANTED_BITS*Y */ { mpz_fdiv_q_2exp (my, my, WANTED_BITS); /* back to Y */ mpz_tdiv_qr (mx, r, r, my); /* oldr = mx*my + newr */ *quo = mpz_get_si (mx); q_is_odd = *quo & 1; } else if (rnd_q == MPFR_RNDN) /* now 0 <= r < 2Y in the remainder case */ { mpz_fdiv_q_2exp (my, my, 1); /* back to Y */ /* least significant bit of q */ q_is_odd = mpz_cmpabs (r, my) >= 0; if (q_is_odd) mpz_sub (r, r, my); } /* now 0 <= |r| < |my|, and if needed, q_is_odd is the least significant bit of q */ } if (mpz_cmp_ui (r, 0) == 0) { inex = mpfr_set_ui (rem, 0, MPFR_RNDN); /* take into account sign of x */ if (signx < 0) mpfr_neg (rem, rem, MPFR_RNDN); } else { if (rnd_q == MPFR_RNDN) { /* FIXME: the comparison 2*r < my could be done more efficiently at the mpn level */ mpz_mul_2exp (r, r, 1); /* if tiny=1, we should compare r with my*2^(ey-ex) */ if (tiny) { if (ex + (mpfr_exp_t) mpz_sizeinbase (r, 2) < ey + (mpfr_exp_t) mpz_sizeinbase (my, 2)) compare = 0; /* r*2^ex < my*2^ey */ else { mpz_mul_2exp (my, my, ey - ex); compare = mpz_cmpabs (r, my); } } else compare = mpz_cmpabs (r, my); mpz_fdiv_q_2exp (r, r, 1); compare = ((compare > 0) || ((rnd_q == MPFR_RNDN) && (compare == 0) && q_is_odd)); /* if compare != 0, we need to subtract my to r, and add 1 to quo */ if (compare) { mpz_sub (r, r, my); if (quo && (rnd_q == MPFR_RNDN)) *quo += 1; } } /* take into account sign of x */ if (signx < 0) mpz_neg (r, r); inex = mpfr_set_z_2exp (rem, r, ex > ey ? ey : ex, rnd); } if (quo) *quo *= sign; mpz_clear (mx); mpz_clear (my); mpz_clear (r); return inex; }
void fmpz_powm_ui(fmpz_t f, const fmpz_t g, ulong e, const fmpz_t m) { if (fmpz_sgn(m) <= 0) { printf("Exception (fmpz_powm_ui). Modulus is less than 1.\n"); abort(); } if (fmpz_is_one(m)) { fmpz_zero(f); } else if (e == 0) { fmpz_one(f); } else /* e != 0, m > 0 */ { fmpz g2 = *g; fmpz m2 = *m; if (!COEFF_IS_MPZ(m2)) /* m is small */ { if (!COEFF_IS_MPZ(g2)) /* g is small */ { mp_limb_t minv = n_preinvert_limb(m2); _fmpz_demote(f); if (g2 >= 0) { g2 = n_mod2_preinv(g2, m2, minv); *f = n_powmod2_preinv(g2, e, m2, minv); } else { g2 = n_mod2_preinv(-g2, m2, minv); *f = n_powmod2_preinv(g2, e, m2, minv); if ((e & 1UL)) *f = n_negmod(*f, m2); } } else /* g is large */ { __mpz_struct *ptr = _fmpz_promote(f); mpz_t m3; mpz_init_set_ui(m3, m2); mpz_powm_ui(ptr, COEFF_TO_PTR(g2), e, m3); mpz_clear(m3); _fmpz_demote_val(f); } } else /* m is large */ { if (!COEFF_IS_MPZ(g2)) /* g is small */ { __mpz_struct *ptr = _fmpz_promote(f); mpz_t g3; mpz_init_set_si(g3, g2); mpz_powm_ui(ptr, g3, e, COEFF_TO_PTR(m2)); mpz_clear(g3); _fmpz_demote_val(f); } else /* g is large */ { __mpz_struct *ptr = _fmpz_promote(f); mpz_powm_ui(ptr, COEFF_TO_PTR(g2), e, COEFF_TO_PTR(m2)); _fmpz_demote_val(f); } } } }
/* See Cohen section 1.5. * See http://www.math.vt.edu/people/brown/doc/sqrts.pdf */ int sqrtmod(mpz_t x, mpz_t a, mpz_t p, mpz_t t, mpz_t q, mpz_t b, mpz_t z) /* 4 temp variables */ { int r, e, m; /* Easy cases from page 31 (or Menezes 3.36, 3.37) */ if (mpz_congruent_ui_p(p, 3, 4)) { mpz_add_ui(t, p, 1); mpz_tdiv_q_2exp(t, t, 2); mpz_powm(x, a, t, p); return verify_sqrt(x, a, p, t, q); } if (mpz_congruent_ui_p(p, 5, 8)) { mpz_sub_ui(t, p, 1); mpz_tdiv_q_2exp(t, t, 2); mpz_powm(q, a, t, p); if (mpz_cmp_si(q, 1) == 0) { /* s = a^((p+3)/8) mod p */ mpz_add_ui(t, p, 3); mpz_tdiv_q_2exp(t, t, 3); mpz_powm(x, a, t, p); } else { /* s = 2a * (4a)^((p-5)/8) mod p */ mpz_sub_ui(t, p, 5); mpz_tdiv_q_2exp(t, t, 3); mpz_mul_ui(q, a, 4); mpz_powm(x, q, t, p); mpz_mul_ui(x, x, 2); mpz_mulmod(x, x, a, p, x); } return verify_sqrt(x, a, p, t, q); } if (mpz_kronecker(a, p) != 1) { /* Possible no solution exists. Check Euler criterion. */ mpz_sub_ui(t, p, 1); mpz_tdiv_q_2exp(t, t, 1); mpz_powm(x, a, t, p); if (mpz_cmp_si(x, 1) != 0) { mpz_set_ui(x, 0); return 0; } } mpz_sub_ui(q, p, 1); e = mpz_scan1(q, 0); /* Remove 2^e from q */ mpz_tdiv_q_2exp(q, q, e); mpz_set_ui(t, 2); while (mpz_legendre(t, p) != -1) /* choose t "at random" */ mpz_add_ui(t, t, 1); mpz_powm(z, t, q, p); /* Step 1 complete */ r = e; mpz_powm(b, a, q, p); mpz_add_ui(q, q, 1); mpz_divexact_ui(q, q, 2); mpz_powm(x, a, q, p); /* Done with q, will use it for y now */ while (mpz_cmp_ui(b, 1)) { /* calculate how many times b^2 mod p == 1 */ mpz_set(t, b); m = 0; do { mpz_powm_ui(t, t, 2, p); m++; } while (m < r && mpz_cmp_ui(t, 1)); if (m >= r) break; mpz_ui_pow_ui(t, 2, r-m-1); mpz_powm(t, z, t, p); mpz_mulmod(x, x, t, p, x); mpz_powm_ui(z, t, 2, p); mpz_mulmod(b, b, z, p, b); r = m; } return verify_sqrt(x, a, p, t, q); }
int quadratic_residue(mpz_t x,mpz_t q,mpz_t n) { int leg; mpz_t tmp,ofac,nr,t,r,c,b; unsigned int mod4; mp_bitcnt_t twofac=0,m,i,ix; mod4=mpz_tstbit(n,0); if(!mod4) // must be odd return 0; mod4+=2*mpz_tstbit(n,1); leg=mpz_legendre(q,n); if(leg!=1) return leg; mpz_init_set(tmp,n); if(mod4==3) // directly, x = q^(n+1)/4 mod n { printf("diretamente\n\n"); mpz_add_ui(tmp,tmp,1UL); mpz_tdiv_q_2exp(tmp,tmp,2); mpz_powm(x,q,tmp,n); gmp_printf("NUMERO X %Zd \n\n",x); mpz_clear(tmp); } else // Tonelli-Shanks { printf("Tonelli shanks!!!\n"); mpz_inits(ofac,t,r,c,b,NULL); // split n - 1 into odd number times power of 2 ofac*2^twofac mpz_sub_ui(tmp,tmp,1UL); twofac=mpz_scan1(tmp,twofac); // largest power of 2 divisor if(twofac) mpz_tdiv_q_2exp(ofac,tmp,twofac); // shift right // look for non-residue mpz_init_set_ui(nr,2UL); while(mpz_legendre(nr,n)!=-1) mpz_add_ui(nr,nr,1UL); mpz_powm(c,nr,ofac,n); // c = nr^ofac mod n mpz_add_ui(tmp,ofac,1UL); mpz_tdiv_q_2exp(tmp,tmp,1); mpz_powm(r,q,tmp,n); // r = q^(ofac+1)/2 mod n mpz_powm(t,q,ofac,n); mpz_mod(t,t,n); // t = q^ofac mod n if(mpz_cmp_ui(t,1UL)!=0) // if t = 1 mod n we're done { m=twofac; do { i=2; ix=1; while(ix<m) { // find lowest 0 < ix < m | t^2^ix = 1 mod n mpz_powm_ui(tmp,t,i,n); // repeatedly square t if(mpz_cmp_ui(tmp,1UL)==0) break; i<<=1; // i = 2, 4, 8, ... ix++; // ix is log2 i } mpz_powm_ui(b,c,1<<(m-ix-1),n); // b = c^2^(m-ix-1) mod n mpz_mul(r,r,b); mpz_mod(r,r,n); // r = r*b mod n mpz_mul(c,b,b); mpz_mod(c,c,n); // c = b^2 mod n mpz_mul(t,t,c); mpz_mod(t,t,n); // t = t b^2 mod n m=ix; }while(mpz_cmp_ui(t,1UL)!=0); // while t mod n != 1 } mpz_set(x,r); mpz_clears(tmp,ofac,nr,t,r,c,b,NULL); } return 1; }
int main(void) { int i, result; flint_rand_t state; printf("powmod_precomp...."); fflush(stdout); flint_randinit(state); for (i = 0; i < 100000; i++) { mp_limb_t a, d, r1, r2, bits; mpz_t a_m, d_m, r2_m; mp_limb_signed_t exp; double dpre; mpz_init(a_m); mpz_init(d_m); mpz_init(r2_m); bits = n_randint(state, FLINT_D_BITS) + 1; d = n_randbits(state, bits); do { a = n_randint(state, d); } while (n_gcd(d, a) != 1UL); exp = n_randtest(state); dpre = n_precompute_inverse(d); r1 = n_powmod_precomp(a, exp, d, dpre); mpz_set_ui(a_m, a); mpz_set_ui(d_m, d); if (exp < 0L) { mpz_powm_ui(r2_m, a_m, -exp, d_m); mpz_invert(r2_m, r2_m, d_m); } else mpz_powm_ui(r2_m, a_m, exp, d_m); r2 = mpz_get_ui(r2_m); result = (r1 == r2); if (!result) { printf("FAIL:\n"); printf("a = %lu, exp = %ld, d = %lu\n", a, exp, d); printf("r1 = %lu, r2 = %lu\n", r1, r2); abort(); } mpz_clear(a_m); mpz_clear(d_m); mpz_clear(r2_m); } flint_randclear(state); printf("PASS\n"); return 0; }
bool Algorithms::MillerRabin(mpz_t number, unsigned int numBits, unsigned int numTest) { unsigned int i, j, k; char *a_str; mpz_t buf, t, gcd, a, c; mpz_init(buf); mpz_init(t); mpz_init(gcd); mpz_init(a); mpz_init(c); if(mpz_cmp_ui(number,(unsigned long)2) == 0) return true; mpz_mod_ui(buf, number, (unsigned long)2); if(mpz_cmp_ui(buf,(unsigned long)0) == 0) return false; unsigned long s = 0; mpz_sub_ui(t,number,(unsigned long)1); mpz_mod_ui(buf, t, (unsigned long)2); while(mpz_cmp_ui(buf,(unsigned long)0) == 0) { mpz_tdiv_qr_ui(t, buf, t, (unsigned long)2); mpz_mod_ui(buf, t, (unsigned long)2); s++; } a_str = new char[numBits]; for(i = 0; i < numTest; i++) { for(k = 0; k < numBits - 1; k++) a_str[k] = (int)(2.0 * rand() / (RAND_MAX + 1.0)) + '0'; a_str[k] = '\0'; mpz_set_str(a,a_str,2); mpz_gcd(gcd,a,number); if(mpz_cmp_ui(gcd,(unsigned long)1) != 0) return false; mpz_powm(c, a, t, number); if(mpz_cmp_ui(c,(unsigned long)1) == 0) continue; mpz_sub_ui(buf,number,(unsigned long)1); if(mpz_cmp(c,buf) == 0) continue; bool f = true; for(j = 0; j < s - 1; j++) { mpz_powm_ui(c, c,(unsigned long)2, number); if(mpz_cmp(c,buf) == 0) f = false; } if(f) return false; } mpz_clear(buf); mpz_clear(t); mpz_clear(gcd); mpz_clear(a); mpz_clear(c); free(a_str); return true; }
// init void bbs_pseudo_init ( PGM_CTX *pgm_ctx ) { RNDBBS *bbs; mpz_t p,q; KEYBUF_128 *kb_128; // pick up handy ptr bbs = &pgm_ctx->rndbbs; // init pgm_ctx mpz_init(bbs->blumint); mpz_init(bbs->x); bbs->key_bitlen = 0; bbs->improved = 1; bbs->xor_urandom = 0; // init local vars mpz_init(p); mpz_init(q); // get p, use key_four as starting point kb_128 = &pgm_ctx->dibit_kb3_i.kb->key_four; bbs_pseudo_cvt_bytes_to_mpz ( kb_128->k, KEYBUF_128_SIZE, p); bbs_pseudo_next_prime ( p ); // encrypt key_four as we've used it up { unsigned char *kc; int i; // pick up ptr to buffer kc = kb_128->k; // make big *kc |= 0xc0; // make odd kc [ KEYBUF_128_SIZE -1 ] |= 0x1; for ( i = 0 ; i < KEYBUF_128_SIZE/AES_BLOCK_SIZE ; i++, kc += AES_BLOCK_SIZE ) { aes_encrypt( &pgm_ctx->pgm_ctx_aes_b.crypto_aes_ctx, pgm_ctx->pgm_ctx_aes_b.crypto_aes_register_a, kc); memcpy(kc,pgm_ctx->pgm_ctx_aes_b.crypto_aes_register_a,AES_BLOCK_SIZE); } } // get q mpz_set(q,p); bbs_pseudo_next_prime ( q ); // calculate blumint mpz_mul(bbs->blumint,p,q); bbs->key_bitlen = mpz_sizeinbase(bbs->blumint, 2); // get bbs->x { mpz_t tmpgcd; unsigned char m[4]; mpz_init(tmpgcd); m[0] = getNKeyBits_3_iterator ( pgm_ctx, 8, &pgm_ctx->dibit_kb3_i ); m[1] = getNKeyBits_3_iterator ( pgm_ctx, 8, &pgm_ctx->dibit_kb3_i ); m[2] = getNKeyBits_3_iterator ( pgm_ctx, 8, &pgm_ctx->dibit_kb3_i ); m[3] = getNKeyBits_3_iterator ( pgm_ctx, 8, &pgm_ctx->dibit_kb3_i ); // get trial x bbs_pseudo_cvt_bytes_to_mpz ( m, 4, bbs->x ); // make sure 'x' is good while ( 1 ) { mpz_gcd(tmpgcd, bbs->blumint, bbs->x); if (mpz_cmp_ui(tmpgcd, 1) != 0) { // here, not so good, try again mpz_add_ui(bbs->x,bbs->x,1); continue; } break; } // finally, calculate x[0] /* x[0] = x^2 (mod n) */ mpz_powm_ui(bbs->x, bbs->x, 2, bbs->blumint); // tidy up mpz_clear(tmpgcd); } // display if necessary if ( trace_flag > 1 ) { printf("\n%s: bbs->key_bitlen = %d\n", __FUNCTION__, bbs->key_bitlen); gmp_printf ("p : %Zx\n", p); gmp_printf ("q : %Zx\n", q); gmp_printf ("x[0] : %Zx\n", bbs->x); gmp_printf ("blumint: %Zx\n", bbs->blumint); printf("\n"); } // cleanup mpz_clear(p); mpz_clear(q); // done }
int is_aks_prime(mpz_t n) { mpz_t *px, *py; int retval; UV i, s, r, a; UV starta = 1; int _verbose = get_verbose_level(); if (mpz_cmp_ui(n, 4) < 0) return (mpz_cmp_ui(n, 1) <= 0) ? 0 : 1; /* Just for performance: check small divisors: 2*3*5*7*11*13*17*19*23 */ if (mpz_gcd_ui(0, n, 223092870UL) != 1 && mpz_cmp_ui(n, 23) > 0) return 0; if (mpz_perfect_power_p(n)) return 0; #if AKS_VARIANT == AKS_VARIANT_V6 /* From the V6 AKS paper */ { mpz_t sqrtn, t; double log2n; UV limit, startr; PRIME_ITERATOR(iter); mpz_init(sqrtn); mpz_sqrt(sqrtn, n); log2n = mpz_log2(n); limit = (UV) floor( log2n * log2n ); if (_verbose>1) gmp_printf("# AKS checking order_r(%Zd) to %"UVuf"\n", n, (unsigned long) limit); /* Using a native r limits us to ~2000 digits in the worst case (r ~ log^5n) * but would typically work for 100,000+ digits (r ~ log^3n). This code is * far too slow to matter either way. Composite r is ok here, but it will * always end up prime, so save time and just check primes. */ retval = 0; /* Start order search at a good spot. Idea from Nemana and Venkaiah. */ startr = (mpz_sizeinbase(n,2)-1) * (mpz_sizeinbase(n,2)-1); startr = (startr < 1002) ? 2 : startr - 100; for (r = 2; /* */; r = prime_iterator_next(&iter)) { if (mpz_divisible_ui_p(n, r) ) /* r divides n. composite. */ { retval = 0; break; } if (mpz_cmp_ui(sqrtn, r) <= 0) /* no r <= sqrtn divides n. prime. */ { retval = 1; break; } if (r < startr) continue; if (mpz_order_ui(r, n, limit) > limit) { retval = 2; break; } } prime_iterator_destroy(&iter); mpz_clear(sqrtn); if (retval != 2) return retval; /* Since r is prime, phi(r) = r-1. */ s = (UV) floor( sqrt(r-1) * log2n ); } #elif AKS_VARIANT == AKS_VARIANT_BORNEMANN /* Bernstein + Voloch */ { UV slim; double c2, x; /* small t = few iters of big poly. big t = many iters of small poly */ double const t = (mpz_sizeinbase(n, 2) <= 64) ? 32 : 40; double const t1 = (1.0/((t+1)*log(t+1)-t*log(t))); double const dlogn = mpz_logn(n); mpz_t tmp; PRIME_ITERATOR(iter); mpz_init(tmp); prime_iterator_setprime(&iter, (UV) (t1*t1 * dlogn*dlogn) ); r = prime_iterator_next(&iter); while (!is_primitive_root_uiprime(n,r)) r = prime_iterator_next(&iter); prime_iterator_destroy(&iter); slim = (UV) (2*t*(r-1)); c2 = dlogn * floor(sqrt(r)); { /* Binary search for first s in [1,slim] where x >= 0 */ UV bi = 1; UV bj = slim; while (bi < bj) { s = bi + (bj-bi)/2; mpz_bin_uiui(tmp, r+s-1, s); x = mpz_logn(tmp) / c2 - 1.0; if (x < 0) bi = s+1; else bj = s; } s = bi-1; } s = (s+3) >> 1; /* Bornemann checks factors up to (s-1)^2, we check to max(r,s) */ /* slim = (s-1)*(s-1); */ slim = (r > s) ? r : s; if (_verbose > 1) printf("# aks trial to %"UVuf"\n", slim); if (_GMP_trial_factor(n, 2, slim) > 1) { mpz_clear(tmp); return 0; } mpz_sqrt(tmp, n); if (mpz_cmp_ui(tmp, slim) <= 0) { mpz_clear(tmp); return 1; } mpz_clear(tmp); } #elif AKS_VARIANT == AKS_VARIANT_BERN21 { /* Bernstein 2003, theorem 2.1 (simplified) */ UV q; double slim, scmp, x; mpz_t t, t2; PRIME_ITERATOR(iter); mpz_init(t); mpz_init(t2); r = s = 0; while (1) { /* todo: Check r|n and r >= sqrt(n) here instead of waiting */ if (mpz_cmp_ui(n, r) <= 0) break; r = prime_iterator_next(&iter); q = largest_factor(r-1); mpz_set_ui(t, r); mpz_powm_ui(t, n, (r-1)/q, t); if (mpz_cmp_ui(t, 1) <= 0) continue; scmp = 2 * floor(sqrt(r)) * mpz_log2(n); slim = 20 * (r-1); /* Check viability */ mpz_bin_uiui(t, q+slim-1, slim); if (mpz_log2(t) < scmp) continue; for (s = 2; s < slim; s++) { mpz_bin_uiui(t, q+s-1, s); if (mpz_log2(t) > scmp) break; } if (s < slim) break; } mpz_clear(t); mpz_clear(t2); prime_iterator_destroy(&iter); if (_GMP_trial_factor(n, 2, s) > 1) return 0; } #elif AKS_VARIANT == AKS_VARIANT_BERN22 { /* Bernstein 2003, theorem 2.2 (simplified) */ UV q; double slim, scmp, x; mpz_t t, t2; PRIME_ITERATOR(iter); mpz_init(t); mpz_init(t2); r = s = 0; while (1) { /* todo: Check r|n and r >= sqrt(n) here instead of waiting */ if (mpz_cmp_ui(n, r) <= 0) break; r = prime_iterator_next(&iter); if (!is_primitive_root_uiprime(n,r)) continue; q = r-1; /* Since r is prime, phi(r) = r-1 */ scmp = 2 * floor(sqrt(r-1)) * mpz_log2(n); slim = 20 * (r-1); /* Check viability */ mpz_bin_uiui(t, q+slim-1, slim); if (mpz_log2(t) < scmp) continue; for (s = 2; s < slim; s++) { mpz_bin_uiui(t, q+s-1, s); if (mpz_log2(t) > scmp) break; } if (s < slim) break; } mpz_clear(t); mpz_clear(t2); prime_iterator_destroy(&iter); if (_GMP_trial_factor(n, 2, s) > 1) return 0; } #elif AKS_VARIANT == AKS_VARIANT_BERN23 { /* Bernstein 2003, theorem 2.3 (simplified) */ UV q, d, limit; double slim, scmp, sbin, x, log2n; mpz_t t, t2; PRIME_ITERATOR(iter); mpz_init(t); mpz_init(t2); log2n = mpz_log2(n); limit = (UV) floor( log2n * log2n ); r = 2; s = 0; while (1) { /* todo: Check r|n and r >= sqrt(n) here instead of waiting */ if (mpz_cmp_ui(n, r) <= 0) break; r++; UV gcd = mpz_gcd_ui(NULL, n, r); if (gcd != 1) { mpz_clear(t); mpz_clear(t2); return 0; } UV v = mpz_order_ui(r, n, limit); if (v >= limit) continue; mpz_set_ui(t2, r); totient(t, t2); q = mpz_get_ui(t); UV phiv = q/v; /* printf("phi(%lu)/v = %lu/%lu = %lu\n", r, q, v, phiv); */ /* This is extremely inefficient. */ /* Choose an s value we'd be happy with */ slim = 20 * (r-1); /* Quick check to see if it could work with s=slim, d=1 */ mpz_bin_uiui(t, q+slim-1, slim); sbin = mpz_log2(t); if (sbin < 2*floor(sqrt(q))*log2n) continue; for (s = 2; s < slim; s++) { mpz_bin_uiui(t, q+s-1, s); sbin = mpz_log2(t); if (sbin < 2*floor(sqrt(q))*log2n) continue; /* d=1 */ /* Check each number dividing phi(r)/v */ for (d = 2; d < phiv; d++) { if ((phiv % d) != 0) continue; scmp = 2 * d * floor(sqrt(q/d)) * log2n; if (sbin < scmp) break; } /* if we did not exit early, this s worked for each d. This s wins. */ if (d >= phiv) break; } if (s < slim) break; } mpz_clear(t); mpz_clear(t2); prime_iterator_destroy(&iter); if (_GMP_trial_factor(n, 2, s) > 1) return 0; } #elif AKS_VARIANT == AKS_VARIANT_BERN41 { double const log2n = mpz_log2(n); /* Tuning: Initial 'r' selection */ double const r0 = 0.008 * log2n * log2n; /* Tuning: Try a larger 'r' if 's' looks very large */ UV const rmult = 8; UV slim; mpz_t tmp, tmp2; PRIME_ITERATOR(iter); mpz_init(tmp); mpz_init(tmp2); /* r has to be at least 3. */ prime_iterator_setprime(&iter, (r0 < 2) ? 2 : (UV) r0); r = prime_iterator_next(&iter); /* r must be a primitive root. For performance, skip if s looks too big. */ while ( !is_primitive_root_uiprime(n, r) || !bern41_acceptable(n, r, rmult*(r-1), tmp, tmp2) ) r = prime_iterator_next(&iter); prime_iterator_destroy(&iter); { /* Binary search for first s in [1,lim] where conditions met */ UV bi = 1; UV bj = rmult * (r-1); while (bi < bj) { s = bi + (bj-bi)/2; if (!bern41_acceptable(n,r,s,tmp,tmp2)) bi = s+1; else bj = s; } s = bj; /* Our S goes from 2 to s+1. */ starta = 2; s = s+1; } /* printf("chose r=%lu s=%lu d = %lu i = %lu j = %lu\n", r, s, d, i, j); */ /* Check divisibility to s(s-1) to cover both gcd conditions */ slim = s * (s-1); if (_verbose > 1) printf("# aks trial to %"UVuf"\n", slim); if (_GMP_trial_factor(n, 2, slim) > 1) { mpz_clear(tmp); mpz_clear(tmp2); return 0; } /* If we checked divisibility to sqrt(n), then it is prime. */ mpz_sqrt(tmp, n); if (mpz_cmp_ui(tmp, slim) <= 0) { mpz_clear(tmp); mpz_clear(tmp2); return 1; } /* Check b^(n-1) = 1 mod n for b in [2..s] */ if (_verbose > 1) printf("# aks checking fermat to %"UVuf"\n", s); mpz_sub_ui(tmp2, n, 1); for (i = 2; i <= s; i++) { mpz_set_ui(tmp, i); mpz_powm(tmp, tmp, tmp2, n); if (mpz_cmp_ui(tmp, 1) != 0) { mpz_clear(tmp); mpz_clear(tmp2); return 0; } } mpz_clear(tmp); mpz_clear(tmp2); } #endif if (_verbose) gmp_printf("# AKS %Zd. r = %"UVuf" s = %"UVuf"\n", n, (unsigned long) r, (unsigned long) s); /* Create the three polynomials we will use */ New(0, px, r, mpz_t); New(0, py, r, mpz_t); if ( !px || !py ) croak("allocation failure\n"); for (i = 0; i < r; i++) { mpz_init(px[i]); mpz_init(py[i]); } retval = 1; for (a = starta; a <= s; a++) { retval = test_anr(a, n, r, px, py); if (!retval) break; if (_verbose>1) { printf("."); fflush(stdout); } } if (_verbose>1) { printf("\n"); fflush(stdout); }; /* Free the polynomials */ for (i = 0; i < r; i++) { mpz_clear(px[i]); mpz_clear(py[i]); } Safefree(px); Safefree(py); return retval; }
int main (int argc, char **argv) { int i; int pass, reps = 400; mpz_t in1, in2, in3; unsigned long int in2i; mp_size_t size; mpz_t res1, res2, res3; mpz_t ref1, ref2, ref3; mpz_t t; unsigned long int r1, r2; gmp_randstate_ptr rands; mpz_t bs; unsigned long bsi, size_range; tests_start (); TESTS_REPS (reps, argv, argc); rands = RANDS; mpz_init (bs); mpz_init (in1); mpz_init (in2); mpz_init (in3); mpz_init (ref1); mpz_init (ref2); mpz_init (ref3); mpz_init (res1); mpz_init (res2); mpz_init (res3); mpz_init (t); for (pass = 1; pass <= reps; pass++) { if (isatty (fileno (stdout))) { printf ("\r%d/%d passes", pass, reps); fflush (stdout); } mpz_urandomb (bs, rands, 32); size_range = mpz_get_ui (bs) % 21 + 2; if ((pass & 1) == 0) { /* Make all input operands have quite different sizes */ mpz_urandomb (bs, rands, 32); size = mpz_get_ui (bs) % size_range; mpz_rrandomb (in1, rands, size); mpz_urandomb (bs, rands, 32); size = mpz_get_ui (bs) % size_range; mpz_rrandomb (in2, rands, size); mpz_urandomb (bs, rands, 32); size = mpz_get_ui (bs) % size_range; mpz_rrandomb (in3, rands, size); } else { /* Make all input operands have about the same size */ mpz_urandomb (bs, rands, size_range); size = mpz_get_ui (bs); mpz_rrandomb (in1, rands, size); mpz_urandomb (bs, rands, size_range); size = mpz_get_ui (bs); mpz_rrandomb (in2, rands, size); mpz_urandomb (bs, rands, size_range); size = mpz_get_ui (bs); mpz_rrandomb (in3, rands, size); } mpz_urandomb (bs, rands, 3); bsi = mpz_get_ui (bs); if ((bsi & 1) != 0) mpz_neg (in1, in1); if ((bsi & 2) != 0) mpz_neg (in2, in2); if ((bsi & 4) != 0) mpz_neg (in3, in3); for (i = 0; i < numberof (dss); i++) { if (dss[i].isdivision && mpz_sgn (in2) == 0) continue; if (dss[i].isslow && size_range > 19) continue; (dss[i].fptr) (ref1, in1, in2); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, in1); INVOKE_RSS (dss[i], res1, res1, in2); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL (dss, i, in1, in2, NULL); mpz_set (res1, in2); INVOKE_RSS (dss[i], res1, in1, res1); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL (dss, i, in1, in2, NULL); } for (i = 0; i < numberof (ddss_div); i++) { if (mpz_sgn (in2) == 0) continue; (ddss_div[i].fptr) (ref1, ref2, in1, in2); MPZ_CHECK_FORMAT (ref1); MPZ_CHECK_FORMAT (ref2); mpz_set (res1, in1); INVOKE_RRSS (ddss_div[i], res1, res2, res1, in2); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0) FAIL (ddss_div, i, in1, in2, NULL); mpz_set (res2, in1); INVOKE_RRSS (ddss_div[i], res1, res2, res2, in2); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0) FAIL (ddss_div, i, in1, in2, NULL); mpz_set (res1, in2); INVOKE_RRSS (ddss_div[i], res1, res2, in1, res1); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0) FAIL (ddss_div, i, in1, in2, NULL); mpz_set (res2, in2); INVOKE_RRSS (ddss_div[i], res1, res2, in1, res2); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0) FAIL (ddss_div, i, in1, in2, NULL); } for (i = 0; i < numberof (ds); i++) { if (ds[i].nonneg && mpz_sgn (in1) < 0) continue; (ds[i].fptr) (ref1, in1); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, in1); INVOKE_RS (ds[i], res1, res1); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL (ds, i, in1, in2, NULL); } in2i = mpz_get_ui (in2); for (i = 0; i < numberof (dsi); i++) { if (dsi[i].mod != 0) in2i = mpz_get_ui (in2) % dsi[i].mod; (dsi[i].fptr) (ref1, in1, in2i); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, in1); INVOKE_RRS (dsi[i], res1, res1, in2i); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL (dsi, i, in1, in2, NULL); } if (in2i != 0) /* Don't divide by 0. */ { for (i = 0; i < numberof (dsi_div); i++) { r1 = (dsi_div[i].fptr) (ref1, in1, in2i); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, in1); r2 = (dsi_div[i].fptr) (res1, res1, in2i); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0 || r1 != r2) FAIL (dsi_div, i, in1, in2, NULL); } for (i = 0; i < numberof (ddsi_div); i++) { r1 = (ddsi_div[i].fptr) (ref1, ref2, in1, in2i); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, in1); r2 = (ddsi_div[i].fptr) (res1, res2, res1, in2i); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || r1 != r2) FAIL (ddsi_div, i, in1, in2, NULL); mpz_set (res2, in1); (ddsi_div[i].fptr) (res1, res2, res2, in2i); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || r1 != r2) FAIL (ddsi_div, i, in1, in2, NULL); } } if (mpz_sgn (in1) >= 0) { mpz_sqrtrem (ref1, ref2, in1); MPZ_CHECK_FORMAT (ref1); MPZ_CHECK_FORMAT (ref2); mpz_set (res1, in1); mpz_sqrtrem (res1, res2, res1); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0) FAIL2 (mpz_sqrtrem, in1, NULL, NULL); mpz_set (res2, in1); mpz_sqrtrem (res1, res2, res2); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0) FAIL2 (mpz_sqrtrem, in1, NULL, NULL); mpz_set (res1, in1); mpz_sqrtrem (res1, res1, res1); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref2, res1) != 0) FAIL2 (mpz_sqrtrem, in1, NULL, NULL); } if (mpz_sgn (in1) >= 0) { mpz_root (ref1, in1, in2i % 0x100 + 1); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, in1); mpz_root (res1, res1, in2i % 0x100 + 1); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL2 (mpz_root, in1, in2, NULL); } if (mpz_sgn (in1) >= 0) { mpz_rootrem (ref1, ref2, in1, in2i % 0x100 + 1); MPZ_CHECK_FORMAT (ref1); MPZ_CHECK_FORMAT (ref2); mpz_set (res1, in1); mpz_rootrem (res1, res2, res1, in2i % 0x100 + 1); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0) FAIL2 (mpz_rootrem, in1, in2, NULL); mpz_set (res2, in1); mpz_rootrem (res1, res2, res2, in2i % 0x100 + 1); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0) FAIL2 (mpz_rootrem, in1, in2, NULL); } if (size_range < 18) /* run fewer tests since gcdext lots of time */ { mpz_gcdext (ref1, ref2, ref3, in1, in2); MPZ_CHECK_FORMAT (ref1); MPZ_CHECK_FORMAT (ref2); MPZ_CHECK_FORMAT (ref3); mpz_set (res1, in1); mpz_gcdext (res1, res2, res3, res1, in2); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); MPZ_CHECK_FORMAT (res3); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || mpz_cmp (ref3, res3) != 0) FAIL2 (mpz_gcdext, in1, in2, NULL); mpz_set (res2, in1); mpz_gcdext (res1, res2, res3, res2, in2); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); MPZ_CHECK_FORMAT (res3); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || mpz_cmp (ref3, res3) != 0) FAIL2 (mpz_gcdext, in1, in2, NULL); mpz_set (res3, in1); mpz_gcdext (res1, res2, res3, res3, in2); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); MPZ_CHECK_FORMAT (res3); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || mpz_cmp (ref3, res3) != 0) FAIL2 (mpz_gcdext, in1, in2, NULL); mpz_set (res1, in2); mpz_gcdext (res1, res2, res3, in1, res1); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); MPZ_CHECK_FORMAT (res3); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || mpz_cmp (ref3, res3) != 0) FAIL2 (mpz_gcdext, in1, in2, NULL); mpz_set (res2, in2); mpz_gcdext (res1, res2, res3, in1, res2); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); MPZ_CHECK_FORMAT (res3); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || mpz_cmp (ref3, res3) != 0) FAIL2 (mpz_gcdext, in1, in2, NULL); mpz_set (res3, in2); mpz_gcdext (res1, res2, res3, in1, res3); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); MPZ_CHECK_FORMAT (res3); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || mpz_cmp (ref3, res3) != 0) FAIL2 (mpz_gcdext, in1, in2, NULL); mpz_set (res1, in1); mpz_gcdext (res1, res2, NULL, res1, in2); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || mpz_cmp (ref3, res3) != 0) FAIL2 (mpz_gcdext, in1, in2, NULL); mpz_set (res2, in1); mpz_gcdext (res1, res2, NULL, res2, in2); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || mpz_cmp (ref3, res3) != 0) FAIL2 (mpz_gcdext, in1, in2, NULL); mpz_set (res1, in2); mpz_gcdext (res1, res2, NULL, in1, res1); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || mpz_cmp (ref3, res3) != 0) FAIL2 (mpz_gcdext, in1, in2, NULL); mpz_set (res2, in2); mpz_gcdext (res1, res2, NULL, in1, res2); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || mpz_cmp (ref3, res3) != 0) FAIL2 (mpz_gcdext, in1, in2, NULL); } /* Don't run mpz_powm for huge exponents or when undefined. */ if (size_range < 17 && mpz_sizeinbase (in2, 2) < 250 && mpz_sgn (in3) != 0 && (mpz_sgn (in2) >= 0 || mpz_invert (t, in1, in3))) { mpz_powm (ref1, in1, in2, in3); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, in1); mpz_powm (res1, res1, in2, in3); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL2 (mpz_powm, in1, in2, in3); mpz_set (res1, in2); mpz_powm (res1, in1, res1, in3); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL2 (mpz_powm, in1, in2, in3); mpz_set (res1, in3); mpz_powm (res1, in1, in2, res1); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL2 (mpz_powm, in1, in2, in3); } /* Don't run mpz_powm_ui when undefined. */ if (size_range < 17 && mpz_sgn (in3) != 0) { mpz_powm_ui (ref1, in1, in2i, in3); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, in1); mpz_powm_ui (res1, res1, in2i, in3); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL2 (mpz_powm_ui, in1, in2, in3); mpz_set (res1, in3); mpz_powm_ui (res1, in1, in2i, res1); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL2 (mpz_powm_ui, in1, in2, in3); } { r1 = mpz_gcd_ui (ref1, in1, in2i); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, in1); r2 = mpz_gcd_ui (res1, res1, in2i); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL2 (mpz_gcd_ui, in1, in2, NULL); } if (mpz_sgn (in2) != 0) { /* Test mpz_remove */ mp_bitcnt_t refretval, retval; refretval = mpz_remove (ref1, in1, in2); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, in1); retval = mpz_remove (res1, res1, in2); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0 || refretval != retval) FAIL2 (mpz_remove, in1, in2, NULL); mpz_set (res1, in2); retval = mpz_remove (res1, in1, res1); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0 || refretval != retval) FAIL2 (mpz_remove, in1, in2, NULL); } if (mpz_sgn (in2) != 0) { /* Test mpz_divexact */ mpz_mul (t, in1, in2); mpz_divexact (ref1, t, in2); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, t); mpz_divexact (res1, res1, in2); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL2 (mpz_divexact, t, in2, NULL); mpz_set (res1, in2); mpz_divexact (res1, t, res1); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL2 (mpz_divexact, t, in2, NULL); } if (mpz_sgn (in2) > 0) { /* Test mpz_divexact_gcd, same as mpz_divexact */ mpz_mul (t, in1, in2); mpz_divexact_gcd (ref1, t, in2); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, t); mpz_divexact_gcd (res1, res1, in2); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL2 (mpz_divexact_gcd, t, in2, NULL); mpz_set (res1, in2); mpz_divexact_gcd (res1, t, res1); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL2 (mpz_divexact_gcd, t, in2, NULL); } } if (isatty (fileno (stdout))) printf ("\r%20s", ""); mpz_clear (bs); mpz_clear (in1); mpz_clear (in2); mpz_clear (in3); mpz_clear (ref1); mpz_clear (ref2); mpz_clear (ref3); mpz_clear (res1); mpz_clear (res2); mpz_clear (res3); mpz_clear (t); if (isatty (fileno (stdout))) printf ("\r"); tests_end (); exit (0); }
unsigned int tonelli_shanks(mpz_t num, unsigned int prime) { fprintf(stderr, "shanks for %d\n", prime); mpz_t tmp, mpz_prime, r, c, t, b; mpz_init(tmp); mpz_init(mpz_prime); mpz_init(r); mpz_init(c); mpz_init(t); mpz_init(b); mpz_set_ui(mpz_prime, prime); unsigned int q = prime-1; unsigned int s = 0; while(!(q & 1)) { s += 1; q >>= 1; } unsigned int z; for(z = 2;; ++z) { mpz_set_ui(tmp, z); mpz_powm_ui(tmp, tmp, (prime-1)/2, mpz_prime); if(mpz_cmp_ui(tmp, 1)) break; // found non-quadratic residue } printf("c=%d^%d\n", z, q); // c = z^q mpz_set_ui(tmp, z); mpz_powm_ui(c, tmp, q, mpz_prime); // r = n^(q+1)/2 mpz_powm_ui(r, num, (q+1)/2, mpz_prime); // t = n^q mpz_powm_ui(t, num, q, mpz_prime); // m = s unsigned int m = s; //mpz_set_ui(m, s); // while t != 1 mod p while(mpz_cmp_ui(t, 1)) { mpz_out_str(stderr, 10, t); fputs(", durr\n", stderr); // find smallest i so that t^2^i = 1 mod p mpz_set(tmp, t); unsigned int i; for(i = 1; ;++i) { mpz_powm_ui(tmp, tmp, 2, mpz_prime); mpz_out_str(stderr, 10, tmp); fputs("!\n", stderr); if(!mpz_cmp_ui(tmp, 1)) break; } // TODO: For some reason i >= m here // set b to c^2^(m-i-1) as well, by repeated squaring mpz_set(b, c); printf("m = %d, i = %d\n", m, i); for(size_t foo = 0; foo < m-i-1; ++foo) { mpz_powm_ui(b, b, 2, mpz_prime); } // r = r*b mpz_mul(r, r, b); mpz_mod_ui(r, r, prime); // t = t*b² mpz_mul(t, t, b); mpz_mul(t, t, b); mpz_mod_ui(t, t, prime); // c = b² mpz_mul(c, b, b); mpz_mod_ui(c, c, prime); // m = i m = i; } unsigned int out = mpz_get_ui(r); mpz_clear(r); mpz_clear(c); mpz_clear(t); mpz_clear(b); mpz_clear(tmp); mpz_init(mpz_prime); return out; }
void find_candidates(mpz_t num, mpz_t gmp_root) { num_cands = 0; mpz_add_ui(gmp_root, gmp_root, 1); size_t sieve_size = primes[B-1]*100; double *table = malloc(sizeof(double)*sieve_size); uint64_t root = mpz_get_ui(gmp_root); double approx = mpz_get_d(num); mpz_t tmp, tmp2; mpz_init(tmp); mpz_init(tmp2); mpz_set_ui(tmp, root); mpz_pow_ui(tmp, tmp, 2); mpz_sub(tmp, tmp, num); mpz_set(first_cands[0], tmp); unsigned int used_primes[B]; double used_log[B]; used_primes[0] = 2; used_log[0] = log_primes[0]; size_t next_prime = 1; size_t offsets[B][2]; uint64_t cand_offsets[B+1]; size_t next_cand = 1; // Find prime numbers that appear in the candidate series for(size_t p = 1; p < B; ++p) { unsigned int prime = primes[p]; mpz_set_ui(tmp2, prime); mpz_powm_ui(tmp, num, (prime-1)/2, tmp2); if(mpz_cmp_ui(tmp, 1)) // Skip non-quadratic residues continue; used_primes[next_prime] = prime; used_log[next_prime] = log_primes[p]; // Generate more exact candidates for(int i = next_cand; i < prime; ++i) { mpz_set_ui(tmp, root + i); mpz_pow_ui(tmp, tmp, 2); mpz_sub(tmp, tmp, num); mpz_set(first_cands[i], tmp); } next_cand = prime; // find offsets for them // TODO Shanks-tonelli unsigned int foo = tonelli_shanks(num, prime); printf("root for %u is %u and %u\n", prime, foo, prime-foo); size_t idx = 0; for(int i = 0; i < prime; ++i) { if(mpz_divisible_ui_p(first_cands[i], prime)) { offsets[next_prime][idx++] = i; if(idx == 2) break; } } assert(idx == 2); ++next_prime; } // sieve until we find more than B candidates, guarantees linear dependence size_t sieve_offset = 0; while(num_cands <= B) { for(size_t i = 0; i < sieve_size; ++i) { double d = root + i; d += sieve_offset; table[i] = log(d*d-approx); } // cross out even ones for(size_t i = mpz_tstbit(tmp, 1)^(sieve_offset & 1); i < sieve_size; i+=2) table[i] -= log_primes[0]; for(int p = 1; p < next_prime && num_cands <= B; ++p) { unsigned int prime = used_primes[p]; double log_prime = used_log[p]; // fprintf(stderr, "offsets[%d] are %d and %d\n", used_primes[p], offsets[p][0], offsets[p][1]); for(int x = 0; x < 2; ++x) { size_t off = (offsets[p][x] + sieve_offset + prime-1) % prime; for(int a = off; a < sieve_size; a += prime) { table[a] -= log_prime; if(table[a] > LIMIT) continue; cand_offsets[num_cands++] = root + a + sieve_offset; if(num_cands > B) break; } } } sieve_offset += sieve_size; } for(size_t i = 0; i < num_cands; ++i) { //fprintf(stderr, "%llu\n", cand_offsets[i]); // TODO REMOVE VERY SLOW STUFF mpz_set_ui(tmp, root + i); mpz_pow_ui(tmp, tmp, 2); mpz_sub(tmp, tmp, num); // mpz_out_str(stderr, 10, tmp); // fputc('\n', stderr); } fprintf(stderr, "%d used candidates\n", num_cands); free(table); mpz_clear(tmp); mpz_clear(tmp2); }
/* p-adic logarithm */ void padiclog(mpz_t ans, const mpz_t a, unsigned long p, unsigned long prec, const mpz_t modulo) { /* Compute the p-adic logarithm of a, which is supposed to be congruent to 1 mod p Algorithm: 1. we raise a at the power p^(v-1) (for a suitable v) in order to make it closer to 1 2. we write the new a as a product 1/a = (1 - a_0*p^v) (1 - a_1*p^(2*v) (1 - a_2*p^(4*v) ... with 0 <= a_i < p^(v*2^i). 3. we compute each log(1 - a_i*p^(v*2^i)) using Taylor expansion and a binary spliting strategy. */ unsigned long i, v, e, N, saveN, Np, tmp, trunc, step; double den = log(p); mpz_t f, arg, trunc_mod, h, hpow, mpz_tmp, mpz_tmp2, d, inv, mod2; mpz_t *num, *denom; mpz_init(mpz_tmp); mpz_init(mpz_tmp2); mpz_init(arg); mpz_set_ui(ans, 0); mpz_fdiv_r_ui(mpz_tmp, a, p); mpz_set(arg, a); /* First we make the argument closer to 1 by raising it to the p^(v-1) */ if (prec < p) { v = 0; e = 1; } else { v = (unsigned long)(log(prec)/den); // v here is v-1 e = pow(p,v); mpz_mul_ui(mpz_tmp, modulo, e); mpz_powm_ui(arg, arg, e, mpz_tmp); prec += v; } /* Where do we need to truncate the Taylor expansion */ N = prec+v; N /= ++v; // note the ++v Np = N; den *= v; while(1) { tmp = Np + (unsigned long)(log(N)/den); if (tmp == N) break; N = tmp; } /* We allocate memory and initialize variables */ mpz_init(f); mpz_init(mod2); mpz_init(h); mpz_init(hpow); mpz_init(d); mpz_init(inv); sig_block(); num = (mpz_t*)malloc(N*sizeof(mpz_t)); denom = (mpz_t*)malloc(N*sizeof(mpz_t)); sig_unblock(); for (i = 0; i < N; i++) { mpz_init(num[i]); mpz_init(denom[i]); } trunc = v << 1; mpz_init(trunc_mod); mpz_ui_pow_ui(trunc_mod, p, trunc); while(1) { /* We compute f = 1 - a_i*p^((v+1)*2^i) trunc_mod is p^((v+1)*2^(i+1)) */ mpz_fdiv_r(f, arg, trunc_mod); if (mpz_cmp_ui(f, 1) != 0) { mpz_ui_sub(f, 2, f); mpz_mul(arg, arg, f); /* We compute the Taylor expansion of log(f) For now, computations are carried out over the rationals */ for (i = 0; i < N; i++) { mpz_set_ui(num[i], 1); mpz_set_ui(denom[i], i+1); } step = 1; mpz_ui_sub(h, 1, f); // we write f = 1 - h, i.e. h = a_i*p^(2^i) mpz_set(hpow, h); while(step < N) { for (i = 0; i < N - step; i += step << 1) { mpz_mul(mpz_tmp2, hpow, num[i+step]); mpz_mul(mpz_tmp, mpz_tmp2, denom[i]); mpz_mul(num[i], num[i], denom[i+step]); mpz_add(num[i], num[i], mpz_tmp); mpz_mul(denom[i], denom[i], denom[i+step]); } step <<= 1; mpz_mul(hpow, hpow, hpow); } /* We simplify the fraction */ Np = N; tmp = 0; while(Np > 0) { Np /= p; tmp += Np; } mpz_ui_pow_ui(d, p, tmp); mpz_divexact(mpz_tmp, num[0], d); mpz_divexact(denom[0], denom[0], d); mpz_divexact_ui(h, h, e); mpz_mul(mpz_tmp, h, mpz_tmp); /* We coerce the result from Q to Zp */ mpz_gcdext(d, inv, NULL, denom[0], modulo); mpz_mul(mpz_tmp, mpz_tmp, inv); /* We add this contribution to log(f) */ mpz_add(ans, ans, mpz_tmp); } if (trunc > prec) break; /* We update the variables for the next step */ mpz_mul(trunc_mod, trunc_mod, trunc_mod); trunc <<= 1; for (i = N >> 1; i < N; i++) { mpz_clear(num[i]); mpz_clear(denom[i]); } N >>= 1; } mpz_fdiv_r(ans, ans, modulo); /* We clear memory */ mpz_clear(arg); mpz_clear(f); mpz_clear(trunc_mod); mpz_clear(h); mpz_clear(hpow); mpz_clear(mpz_tmp); mpz_clear(d); mpz_clear(inv); mpz_clear(mod2); for (i = 0; i < N; i++) { mpz_clear(num[i]); mpz_clear(denom[i]); } sig_block(); free(num); free(denom); sig_unblock(); }
int rsa_createkey_ex(PPUBKEY_EX ppubkey,PPRIVKEY_EX pprivkey){ int retval; gmp_randstate_t hrandstate; mpz_t n; mpz_t pminus; mpz_t qminus; mpz_t z; mpz_t gcd; mpz_t dua; // untuk menghitung R2P,R2Q dan R2N //mpz_t d; unsigned long int k_int = 65537; /* inisialisasi semuanya */ gmp_randinit_default(hrandstate); mpz_init(n); mpz_init(pminus); mpz_init(qminus); mpz_init(z); mpz_init(gcd); mpz_init(dua); mpz_init(ppubkey->p); mpz_init(ppubkey->q); mpz_init(ppubkey->e); mpz_init(pprivkey->p); mpz_init(pprivkey->q); mpz_init(pprivkey->d); mpz_init(pprivkey->dp); mpz_init(pprivkey->dq); mpz_init(pprivkey->zp); mpz_init(pprivkey->zq); mpz_init(pprivkey->r2p); mpz_init(pprivkey->r2q); mpz_init(pprivkey->r2n); mpz_init(pprivkey->r2modp); mpz_init(pprivkey->r2modq); /* inisialisasi randomizer */ gmp_randseed_ui(hrandstate,GetTickCount()); /* pick two random prime number (p and q ) */ mpz_urandomb(pprivkey->p,hrandstate,PRIMESIZE); mpz_nextprime(pprivkey->p,pprivkey->p); mpz_urandomb(pprivkey->q,hrandstate,PRIMESIZE); mpz_nextprime(pprivkey->q,pprivkey->q); /* set public key p and q */ mpz_set(ppubkey->p,pprivkey->p); mpz_set(ppubkey->q,pprivkey->q); /* calculate n = (p * q) */ mpz_mul(n,pprivkey->q,pprivkey->p); /* calculate z = (p-1) * ( q - 1) */ mpz_sub_ui(pminus,pprivkey->p,(unsigned int)1); mpz_sub_ui(qminus,pprivkey->q,(unsigned int)1); mpz_mul(z,pminus,qminus); /* choose k, such that k is co-prime to z, i.e z is not divisible by k or in other word gcd(k,z) = 1 */ while(1){ mpz_gcd_ui(gcd,z,k_int); if(mpz_cmp_ui(gcd,(unsigned long)1) == 0) break; k_int +=1; } mpz_set_ui(ppubkey->e,k_int); /* calculate d for e * d = 1 mod z which result d = e^(-1) mod z; */ if(mpz_invert(pprivkey->d,ppubkey->e,z) == 0){ /* cannot find d (multiplicative inverse) */ rsa_cleanup_key(ppubkey,pprivkey); retval = -1; goto closure; } /* dp = d mod (p-1), dq = d mod (q-1) */ mpz_mod(pprivkey->dp,pprivkey->d,pminus); mpz_mod(pprivkey->dq,pprivkey->d,qminus); /* zp = q^(p-1) mod n, zq = p^(q-1) mod n */ mpz_powm(pprivkey->zp,pprivkey->q,pminus,n); mpz_powm(pprivkey->zq,pprivkey->p,qminus,n); /* R2P = 2^(Jml bit P + 2 ) mod q */ mpz_set_ui(dua,2); mpz_powm_ui(pprivkey->r2p,dua,(PRIMESIZE+2),pprivkey->p); /* R2Q = 2^(Jml bit Q + 2 ) mod q */ mpz_powm_ui(pprivkey->r2q,dua,(PRIMESIZE+2),pprivkey->q); /* R2N = 2^(Jml bit N + 2 ) mod n */ mpz_powm_ui(pprivkey->r2n,dua,(BITSTRENGTH+2),n); /* R2MODP = 2^(jml key size + 2) mod P */ mpz_powm_ui(pprivkey->r2modp,dua,(BITSTRENGTH+2),pprivkey->p); /* R2MODQ = 2^(jml key size + 2) mod Q */ mpz_powm_ui(pprivkey->r2modq,dua,(BITSTRENGTH+2),pprivkey->q); retval = 0; goto closure; closure: mpz_clear(n); mpz_clear(pminus); mpz_clear(qminus); mpz_clear(z); mpz_clear(gcd); mpz_clear(dua); return retval; }
void mexp(int k, mpz_t b[k], mpz_t e[k], mpz_t *m, mpz_t *r) { // Main multiexp alg from paper int i, j, jnew, J, l, precompindex, offset,km; unsigned det; int msb_set; unsigned bitlen, maxbitlen = 0; // Setup and precomputation bases = b; modulus = m; numberOfFactors = k; // Compute window size for (i = 0; i < k; i++) { bitlen = mpz_sizeinbase(e[i], 2); if (bitlen > maxbitlen) maxbitlen = bitlen; } // TODO: Make this more elegant double lmb = log(maxbitlen)/log(2); winSize = (int) ceil((lmb - 2*(log(lmb)/log(2))) / k); if(winSize <= 0) winSize =1; // Build up precomputation table precomputation(); km = k -1; mpz_set_ui(*r, 1); // Find maximal bit length of all exponents // Type conversion from unsigned to int. Only a problem for exponents // that have more binary digits than max(int). This is unlikely to occur in practice. // Maybe add check on arg to m_exp() to test for this possible problem? j = maxbitlen - 1; // A-while while (j >= 0) { // check if bit #maxbitlen is zero for all exponents // TODO: in the first iteraration this is the case by def of maxbitlen // -> can we skip first iteration to improve efficiency? msb_set = 0; for(i=0; i< k && msb_set == 0; i++) msb_set = mpz_tstbit(e[i], j); // B-if if (msb_set == 0) { mpz_powm_ui(*r, *r, 2, *m); j--; } // C-else else { if ( (j-winSize) > -1) jnew = j-winSize; else jnew = -1; J = jnew + 1; // D-while (is implemented as do-while) for(;;) { i = km; msb_set = 0; for(i=0; i< k && msb_set == 0; i++) msb_set = mpz_tstbit(e[i], j); if (msb_set == 0) J++; else break; } // E-for precompindex = 0; offset = winSize - (j - J) -1; for (i = km; i >= 0; i--) { // Compute access index into pre-computation table precompindex <<= offset; for (l = j; l >= J; l--) { precompindex <<= 1; precompindex = precompindex | mpz_tstbit(e[i], l); } } // F-while det = 1; det <<= ((j-J)+1); mpz_powm_ui(*r, *r,det, *m); j = J-1; mpz_mul(*r, *r, preCompTable[precompindex]); mpz_mod(*r, *r, *m); // G-while if (j > jnew) { det =1; det <<= (j-jnew); mpz_powm_ui(*r, *r,det, *m); j = jnew + 1; } } } freeMemory(); }
int main (int argc, char **argv) { mpz_t base, exp, mod; mpz_t r1, r2, base2; mp_size_t base_size, exp_size, mod_size; unsigned long int exp2; int i; int reps = 100; gmp_randstate_ptr rands; mpz_t bs; unsigned long bsi, size_range; tests_start (); rands = RANDS; mpz_init (bs); if (argc == 2) reps = atoi (argv[1]); mpz_init (base); mpz_init (exp); mpz_init (mod); mpz_init (r1); mpz_init (r2); mpz_init (base2); for (i = 0; i < reps; i++) { mpz_urandomb (bs, rands, 32); size_range = mpz_get_ui (bs) % 18 + 2; do /* Loop until mathematically well-defined. */ { mpz_urandomb (bs, rands, size_range); base_size = mpz_get_ui (bs); mpz_rrandomb (base, rands, base_size); mpz_urandomb (bs, rands, 6L); exp_size = mpz_get_ui (bs); mpz_rrandomb (exp, rands, exp_size); exp2 = mpz_getlimbn (exp, (mp_size_t) 0); } while (mpz_cmp_ui (base, 0) == 0 && exp2 == 0); do { mpz_urandomb (bs, rands, size_range); mod_size = mpz_get_ui (bs); mpz_rrandomb (mod, rands, mod_size); } while (mpz_cmp_ui (mod, 0) == 0); mpz_urandomb (bs, rands, 2); bsi = mpz_get_ui (bs); if ((bsi & 1) != 0) mpz_neg (base, base); /* printf ("%ld %ld\n", SIZ (base), SIZ (mod)); */ #if 0 putc ('\n', stderr); debug_mp (base, -16); debug_mp (mod, -16); #endif mpz_powm_ui (r1, base, exp2, mod); MPZ_CHECK_FORMAT (r1); mpz_set_ui (r2, 1); mpz_set (base2, base); mpz_mod (r2, r2, mod); /* needed when exp==0 and mod==1 */ while (exp2 != 0) { if (exp2 % 2 != 0) { mpz_mul (r2, r2, base2); mpz_mod (r2, r2, mod); } mpz_mul (base2, base2, base2); mpz_mod (base2, base2, mod); exp2 = exp2 / 2; } #if 0 debug_mp (r1, -16); debug_mp (r2, -16); #endif if (mpz_cmp (r1, r2) != 0) { fprintf (stderr, "\ntest %d: Incorrect results for operands:\n", i); debug_mp (base, -16); debug_mp (exp, -16); debug_mp (mod, -16); fprintf (stderr, "mpz_powm_ui result:\n"); debug_mp (r1, -16); fprintf (stderr, "reference result:\n"); debug_mp (r2, -16); abort (); } } mpz_clear (bs); mpz_clear (base); mpz_clear (exp); mpz_clear (mod); mpz_clear (r1); mpz_clear (r2); mpz_clear (base2); tests_end (); exit (0); }
void field_init_mont_fp(field_ptr f, mpz_t prime) { PBC_ASSERT(!mpz_fits_ulong_p(prime), "modulus too small"); fptr p; field_init(f); f->init = fp_init; f->clear = fp_clear; f->set_si = fp_set_si; f->set_mpz = fp_set_mpz; f->out_str = fp_out_str; f->snprint = fp_snprint; f->set_str = fp_set_str; f->add = fp_add; f->sub = fp_sub; f->set = fp_set; f->mul = fp_mul; f->doub = fp_double; f->halve = fp_halve; f->pow_mpz = fp_pow_mpz; f->neg = fp_neg; f->sign = fp_sgn_odd; f->cmp = fp_cmp; f->invert = fp_invert; f->random = fp_random; f->from_hash = fp_from_hash; f->is1 = fp_is1; f->is0 = fp_is0; f->set0 = fp_set0; f->set1 = fp_set1; f->is_sqr = fp_is_sqr; f->sqrt = element_tonelli; f->field_clear = fp_field_clear; f->to_bytes = fp_to_bytes; f->from_bytes = fp_from_bytes; f->to_mpz = fp_to_mpz; f->out_info = fp_out_info; // Initialize per-field data specific to this implementation. f->data = pbc_malloc(sizeof(*p)); p = (fptr)f->data; p->limbs = mpz_size(prime); p->bytes = p->limbs * sizeof(mp_limb_t); p->primelimbs = (mp_limb_t*)pbc_malloc(p->bytes); mpz_export(p->primelimbs, &p->limbs, -1, sizeof(mp_limb_t), 0, 0, prime); mpz_set(f->order, prime); f->fixed_length_in_bytes = (mpz_sizeinbase(prime, 2) + 7) / 8; // Compute R, R3 and negpinv. mpz_t z; mpz_init(z); p->R = (mp_limb_t*)pbc_malloc(p->bytes); p->R3 = (mp_limb_t*)pbc_malloc(p->bytes); mpz_setbit(z, p->bytes * 8); mpz_mod(z, z, prime); set_limbs(p->R, z, p->limbs); mpz_powm_ui(z, z, 3, prime); set_limbs(p->R3, z, p->limbs); mpz_set_ui(z, 0); // Algorithm II.5 in Blake, Seroussi and Smart is better but this suffices // since we're only doing it once. mpz_setbit(z, p->bytes * 8); mpz_invert(z, prime, z); #ifdef _MSC_VER // for VC++ compatibility int tmp = mpz_get_ui(z); p->negpinv = -tmp; #else p->negpinv = -mpz_get_ui(z); #endif mpz_clear(z); }
/* * This function reads the encrypted query sent by client, computes the intermediate cosine tfidf product and cosine co-ordination factor, * randomizes these two values and writes them along with respective randomizing values into the output_file_name. * */ int read_encrypt_vec_from_file_comp_inter_sec_prod( int vsizelocal, const char * input_encr_tfidf_file_name, const char * input_encr_bin_file_name, const char * input_tfidf_vec_file_name, const char * input_bin_vec_file_name, const char * output_file_name, const char * key_file_name) { int input_size = 0, i, temp, *p_tfidf_vec, *p_bin_vec; mpz_t *vec1; //holds input encrypted tfidf q values mpz_t *vec2; //holds input encrypted binary q values mpz_t cosine_result; mpz_t co_ord_factor; mpz_t random_no; FILE *input_encr_tfidf_file, *input_tfidf_vec_file, *input_bin_vec_file, *output_file, *input_encr_bin_file; vsize = vsizelocal; input_encr_tfidf_file = fopen(input_encr_tfidf_file_name, "r"); input_encr_bin_file = fopen(input_encr_bin_file_name, "r"); input_tfidf_vec_file = fopen(input_tfidf_vec_file_name, "r"); input_bin_vec_file = fopen(input_bin_vec_file_name, "r"); output_file = fopen(output_file_name, "w"); strncpy(g_key_file_name, key_file_name, sizeof(g_key_file_name)); printf("Number of vector dimensions = %d\n", vsizelocal); //printf("p_tfidf_vec:%p, ENOMEM:%d\n", p_tfidf_vec, (errno == ENOMEM)?1:0); //initialize vectors and big number variables //Dynamically creating the array vec1 = (mpz_t *)malloc(vsizelocal*sizeof(mpz_t)); vec2 = (mpz_t *)malloc(vsizelocal*sizeof(mpz_t)); p_tfidf_vec = (int*)malloc(vsize*sizeof(int)); p_bin_vec = (int*)malloc(vsize*sizeof(int)); printf("p_tfidf_vec:%p, ENOMEM:%d\n", p_tfidf_vec, (errno == ENOMEM)?1:0); //initialize vectors and big number variables for (i = 0; i < vsizelocal; i++) mpz_init(*(vec1+i)); for (i = 0; i < vsizelocal; i++) mpz_init(*(vec2+i)); //variables are set to 0 mpz_init(cosine_result); mpz_init(co_ord_factor); mpz_init(random_no); init(); //variables are set to 0 //init(); //check if files are opened properly if (input_encr_tfidf_file == NULL) { printf("\n%s", "Error: open input_encr_tfidf_file!"); return -2; } if (input_encr_bin_file == NULL) { printf("\n%s", "Error: open input_encr_bin_file!"); return -2; } if (input_tfidf_vec_file == NULL) { printf("\n%s", "Error: open input_tfidf_vec_file!"); return -3; } if (input_bin_vec_file == NULL) { printf("\n%s", "Error: open input_bin_vec_file!"); return -4; } if (output_file == NULL) { printf("\n%s", "Error: open output_file!"); exit(1); } //fill in the first vector input_size = 0; while ( (input_size < vsizelocal) ) { if ( input_size == vsizelocal - 1 ) { gmp_fscanf(input_encr_tfidf_file,"%Zd", (vec1+input_size)); } else { gmp_fscanf(input_encr_tfidf_file,"%Zd\n", (vec1+input_size)); } gmp_printf("%d>> READ %Zd\n", input_size+1, *(vec1+input_size)); input_size++; } if ( !( input_size == vsizelocal ) ) { fprintf(stderr, "%s:%d::ERROR! TFIDF: Nothing to read OR parsing error! input_size:%d, vsizelocal:%d\n", __func__, __LINE__, input_size, vsizelocal); return -4; } input_size = 0; while ( (input_size < vsizelocal) ) { if ( input_size == vsizelocal - 1 ) { gmp_fscanf(input_encr_bin_file,"%Zd", (vec2+input_size)); } else { gmp_fscanf(input_encr_bin_file,"%Zd\n", (vec2+input_size)); } gmp_printf("%d>> READ %Zd\n", input_size+1, *(vec2+input_size)); input_size++; } if ( !( input_size == vsizelocal ) ) { fprintf(stderr, "%s:%d::ERROR! Binary: Nothing to read OR parsing error! input_size:%d, vsizelocal:%d\n", __func__, __LINE__, input_size, vsizelocal); return -4; } printf("\n"); input_size = 0; //fill in the second vector for( fscanf(input_tfidf_vec_file,"%d", &temp); temp != EOF && input_size < vsize; fscanf(input_tfidf_vec_file, "%d", &temp) ){ printf("Non encrypted TFIDF Input::Wt.:%d\n", temp); *(p_tfidf_vec + input_size) = temp; input_size ++; } input_size = 0; for( fscanf(input_bin_vec_file,"%d", &temp); temp != EOF && input_size < vsize; fscanf(input_bin_vec_file, "%d", &temp) ){ printf("Non encrypted Binary Input::Wt.:%d\n", temp); *(p_bin_vec + input_size) = temp; input_size ++; } encrypt(cosine_result, 0); //compute encrypted the vec1 * p_tfidf_vec (dot product) for (i = 0; i < input_size; i++) { //compute m1 * m2 mpz_powm_ui(big_temp, *(vec1+i), *(p_tfidf_vec+i), n_square); //compute m1 + m2 mpz_mul(cosine_result, cosine_result, big_temp); mpz_mod(cosine_result, cosine_result, n_square); } encrypt(co_ord_factor, 0); //compute encrypted the vec2 * co_ord_factor (dot product) for (i = 0; i < input_size; i++) { //compute m1 * m2 mpz_powm_ui(big_temp, *(vec2+i), *(p_bin_vec+i), n_square); //compute m1 + m2 mpz_mul(co_ord_factor, co_ord_factor, big_temp); mpz_mod(co_ord_factor, co_ord_factor, n_square); } /* * Donot decrypt here as we would not be having the CORRESPONDING private key * */ //decrypt the encrypted dot product //decrypt(cosine_result); //TODO: Remove this debug decryption. - START mpz_t dot_prod; mpz_init(dot_prod); mpz_set(dot_prod, cosine_result); decrypt(dot_prod); gmp_fprintf(stderr, "\n%s:%d:: Query*%s TFIDF cosine product: %Zd\n", __func__, __LINE__, input_encr_tfidf_file_name, dot_prod); mpz_set(dot_prod, co_ord_factor); decrypt(dot_prod); gmp_fprintf(stderr, "%s:%d:: Query*%s CO-ORD. cosine product: %Zd\n\n", __func__, __LINE__, input_encr_bin_file_name, dot_prod); fflush(stderr); mpz_clear(dot_prod); //TODO: Remove this debug decryption. - END //decrypt the encrypted co ordination factor //decrypt(co_ord_factor); /* * Generate two random numbers of the modulo n_square and the add these two * to the two results - cosine product and co_ord_factor. * Write these two random values one after the other * and then the randomized values after them in the output file * given for performing the secure multiplication * protocol. All should be seperated by a newline except maybe the last one * written to the file. FORMAT - output file * ===START=== * r_1 * randomized cosine tfidf product * r_2 * randomized cosine co-ord. product * ===END=== * */ //Generate random number, say r_1 get_random_r_given_modulo(random_no, n_square); //Write r_1 to outputfile mpz_out_str(output_file, 10, random_no); fprintf(output_file, "\n"); //Calculate randomized cosine tfidf product, MULTIPLYING to add mpz_mul(cosine_result, cosine_result, random_no); //Compute modulus mpz_mod(cosine_result, cosine_result, n_square); //Write randomized cosine tfidf product to output file mpz_out_str(output_file, 10, cosine_result); fprintf(output_file, "\n"); //Generate random number, say r_2 get_random_r_given_modulo(random_no, n_square); //Write r_2 to outputfile mpz_out_str(output_file, 10, random_no); fprintf(output_file, "\n"); //Calculate randomized cosine tfidf product, MULTIPLYING to add mpz_mul(co_ord_factor, co_ord_factor, random_no); //Compute modulus mpz_mod(co_ord_factor, co_ord_factor, n_square); //Write randomized cosine co_ord product to output file mpz_out_str(output_file, 10, co_ord_factor); gmp_printf("\nThus similarity of %s and %s score = %Zd written in %s\n", input_encr_tfidf_file_name, input_tfidf_vec_file_name, cosine_result, output_file_name); #if 0 //print the cosine_result if (mpz_out_str(output_file, 10, cosine_result) == 0) printf("ERROR: Not able to write the cosine_result!\n"); fprintf(output_file, "\n"); #endif gmp_printf("\nThus co-ord. factor of %s and %s score = %Zd written in %s\n", input_encr_bin_file_name, input_bin_vec_file_name, co_ord_factor, output_file_name); #if 0 //print the co_ord_factor if (mpz_out_str(output_file, 10, co_ord_factor) == 0) printf("ERROR: Not able to write the co_ord_factor!\n"); #endif fclose(input_encr_tfidf_file); fclose(input_encr_bin_file); //fflush(input_tfidf_vec_file); fclose(input_tfidf_vec_file); //fflush(input_bin_vec_file); fclose(input_bin_vec_file); fflush(output_file); fclose(output_file); //release space used by big number variables for (i = 0; i < vsizelocal; i++) mpz_clear(*(vec1+i)); for (i = 0; i < vsizelocal; i++) mpz_clear(*(vec2+i)); mpz_clear(cosine_result); mpz_clear(co_ord_factor); mpz_clear(random_no); clear(); free(vec1); free(vec2); free(p_tfidf_vec); free(p_bin_vec); return 0; }