static int mpfr_fsss (mpfr_ptr z, mpfr_srcptr a, mpfr_srcptr c, mpfr_rnd_t rnd) { /* Computes z = a^2 - c^2. Assumes that a and c are finite and non-zero; so a squaring yielding an infinity is an overflow, and a squaring yielding 0 is an underflow. Assumes further that z is distinct from a and c. */ int inex; mpfr_t u, v; /* u=a^2, v=c^2 exactly */ mpfr_init2 (u, 2*mpfr_get_prec (a)); mpfr_init2 (v, 2*mpfr_get_prec (c)); mpfr_sqr (u, a, MPFR_RNDN); mpfr_sqr (v, c, MPFR_RNDN); /* tentatively compute z as u-v; here we need z to be distinct from a and c to not lose the latter */ inex = mpfr_sub (z, u, v, rnd); if (mpfr_inf_p (z)) { /* replace by "correctly rounded overflow" */ mpfr_set_si (z, (mpfr_signbit (z) ? -1 : 1), MPFR_RNDN); inex = mpfr_mul_2ui (z, z, mpfr_get_emax (), rnd); } else if (mpfr_zero_p (u) && !mpfr_zero_p (v)) { /* exactly u underflowed, determine inexact flag */ inex = (mpfr_signbit (u) ? 1 : -1); } else if (mpfr_zero_p (v) && !mpfr_zero_p (u)) { /* exactly v underflowed, determine inexact flag */ inex = (mpfr_signbit (v) ? -1 : 1); } else if (mpfr_nan_p (z) || (mpfr_zero_p (u) && mpfr_zero_p (v))) { /* In the first case, u and v are +inf. In the second case, u and v are zeroes; their difference may be 0 or the least representable number, with a sign to be determined. Redo the computations with mpz_t exponents */ mpfr_exp_t ea, ec; mpz_t eu, ev; /* cheat to work around the const qualifiers */ /* Normalise the input by shifting and keep track of the shifts in the exponents of u and v */ ea = mpfr_get_exp (a); ec = mpfr_get_exp (c); mpfr_set_exp ((mpfr_ptr) a, (mpfr_prec_t) 0); mpfr_set_exp ((mpfr_ptr) c, (mpfr_prec_t) 0); mpz_init (eu); mpz_init (ev); mpz_set_si (eu, (long int) ea); mpz_mul_2exp (eu, eu, 1); mpz_set_si (ev, (long int) ec); mpz_mul_2exp (ev, ev, 1); /* recompute u and v and move exponents to eu and ev */ mpfr_sqr (u, a, MPFR_RNDN); /* exponent of u is non-positive */ mpz_sub_ui (eu, eu, (unsigned long int) (-mpfr_get_exp (u))); mpfr_set_exp (u, (mpfr_prec_t) 0); mpfr_sqr (v, c, MPFR_RNDN); mpz_sub_ui (ev, ev, (unsigned long int) (-mpfr_get_exp (v))); mpfr_set_exp (v, (mpfr_prec_t) 0); if (mpfr_nan_p (z)) { mpfr_exp_t emax = mpfr_get_emax (); int overflow; /* We have a = ma * 2^ea with 1/2 <= |ma| < 1 and ea <= emax. So eu <= 2*emax, and eu > emax since we have an overflow. The same holds for ev. Shift u and v by as much as possible so that one of them has exponent emax and the remaining exponents in eu and ev are the same. Then carry out the addition. Shifting u and v prevents an underflow. */ if (mpz_cmp (eu, ev) >= 0) { mpfr_set_exp (u, emax); mpz_sub_ui (eu, eu, (long int) emax); mpz_sub (ev, ev, eu); mpfr_set_exp (v, (mpfr_exp_t) mpz_get_ui (ev)); /* remaining common exponent is now in eu */ } else { mpfr_set_exp (v, emax); mpz_sub_ui (ev, ev, (long int) emax); mpz_sub (eu, eu, ev); mpfr_set_exp (u, (mpfr_exp_t) mpz_get_ui (eu)); mpz_set (eu, ev); /* remaining common exponent is now also in eu */ } inex = mpfr_sub (z, u, v, rnd); /* Result is finite since u and v have the same sign. */ overflow = mpfr_mul_2ui (z, z, mpz_get_ui (eu), rnd); if (overflow) inex = overflow; } else { int underflow; /* Subtraction of two zeroes. We have a = ma * 2^ea with 1/2 <= |ma| < 1 and ea >= emin and similarly for b. So 2*emin < 2*emin+1 <= eu < emin < 0, and analogously for v. */ mpfr_exp_t emin = mpfr_get_emin (); if (mpz_cmp (eu, ev) <= 0) { mpfr_set_exp (u, emin); mpz_add_ui (eu, eu, (unsigned long int) (-emin)); mpz_sub (ev, ev, eu); mpfr_set_exp (v, (mpfr_exp_t) mpz_get_si (ev)); } else { mpfr_set_exp (v, emin); mpz_add_ui (ev, ev, (unsigned long int) (-emin)); mpz_sub (eu, eu, ev); mpfr_set_exp (u, (mpfr_exp_t) mpz_get_si (eu)); mpz_set (eu, ev); } inex = mpfr_sub (z, u, v, rnd); mpz_neg (eu, eu); underflow = mpfr_div_2ui (z, z, mpz_get_ui (eu), rnd); if (underflow) inex = underflow; } mpz_clear (eu); mpz_clear (ev); mpfr_set_exp ((mpfr_ptr) a, ea); mpfr_set_exp ((mpfr_ptr) c, ec); /* works also when a == c */ } mpfr_clear (u); mpfr_clear (v); return inex; }
int main(int argc, char **argv) { mpz_t year, tmp1, tmp2, tmp3, tmp4; unsigned long day_of_week = 0; uintmax_t month_min = 1, month_max = 12; int_fast8_t month_days = 0; const int_fast8_t months_days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; time_t t = time(NULL); char weekday[13] = {0}, weekdays[92] = {0}, month_name[13] = {0}; struct tm *time_struct = localtime(&t); setlocale(LC_ALL, ""); mpz_init(year); switch(argc) { case 1: mpz_set_ui(year, time_struct->tm_year + 1900); month_min = month_max = time_struct->tm_mon + 1; break; case 2: mpz_set_str(year, argv[1], 10); break; default: month_min = month_max = strtoumax(argv[1], NULL, 10); mpz_set_str(year, argv[2], 10); } if(mpz_sgn(year) < 1 || !month_min || month_min > 12) { fputs("http://opengroup.org/onlinepubs/9699919799/utilities/cal.html\n", stderr); exit(1); } for(int_fast8_t i = 0; i < 7; ++i) { time_struct->tm_wday = i; strftime(weekday, 13, "%a", time_struct); strcat(weekdays, weekday); strcat(weekdays, " "); } strcat(weekdays, "\n"); for(uintmax_t month = month_min; month <= month_max; ++month) { time_struct->tm_mon = month - 1; strftime(month_name, 13, "%b", time_struct); if(month > month_min) putchar('\n'); for(int_fast8_t i = (23 - strlen(mpz_get_str(NULL, 10, year))) / 2; i > 0; --i) putchar(' '); fputs(month_name, stdout); putchar(' '); printf("%s\n", mpz_get_str(NULL, 10, year)); fputs(weekdays, stdout); if(!mpz_cmp_ui(year, 1752) && month == 9) { fputs(" 1 2 14 15 16", stdout); fputs("17 18 19 20 21 22 23", stdout); fputs("24 25 26 27 28 29 30", stdout); } else { month_days = months_days[month - 1]; mpz_init(tmp1); mpz_init(tmp2); mpz_init(tmp3); mpz_init(tmp4); if(mpz_cmp_ui(year, 1752) > 0 || (!mpz_cmp_ui(year, 1752) && month > 9)) { /* Gregorian */ if(month == 2 && mpz_divisible_ui_p(year, 4) && (!mpz_divisible_ui_p(year, 100) || mpz_divisible_ui_p(year, 400))) month_days = 29; mpz_add_ui(tmp4, year, 4800 - (14 - month) / 12); mpz_tdiv_q_ui(tmp1, tmp4, 4); mpz_tdiv_q_ui(tmp2, tmp4, 100); mpz_tdiv_q_ui(tmp3, tmp4, 400); mpz_mul_ui(tmp4, tmp4, 365); mpz_add(tmp4, tmp4, tmp1); mpz_sub(tmp4, tmp4, tmp2); mpz_add(tmp4, tmp4, tmp3); mpz_add_ui(tmp4, tmp4, (153 * (month + 12 * ((14 - month) / 12) - 3) + 2) / 5); mpz_sub_ui(tmp4, tmp4, 32043); day_of_week = mpz_tdiv_ui(tmp4, 7); } else { /* Julian */ if(month == 2 && mpz_divisible_ui_p(year, 4)) month_days = 29; mpz_add_ui(tmp2, year, 4800 - (14 - month) / 12); mpz_tdiv_q_ui(tmp1, tmp2, 4); mpz_mul_ui(tmp2, tmp2, 365); mpz_add(tmp2, tmp2, tmp1); mpz_add_ui(tmp2, tmp2, (153 * (month + 12 * ((14 - month) / 12) - 3) + 2) / 5); mpz_sub_ui(tmp2, tmp2, 32081); day_of_week = mpz_tdiv_ui(tmp2, 7); } mpz_clear(tmp1); mpz_clear(tmp2); mpz_clear(tmp3); mpz_clear(tmp4); for(uint_fast8_t i = 0; i < day_of_week; ++i) fputs(" ", stdout); for(int_fast8_t i = 1; i <= month_days; ++i) { printf("%2u", i); ++day_of_week; if(i < month_days) fputs((day_of_week %= 7) ? " " : "\n", stdout); } } putchar('\n'); } mpz_clear(year); return 0; }
void mpz_bin_ui (mpz_ptr r, mpz_srcptr n, unsigned long int k) { mpz_t ni; mp_limb_t i; mpz_t nacc; mp_limb_t kacc; mp_size_t negate; if (mpz_sgn (n) < 0) { /* bin(n,k) = (-1)^k * bin(-n+k-1,k), and set ni = -n+k-1 - k = -n-1 */ mpz_init (ni); mpz_neg (ni, n); mpz_sub_ui (ni, ni, 1L); negate = (k & 1); /* (-1)^k */ } else { /* bin(n,k) == 0 if k>n (no test for this under the n<0 case, since -n+k-1 >= k there) */ if (mpz_cmp_ui (n, k) < 0) { mpz_set_ui (r, 0L); return; } /* set ni = n-k */ mpz_init (ni); mpz_sub_ui (ni, n, k); negate = 0; } /* Now wanting bin(ni+k,k), with ni positive, and "negate" is the sign (0 for positive, 1 for negative). */ mpz_set_ui (r, 1L); /* Rewrite bin(n,k) as bin(n,n-k) if that is smaller. In this case it's whether ni+k-k < k meaning ni<k, and if so change to denominator ni+k-k = ni, and new ni of ni+k-ni = k. */ if (mpz_cmp_ui (ni, k) < 0) { unsigned long tmp; tmp = k; k = mpz_get_ui (ni); mpz_set_ui (ni, tmp); } kacc = 1; mpz_init_set_ui (nacc, 1L); for (i = 1; i <= k; i++) { mp_limb_t k1, k0; #if 0 mp_limb_t nacclow; int c; nacclow = PTR(nacc)[0]; for (c = 0; (((kacc | nacclow) & 1) == 0); c++) { kacc >>= 1; nacclow >>= 1; } mpz_div_2exp (nacc, nacc, c); #endif mpz_add_ui (ni, ni, 1L); mpz_mul (nacc, nacc, ni); umul_ppmm (k1, k0, kacc, i << GMP_NAIL_BITS); k0 >>= GMP_NAIL_BITS; if (k1 != 0) { /* Accumulator overflow. Perform bignum step. */ mpz_mul (r, r, nacc); mpz_set_ui (nacc, 1L); DIVIDE (); kacc = i; } else { /* Save new products in accumulators to keep accumulating. */ kacc = k0; } } mpz_mul (r, r, nacc); DIVIDE (); SIZ(r) = (SIZ(r) ^ -negate) + negate; mpz_clear (nacc); mpz_clear (ni); }
static PyObject * GMPY_mpz_is_strong_prp(PyObject *self, PyObject *args) { MPZ_Object *a, *n; PyObject *result = 0; mpz_t s, nm1, mpz_test; mp_bitcnt_t r = 0; if (PyTuple_Size(args) != 2) { TYPE_ERROR("is_strong_prp() requires 2 integer arguments"); return NULL; } n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL); a = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL); if (!a || !n) { TYPE_ERROR("is_strong_prp() requires 2 integer arguments"); goto cleanup; } mpz_init(s); mpz_init(nm1); mpz_init(mpz_test); /* Require a >= 2. */ if (mpz_cmp_ui(a->z, 2) < 0) { VALUE_ERROR("is_strong_prp() requires 'a' greater than or equal to 2"); goto cleanup; } /* Require n > 0. */ if (mpz_sgn(n->z) <= 0) { VALUE_ERROR("is_strong_prp() requires 'n' be greater than 0"); goto cleanup; } /* Check for n == 1 */ if (mpz_cmp_ui(n->z, 1) == 0) { result = Py_False; goto cleanup; } /* Handle n even. */ if (mpz_divisible_ui_p(n->z, 2)) { if (mpz_cmp_ui(n->z, 2) == 0) result = Py_True; else result = Py_False; goto cleanup; } /* Check gcd(a,b) */ mpz_gcd(s, n->z, a->z); if (mpz_cmp_ui(s, 1) > 0) { VALUE_ERROR("is_strong_prp() requires gcd(n,a) == 1"); goto cleanup; } mpz_set(nm1, n->z); mpz_sub_ui(nm1, nm1, 1); /* Find s and r satisfying: n-1=(2^r)*s, s odd */ r = mpz_scan1(nm1, 0); mpz_fdiv_q_2exp(s, nm1, r); /* Check a^((2^t)*s) mod n for 0 <= t < r */ mpz_powm(mpz_test, a->z, s, n->z); if ((mpz_cmp_ui(mpz_test, 1) == 0) || (mpz_cmp(mpz_test, nm1) == 0)) { result = Py_True; goto cleanup; } while (--r) { /* mpz_test = mpz_test^2%n */ mpz_mul(mpz_test, mpz_test, mpz_test); mpz_mod(mpz_test, mpz_test, n->z); if (mpz_cmp(mpz_test, nm1) == 0) { result = Py_True; goto cleanup; } } result = Py_False; cleanup: Py_XINCREF(result); mpz_clear(s); mpz_clear(nm1); mpz_clear(mpz_test); Py_XDECREF((PyObject*)a); Py_XDECREF((PyObject*)n); return result; }
static PyObject * GMPY_mpz_is_lucas_prp(PyObject *self, PyObject *args) { MPZ_Object *n, *p, *q; PyObject *result = 0; mpz_t zD, res, index; /* used for calculating the Lucas U sequence */ mpz_t uh, vl, vh, ql, qh, tmp; mp_bitcnt_t s = 0, j = 0; int ret; if (PyTuple_Size(args) != 3) { TYPE_ERROR("is_lucas_prp() requires 3 integer arguments"); return NULL; } mpz_init(zD); mpz_init(res); mpz_init(index); mpz_init(uh); mpz_init(vl); mpz_init(vh); mpz_init(ql); mpz_init(qh); mpz_init(tmp); n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL); p = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL); q = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 2), NULL); if (!n || !p || !q) { TYPE_ERROR("is_lucas_prp() requires 3 integer arguments"); goto cleanup; } /* Check if p*p - 4*q == 0. */ mpz_mul(zD, p->z, p->z); mpz_mul_ui(tmp, q->z, 4); mpz_sub(zD, zD, tmp); if (mpz_sgn(zD) == 0) { VALUE_ERROR("invalid values for p,q in is_lucas_prp()"); goto cleanup; } /* Require n > 0. */ if (mpz_sgn(n->z) <= 0) { VALUE_ERROR("is_lucas_prp() requires 'n' be greater than 0"); goto cleanup; } /* Check for n == 1 */ if (mpz_cmp_ui(n->z, 1) == 0) { result = Py_False; goto cleanup; } /* Handle n even. */ if (mpz_divisible_ui_p(n->z, 2)) { if (mpz_cmp_ui(n->z, 2) == 0) result = Py_True; else result = Py_False; goto cleanup; } /* Check GCD */ mpz_mul(res, zD, q->z); mpz_mul_ui(res, res, 2); mpz_gcd(res, res, n->z); if ((mpz_cmp(res, n->z) != 0) && (mpz_cmp_ui(res, 1) > 0)) { VALUE_ERROR("is_lucas_prp() requires gcd(n,2*q*D) == 1"); goto cleanup; } /* index = n-(D/n), where (D/n) is the Jacobi symbol */ mpz_set(index, n->z); ret = mpz_jacobi(zD, n->z); if (ret == -1) mpz_add_ui(index, index, 1); else if (ret == 1) mpz_sub_ui(index, index, 1); /* mpz_lucasumod(res, p, q, index, n); */ mpz_set_si(uh, 1); mpz_set_si(vl, 2); mpz_set(vh, p->z); mpz_set_si(ql, 1); mpz_set_si(qh, 1); mpz_set_si(tmp,0); s = mpz_scan1(index, 0); for (j = mpz_sizeinbase(index,2)-1; j >= s+1; j--) { /* ql = ql*qh (mod n) */ mpz_mul(ql, ql, qh); mpz_mod(ql, ql, n->z); if (mpz_tstbit(index,j) == 1) { /* qh = ql*q */ mpz_mul(qh, ql, q->z); /* uh = uh*vh (mod n) */ mpz_mul(uh, uh, vh); mpz_mod(uh, uh, n->z); /* vl = vh*vl - p*ql (mod n) */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); /* vh = vh*vh - 2*qh (mod n) */ mpz_mul(vh, vh, vh); mpz_mul_si(tmp, qh, 2); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n->z); } else { /* qh = ql */ mpz_set(qh, ql); /* uh = uh*vl - ql (mod n) */ mpz_mul(uh, uh, vl); mpz_sub(uh, uh, ql); mpz_mod(uh, uh, n->z); /* vh = vh*vl - p*ql (mod n) */ mpz_mul(vh, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n->z); /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); } } /* ql = ql*qh */ mpz_mul(ql, ql, qh); /* qh = ql*q */ mpz_mul(qh, ql, q->z); /* uh = uh*vl - ql */ mpz_mul(uh, uh, vl); mpz_sub(uh, uh, ql); /* vl = vh*vl - p*ql */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); /* ql = ql*qh */ mpz_mul(ql, ql, qh); for (j = 1; j <= s; j++) { /* uh = uh*vl (mod n) */ mpz_mul(uh, uh, vl); mpz_mod(uh, uh, n->z); /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); /* ql = ql*ql (mod n) */ mpz_mul(ql, ql, ql); mpz_mod(ql, ql, n->z); } /* uh contains our return value */ mpz_mod(res, uh, n->z); if (mpz_cmp_ui(res, 0) == 0) result = Py_True; else result = Py_False; cleanup: Py_XINCREF(result); mpz_clear(zD); mpz_clear(res); mpz_clear(index); mpz_clear(uh); mpz_clear(vl); mpz_clear(vh); mpz_clear(ql); mpz_clear(qh); mpz_clear(tmp); Py_XDECREF((PyObject*)p); Py_XDECREF((PyObject*)q); Py_XDECREF((PyObject*)n); return result; }
int main(void) { mpz_t p, q, N, d; mpz_t dmp1, dmq1; mpz_t ipmq, iqmp; mpz_t adq, adp; field_t f; element_t a, b; double t0, t1, tnaive = 0, tcrt=0; int i, n; mpz_init(p); mpz_init(q); mpz_init(N); mpz_init(d); mpz_init(dmp1); mpz_init(dmq1); mpz_init(ipmq); mpz_init(iqmp); mpz_init(adp); mpz_init(adq); pbc_mpz_randomb(p, 512); pbc_mpz_randomb(q, 512); mpz_nextprime(p, p); mpz_nextprime(q, q); mpz_mul(N, p, q); mpz_invert(ipmq, p, q); mpz_invert(iqmp, q, p); field_init_fp(f, N); element_init(a, f); element_init(b, f); n = 10; for (i=0; i<n; i++) { pbc_mpz_random(d, N); element_random(a); t0 = pbc_get_time(); element_pow_mpz(b, a, d); t1 = pbc_get_time(); tnaive += t1 - t0; mpz_sub_ui(p, p, 1); mpz_sub_ui(q, q, 1); mpz_mod(dmp1, d, p); mpz_mod(dmq1, d, q); mpz_add_ui(p, p, 1); mpz_add_ui(q, q, 1); element_to_mpz(adq, a); element_to_mpz(adp, a); t0 = pbc_get_time(); mpz_powm(adp, adp, d, p); mpz_powm(adq, adq, d, q); /* textbook CRT mpz_mul(adp, adp, q); mpz_mul(adp, adp, iqmp); mpz_mul(adq, adq, p); mpz_mul(adq, adq, ipmq); mpz_add(adp, adp, adq); */ // Garner's algorithm mpz_sub(adq, adq, adp); mpz_mul(adq, adq, ipmq); mpz_mod(adq, adq, q); mpz_mul(adq, adq, p); mpz_add(adp, adp, adq); t1 = pbc_get_time(); tcrt += t1 - t0; element_set_mpz(b, adp); } printf("average RSA exp time = %lf\n", tnaive / n); printf("average RSA exp time (CRT) = %lf\n", tcrt / n); return 0; }
static void derive_rsa_keys(MP_INT *n, MP_INT *e, MP_INT *d, MP_INT *u, MP_INT *p, MP_INT *q, unsigned int ebits) { MP_INT p_minus_1, q_minus_1, aux, phi, G, F; assert(mpz_cmp(p, q) < 0); mpz_init(&p_minus_1); mpz_init(&q_minus_1); mpz_init(&aux); mpz_init(&phi); mpz_init(&G); mpz_init(&F); /* Compute p-1 and q-1. */ mpz_sub_ui(&p_minus_1, p, 1); mpz_sub_ui(&q_minus_1, q, 1); /* phi = (p - 1) * (q - 1); the number of positive integers less than p*q that are relatively prime to p*q. */ mpz_mul(&phi, &p_minus_1, &q_minus_1); /* G is the number of "spare key sets" for a given modulus n. The smaller G is, the better. The smallest G can get is 2. */ mpz_gcd(&G, &p_minus_1, &q_minus_1); if (rsa_verbose) { if (mpz_cmp_ui(&G, 100) >= 0) { fprintf(stderr, "Warning: G="); mpz_out_str(stdout, 10, &G); fprintf(stderr, " is large (many spare key sets); key may be bad!\n"); } } /* F = phi / G; the number of relative prime numbers per spare key set. */ mpz_div(&F, &phi, &G); /* Find a suitable e (the public exponent). */ mpz_set_ui(e, 1); mpz_mul_2exp(e, e, ebits); mpz_sub_ui(e, e, 1); /* make lowest bit 1, and substract 2. */ /* Keep adding 2 until it is relatively prime to (p-1)(q-1). */ do { mpz_add_ui(e, e, 2); mpz_gcd(&aux, e, &phi); } while (mpz_cmp_ui(&aux, 1) != 0); /* d is the multiplicative inverse of e, mod F. Could also be mod (p-1)(q-1); however, we try to choose the smallest possible d. */ mpz_mod_inverse(d, e, &F); /* u is the multiplicative inverse of p, mod q, if p < q. It is used when doing private key RSA operations using the chinese remainder theorem method. */ mpz_mod_inverse(u, p, q); /* n = p * q (the public modulus). */ mpz_mul(n, p, q); /* Clear auxiliary variables. */ mpz_clear(&p_minus_1); mpz_clear(&q_minus_1); mpz_clear(&aux); mpz_clear(&phi); mpz_clear(&G); mpz_clear(&F); }
void pbc_param_init_e_gen(pbc_param_t par, int rbits, int qbits) { e_init(par); e_param_ptr p = par->data; //3 takes 2 bits to represent int hbits = (qbits - 2) / 2 - rbits; mpz_ptr q = p->q; mpz_ptr r = p->r; mpz_ptr h = p->h; mpz_t n; field_t Fq; field_t cc; element_t j; int found = 0; //won't find any curves is hbits is too low if (hbits < 3) hbits = 3; mpz_init(n); do { int i; mpz_set_ui(r, 0); if (rand() % 2) { p->exp2 = rbits - 1; p->sign1 = 1; } else { p->exp2 = rbits; p->sign1 = -1; } mpz_setbit(r, p->exp2); p->exp1 = (rand() % (p->exp2 - 1)) + 1; //use q as a temp variable mpz_set_ui(q, 0); mpz_setbit(q, p->exp1); if (p->sign1 > 0) { mpz_add(r, r, q); } else { mpz_sub(r, r, q); } if (rand() % 2) { p->sign0 = 1; mpz_add_ui(r, r, 1); } else { p->sign0 = -1; mpz_sub_ui(r, r, 1); } if (!mpz_probab_prime_p(r, 10)) continue; for (i=0; i<10; i++) { //use q as a temp variable mpz_set_ui(q, 0); mpz_setbit(q, hbits + 1); pbc_mpz_random(h, q); mpz_mul(h, h, h); mpz_mul_ui(h, h, 3); //finally q takes the value it should mpz_mul(n, r, r); mpz_mul(n, n, h); mpz_add_ui(q, n, 1); if (mpz_probab_prime_p(q, 10)) { found = 1; break; } } } while (!found); /* do { mpz_set_ui(r, 0); mpz_setbit(r, rbits); pbc_mpz_random(r, r); mpz_nextprime(r, r); mpz_mul(n, r, r); mpz_mul_ui(n, n, 3); mpz_add_ui(q, n, 1); } while (!mpz_probab_prime_p(q, 10)); */ field_init_fp(Fq, q); element_init(j, Fq); element_set_si(j, 1); field_init_curve_b(cc, j, n, NULL); element_clear(j); // We may need to twist it. { // Pick a random point P and twist the curve if P has the wrong order. element_t P; element_init(P, cc); element_random(P); element_mul_mpz(P, P, n); if (!element_is0(P)) field_reinit_curve_twist(cc); element_clear(P); } element_to_mpz(p->a, curve_field_a_coeff(cc)); element_to_mpz(p->b, curve_field_b_coeff(cc)); mpz_clear(n); }
/* This generates p,q params using the B.3.2.2 algorithm in FIPS 186-4. * * The hash function used is SHA384. * The exponent e used is the value in pub->e. */ int _rsa_generate_fips186_4_keypair(struct rsa_public_key *pub, struct rsa_private_key *key, unsigned seed_length, uint8_t * seed, void *progress_ctx, nettle_progress_func * progress, /* Desired size of modulo, in bits */ unsigned n_size) { mpz_t t, r, p1, q1, lcm; int ret; struct dss_params_validation_seeds cert; unsigned l = n_size / 2; if (_gnutls_fips_mode_enabled() != 0) { if (n_size == 2048) { if (seed_length != 14 * 2) { _gnutls_debug_log("Seed length must be 28 bytes (it is %d)\n", seed_length); return 0; } } else if (n_size == 3072) { if (seed_length != 16 * 2) { _gnutls_debug_log("Seed length must be 32 bytes (it is %d)\n", seed_length); return 0; } } else { _gnutls_debug_log("Unsupported size for modulus\n"); return 0; } } if (!mpz_tstbit(pub->e, 0)) { _gnutls_debug_log("Unacceptable e (it is even)\n"); return 0; } if (mpz_cmp_ui(pub->e, 65536) <= 0) { _gnutls_debug_log("Unacceptable e\n"); return 0; } mpz_init(p1); mpz_init(q1); mpz_init(lcm); mpz_init(t); mpz_init(r); mpz_set_ui(t, 1); mpz_mul_2exp(t, t, 256); if (mpz_cmp(pub->e, t) >= 0) { ret = 0; goto cleanup; } cert.pseed_length = sizeof(cert.pseed); ret = rsa_provable_prime(key->p, &cert.pseed_length, cert.pseed, l, seed_length, seed, pub->e, progress_ctx, progress); if (ret == 0) { goto cleanup; } mpz_set_ui(r, 1); mpz_mul_2exp(r, r, (l) - 100); do { cert.qseed_length = sizeof(cert.qseed); ret = rsa_provable_prime(key->q, &cert.qseed_length, cert.qseed, l, cert.pseed_length, cert.pseed, pub->e, progress_ctx, progress); if (ret == 0) { goto cleanup; } cert.pseed_length = cert.qseed_length; memcpy(cert.pseed, cert.qseed, cert.qseed_length); if (mpz_cmp(key->p, key->q) > 0) mpz_sub(t, key->p, key->q); else mpz_sub(t, key->q, key->p); } while (mpz_cmp(t, r) <= 0); memset(&cert, 0, sizeof(cert)); mpz_mul(pub->n, key->p, key->q); assert(mpz_sizeinbase(pub->n, 2) == n_size); /* c = q^{-1} (mod p) */ assert(mpz_invert(key->c, key->q, key->p) != 0); mpz_sub_ui(p1, key->p, 1); mpz_sub_ui(q1, key->q, 1); mpz_lcm(lcm, p1, q1); if (mpz_invert(key->d, pub->e, lcm) == 0) { ret = 0; goto cleanup; } /* Done! Almost, we must compute the auxillary private values. */ /* a = d % (p-1) */ mpz_fdiv_r(key->a, key->d, p1); /* b = d % (q-1) */ mpz_fdiv_r(key->b, key->d, q1); /* c was computed earlier */ pub->size = key->size = (n_size + 7) / 8; assert(pub->size >= RSA_MINIMUM_N_OCTETS); ret = 1; cleanup: mpz_clear(p1); mpz_clear(q1); mpz_clear(lcm); mpz_clear(t); mpz_clear(r); return ret; }
int main (int argc, char *argv[]) { char *progname = argv[0]; mpz_t fr, to; mpz_t fr2, to2; unsigned long sieve_lim; unsigned long est_n_primes; unsigned char *s; mpz_t tmp; mpz_t siev_sqr_lim; while (argc != 1) { if (strcmp (argv[1], "-c") == 0) { flag_count = 1; argv++; argc--; } else if (strcmp (argv[1], "-p") == 0) { flag_print = 2; argv++; argc--; } else if (strcmp (argv[1], "-g") == 0) { flag_maxgap = 1; argv++; argc--; } else break; } if (flag_count || flag_maxgap) flag_print--; /* clear unless an explicit -p */ mpz_init (fr); mpz_init (to); mpz_init (fr2); mpz_init (to2); if (argc == 3) { mpz_set_str (fr, argv[1], 0); if (argv[2][0] == '+') { mpz_set_str (to, argv[2] + 1, 0); mpz_add (to, to, fr); } else mpz_set_str (to, argv[2], 0); } else if (argc == 2) { mpz_set_ui (fr, 0); mpz_set_str (to, argv[1], 0); } else { fprintf (stderr, "usage: %s [-c] [-p] [-g] [from [+]]to\n", progname); exit (1); } mpz_set (fr2, fr); if (mpz_cmp_ui (fr2, 3) < 0) { mpz_set_ui (fr2, 2); report (fr2); mpz_set_ui (fr2, 3); } mpz_setbit (fr2, 0); /* make odd */ mpz_sub_ui (to2, to, 1); mpz_setbit (to2, 0); /* make odd */ mpz_init (tmp); mpz_init (siev_sqr_lim); mpz_sqrt (tmp, to2); #define SIEVE_LIMIT 10000000 if (mpz_cmp_ui (tmp, SIEVE_LIMIT) < 0) { sieve_lim = mpz_get_ui (tmp); } else { sieve_lim = SIEVE_LIMIT; mpz_sub (tmp, to2, fr2); if (mpz_cmp_ui (tmp, sieve_lim) < 0) sieve_lim = mpz_get_ui (tmp); /* limit sieving for small ranges */ } mpz_set_ui (siev_sqr_lim, sieve_lim + 1); mpz_mul_ui (siev_sqr_lim, siev_sqr_lim, sieve_lim + 1); est_n_primes = (size_t) (sieve_lim / log((double) sieve_lim) * 1.13) + 10; primes = malloc (est_n_primes * sizeof primes[0]); make_primelist (sieve_lim); assert (est_n_primes >= n_primes); #if DEBUG printf ("sieve_lim = %lu\n", sieve_lim); printf ("n_primes = %lu (3..%u)\n", n_primes, primes[n_primes - 1].prime); #endif #define S (1 << 15) /* FIXME: Figure out L1 cache size */ s = malloc (S/2); while (mpz_cmp (fr2, to2) <= 0) { unsigned long rsize; rsize = S; mpz_add_ui (tmp, fr2, rsize); if (mpz_cmp (tmp, to2) > 0) { mpz_sub (tmp, to2, fr2); rsize = mpz_get_ui (tmp) + 2; } #if DEBUG printf ("Sieving region ["); mpz_out_str (stdout, 10, fr2); printf (","); mpz_add_ui (tmp, fr2, rsize - 2); mpz_out_str (stdout, 10, tmp); printf ("]\n"); #endif sieve_region (s, fr2, rsize); find_primes (s, fr2, rsize / 2, siev_sqr_lim); mpz_add_ui (fr2, fr2, S); } free (s); if (flag_count) printf ("Pi(interval) = %lu\n", total_primes); if (flag_maxgap) printf ("max gap: %lu\n", maxgap); return 0; }
int rsa_generate_key(rsa_private_key_t *key, int key_size) { mpz_t e, p, q, n, t1, t2, phi, d, u; /* bit_size must be even */ if (key_size & 0x01) key_size++; /* we use e = 65537 */ mpz_init_set_ui(e, 65537); mpz_init2(p, key_size / 2 + GMP_NUMB_BITS); mpz_init2(q, key_size / 2 + GMP_NUMB_BITS); mpz_init2(n, key_size + GMP_NUMB_BITS); mpz_init2(t1, key_size / 2 + GMP_NUMB_BITS); mpz_init2(t2, key_size / 2 + GMP_NUMB_BITS); mpz_init2(phi, key_size + GMP_NUMB_BITS); mpz_init2(d, key_size + GMP_NUMB_BITS); mpz_init2(u, key_size / 2 + GMP_NUMB_BITS); do { /* get prime p */ mpz_urandomb(p, NULL, key_size / 2); mpz_setbit(p, 0); mpz_setbit(p, key_size / 2 - 1); mpz_setbit(p, key_size / 2 - 2); mpz_nextprime(p, p); mpz_sub_ui(t1, p, 1); mpz_gcd(phi, e, t1); if (mpz_cmp_ui(phi, 1) != 0) continue; /* get prime q */ mpz_urandomb(q, NULL, key_size / 2); mpz_setbit(q, 0); mpz_setbit(q, key_size / 2 - 1); mpz_setbit(q, key_size / 2 - 2); mpz_nextprime(q, q); mpz_sub_ui(t2, q, 1); mpz_gcd(phi, e, t1); if (mpz_cmp_ui(phi, 1) != 0) continue; /* p shall be smaller than q */ if (mpz_cmp(p, q) > 0) mpz_swap(p, q); /* calculate the modulus */ mpz_mul(n, p, q); } while (mpz_sizeinbase(n, 2) != key_size); /* calculate Euler totient: phi = (p-1)(q-1) */ mpz_mul(phi, t1, t2); /* calculate the secret key d = e^(-1) mod phi */ mpz_invert(d, e, phi); /* calculate the inverse of p and q (used for chinese remainder theorem) */ mpz_invert(u, p, q); /* setup private key */ mpz_init_set(key->n, n); mpz_init_set(key->e, e); mpz_init_set(key->p, p); mpz_init_set(key->q, q); mpz_init_set(key->d, d); mpz_init_set(key->u, u); key->size = key_size; /* release helper variables */ mpz_clear(e); mpz_clear(p); mpz_clear(q); mpz_clear(n); mpz_clear(t1); mpz_clear(t2); mpz_clear(phi); mpz_clear(d); mpz_clear(u); /* test key */ if (rsa_test_key(key) != 0) { rsa_release_private_key(key); return -1; } return 0; }
/*-------------------------------------------------------------------*/ static uint32 get_final_sqrt(msieve_obj *obj, gmp_poly_t *alg_poly, gmp_poly_t *prod, gmp_poly_t *isqrt_mod_q, mpz_t q) { /* the main q-adic Newton iteration. On input, isqrt_mod_q contains the starting value of the reciprocal square root R[0](x) of the polynomial prod(x). The iteration is R[k](x) = R[k-1](x) * (3 - prod(x)*R[k-1](x)^2) / 2 mod (q^(2^k)) and at the end of iteration k, prod(x)*R[k-1](x)^2 mod (q^(2^k)) is 1. We keep iterating until q^(2^k) is larger than the size of the coefficients of the square root (i.e. about half the size of the coefficients of prod(x)). Then the square root to use is R[k](x) * prod(x) mod (q^(2^k)), which is written to isqrt_mod_q */ uint32 i, j; uint32 prod_bits, prod_max_bits; uint32 num_iter; /* initialize */ gmp_poly_bits(prod, &prod_bits, &prod_max_bits); /* since prod(x) only matters mod q^(2^(final_k)), we can cut the memory use in half by changing prod(x) to this. Remember final_k as well */ i = mpz_get_ui(q); for (num_iter = 0; mpz_sizeinbase(q, 2) < prod_max_bits / 2 + 4000; num_iter++) { mpz_mul(q, q, q); } gmp_poly_mod_q(prod, q, prod); mpz_set_ui(q, (unsigned long)i); mpz_realloc2(q, 33); /* do the main iteration */ for (i = 0; i < num_iter; i++) { gmp_poly_t tmp_poly; /* square the previous modulus */ mpz_mul(q, q, q); /* compute prod(x) * (previous R)^2 */ gmp_poly_init(&tmp_poly); gmp_poly_mod_q(prod, q, &tmp_poly); gmp_poly_mul(&tmp_poly, isqrt_mod_q, alg_poly, 0); gmp_poly_mod_q(&tmp_poly, q, &tmp_poly); gmp_poly_mul(&tmp_poly, isqrt_mod_q, alg_poly, 0); gmp_poly_mod_q(&tmp_poly, q, &tmp_poly); /* compute ( (3 - that) / 2 ) mod q */ mpz_sub_ui(tmp_poly.coeff[0], tmp_poly.coeff[0], (unsigned long)3); for (j = 0; j <= tmp_poly.degree; j++) { mpz_t *c = tmp_poly.coeff + j; if (mpz_sgn(*c) != 0) { mpz_neg(*c, *c); if (mpz_tstbit(*c, (unsigned long)0)) mpz_add(*c, *c, q); mpz_tdiv_q_2exp(*c, *c, (unsigned long)1); } } /* finally, compute the new R(x) by multiplying the result above by the old R(x) */ gmp_poly_mul(&tmp_poly, isqrt_mod_q, alg_poly, 1); gmp_poly_mod_q(&tmp_poly, q, isqrt_mod_q); gmp_poly_clear(&tmp_poly); } /* attempt to compute the square root. First multiply R(x) by prod(x), deleting prod(x) since we won't need it beyond this point */ gmp_poly_mul(isqrt_mod_q, prod, alg_poly, 1); gmp_poly_mod_q(isqrt_mod_q, q, isqrt_mod_q); /* this is a little tricky. Up until now we've been working modulo big numbers, but the coef- ficients of the square root are just integers, and may be negative. Negative numbers mod q have a numerical value near that of +q, but we want the square root to have a negative coef- ficient in that case. Hence, if the top few words of any coefficent of the square root match the top few words of q, we assume this coefficient is negative and subtract q from it. Theoretically we could be wrong, and the coefficient really is supposed to be a big positive number near q in size. However, if q is thousands of bits larger than the size we expect for the square root coefficients, this is so unlikely that it's not worth worrying about */ for (i = 0; i <= isqrt_mod_q->degree; i++) { mpz_t *c = isqrt_mod_q->coeff + i; size_t limbs = mpz_size(*c); if (limbs == mpz_size(q) && mpz_getlimbn(*c, (mp_size_t)(limbs-1)) == mpz_getlimbn(q, (mp_size_t)(limbs-1)) && mpz_getlimbn(*c, (mp_size_t)(limbs-2)) == mpz_getlimbn(q, (mp_size_t)(limbs-2)) && mpz_getlimbn(*c, (mp_size_t)(limbs-3)) == mpz_getlimbn(q, (mp_size_t)(limbs-3))) { mpz_sub(*c, *c, q); } } /* another heuristic: we will assume the Newton iteration has converged if, after applying the correction above for negative square root coefficients, the total number of bits in the coefficients of the resulting polynomial is much smaller than we would expect from random polynomials modulo q */ gmp_poly_bits(isqrt_mod_q, &prod_bits, &i); if (prod_bits >= (isqrt_mod_q->degree + 1) * mpz_sizeinbase(q, 2) - 100) { logprintf(obj, "Newton iteration failed to converge\n"); return 0; } return 1; }
unsigned long tiny_evaluate_candidate(linalg_t * la_inf, QS_t * qs_inf, poly_t * poly_inf, unsigned long i, unsigned char * sieve) { unsigned long bits, exp, extra_bits, modp, prime; unsigned long num_primes = qs_inf->num_primes; prime_t * factor_base = qs_inf->factor_base; unsigned long * soln1 = poly_inf->soln1; unsigned long * soln2 = poly_inf->soln2; unsigned long * small = la_inf->small; fac_t * factor = la_inf->factor; unsigned long A = poly_inf->A; unsigned long B = poly_inf->B; unsigned long num_factors = 0; unsigned long j; mpz_t * C = &poly_inf->C; unsigned long relations = 0; double pinv; mpz_t X, Y, res, p; mpz_init(X); mpz_init(Y); mpz_init(res); mpz_init(p); #if POLYS printf("X = %ld\n", i); printf("%ldX^2+2*%ldX+%ld\n", A, B, C); #endif mpz_set_ui(X, i); mpz_sub_ui(X, X, SIEVE_SIZE/2); //X mpz_mul_ui(Y, X, A); if ((long) B < 0) { mpz_sub_ui(Y, Y, -B); // Y = AX+B mpz_sub_ui(res, Y, -B); } else { mpz_add_ui(Y, Y, B); mpz_add_ui(res, Y, B); } mpz_mul(res, res, X); mpz_add(res, res, *C); // res = AX^2+2BX+C bits = mpz_sizeinbase(res, 2); bits -= 10; extra_bits = 0; mpz_set_ui(p, 2); // divide out by powers of 2 exp = mpz_remove(res, res, p); #if RELATIONS if (exp) printf("2^%ld ", exp); #endif extra_bits += exp; small[1] = exp; if (factor_base[0].p != 1) // divide out powers of the multiplier { mpz_set_ui(p, factor_base[0].p); exp = mpz_remove(res, res, p); if (exp) extra_bits += exp*qs_inf->sizes[0]; small[0] = exp; #if RELATIONS if (exp) printf("%ld^%ld ", factor_base[0].p, exp); #endif } else small[0] = 0; for (j = 2; j < SMALL_PRIMES; j++) // pull out small primes { prime = factor_base[j].p; pinv = factor_base[j].pinv; modp = z_mod_64_precomp(i, prime, pinv); if ((modp == soln1[j]) || (modp == soln2[j])) { mpz_set_ui(p, prime); exp = mpz_remove(res, res, p); if (exp) extra_bits += qs_inf->sizes[j]; small[j] = exp; #if RELATIONS if (exp) gmp_printf("%Zd^%ld ", p, exp); #endif } else small[j] = 0; } if (extra_bits + sieve[i] > bits) { sieve[i] += extra_bits; for (j = SMALL_PRIMES; (j < num_primes) && (extra_bits < sieve[i]); j++) // pull out remaining primes { prime = factor_base[j].p; pinv = factor_base[j].pinv; modp = z_mod_64_precomp(i, prime, pinv); if (soln2[j] != -1L) { if ((modp == soln1[j]) || (modp == soln2[j])) { mpz_set_ui(p, prime); exp = mpz_remove(res, res, p); #if RELATIONS if (exp) gmp_printf("%Zd^%ld ", p, exp); #endif if (exp) { extra_bits += qs_inf->sizes[j]; factor[num_factors].ind = j; factor[num_factors++].exp = exp; } } } else { mpz_set_ui(p, prime); exp = mpz_remove(res, res, p); factor[num_factors].ind = j; factor[num_factors++].exp = exp+1; #if RELATIONS if (exp) gmp_printf("%Zd^%ld ", p, exp); #endif } } if (mpz_cmpabs_ui(res, 1) == 0) // We've found a relation { unsigned long * A_ind = poly_inf->A_ind; unsigned long i; for (i = 0; i < poly_inf->s; i++) // Commit any outstanding A factors { if (A_ind[i] >= j) { factor[num_factors].ind = A_ind[i]; factor[num_factors++].exp = 1; } } la_inf->num_factors = num_factors; relations += tiny_insert_relation(la_inf, poly_inf, Y); // Insert the relation in the matrix if (la_inf->num_relations >= 2*(qs_inf->num_primes + EXTRA_RELS + 100)) { printf("Error: too many duplicate relations!\n"); abort(); } goto cleanup; } } #if RELATIONS printf("\n"); #endif cleanup: mpz_clear(X); mpz_clear(Y); mpz_clear(res); mpz_clear(p); return relations; }
int main (void) { mpz_t z; int got; const char *expr; int error = 0; tests_start (); mpz_init (z); mpz_set_ui (z, 0L); expr = "0"; EXPECT (mpz_fits_ulong_p, 1); EXPECT (mpz_fits_uint_p, 1); EXPECT (mpz_fits_ushort_p, 1); EXPECT (mpz_fits_slong_p, 1); EXPECT (mpz_fits_sint_p, 1); EXPECT (mpz_fits_sshort_p, 1); mpz_set_ui (z, 1L); expr = "1"; EXPECT (mpz_fits_ulong_p, 1); EXPECT (mpz_fits_uint_p, 1); EXPECT (mpz_fits_ushort_p, 1); EXPECT (mpz_fits_slong_p, 1); EXPECT (mpz_fits_sint_p, 1); EXPECT (mpz_fits_sshort_p, 1); mpz_set_si (z, -1L); expr = "-1"; EXPECT (mpz_fits_ulong_p, 0); EXPECT (mpz_fits_uint_p, 0); EXPECT (mpz_fits_ushort_p, 0); EXPECT (mpz_fits_slong_p, 1); EXPECT (mpz_fits_sint_p, 1); EXPECT (mpz_fits_sshort_p, 1); mpz_set_ui (z, 1L); mpz_mul_2exp (z, z, 5L*GMP_LIMB_BITS); expr = "2^(5*BPML)"; EXPECT (mpz_fits_ulong_p, 0); EXPECT (mpz_fits_uint_p, 0); EXPECT (mpz_fits_ushort_p, 0); EXPECT (mpz_fits_slong_p, 0); EXPECT (mpz_fits_sint_p, 0); EXPECT (mpz_fits_sshort_p, 0); mpz_set_ui (z, (unsigned long) USHRT_MAX); expr = "USHRT_MAX"; EXPECT (mpz_fits_ulong_p, 1); EXPECT (mpz_fits_uint_p, 1); EXPECT (mpz_fits_ushort_p, 1); mpz_set_ui (z, (unsigned long) USHRT_MAX); mpz_add_ui (z, z, 1L); expr = "USHRT_MAX + 1"; EXPECT (mpz_fits_ushort_p, 0); mpz_set_ui (z, (unsigned long) UINT_MAX); expr = "UINT_MAX"; EXPECT (mpz_fits_ulong_p, 1); EXPECT (mpz_fits_uint_p, 1); mpz_set_ui (z, (unsigned long) UINT_MAX); mpz_add_ui (z, z, 1L); expr = "UINT_MAX + 1"; EXPECT (mpz_fits_uint_p, 0); mpz_set_ui (z, ULONG_MAX); expr = "ULONG_MAX"; EXPECT (mpz_fits_ulong_p, 1); mpz_set_ui (z, ULONG_MAX); mpz_add_ui (z, z, 1L); expr = "ULONG_MAX + 1"; EXPECT (mpz_fits_ulong_p, 0); mpz_set_si (z, (long) SHRT_MAX); expr = "SHRT_MAX"; EXPECT (mpz_fits_slong_p, 1); EXPECT (mpz_fits_sint_p, 1); EXPECT (mpz_fits_sshort_p, 1); mpz_set_si (z, (long) SHRT_MAX); mpz_add_ui (z, z, 1L); expr = "SHRT_MAX + 1"; EXPECT (mpz_fits_sshort_p, 0); mpz_set_si (z, (long) INT_MAX); expr = "INT_MAX"; EXPECT (mpz_fits_slong_p, 1); EXPECT (mpz_fits_sint_p, 1); mpz_set_si (z, (long) INT_MAX); mpz_add_ui (z, z, 1L); expr = "INT_MAX + 1"; EXPECT (mpz_fits_sint_p, 0); mpz_set_si (z, LONG_MAX); expr = "LONG_MAX"; EXPECT (mpz_fits_slong_p, 1); mpz_set_si (z, LONG_MAX); mpz_add_ui (z, z, 1L); expr = "LONG_MAX + 1"; EXPECT (mpz_fits_slong_p, 0); mpz_set_si (z, (long) SHRT_MIN); expr = "SHRT_MIN"; EXPECT (mpz_fits_slong_p, 1); EXPECT (mpz_fits_sint_p, 1); EXPECT (mpz_fits_sshort_p, 1); mpz_set_si (z, (long) SHRT_MIN); mpz_sub_ui (z, z, 1L); expr = "SHRT_MIN + 1"; EXPECT (mpz_fits_sshort_p, 0); mpz_set_si (z, (long) INT_MIN); expr = "INT_MIN"; EXPECT (mpz_fits_slong_p, 1); EXPECT (mpz_fits_sint_p, 1); mpz_set_si (z, (long) INT_MIN); mpz_sub_ui (z, z, 1L); expr = "INT_MIN + 1"; EXPECT (mpz_fits_sint_p, 0); mpz_set_si (z, LONG_MIN); expr = "LONG_MIN"; EXPECT (mpz_fits_slong_p, 1); mpz_set_si (z, LONG_MIN); mpz_sub_ui (z, z, 1L); expr = "LONG_MIN + 1"; EXPECT (mpz_fits_slong_p, 0); if (error) abort (); mpz_clear (z); tests_end (); exit (0); }
int main (int argc, char **argv) { mpz_t op1, op2, r1, r2; mp_size_t op1n, op2n; unsigned long int op2long; int i; int reps = 100000; 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 (op1); mpz_init (op2); mpz_init (r1); mpz_init (r2); for (i = 0; i < reps; i++) { mpz_urandomb (bs, rands, 32); size_range = mpz_get_ui (bs) % 10 + 2; mpz_urandomb (bs, rands, size_range); op1n = mpz_get_ui (bs); mpz_rrandomb (op1, rands, op1n); mpz_urandomb (bs, rands, size_range); op2n = mpz_get_ui (bs); mpz_rrandomb (op2, rands, op2n); mpz_urandomb (bs, rands, 2); bsi = mpz_get_ui (bs); if ((bsi & 1) != 0) mpz_neg (op1, op1); if ((bsi & 2) != 0) mpz_neg (op2, op2); /* printf ("%ld %ld\n", SIZ (multiplier), SIZ (multiplicand)); */ mpz_add (r1, op1, op2); mpz_sub (r2, r1, op2); if (mpz_cmp (r2, op1) != 0) dump_abort (i, "mpz_add or mpz_sub incorrect", op1, op2); if (mpz_fits_ulong_p (op2)) { op2long = mpz_get_ui (op2); mpz_add_ui (r1, op1, op2long); mpz_sub_ui (r2, r1, op2long); if (mpz_cmp (r2, op1) != 0) dump_abort (i, "mpz_add_ui or mpz_sub_ui incorrect", op1, op2); mpz_ui_sub (r1, op2long, op1); mpz_sub_ui (r2, op1, op2long); mpz_neg (r2, r2); if (mpz_cmp (r1, r2) != 0) dump_abort (i, "mpz_add_ui or mpz_ui_sub incorrect", op1, op2); } } mpz_clear (bs); mpz_clear (op1); mpz_clear (op2); mpz_clear (r1); mpz_clear (r2); tests_end (); exit (0); }
static int rsa_provable_prime (mpz_t p, unsigned *prime_seed_length, void *prime_seed, unsigned bits, unsigned seed_length, const void *seed, mpz_t e, void *progress_ctx, nettle_progress_func * progress) { mpz_t x, t, s, r1, r2, p0, sq; int ret; unsigned pcounter = 0; unsigned iterations; unsigned storage_length = 0, i; uint8_t *storage = NULL; uint8_t pseed[MAX_PVP_SEED_SIZE+1]; unsigned pseed_length = sizeof(pseed), tseed_length; unsigned max = bits*5; mpz_init(p0); mpz_init(sq); mpz_init(x); mpz_init(t); mpz_init(s); mpz_init(r1); mpz_init(r2); /* p1 = p2 = 1 */ ret = st_provable_prime(p0, &pseed_length, pseed, NULL, 1+div_ceil(bits,2), seed_length, seed, progress_ctx, progress); if (ret == 0) { goto cleanup; } iterations = div_ceil(bits, DIGEST_SIZE*8); mpz_set_ui(x, 0); if (iterations > 0) { storage_length = iterations * DIGEST_SIZE; storage = malloc(storage_length); if (storage == NULL) { goto fail; } nettle_mpz_set_str_256_u(s, pseed_length, pseed); for (i = 0; i < iterations; i++) { tseed_length = mpz_seed_sizeinbase_256_u(s, pseed_length); if (tseed_length > sizeof(pseed)) goto fail; nettle_mpz_get_str_256(tseed_length, pseed, s); hash(&storage[(iterations - i - 1) * DIGEST_SIZE], tseed_length, pseed); mpz_add_ui(s, s, 1); } nettle_mpz_set_str_256_u(x, storage_length, storage); } /* x = sqrt(2)*2^(bits-1) + (x mod 2^(bits) - sqrt(2)*2(bits-1)) */ /* sq = sqrt(2)*2^(bits-1) */ mpz_set_ui(r1, 1); mpz_mul_2exp(r1, r1, 2*bits-1); mpz_sqrt(sq, r1); /* r2 = 2^bits - sq */ mpz_set_ui(r2, 1); mpz_mul_2exp(r2, r2, bits); mpz_sub(r2, r2, sq); /* x = sqrt(2)*2^(bits-1) + (x mod (2^L - sqrt(2)*2^(bits-1)) */ mpz_mod(x, x, r2); mpz_add(x, x, sq); /* y = p2 = p1 = 1 */ /* r1 = (2 y p0 p1) */ mpz_mul_2exp(r1, p0, 1); /* r2 = 2 p0 p1 p2 (p2=y=1) */ mpz_set(r2, r1); /* r1 = (2 y p0 p1) + x */ mpz_add(r1, r1, x); /* t = ((2 y p0 p1) + x) / (2 p0 p1 p2) */ mpz_cdiv_q(t, r1, r2); retry: /* p = t p2 - y = t - 1 */ mpz_sub_ui(p, t, 1); /* p = 2(tp2-y)p0p1 */ mpz_mul(p, p, p0); mpz_mul_2exp(p, p, 1); /* p = 2(tp2-y)p0p1 + 1*/ mpz_add_ui(p, p, 1); mpz_set_ui(r2, 1); mpz_mul_2exp(r2, r2, bits); if (mpz_cmp(p, r2) > 0) { /* t = (2 y p0 p1) + sqrt(2)*2^(bits-1) / (2p0p1p2) */ mpz_set(r1, p0); /* r1 = (2 y p0 p1) */ mpz_mul_2exp(r1, r1, 1); /* sq = sqrt(2)*2^(bits-1) */ /* r1 = (2 y p0 p1) + sq */ mpz_add(r1, r1, sq); /* r2 = 2 p0 p1 p2 */ mpz_mul_2exp(r2, p0, 1); /* t = ((2 y p0 p1) + sq) / (2 p0 p1 p2) */ mpz_cdiv_q(t, r1, r2); } pcounter++; /* r2 = p - 1 */ mpz_sub_ui(r2, p, 1); /* r1 = GCD(p1, e) */ mpz_gcd(r1, e, r2); if (mpz_cmp_ui(r1, 1) == 0) { mpz_set_ui(x, 0); /* a = 0 */ if (iterations > 0) { for (i = 0; i < iterations; i++) { tseed_length = mpz_seed_sizeinbase_256_u(s, pseed_length); if (tseed_length > sizeof(pseed)) goto fail; nettle_mpz_get_str_256(tseed_length, pseed, s); hash(&storage[(iterations - i - 1) * DIGEST_SIZE], tseed_length, pseed); mpz_add_ui(s, s, 1); } nettle_mpz_set_str_256_u(x, storage_length, storage); } /* a = 2 + a mod p-3 */ mpz_sub_ui(r1, p, 3); /* p is too large to worry about negatives */ mpz_mod(x, x, r1); mpz_add_ui(x, x, 2); /* z = a^(2(tp2-y)p1) mod p */ /* r1 = (tp2-y) */ mpz_sub_ui(r1, t, 1); /* r1 = 2(tp2-y)p1 */ mpz_mul_2exp(r1, r1, 1); /* z = r2 = a^r1 mod p */ mpz_powm(r2, x, r1, p); mpz_sub_ui(r1, r2, 1); mpz_gcd(x, r1, p); if (mpz_cmp_ui(x, 1) == 0) { mpz_powm(r1, r2, p0, p); if (mpz_cmp_ui(r1, 1) == 0) { if (prime_seed_length != NULL) { tseed_length = mpz_seed_sizeinbase_256_u(s, pseed_length); if (tseed_length > sizeof(pseed)) goto fail; nettle_mpz_get_str_256(tseed_length, pseed, s); if (*prime_seed_length < tseed_length) { *prime_seed_length = tseed_length; goto fail; } *prime_seed_length = tseed_length; if (prime_seed != NULL) memcpy(prime_seed, pseed, tseed_length); } ret = 1; goto cleanup; } } } if (pcounter >= max) { goto fail; } mpz_add_ui(t, t, 1); goto retry; fail: ret = 0; cleanup: free(storage); mpz_clear(p0); mpz_clear(sq); mpz_clear(r1); mpz_clear(r2); mpz_clear(x); mpz_clear(t); mpz_clear(s); return ret; }
int main(long argc, char *argv[]) { if(argc != 4) { printf("three arguments required\n"); exit(1); } mpz_t n, buffer1, buffer2; mpz_init(n); mpz_init(buffer1); mpz_init(buffer2); mpz_ui_pow_ui(n, atol(argv[2]), atol(argv[3])); mpz_mul_ui(n, n, atol(argv[1])); uint64_t crn = lpow(n, 1, 3); uint64_t srn = lpow(n, 1, 2); uint64_t ttrn = lpow(n, 2, 3); uint64_t start_block = 1; uint64_t finish_block = ttrn/crn; size_t psize = (size_t)(((1.26*crn)/log(crn) + 1) * sizeof(uint64_t)); uint64_t* primes = (uint64_t*)malloc(psize); assert(primes!=NULL); uint64_t pi_crn = sieve(crn, primes); int8_t* mu = malloc(sizeof(int8_t) * (crn+1)); //mu will run from 1 to crn with s[0] not used assert(mu != NULL); memset(mu, 1, sizeof(int8_t) * (crn+1)); uint64_t* lpf = malloc(sizeof(uint64_t) * (crn+1)); //lpf will run from 1 to crn with s[0] not used assert(lpf != NULL); memset(lpf, 0, sizeof(uint64_t) * (crn+1)); uint64_t i, j; for(i=1; i<=pi_crn; i++) for(j=primes[i]; j<=crn; j+=primes[i]) { mu[j] = -mu[j]; if(lpf[j] == 0) lpf[j] = primes[i]; } for(i=1; i<=pi_crn; i++) for(j=sqr(primes[i]); j<=crn; j+=sqr(primes[i])) mu[j]=0; //remove numbers that are not squarefree uint64_t blocksize = crn; uint64_t num_blocks = ttrn/blocksize; assert(start_block <= finish_block); assert(finish_block <= num_blocks); mpz_t S2_result; mpz_init(S2_result); uint64_t* s = malloc((crn/64+2)*sizeof(uint64_t)); assert(s != NULL); uint64_t* phi = malloc((pi_crn+1)*sizeof(uint64_t)); memset(phi, 0, (pi_crn+1)*sizeof(uint64_t)); int64_t* cum_mu = malloc((pi_crn+1)*sizeof(int64_t)); memset(cum_mu, 0, (pi_crn+1)*sizeof(int64_t)); uint64_t p, f, m, k, start, q, block_id, first_m, last_m, L, U, first_f; //Experimental mod 30 sieve uint64_t wheel_size = (crn + PREV[crn % MOD])/MOD * GROUPS + POS[crn % MOD]; uint64_t* s2 = malloc((wheel_size/64 + 2) * sizeof(uint64_t)); for(block_id = start_block; block_id <= finish_block; block_id++) { memset(s, ~0, sizeof(uint64_t) * (crn/64+2)); memset(s2, ~0, sizeof(uint64_t) * (wheel_size/64+2)); L = (block_id -1)*blocksize + 1; U = L + blocksize; for(i=1; i<=pi_crn; i++) { p = primes[i]; mpz_fdiv_q_ui(buffer1, n, L*p); mpz_fdiv_q_ui(buffer2, n, U*p); first_m = mpz_get_ui(buffer1); last_m = mpz_get_ui(buffer2); if(first_m > crn) first_m = crn; if(last_m > first_m) last_m = first_m; if(p > first_m) break; start = L; for(m = first_m; m > last_m && p*m > crn ; m--) { if(mu[m] != 0 && p < lpf[m] && p*m > crn && m <= crn) { cum_mu[i] += -mu[m]; mpz_fdiv_q_ui(buffer1, n, p*m); q = mpz_get_ui(buffer1); assert(q>=L); assert(q<=U); phi[i] += sieve_count(s, i, start, q, L, U, s2); start = q+1; if(mu[m] > 0) mpz_sub_ui(S2_result, S2_result, mu[m] * phi[i]); else mpz_add_ui(S2_result, S2_result, -mu[m] * phi[i]); } } phi[i] += sieve_count(s, i, start, U - 1, L, U, s2); sieve_step(s, U, L, p, s2); } } uint64_t short_block_length = ttrn % blocksize; if(short_block_length>0) { //short block L = L + blocksize; U = L + short_block_length; memset(s, ~0, sizeof(uint64_t) * (crn/64+2)); for(i=1; i<=pi_crn; i++) { start = L; p = primes[i]; mpz_fdiv_q_ui(buffer1, n, L*p); mpz_fdiv_q_ui(buffer2, n, U*p); first_m = mpz_get_ui(buffer1); last_m = mpz_get_ui(buffer2); if(first_m > crn) first_m = crn; if(last_m > first_m) last_m = first_m; if(p > first_m) break; for(m=first_m; m>last_m && p*m>crn ; m--) { if(mu[m]!=0 && p<lpf[m] && p*m>crn && m<=crn) { mpz_fdiv_q_ui(buffer1, n, p*m); q = mpz_get_ui(buffer1); assert(q>=L); assert(q<=U); phi[i] += count_bits(s, start - L, q - L); start = q+1; if(mu[m] > 0) mpz_sub_ui(S2_result, S2_result, mu[m]*phi[i]); else mpz_add_ui(S2_result, S2_result, -mu[m]*phi[i]); } } sieve_step(s, U, L, p, s2); } } mpz_out_str (stdout, 10, S2_result); printf("\n"); mpz_clears(buffer1, buffer2, n, S2_result, NULL); free(s); free(phi); free(primes); free(mu); free(lpf); free(cum_mu); free(s2); return(0); }
// x in Z_r, g, h in some group of order r // finds x such that g^x = h void element_dlog_pollard_rho(element_t x, element_t g, element_t h) { // see Blake, Seroussi and Smart // only one snark for this implementation int i, s = 20; field_ptr Zr = x->field, G = g->field; element_t asum; element_t bsum; element_t *a = _alloca(s * sizeof(element_t)); element_t *b = _alloca(s * sizeof(element_t)); element_t *m = _alloca(s * sizeof(element_t)); element_t g0, snark; darray_t hole; int interval = 5; mpz_t counter; int found = 0; mpz_init(counter); element_init(g0, G); element_init(snark, G); element_init(asum, Zr); element_init(bsum, Zr); darray_init(hole); //set up multipliers for (i = 0; i < s; i++) { element_init(a[i], Zr); element_init(b[i], Zr); element_init(m[i], G); element_random(a[i]); element_random(b[i]); element_pow_zn(g0, g, a[i]); element_pow_zn(m[i], h, b[i]); element_mul(m[i], m[i], g0); } element_random(asum); element_random(bsum); element_pow_zn(g0, g, asum); element_pow_zn(snark, h, bsum); element_mul(snark, snark, g0); record(asum, bsum, snark, hole, counter); for (;;) { int len = element_length_in_bytes(snark); unsigned char *buf = pbc_malloc(len); unsigned char hash = 0; element_to_bytes(buf, snark); for (i = 0; i < len; i++) { hash += buf[i]; } i = hash % s; pbc_free(buf); element_mul(snark, snark, m[i]); element_add(asum, asum, a[i]); element_add(bsum, bsum, b[i]); for (i = 0; i < hole->count; i++) { snapshot_ptr ss = hole->item[i]; if (!element_cmp(snark, ss->snark)) { element_sub(bsum, bsum, ss->b); element_sub(asum, ss->a, asum); //answer is x such that x * bsum = asum //complications arise if gcd(bsum, r) > 1 //which can happen if r is not prime if (!mpz_probab_prime_p(Zr->order, 10)) { mpz_t za, zb, zd, zm; mpz_init(za); mpz_init(zb); mpz_init(zd); mpz_init(zm); element_to_mpz(za, asum); element_to_mpz(zb, bsum); mpz_gcd(zd, zb, Zr->order); mpz_divexact(zm, Zr->order, zd); mpz_divexact(zb, zb, zd); //if zd does not divide za there is no solution mpz_divexact(za, za, zd); mpz_invert(zb, zb, zm); mpz_mul(zb, za, zb); mpz_mod(zb, zb, zm); do { element_pow_mpz(g0, g, zb); if (!element_cmp(g0, h)) { element_set_mpz(x, zb); break; } mpz_add(zb, zb, zm); mpz_sub_ui(zd, zd, 1); } while (mpz_sgn(zd)); mpz_clear(zm); mpz_clear(za); mpz_clear(zb); mpz_clear(zd); } else { element_div(x, asum, bsum); } found = 1; break; } } if (found) break; mpz_add_ui(counter, counter, 1); if (mpz_tstbit(counter, interval)) { record(asum, bsum, snark, hole, counter); interval++; } } for (i = 0; i < s; i++) { element_clear(a[i]); element_clear(b[i]); element_clear(m[i]); } element_clear(g0); element_clear(snark); for (i = 0; i < hole->count; i++) { snapshot_ptr ss = hole->item[i]; element_clear(ss->a); element_clear(ss->b); element_clear(ss->snark); pbc_free(ss); } darray_clear(hole); element_clear(asum); element_clear(bsum); mpz_clear(counter); }
void rsa_private(MP_INT *output, MP_INT *input, RSAPrivateKey *prv) { MP_INT dp, dq, p2, q2, k; /* Initialize temporary variables. */ mpz_init(&dp); mpz_init(&dq); mpz_init(&p2); mpz_init(&q2); mpz_init(&k); /* Compute dp = d mod p-1. */ mpz_sub_ui(&dp, &prv->p, 1); mpz_mod(&dp, &prv->d, &dp); /* Compute dq = d mod q-1. */ mpz_sub_ui(&dq, &prv->q, 1); mpz_mod(&dq, &prv->d, &dq); /* Compute p2 = (input mod p) ^ dp mod p. */ mpz_mod(&p2, input, &prv->p); mpz_powm(&p2, &p2, &dp, &prv->p); /* Compute q2 = (input mod q) ^ dq mod q. */ mpz_mod(&q2, input, &prv->q); mpz_powm(&q2, &q2, &dq, &prv->q); /* Compute k = ((q2 - p2) mod q) * u mod q. */ mpz_sub(&k, &q2, &p2); mpz_mul(&k, &k, &prv->u); mpz_mmod(&k, &k, &prv->q); /* Compute output = p2 + p * k. */ mpz_mul(output, &prv->p, &k); mpz_add(output, output, &p2); /* Clear temporary variables. */ mpz_clear(&dp); mpz_clear(&dq); mpz_clear(&p2); mpz_clear(&q2); mpz_clear(&k); }
int _dsa_validate_dss_pq(struct dsa_params *pub, struct dss_params_validation_seeds *cert) { int ret; unsigned p_bits, q_bits; struct dsa_params pub2; struct dss_params_validation_seeds cert2; mpz_t r, s; p_bits = mpz_sizeinbase(pub->p, 2); q_bits = mpz_sizeinbase(pub->q, 2); ret = _dsa_check_qp_sizes(q_bits, p_bits, 0); if (ret == 0) { return 0; } mpz_init(r); mpz_init(s); dsa_params_init(&pub2); nettle_mpz_set_str_256_u(s, cert->seed_length, cert->seed); /* firstseed < 2^(N-1) */ mpz_set_ui(r, 1); mpz_mul_2exp(r, r, q_bits - 1); if (mpz_cmp(s, r) < 0) { goto fail; } /* 2^N <= q */ mpz_set_ui(r, 1); mpz_mul_2exp(r, r, q_bits); if (mpz_cmp(r, pub->q) <= 0) { goto fail; } /* 2^L <= p */ mpz_set_ui(r, 1); mpz_mul_2exp(r, r, p_bits); if (mpz_cmp(r, pub->p) <= 0) { goto fail; } /* p-1 mod q != 0 */ mpz_set(r, pub->p); mpz_sub_ui(r, r, 1); mpz_mod(r, r, pub->q); if (mpz_cmp_ui(r, 0) != 0) { goto fail; } /* replay the construction */ ret = _dsa_generate_dss_pq(&pub2, &cert2, cert->seed_length, cert->seed, NULL, NULL, p_bits, q_bits); if (ret == 0) { goto fail; } if ((cert->pseed_length > 0 && cert->pseed_length != cert2.pseed_length) || (cert->qseed_length > 0 && cert->qseed_length != cert2.qseed_length) || (cert->pgen_counter > 0 && cert->pgen_counter != cert2.pgen_counter) || (cert->qgen_counter > 0 && cert->qgen_counter != cert2.qgen_counter) || (cert->qseed_length > 0 && memcmp(cert->qseed, cert2.qseed, cert2.qseed_length) != 0) || (cert->pseed_length > 0 && memcmp(cert->pseed, cert2.pseed, cert2.pseed_length) != 0)) { goto fail; } if (mpz_cmp(pub->q, pub2.q) != 0) { goto fail; } if (mpz_cmp(pub->p, pub2.p) != 0) { goto fail; } if (mpz_sizeinbase(s, 2) < q_bits - 1) { goto fail; } ret = 1; goto finish; fail: ret = 0; finish: dsa_params_clear(&pub2); mpz_clear(r); mpz_clear(s); return ret; }
static PyObject * GMPY_mpz_is_euler_prp(PyObject *self, PyObject *args) { MPZ_Object *a, *n; PyObject *result = 0; mpz_t res, exp; int ret; if (PyTuple_Size(args) != 2) { TYPE_ERROR("is_euler_prp() requires 2 integer arguments"); return NULL; } n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL); a = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL); if (!a || !n) { TYPE_ERROR("is_euler_prp() requires 2 integer arguments"); goto cleanup; } mpz_init(res); mpz_init(exp); /* Require a >= 2. */ if (mpz_cmp_ui(a->z, 2) < 0) { VALUE_ERROR("is_euler_prp() requires 'a' greater than or equal to 2"); goto cleanup; } /* Require n > 0. */ if (mpz_sgn(n->z) <= 0) { VALUE_ERROR("is_euler_prp() requires 'n' be greater than 0"); goto cleanup; } /* Check for n == 1 */ if (mpz_cmp_ui(n->z, 1) == 0) { result = Py_False; goto cleanup; } /* Handle n even. */ if (mpz_divisible_ui_p(n->z, 2)) { if (mpz_cmp_ui(n->z, 2) == 0) result = Py_True; else result = Py_False; goto cleanup; } /* Check gcd(a,b) */ mpz_gcd(res, n->z, a->z); if (mpz_cmp_ui(res, 1) > 0) { VALUE_ERROR("is_euler_prp() requires gcd(n,a) == 1"); goto cleanup; } mpz_set(exp, n->z); mpz_sub_ui(exp, exp, 1); mpz_divexact_ui(exp, exp, 2); mpz_powm(res, a->z, exp, n->z); /* reuse exp to calculate jacobi(a,n) mod n */ ret = mpz_jacobi(a->z,n->z); mpz_set(exp, n->z); if (ret == -1) mpz_sub_ui(exp, exp, 1); else if (ret == 1) mpz_add_ui(exp, exp, 1); mpz_mod(exp, exp, n->z); if (mpz_cmp(res, exp) == 0) result = Py_True; else result = Py_False; cleanup: Py_XINCREF(result); mpz_clear(res); mpz_clear(exp); Py_XDECREF((PyObject*)a); Py_XDECREF((PyObject*)n); return result; }
int _dsa_validate_dss_g(struct dsa_params *pub, unsigned domain_seed_size, const uint8_t *domain_seed, unsigned index) { int ret; unsigned p_bits, q_bits; struct dsa_params pub2; mpz_t r; p_bits = mpz_sizeinbase(pub->p, 2); q_bits = mpz_sizeinbase(pub->q, 2); ret = _dsa_check_qp_sizes(q_bits, p_bits, 0); if (ret == 0) { return 0; } mpz_init(r); dsa_params_init(&pub2); mpz_set(pub2.p, pub->p); mpz_set(pub2.q, pub->q); /* verify g */ if (index > 255) { goto fail; } /* 2<= g <= p-1 */ mpz_set(r, pub->p); mpz_sub_ui(r, r, 1); if (mpz_cmp_ui(pub->g, 2) < 0 || mpz_cmp(pub->g, r) >= 0) { goto fail; } /* g^q == 1 mod p */ mpz_powm(r, pub->g, pub->q, pub->p); if (mpz_cmp_ui(r, 1) != 0) { goto fail; } /* repeat g generation */ ret = _dsa_generate_dss_g(&pub2, domain_seed_size, domain_seed, NULL, NULL, index); if (ret == 0) { goto fail; } if (mpz_cmp(pub->g, pub2.g) != 0) { goto fail; } /* everything looks ok */ ret = 1; goto finish; fail: ret = 0; finish: dsa_params_clear(&pub2); mpz_clear(r); return ret; }
static PyObject * GMPY_mpz_is_fermat_prp(PyObject *self, PyObject *args) { MPZ_Object *a, *n; PyObject *result = 0; mpz_t res, nm1; if (PyTuple_Size(args) != 2) { TYPE_ERROR("is_fermat_prp() requires 2 integer arguments"); return NULL; } n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL); a = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL); if (!a || !n) { TYPE_ERROR("is_fermat_prp() requires 2 integer arguments"); goto cleanup; } mpz_init(res); mpz_init(nm1); /* Require a >= 2. */ if (mpz_cmp_ui(a->z, 2) < 0) { VALUE_ERROR("is_fermat_prp() requires 'a' greater than or equal to 2"); goto cleanup; } /* Require n > 0. */ if (mpz_sgn(n->z) <= 0) { VALUE_ERROR("is_fermat_prp() requires 'n' be greater than 0"); goto cleanup; } /* Check for n == 1 */ if (mpz_cmp_ui(n->z, 1) == 0) { result = Py_False; goto cleanup; } /* Handle n even. */ /* Should n even raise an exception? */ if (mpz_divisible_ui_p(n->z, 2)) { if (mpz_cmp_ui(n->z, 2) == 0) result = Py_True; else result = Py_False; goto cleanup; } /* Check gcd(a,n) */ mpz_gcd(res, n->z, a->z); if (mpz_cmp_ui(res, 1) > 0) { VALUE_ERROR("is_fermat_prp() requires gcd(n,a) == 1"); goto cleanup; } mpz_set(nm1, n->z); mpz_sub_ui(nm1, nm1, 1); mpz_powm(res, a->z, nm1, n->z); if (mpz_cmp_ui(res, 1) == 0) result = Py_True; else result = Py_False; cleanup: Py_XINCREF(result); mpz_clear(res); mpz_clear(nm1); Py_XDECREF((PyObject*)a); Py_XDECREF((PyObject*)n); return result; }
/* Evaluate the expression E and put the result in R. */ void mpz_eval_expr (mpz_ptr r, expr_t e) { mpz_t lhs, rhs; switch (e->op) { case LIT: mpz_set (r, e->operands.val); return; case PLUS: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_add (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; case MINUS: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_sub (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; case MULT: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_mul (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; case DIV: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_fdiv_q (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; case MOD: mpz_init (rhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_abs (rhs, rhs); mpz_eval_mod_expr (r, e->operands.ops.lhs, rhs); mpz_clear (rhs); return; case REM: /* Check if lhs operand is POW expression and optimize for that case. */ if (e->operands.ops.lhs->op == POW) { mpz_t powlhs, powrhs; mpz_init (powlhs); mpz_init (powrhs); mpz_init (rhs); mpz_eval_expr (powlhs, e->operands.ops.lhs->operands.ops.lhs); mpz_eval_expr (powrhs, e->operands.ops.lhs->operands.ops.rhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_powm (r, powlhs, powrhs, rhs); if (mpz_cmp_si (rhs, 0L) < 0) mpz_neg (r, r); mpz_clear (powlhs); mpz_clear (powrhs); mpz_clear (rhs); return; } mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_fdiv_r (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; #if __GNU_MP_VERSION >= 2 case INVMOD: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_invert (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; #endif case POW: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); if (mpz_cmp_si (rhs, 0L) == 0) /* x^0 is 1 */ mpz_set_ui (r, 1L); else if (mpz_cmp_si (lhs, 0L) == 0) /* 0^y (where y != 0) is 0 */ mpz_set_ui (r, 0L); else if (mpz_cmp_ui (lhs, 1L) == 0) /* 1^y is 1 */ mpz_set_ui (r, 1L); else if (mpz_cmp_si (lhs, -1L) == 0) /* (-1)^y just depends on whether y is even or odd */ mpz_set_si (r, (mpz_get_ui (rhs) & 1) ? -1L : 1L); else if (mpz_cmp_si (rhs, 0L) < 0) /* x^(-n) is 0 */ mpz_set_ui (r, 0L); else { unsigned long int cnt; unsigned long int y; /* error if exponent does not fit into an unsigned long int. */ if (mpz_cmp_ui (rhs, ~(unsigned long int) 0) > 0) goto pow_err; y = mpz_get_ui (rhs); /* x^y == (x/(2^c))^y * 2^(c*y) */ #if __GNU_MP_VERSION >= 2 cnt = mpz_scan1 (lhs, 0); #else cnt = 0; #endif if (cnt != 0) { if (y * cnt / cnt != y) goto pow_err; mpz_tdiv_q_2exp (lhs, lhs, cnt); mpz_pow_ui (r, lhs, y); mpz_mul_2exp (r, r, y * cnt); } else mpz_pow_ui (r, lhs, y); } mpz_clear (lhs); mpz_clear (rhs); return; pow_err: error = "result of `pow' operator too large"; mpz_clear (lhs); mpz_clear (rhs); longjmp (errjmpbuf, 1); case GCD: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_gcd (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1 case LCM: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_lcm (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; #endif case AND: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_and (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; case IOR: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_ior (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1 case XOR: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_xor (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; #endif case NEG: mpz_eval_expr (r, e->operands.ops.lhs); mpz_neg (r, r); return; case NOT: mpz_eval_expr (r, e->operands.ops.lhs); mpz_com (r, r); return; case SQRT: mpz_init (lhs); mpz_eval_expr (lhs, e->operands.ops.lhs); if (mpz_sgn (lhs) < 0) { error = "cannot take square root of negative numbers"; mpz_clear (lhs); longjmp (errjmpbuf, 1); } mpz_sqrt (r, lhs); return; #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1 case ROOT: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); if (mpz_sgn (rhs) <= 0) { error = "cannot take non-positive root orders"; mpz_clear (lhs); mpz_clear (rhs); longjmp (errjmpbuf, 1); } if (mpz_sgn (lhs) < 0 && (mpz_get_ui (rhs) & 1) == 0) { error = "cannot take even root orders of negative numbers"; mpz_clear (lhs); mpz_clear (rhs); longjmp (errjmpbuf, 1); } { unsigned long int nth = mpz_get_ui (rhs); if (mpz_cmp_ui (rhs, ~(unsigned long int) 0) > 0) { /* If we are asked to take an awfully large root order, cheat and ask for the largest order we can pass to mpz_root. This saves some error prone special cases. */ nth = ~(unsigned long int) 0; } mpz_root (r, lhs, nth); } mpz_clear (lhs); mpz_clear (rhs); return; #endif case FAC: mpz_eval_expr (r, e->operands.ops.lhs); if (mpz_size (r) > 1) { error = "result of `!' operator too large"; longjmp (errjmpbuf, 1); } mpz_fac_ui (r, mpz_get_ui (r)); return; #if __GNU_MP_VERSION >= 2 case POPCNT: mpz_eval_expr (r, e->operands.ops.lhs); { unsigned long int cnt; cnt = mpz_popcount (r); mpz_set_ui (r, cnt); } return; #endif case LOG2: mpz_eval_expr (r, e->operands.ops.lhs); { unsigned long int cnt; if (mpz_sgn (r) <= 0) { error = "logarithm of non-positive number"; longjmp (errjmpbuf, 1); } cnt = mpz_sizeinbase (r, 2); mpz_set_ui (r, cnt - 1); } return; case LOG: { unsigned long int cnt; mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); if (mpz_sgn (lhs) <= 0) { error = "logarithm of non-positive number"; mpz_clear (lhs); mpz_clear (rhs); longjmp (errjmpbuf, 1); } if (mpz_cmp_ui (rhs, 256) >= 0) { error = "logarithm base too large"; mpz_clear (lhs); mpz_clear (rhs); longjmp (errjmpbuf, 1); } cnt = mpz_sizeinbase (lhs, mpz_get_ui (rhs)); mpz_set_ui (r, cnt - 1); mpz_clear (lhs); mpz_clear (rhs); } return; case FERMAT: { unsigned long int t; mpz_init (lhs); mpz_eval_expr (lhs, e->operands.ops.lhs); t = (unsigned long int) 1 << mpz_get_ui (lhs); if (mpz_cmp_ui (lhs, ~(unsigned long int) 0) > 0 || t == 0) { error = "too large Mersenne number index"; mpz_clear (lhs); longjmp (errjmpbuf, 1); } mpz_set_ui (r, 1); mpz_mul_2exp (r, r, t); mpz_add_ui (r, r, 1); mpz_clear (lhs); } return; case MERSENNE: mpz_init (lhs); mpz_eval_expr (lhs, e->operands.ops.lhs); if (mpz_cmp_ui (lhs, ~(unsigned long int) 0) > 0) { error = "too large Mersenne number index"; mpz_clear (lhs); longjmp (errjmpbuf, 1); } mpz_set_ui (r, 1); mpz_mul_2exp (r, r, mpz_get_ui (lhs)); mpz_sub_ui (r, r, 1); mpz_clear (lhs); return; case FIBONACCI: { mpz_t t; unsigned long int n, i; mpz_init (lhs); mpz_eval_expr (lhs, e->operands.ops.lhs); if (mpz_sgn (lhs) <= 0 || mpz_cmp_si (lhs, 1000000000) > 0) { error = "Fibonacci index out of range"; mpz_clear (lhs); longjmp (errjmpbuf, 1); } n = mpz_get_ui (lhs); mpz_clear (lhs); #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1 mpz_fib_ui (r, n); #else mpz_init_set_ui (t, 1); mpz_set_ui (r, 1); if (n <= 2) mpz_set_ui (r, 1); else { for (i = 3; i <= n; i++) { mpz_add (t, t, r); mpz_swap (t, r); } } mpz_clear (t); #endif } return; default: abort (); } }
static PyObject * GMPY_mpz_is_extrastronglucas_prp(PyObject *self, PyObject *args) { MPZ_Object *n, *p; PyObject *result = 0; mpz_t zD, s, nmj, nm2, res; /* these are needed for the LucasU and LucasV part of this function */ mpz_t uh, vl, vh, ql, qh, tmp; mp_bitcnt_t r = 0, j = 0; int ret = 0; if (PyTuple_Size(args) != 2) { TYPE_ERROR("is_extra_strong_lucas_prp() requires 2 integer arguments"); return NULL; } mpz_init(zD); mpz_init(s); mpz_init(nmj); mpz_init(nm2); mpz_init(res); mpz_init(uh); mpz_init(vl); mpz_init(vh); mpz_init(ql); mpz_init(qh); mpz_init(tmp); n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL); p = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL); if (!n || !p) { TYPE_ERROR("is_extra_strong_lucas_prp() requires 2 integer arguments"); goto cleanup; } /* Check if p*p - 4 == 0. */ mpz_mul(zD, p->z, p->z); mpz_sub_ui(zD, zD, 4); if (mpz_sgn(zD) == 0) { VALUE_ERROR("invalid value for p in is_extra_strong_lucas_prp()"); goto cleanup; } /* Require n > 0. */ if (mpz_sgn(n->z) <= 0) { VALUE_ERROR("is_extra_strong_lucas_prp() requires 'n' be greater than 0"); goto cleanup; } /* Check for n == 1 */ if (mpz_cmp_ui(n->z, 1) == 0) { result = Py_False; goto cleanup; } /* Handle n even. */ if (mpz_divisible_ui_p(n->z, 2)) { if (mpz_cmp_ui(n->z, 2) == 0) result = Py_True; else result = Py_False; goto cleanup; } /* Check GCD */ mpz_mul_ui(res, zD, 2); mpz_gcd(res, res, n->z); if ((mpz_cmp(res, n->z) != 0) && (mpz_cmp_ui(res, 1) > 0)) { VALUE_ERROR("is_extra_strong_lucas_prp() requires gcd(n,2*D) == 1"); goto cleanup; } /* nmj = n - (D/n), where (D/n) is the Jacobi symbol */ mpz_set(nmj, n->z); ret = mpz_jacobi(zD, n->z); if (ret == -1) mpz_add_ui(nmj, nmj, 1); else if (ret == 1) mpz_sub_ui(nmj, nmj, 1); r = mpz_scan1(nmj, 0); mpz_fdiv_q_2exp(s, nmj, r); mpz_set(nm2, n->z); mpz_sub_ui(nm2, nm2, 2); /* make sure that either U_s == 0 mod n or V_s == +/-2 mod n, or */ /* V_((2^t)*s) == 0 mod n for some t with 0 <= t < r-1 */ mpz_set_si(uh, 1); mpz_set_si(vl, 2); mpz_set(vh, p->z); mpz_set_si(ql, 1); mpz_set_si(qh, 1); mpz_set_si(tmp,0); for (j = mpz_sizeinbase(s,2)-1; j >= 1; j--) { /* ql = ql*qh (mod n) */ mpz_mul(ql, ql, qh); mpz_mod(ql, ql, n->z); if (mpz_tstbit(s,j) == 1) { /* qh = ql*q */ mpz_set(qh, ql); /* uh = uh*vh (mod n) */ mpz_mul(uh, uh, vh); mpz_mod(uh, uh, n->z); /* vl = vh*vl - p*ql (mod n) */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); /* vh = vh*vh - 2*qh (mod n) */ mpz_mul(vh, vh, vh); mpz_mul_si(tmp, qh, 2); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n->z); } else { /* qh = ql */ mpz_set(qh, ql); /* uh = uh*vl - ql (mod n) */ mpz_mul(uh, uh, vl); mpz_sub(uh, uh, ql); mpz_mod(uh, uh, n->z); /* vh = vh*vl - p*ql (mod n) */ mpz_mul(vh, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n->z); /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); } } /* ql = ql*qh */ mpz_mul(ql, ql, qh); /* qh = ql*q */ mpz_set(qh, ql); /* uh = uh*vl - ql */ mpz_mul(uh, uh, vl); mpz_sub(uh, uh, ql); /* vl = vh*vl - p*ql */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); /* ql = ql*qh */ mpz_mul(ql, ql, qh); mpz_mod(uh, uh, n->z); mpz_mod(vl, vl, n->z); /* uh contains LucasU_s and vl contains LucasV_s */ if ((mpz_cmp_ui(uh, 0) == 0) || (mpz_cmp_ui(vl, 0) == 0) || (mpz_cmp(vl, nm2) == 0) || (mpz_cmp_si(vl, 2) == 0)) { result = Py_True; goto cleanup; } for (j = 1; j < r-1; j++) { /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); /* ql = ql*ql (mod n) */ mpz_mul(ql, ql, ql); mpz_mod(ql, ql, n->z); if (mpz_cmp_ui(vl, 0) == 0) { result = Py_True; goto cleanup; } } result = Py_False; cleanup: Py_XINCREF(result); mpz_clear(zD); mpz_clear(s); mpz_clear(nmj); mpz_clear(nm2); mpz_clear(res); mpz_clear(uh); mpz_clear(vl); mpz_clear(vh); mpz_clear(ql); mpz_clear(qh); mpz_clear(tmp); Py_XDECREF((PyObject*)p); Py_XDECREF((PyObject*)n); return result; }
void generate_mod (int limb_bits, int nail_bits) { int numb_bits = limb_bits - nail_bits; int i, divisor; mpz_init_set_ui (pp, 0L); mpz_init_set_ui (pp_norm, 0L); mpz_init_set_ui (pp_inverted, 0L); /* no more than limb_bits many factors in a one limb modulus (and of course in reality nothing like that many) */ factor_alloc = limb_bits; factor = xmalloc (factor_alloc * sizeof (*factor)); rawfactor = xmalloc (factor_alloc * sizeof (*rawfactor)); if (numb_bits % 4 != 0) { strcpy (mod34_excuse, "GMP_NUMB_BITS % 4 != 0"); goto use_pp; } max_divisor = 2*limb_bits; max_divisor_bits = log2_ceil (max_divisor); if (numb_bits / 4 < max_divisor_bits) { /* Wind back to one limb worth of max_divisor, if that will let us use mpn_mod_34lsub1. */ max_divisor = limb_bits; max_divisor_bits = log2_ceil (max_divisor); if (numb_bits / 4 < max_divisor_bits) { strcpy (mod34_excuse, "GMP_NUMB_BITS / 4 too small"); goto use_pp; } } { /* Can use mpn_mod_34lsub1, find small factors of 2^mod34_bits-1. */ mpz_t m, q, r; int multiplicity; mod34_bits = (numb_bits / 4) * 3; /* mpn_mod_34lsub1 returns a full limb value, PERFSQR_MOD_34 folds it at the mod34_bits mark, adding the two halves for a remainder of at most mod34_bits+1 many bits */ mod_bits = mod34_bits + 1; mpz_init_set_ui (m, 1L); mpz_mul_2exp (m, m, mod34_bits); mpz_sub_ui (m, m, 1L); mpz_init (q); mpz_init (r); for (i = 3; i <= max_divisor; i++) { if (! isprime (i)) continue; mpz_tdiv_qr_ui (q, r, m, (unsigned long) i); if (mpz_sgn (r) != 0) continue; /* if a repeated prime is found it's used as an i^n in one factor */ divisor = 1; multiplicity = 0; do { if (divisor > max_divisor / i) break; multiplicity++; mpz_set (m, q); mpz_tdiv_qr_ui (q, r, m, (unsigned long) i); } while (mpz_sgn (r) == 0); assert (nrawfactor < factor_alloc); rawfactor[nrawfactor].divisor = i; rawfactor[nrawfactor].multiplicity = multiplicity; nrawfactor++; } mpz_clear (m); mpz_clear (q); mpz_clear (r); } if (nrawfactor <= 2) { mpz_t new_pp; sprintf (mod34_excuse, "only %d small factor%s", nrawfactor, nrawfactor == 1 ? "" : "s"); use_pp: /* reset to two limbs of max_divisor, in case the mpn_mod_34lsub1 code tried with just one */ max_divisor = 2*limb_bits; max_divisor_bits = log2_ceil (max_divisor); mpz_init (new_pp); nrawfactor = 0; mod_bits = MIN (numb_bits, limb_bits - max_divisor_bits); /* one copy of each small prime */ mpz_set_ui (pp, 1L); for (i = 3; i <= max_divisor; i++) { if (! isprime (i)) continue; mpz_mul_ui (new_pp, pp, (unsigned long) i); if (mpz_sizeinbase (new_pp, 2) > mod_bits) break; mpz_set (pp, new_pp); assert (nrawfactor < factor_alloc); rawfactor[nrawfactor].divisor = i; rawfactor[nrawfactor].multiplicity = 1; nrawfactor++; } /* Plus an extra copy of one or more of the primes selected, if that still fits in max_divisor and the total in mod_bits. Usually only 3 or 5 will be candidates */ for (i = nrawfactor-1; i >= 0; i--) { if (rawfactor[i].divisor > max_divisor / rawfactor[i].divisor) continue; mpz_mul_ui (new_pp, pp, (unsigned long) rawfactor[i].divisor); if (mpz_sizeinbase (new_pp, 2) > mod_bits) continue; mpz_set (pp, new_pp); rawfactor[i].multiplicity++; } mod_bits = mpz_sizeinbase (pp, 2); mpz_set (pp_norm, pp); while (mpz_sizeinbase (pp_norm, 2) < numb_bits) mpz_add (pp_norm, pp_norm, pp_norm); mpz_preinv_invert (pp_inverted, pp_norm, numb_bits); mpz_clear (new_pp); } /* start the factor array */ for (i = 0; i < nrawfactor; i++) { int j; assert (nfactor < factor_alloc); factor[nfactor].divisor = 1; for (j = 0; j < rawfactor[i].multiplicity; j++) factor[nfactor].divisor *= rawfactor[i].divisor; nfactor++; } combine: /* Combine entries in the factor array. Combine the smallest entry with the biggest one that will fit with it (ie. under max_divisor), then repeat that with the new smallest entry. */ qsort (factor, nfactor, sizeof (factor[0]), f_cmp_divisor); for (i = nfactor-1; i >= 1; i--) { if (factor[i].divisor <= max_divisor / factor[0].divisor) { factor[0].divisor *= factor[i].divisor; COLLAPSE_ELEMENT (factor, i, nfactor); goto combine; } } total_fraction = 1.0; for (i = 0; i < nfactor; i++) { mpz_init (factor[i].inverse); mpz_invert_ui_2exp (factor[i].inverse, (unsigned long) factor[i].divisor, (unsigned long) mod_bits); mpz_init (factor[i].mask); square_mask (factor[i].mask, factor[i].divisor); /* fraction of possible squares */ factor[i].fraction = (double) mpz_popcount (factor[i].mask) / factor[i].divisor; /* total fraction of possible squares */ total_fraction *= factor[i].fraction; } /* best tests first (ie. smallest fraction) */ qsort (factor, nfactor, sizeof (factor[0]), f_cmp_fraction); }
void table (int limb_bits, int nail_bits) { int numb_bits = limb_bits - nail_bits; int base; mpz_t r, t, logb2, log2b; mpz_init (r); mpz_init (t); mpz_init (logb2); mpz_init (log2b); printf ("/* This file generated by gen-bases.c - DO NOT EDIT. */\n"); printf ("\n"); printf ("#include \"gmp.h\"\n"); printf ("#include \"gmp-impl.h\"\n"); printf ("\n"); printf ("#if GMP_NUMB_BITS != %d\n", numb_bits); printf ("Error, error, this data is for %d bits\n", numb_bits); printf ("#endif\n"); printf ("\n"); puts ("const struct bases mp_bases[257] =\n{"); puts (" /* 0 */ { 0, 0, 0, 0, 0 },"); puts (" /* 1 */ { 0, 0, 0, 0, 0 },"); for (base = 2; base <= 256; base++) { generate (limb_bits, nail_bits, base); mp_2logb (r, base, limb_bits + 8); mpz_tdiv_q_2exp (logb2, r, 8); mpz_set_ui (t, 1); mpz_mul_2exp (t, t, 2*limb_bits + 5); mpz_sub_ui (t, t, 1); mpz_add_ui (r, r, 1); mpz_tdiv_q (log2b, t, r); printf (" /* %3u */ { ", base); if (POW2_P (base)) { mpz_set_ui (big_base, ulog2 (base) - 1); mpz_set_ui (big_base_inverted, 0); } printf ("%u,", chars_per_limb); printf (" CNST_LIMB(0x"); mpz_out_str (stdout, 16, logb2); printf ("), CNST_LIMB(0x"); mpz_out_str (stdout, 16, log2b); printf ("), CNST_LIMB(0x"); mpz_out_str (stdout, 16, big_base); printf ("), CNST_LIMB(0x"); mpz_out_str (stdout, 16, big_base_inverted); printf (") },\n"); } puts ("};"); mpz_clear (r); mpz_clear (t); mpz_clear (logb2); mpz_clear (log2b); }
bool bbp_pi(bool const & abortTask, std::string const & digitIndex, uint32_t const digitStep, std::string & piSequence) { unsigned long const mantissa_bits = 132; unsigned long const count_offset = 7; // settings above gives 32 hexadecimal digits unsigned long count = static_cast<unsigned long>( floor(log10(pow(2.0, static_cast<double>(mantissa_bits))))); count -= count_offset; // starting digit mpz_t digit; mpz_init(digit); if (mpz_set_str(digit, digitIndex.c_str(), 10) < 0) return false; mpz_sub_ui(digit, digit, 1); // subtract the 3 digit mpz_add_ui(digit, digit, digitStep); mpz_t tmpI[TEMPORARY_INTEGERS]; for (size_t i = 0; i < (sizeof(tmpI) / sizeof(mpz_t)); ++i) mpz_init(tmpI[i]); mpf_t tmpF[TEMPORARY_FLOATS]; for (size_t i = 0; i < (sizeof(tmpF) / sizeof(mpf_t)); ++i) mpf_init2(tmpF[i], mantissa_bits); // determine epsilon based on the number of digits required mpf_t epsilon; mpf_init2(epsilon, mantissa_bits); mpf_set_ui(epsilon, 10); mpf_pow_ui(epsilon, epsilon, count + count_offset); mpf_ui_div(epsilon, 1, epsilon); // integer constant mpz_t sixteen; mpz_init(sixteen); mpz_set_ui(sixteen, 16); // determine the series mpf_t s1, s2, s3, s4; mpf_init2(s1, mantissa_bits); mpf_init2(s2, mantissa_bits); mpf_init2(s3, mantissa_bits); mpf_init2(s4, mantissa_bits); series(abortTask, s1, 1, tmpI, tmpF, sixteen, digit, epsilon); if (abortTask) return false; series(abortTask, s2, 4, tmpI, tmpF, sixteen, digit, epsilon); if (abortTask) return false; series(abortTask, s3, 5, tmpI, tmpF, sixteen, digit, epsilon); if (abortTask) return false; series(abortTask, s4, 6, tmpI, tmpF, sixteen, digit, epsilon); if (abortTask) return false; // pid = 4. * s1 - 2. * s2 - s3 - s4; mpf_mul_ui(s1, s1, 4); mpf_mul_ui(s2, s2, 2); mpf_t result; mpf_init2(result, mantissa_bits); mpf_sub(result, s1, s2); mpf_sub(result, result, s3); mpf_sub(result, result, s4); // pid = pid - (int) pid + 1.; mpf_t & tmp1 = tmpF[0]; mpf_floor(tmp1, result); mpf_sub(result, result, tmp1); mpf_add_ui(result, result, 1); mpf_abs(result, result); // output the result char resultStr[256]; mp_exp_t exponent; mpf_get_str(resultStr, &exponent, 16, 254, result); resultStr[count + 1] = '\0'; // cut off any erroneous bits piSequence.assign(&resultStr[1]); // cleanup for (size_t i = 0; i < (sizeof(tmpI) / sizeof(mpz_t)); ++i) mpz_clear(tmpI[i]); for (size_t i = 0; i < (sizeof(tmpF) / sizeof(mpf_t)); ++i) mpf_clear(tmpF[i]); mpz_clear(digit); mpf_clear(epsilon); mpz_clear(sixteen); mpf_clear(s1); mpf_clear(s2); mpf_clear(s3); mpf_clear(s4); mpf_clear(result); return true; }
static int generator_rule_TYPE(Generator *gen) { GeneratorState *next, *state = gen->tip; unsigned long val; int res; /* * TYPE ::= basic * | 'v' * | '(' ')' * | 'm' TYPE * | 'a' TYPE * | '(' TUPLE ')' * | '{' PAIR '}' */ res = mpz_cmp_ui(state->seed, _GENERATOR_BASIC_N + 2); if (res < 0) { /* * TYPE ::= basic | 'v' | '(' ')' */ val = mpz_get_ui(state->seed); switch (val) { case _GENERATOR_BASIC_N + 0: /* * TYPE ::= 'v' */ generator_pop(gen); return 'v'; case _GENERATOR_BASIC_N + 1: /* * TYPE ::= '(' ')' */ state->rule = GENERATOR_RULE_TUPLE_CLOSE; return '('; default: /* * TYPE ::= basic */ generator_pop(gen); return generator_map_basic(val); } } else { /* * TYPE ::= 'm' TYPE | 'a' TYPE | '(' TUPLE ')' | '{' PAIR '}' */ mpz_sub_ui(state->seed, state->seed, _GENERATOR_BASIC_N + 2); val = mpz_fdiv_q_ui(state->seed, state->seed, _GENERATOR_COMPOUND_N); switch (val) { case GENERATOR_COMPOUND_m: /* * TYPE ::= 'm' TYPE */ state->rule = GENERATOR_RULE_TYPE; return 'm'; case GENERATOR_COMPOUND_a: /* * TYPE ::= 'a' TYPE */ state->rule = GENERATOR_RULE_TYPE; return 'a'; case GENERATOR_COMPOUND_r: /* * TYPE ::= '(' TUPLE ')' */ state->rule = GENERATOR_RULE_TUPLE_CLOSE; next = generator_push(gen); next->rule = GENERATOR_RULE_TUPLE; mpz_set(next->seed, state->seed); return '('; case GENERATOR_COMPOUND_e: /* * TYPE ::= '{' PAIR '}' */ state->rule = GENERATOR_RULE_PAIR_CLOSE; next = generator_push(gen); next->rule = GENERATOR_RULE_PAIR; mpz_set(next->seed, state->seed); return '{'; default: assert(0); return 0; } } }
int main(int argc, char** argv) { int my_rank, procs; MPI_Status status; mpz_t q, p, pq, n, gap, sqn; mpz_t *k; double *timearray; double begin, end; double time_spent; int done = 0, found = 0; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); MPI_Comm_size(MPI_COMM_WORLD, &procs); begin = MPI_Wtime(); mpz_init(n); mpz_init(q); mpz_init(p); mpz_init(pq); mpz_init(sqn); mpz_init(gap); mpz_set_str(n,argv[1],10); mpz_sqrt(sqn,n); mpz_set(gap, sqn); mpz_set_ui(p,1); mpz_nextprime(q, p); size_t mag = mpz_sizeinbase (gap, 10); mag=mag*procs; k = (mpz_t*)malloc(sizeof(mpz_t)*(mag+1)); mpz_t temp; mpz_init(temp); mpz_tdiv_q_ui(temp,gap,mag); for (int i=0;i<=mag;i++) { mpz_init(k[i]); mpz_mul_ui(k[i],temp,i); } mpz_set(k[mag],sqn); int counter=0; for (int i=my_rank; i<mag; i=i+procs) { mpz_set(q,k[i]); mpz_sub_ui(q,q,1); mpz_nextprime(q,q); while (( mpz_cmp(q,k[i+1]) <= 0 )&&(!done)&&(!found)&&(mpz_cmp(q,sqn)<=0)) {//finding the prime numbers counter++; if (counter%5000==0)MPI_Allreduce(&found, &done, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD); if (mpz_divisible_p(n,q)==0) {//if n is not divisible by q mpz_nextprime(q,q); continue; } //since it is divisible, try n/q and see if result is prime mpz_divexact(p,n,q); int reps; if (mpz_probab_prime_p(p,reps)!=0) { found = 1; done = 1; } else { mpz_nextprime(q,q); } }//done finding primes if (found || done) break; } end = MPI_Wtime(); if (found) { MPI_Allreduce(&found, &done, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD); gmp_printf("*************************\nP%d: Finished\np*q=n\np=%Zd q=%Zd n=%Zd\n*************************\n", my_rank,p,q,n); } else if (!done) { while (!done&&!found) MPI_Allreduce(&found, &done, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD); } time_spent = (double)(end - begin); if (my_rank!=0) { MPI_Send(&time_spent, sizeof(double),MPI_CHAR,0,0,MPI_COMM_WORLD); } else { timearray = (double*)malloc(sizeof(double)*procs); timearray[0] = time_spent; int j; for (j = 1; j<procs;j++) { double *ptr = timearray+j; MPI_Recv(ptr, sizeof(double),MPI_CHAR,j,0,MPI_COMM_WORLD,&status); } writeTime(argv[1],timearray,procs); free(timearray); } free(k); MPI_Finalize(); return 0; }