예제 #1
0
int main(void)
{
	DIGIT_T x, y, g;
	DIGIT_T m, e, n, c, z, t;
	DIGIT_T p, v, u, w, a, q;
	int res, i, ntries;
	DIGIT_T primes32[] = { 5, 17, 65, 99 };
	DIGIT_T primes16[] = { 15, 17, 39 };

	/* Test greatest common divisor (gcd) */
	printf("Test spGcd:\n");
	/* simple one */
	x = 15; y = 27;
	g = spGcd(x, y);
	printf("gcd(%" PRIuBIGD ", %" PRIuBIGD ") = %" PRIuBIGD "\n", x, y, g);
	assert(g == 3);

	/* contrived using small primes */
	x = 53 * 37; y = 53 * 83;
	g = spGcd(x, y);
	printf("gcd(%" PRIuBIGD ", %" PRIuBIGD ") = %" PRIuBIGD "\n", x, y, g);
	assert(g == 53);

	/* contrived using bigger primes */
	x = 0x0345 * 0xfedc; y = 0xfedc * 0x0871;
	g = spGcd(x, y);
	printf("gcd(0x%" PRIxBIGD ", 0x%" PRIxBIGD ") = 0x%" PRIxBIGD "\n", x, y, g);
	assert(g == 0xfedc);

	/* Known primes: 2^16-15, 2^32-5 */
	y = 0x10000 - 15;
	x = spSimpleRand(1, y);
	g = spGcd(x, y);
	printf("gcd(0x%" PRIxBIGD ", 0x%" PRIxBIGD ") = %" PRIxBIGD "\n", x, y, g);
	assert(g == 1);

	y = 0xffffffff - 5 + 1;
	x = spSimpleRand(1, y);
	g = spGcd(x, y);
	printf("gcd(0x%" PRIxBIGD ", 0x%" PRIxBIGD ") = %" PRIxBIGD "\n", x, y, g);
	assert(g == 1);

	/* Test spModExp */
	printf("Test spModExp:\n");
	/* Verify that (m^e mod n).(z^e mod n) == (m.z)^e mod n 
	   for random m, e, n, z */
	/* Generate some random numbers */
	n = spSimpleRand(MAX_DIGIT / 2, MAX_DIGIT);
	m = spSimpleRand(1, n -1);
	e = spSimpleRand(1, n -1);
	z = spSimpleRand(1, n -1);
	/* Compute c = m^e mod n */
	spModExp(&c, m, e, n);
	printf("c=m^e mod n=%" PRIxBIGD "^%" PRIxBIGD " mod %" PRIxBIGD "=%" PRIxBIGD "\n", m, e, n, c);
	/* Compute x = c.z^e mod n */
	printf("z=%" PRIxBIGD "\n", z);
	spModExp(&t, z, e, n);
	spModMult(&x, c, t, n);
	printf("x = c.z^e mod n =   %" PRIxBIGD "\n", x);
	/* Compute y = (m.z)^e mod n */
	spModMult(&t, m, z, n);
	spModExp(&y, t, e, n);
	printf("y = (m.z)^e mod n = %" PRIxBIGD "\n", x);
	/* Check they are equal */
	assert(x == y);

	/* Test spModInv */
	printf("Test spModInv:\n");
	/* Use identity that (vp-1)^-1 mod p = p-1 
	   for prime p and integer v */
	/* known prime */
	p = 0x10000 - 15;
	/* small multiplier */
	v = spSimpleRand(2, 10);
	u = v * p - 1;
	printf("u = vp-1 = %" PRIuBIGD " * %" PRIuBIGD " - 1 = %" PRIuBIGD "\n", v, p, u);
	/* compute w = u^-1 mod p */
	spModInv(&w, u, p);
	printf("w = u^-1 mod p = %" PRIuBIGD "\n", w);
	/* check wu mod p == 1 */
	spModMult(&c, w, u, p);
	printf("Check 1 == wu mod p = %" PRIuBIGD "\n", c);
	assert(c == 1);
	/* Try mod inversion that should fail */
	/* Set u = pq so that gcd(u, p) != 1 */
	q = 31;
	u = p * q;
	printf("p=%" PRIuBIGD " q=%" PRIuBIGD " pq=%" PRIuBIGD "\n", p, q, u);
	printf("gcd(pq, p) = %" PRIuBIGD " (i.e. not 1)\n", spGcd(u, p));
	res = spModInv(&w, u, p);
	printf("w = (pq)^-1 mod p returns error %d (expected 1)\n", res);
	assert(res != 0);

	/* Test spIsPrime */
	printf("Test spIsPrime:\n");
	/* Find primes just less than 2^32. Ref: Knuth p408 */
	for (n = 0xffffffff, a = 1; a < 100; a++, n--)
	{
		if (spIsPrime(n, 50))
		{
			printf("2^32-%" PRIuBIGD " is prime\n", a);
			assert(is_in_list(a, primes32, NELEMS(primes32)));
		}
	}
	/* And just less than 2^16 */
	for (n = 0xffff, a = 1; a < 50; a++, n--)
	{
		if (spIsPrime(n, 50))
		{
			printf("2^16-%" PRIuBIGD " is prime\n", a);
			assert(is_in_list(a, primes16, NELEMS(primes16)));
		}
	}
	/* Generate a random prime < MAX_DIGIT */
	n = spSimpleRand(0, MAX_DIGIT);
	/* make sure odd */
	n |= 0x01;
	/* expect to find a prime approx every lg(n) numbers, 
	   so for sure within 100 times that */
	ntries = BITS_PER_DIGIT * 100;
	for (i = 0; i < ntries; i++)
	{
		if (spIsPrime(n, 50))
			break;
		n += 2;
	}
	printf("Random prime, n = %" PRIuBIGD " (0x%" PRIxBIGD ")\n", n, n);
	printf("found after %d candidates\n", i+1);
	if (i >= ntries)
		printf("Didn't manage to find a prime in %d tries!\n", ntries);
	else
		assert(spIsPrime(n, 50));

	res = spIsPrime(n, 50);
	printf("spIsPrime(%" PRIuBIGD ") is %s\n", n, (res ? "TRUE" : "FALSE"));

	/* Check using (less accurate) Fermat test (these could fail) */
	w = 2;
	spModExp(&x, w, n-1, n);
	printf("Fermat test: %" PRIxBIGD "^(n-1) mod n = %" PRIxBIGD " (%s)\n", w, x, (x == 1 ? "PASSED" : "FAILED!"));
	w = 3;
	spModExp(&x, w, n-1, n);
	printf("Fermat test: %" PRIxBIGD "^(n-1) mod n = %" PRIxBIGD " (%s)\n", w, x, (x == 1 ? "PASSED" : "FAILED!"));
	w = 5;
	spModExp(&x, w, n-1, n);
	printf("Fermat test: %" PRIxBIGD "^(n-1) mod n = %" PRIxBIGD " (%s)\n", w, x, (x == 1 ? "PASSED" : "FAILED!"));

	/* Try a known Fermat liar (Carmichael number) */
	n = 561;
	printf("Try n = 561 = 3.11.17 (a `Fermat liar')\n");
	w = 5;
	spModExp(&x, w, n-1, n);
	printf("Fermat test: %" PRIxBIGD "^(n-1) mod n = %" PRIxBIGD " (%s)\n", w, x, (x == 1 ? "PASSED" : "FAILED!"));
	res = spIsPrime(n, 50);
	printf("spIsPrime(%" PRIuBIGD ") is %s\n", n, (res ? "TRUE" : "FALSE"));
	assert(!res);

	return 0;
}
예제 #2
0
int spIsPrime(DIGIT_T w, size_t t)
{	/*	Returns true if w is a probable prime 
		Carries out t iterations
		(Use t = 50 for DSS Standard) 
	*/
	/*	Uses Rabin-Miller Probabilistic Primality Test,
		Ref: FIPS-186-2 Appendix 2.
		Also Schneier 2nd ed p 260 & Knuth Vol 2, p 379
		and ANSI 9.42-2003 Annex B.1.1.
	*/

	unsigned int i, j;
	DIGIT_T m, a, b, z;
	int failed;

	/*	First check for small primes */
	for (i = 0; i < N_SMALL_PRIMES; i++)
	{
		if (w % SMALL_PRIMES[i] == 0)
			return 0;	/* Failed */
	}

	/*	Now do Rabin-Miller  */
	/*	Step 2. Find a and m where w = 1 + (2^a)m
		m is odd and 2^a is largest power of 2 dividing w - 1 */

	m = w - 1;
	for (a = 0; ISEVEN(m); a++)
		m >>= 1;	/* Divide by 2 until m is odd */

	/*
	assert((1 << a) * m + 1 == w);
	*/

	for (i = 0; i < t; i++)
	{
		failed = 1;	/* Assume fail unless passed in loop */
		/* Step 3. Generate a random integer 1 < b < w */
		/* [v2.1] changed to 1 < b < w-1 */
		b = spSimpleRand(2, w - 2);

		/*
		assert(1 < b && b < w-1);
		*/

		/* Step 4. Set j = 0 and z = b^m mod w */
		j = 0;
		spModExp(&z, b, m, w);
		do
		{
			/* Step 5. If j = 0 and z = 1, or if z = w - 1 */
			if ((j == 0 && z == 1) || (z == w - 1))
			{	/* Passes on this loop  - go to Step 9 */
				failed = 0;
				break;
			}

			/* Step 6. If j > 0 and z = 1 */
			if (j > 0 && z == 1)
			{	/* Fails - go to Step 8 */
				failed = 1;
				break;
			}

			/* Step 7. j = j + 1. If j < a set z = z^2 mod w */
			j++;
			if (j < a)
				spModMult(&z, z, z, w);
			/* Loop: if j < a go to Step 5 */
		} while (j < a);

		if (failed)
		{	/* Step 8. Not a prime - stop */
			return 0;
		}
	}	/* Step 9. Go to Step 3 until i >= n */
	/* If got here, probably prime => success */
	return 1;
}
예제 #3
0
void trial_divide_Q_siqs(uint32 report_num,  uint8 parity,
                         uint32 poly_id, uint32 bnum,
                         static_conf_t *sconf, dynamic_conf_t *dconf)
{
    //we have flagged this sieve offset as likely to produce a relation
    //nothing left to do now but check and see.
    uint64 q64, f64;
    int j,it;
    uint32 prime;
    int smooth_num;
    uint32 *fb_offsets;
    uint32 polya_factors[20];
    sieve_fb *fb;
    uint32 offset, block_loc;
    fb_offsets = &dconf->fb_offsets[report_num][0];
    smooth_num = dconf->smooth_num[report_num];
    block_loc = dconf->reports[report_num];

#ifdef QS_TIMING
    gettimeofday(&qs_timing_start, NULL);
#endif

    offset = (bnum << sconf->qs_blockbits) + block_loc;

    if (parity)
        fb = dconf->fb_sieve_n;
    else
        fb = dconf->fb_sieve_p;

#ifdef USE_YAFU_TDIV
    z32_to_mpz(&dconf->Qvals32[report_num], dconf->Qvals[report_num]);
#endif

    //check for additional factors of the a-poly factors
    //make a separate list then merge it with fb_offsets
    it=0;	//max 20 factors allocated for - should be overkill
    for (j = 0; (j < dconf->curr_poly->s) && (it < 20); j++)
    {
        //fbptr = fb + dconf->curr_poly->qlisort[j];
        //prime = fbptr->prime;
        prime = fb[dconf->curr_poly->qlisort[j]].prime;

        while ((mpz_tdiv_ui(dconf->Qvals[report_num],prime) == 0) && (it < 20))
        {
            mpz_tdiv_q_ui(dconf->Qvals[report_num], dconf->Qvals[report_num], prime);
            polya_factors[it++] = dconf->curr_poly->qlisort[j];
        }
    }

    //check if it completely factored by looking at the unfactored portion in tmp
    //if ((mpz_size(dconf->Qvals[report_num]) == 1) &&
    //(mpz_get_64(dconf->Qvals[report_num]) < (uint64)sconf->large_prime_max))
    if ((mpz_size(dconf->Qvals[report_num]) == 1) &&
            (mpz_cmp_ui(dconf->Qvals[report_num], sconf->large_prime_max) < 0))
    {
        uint32 large_prime[2];

        large_prime[0] = (uint32)mpz_get_ui(dconf->Qvals[report_num]); //Q->val[0];
        large_prime[1] = 1;

        //add this one
        if (sconf->is_tiny)
        {
            // we need to encode both the a_poly and b_poly index
            // in poly_id
            poly_id |= (sconf->total_poly_a << 16);
            buffer_relation(offset,large_prime,smooth_num+1,
                            fb_offsets,poly_id,parity,dconf,polya_factors,it);
        }
        else
            buffer_relation(offset,large_prime,smooth_num+1,
                            fb_offsets,poly_id,parity,dconf,polya_factors,it);

#ifdef QS_TIMING
        gettimeofday (&qs_timing_stop, NULL);
        qs_timing_diff = my_difftime (&qs_timing_start, &qs_timing_stop);

        TF_STG6 += ((double)qs_timing_diff->secs + (double)qs_timing_diff->usecs / 1000000);
        free(qs_timing_diff);
#endif

        return;
    }

    if (sconf->use_dlp == 0)
        return;

    //quick check if Q is way too big for DLP (more than 64 bits)
    if (mpz_sizeinbase(dconf->Qvals[report_num], 2) >= 64)
        return;

    q64 = mpz_get_64(dconf->Qvals[report_num]);

    if ((q64 > sconf->max_fb2) && (q64 < sconf->large_prime_max2))
    {
        //quick prime check: compute 2^(residue-1) mod residue.
        uint64 res;
        //printf("%llu\n",q64);

#if BITS_PER_DIGIT == 32
        mpz_set_64(dconf->gmptmp1, q64);
        mpz_set_64(dconf->gmptmp2, 2);
        mpz_set_64(dconf->gmptmp3, q64-1);

        mpz_powm(dconf->gmptmp1, dconf->gmptmp2, dconf->gmptmp3, dconf->gmptmp1);
        res = mpz_get_64(dconf->gmptmp1);
#else
        spModExp(2, q64 - 1, q64, &res);
#endif

        //if equal to 1, assume it is prime.  this may be wrong sometimes, but we don't care.
        //more important to quickly weed out probable primes than to spend more time to be
        //more sure.
        if (res == 1)
        {
#ifdef QS_TIMING
            gettimeofday (&qs_timing_stop, NULL);
            qs_timing_diff = my_difftime (&qs_timing_start, &qs_timing_stop);

            TF_STG6 += ((double)qs_timing_diff->secs + (double)qs_timing_diff->usecs / 1000000);
            free(qs_timing_diff);
#endif
            dconf->dlp_prp++;
            return;
        }

        //try to find a double large prime
#ifdef HAVE_CUDA
        {
            uint32 large_prime[2] = {1,1};

            // remember the residue and the relation it is associated with
            dconf->buf_id[dconf->num_squfof_cand] = dconf->buffered_rels;
            dconf->squfof_candidates[dconf->num_squfof_cand++] = q64;

            // buffer the relation
            buffer_relation(offset,large_prime,smooth_num+1,
                            fb_offsets,poly_id,parity,dconf,polya_factors,it);
        }
#else

        dconf->attempted_squfof++;
        mpz_set_64(dconf->gmptmp1, q64);
        f64 = sp_shanks_loop(dconf->gmptmp1, sconf->obj);
        if (f64 > 1 && f64 != q64)
        {
            uint32 large_prime[2];

            large_prime[0] = (uint32)f64;
            large_prime[1] = (uint32)(q64 / f64);

            if (large_prime[0] < sconf->large_prime_max
                    && large_prime[1] < sconf->large_prime_max)
            {
                //add this one
                dconf->dlp_useful++;
                buffer_relation(offset,large_prime,smooth_num+1,
                                fb_offsets,poly_id,parity,dconf,polya_factors,it);
            }

        }
        else
        {
            dconf->failed_squfof++;
            //printf("squfof failure: %" PRIu64 "\n", q64);
        }
#endif

    }
    else
        dconf->dlp_outside_range++;

#ifdef QS_TIMING
    gettimeofday (&qs_timing_stop, NULL);
    qs_timing_diff = my_difftime (&qs_timing_start, &qs_timing_stop);

    TF_STG6 += ((double)qs_timing_diff->secs + (double)qs_timing_diff->usecs / 1000000);
    free(qs_timing_diff);
#endif

    return;
}