📄 moduli.c
字号:
/* validation check: count the number of primes tried */ largetries = 0; q = BN_new(); /* * Generate random starting point for subprime search, or use * specified parameter. */ largebase = BN_new(); if (start == NULL) BN_rand(largebase, power, 1, 1); else BN_copy(largebase, start); /* ensure odd */ BN_set_bit(largebase, 0); time(&time_start); logit("%.24s Sieve next %u plus %u-bit", ctime(&time_start), largenumbers, power); debug2("start point: 0x%s", BN_bn2hex(largebase)); /* * TinySieve */ for (i = 0; i < tinybits; i++) { if (BIT_TEST(TinySieve, i)) continue; /* 2*i+3 is composite */ /* The next tiny prime */ t = 2 * i + 3; /* Mark all multiples of t */ for (j = i + t; j < tinybits; j += t) BIT_SET(TinySieve, j); sieve_large(t); } /* * Start the small block search at the next possible prime. To avoid * fencepost errors, the last pass is skipped. */ for (smallbase = TINY_NUMBER + 3; smallbase < (SMALL_MAXIMUM - TINY_NUMBER); smallbase += TINY_NUMBER) { for (i = 0; i < tinybits; i++) { if (BIT_TEST(TinySieve, i)) continue; /* 2*i+3 is composite */ /* The next tiny prime */ t = 2 * i + 3; r = smallbase % t; if (r == 0) { s = 0; /* t divides into smallbase exactly */ } else { /* smallbase+s is first entry divisible by t */ s = t - r; } /* * The sieve omits even numbers, so ensure that * smallbase+s is odd. Then, step through the sieve * in increments of 2*t */ if (s & 1) s += t; /* Make smallbase+s odd, and s even */ /* Mark all multiples of 2*t */ for (s /= 2; s < smallbits; s += t) BIT_SET(SmallSieve, s); } /* * SmallSieve */ for (i = 0; i < smallbits; i++) { if (BIT_TEST(SmallSieve, i)) continue; /* 2*i+smallbase is composite */ /* The next small prime */ sieve_large((2 * i) + smallbase); } memset(SmallSieve, 0, smallwords << SHIFT_BYTE); } time(&time_stop); logit("%.24s Sieved with %u small primes in %ld seconds", ctime(&time_stop), largetries, (long) (time_stop - time_start)); for (j = r = 0; j < largebits; j++) { if (BIT_TEST(LargeSieve, j)) continue; /* Definitely composite, skip */ debug2("test q = largebase+%u", 2 * j); BN_set_word(q, 2 * j); BN_add(q, q, largebase); if (qfileout(out, QTYPE_SOPHIE_GERMAIN, QTEST_SIEVE, largetries, (power - 1) /* MSB */, (0), q) == -1) { ret = -1; break; } r++; /* count q */ } time(&time_stop); xfree(LargeSieve); xfree(SmallSieve); xfree(TinySieve); logit("%.24s Found %u candidates", ctime(&time_stop), r); return (ret);}/* * perform a Miller-Rabin primality test * on the list of candidates * (checking both q and p) * The result is a list of so-call "safe" primes */intprime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted){ BIGNUM *q, *p, *a; BN_CTX *ctx; char *cp, *lp; u_int32_t count_in = 0, count_out = 0, count_possible = 0; u_int32_t generator_known, in_tests, in_tries, in_type, in_size; time_t time_start, time_stop; int res; if (trials < TRIAL_MINIMUM) { error("Minimum primality trials is %d", TRIAL_MINIMUM); return (-1); } time(&time_start); p = BN_new(); q = BN_new(); ctx = BN_CTX_new(); debug2("%.24s Final %u Miller-Rabin trials (%x generator)", ctime(&time_start), trials, generator_wanted); res = 0; lp = xmalloc(QLINESIZE + 1); while (fgets(lp, QLINESIZE, in) != NULL) { int ll = strlen(lp); count_in++; if (ll < 14 || *lp == '!' || *lp == '#') { debug2("%10u: comment or short line", count_in); continue; } /* XXX - fragile parser */ /* time */ cp = &lp[14]; /* (skip) */ /* type */ in_type = strtoul(cp, &cp, 10); /* tests */ in_tests = strtoul(cp, &cp, 10); if (in_tests & QTEST_COMPOSITE) { debug2("%10u: known composite", count_in); continue; } /* tries */ in_tries = strtoul(cp, &cp, 10); /* size (most significant bit) */ in_size = strtoul(cp, &cp, 10); /* generator (hex) */ generator_known = strtoul(cp, &cp, 16); /* Skip white space */ cp += strspn(cp, " "); /* modulus (hex) */ switch (in_type) { case QTYPE_SOPHIE_GERMAIN: debug2("%10u: (%u) Sophie-Germain", count_in, in_type); a = q; BN_hex2bn(&a, cp); /* p = 2*q + 1 */ BN_lshift(p, q, 1); BN_add_word(p, 1); in_size += 1; generator_known = 0; break; case QTYPE_UNSTRUCTURED: case QTYPE_SAFE: case QTYPE_SCHNORR: case QTYPE_STRONG: case QTYPE_UNKNOWN: debug2("%10u: (%u)", count_in, in_type); a = p; BN_hex2bn(&a, cp); /* q = (p-1) / 2 */ BN_rshift(q, p, 1); break; default: debug2("Unknown prime type"); break; } /* * due to earlier inconsistencies in interpretation, check * the proposed bit size. */ if (BN_num_bits(p) != (in_size + 1)) { debug2("%10u: bit size %u mismatch", count_in, in_size); continue; } if (in_size < QSIZE_MINIMUM) { debug2("%10u: bit size %u too short", count_in, in_size); continue; } if (in_tests & QTEST_MILLER_RABIN) in_tries += trials; else in_tries = trials; /* * guess unknown generator */ if (generator_known == 0) { if (BN_mod_word(p, 24) == 11) generator_known = 2; else if (BN_mod_word(p, 12) == 5) generator_known = 3; else { u_int32_t r = BN_mod_word(p, 10); if (r == 3 || r == 7) generator_known = 5; } } /* * skip tests when desired generator doesn't match */ if (generator_wanted > 0 && generator_wanted != generator_known) { debug2("%10u: generator %d != %d", count_in, generator_known, generator_wanted); continue; } /* * Primes with no known generator are useless for DH, so * skip those. */ if (generator_known == 0) { debug2("%10u: no known generator", count_in); continue; } count_possible++; /* * The (1/4)^N performance bound on Miller-Rabin is * extremely pessimistic, so don't spend a lot of time * really verifying that q is prime until after we know * that p is also prime. A single pass will weed out the * vast majority of composite q's. */ if (BN_is_prime(q, 1, NULL, ctx, NULL) <= 0) { debug("%10u: q failed first possible prime test", count_in); continue; } /* * q is possibly prime, so go ahead and really make sure * that p is prime. If it is, then we can go back and do * the same for q. If p is composite, chances are that * will show up on the first Rabin-Miller iteration so it * doesn't hurt to specify a high iteration count. */ if (!BN_is_prime(p, trials, NULL, ctx, NULL)) { debug("%10u: p is not prime", count_in); continue; } debug("%10u: p is almost certainly prime", count_in); /* recheck q more rigorously */ if (!BN_is_prime(q, trials - 1, NULL, ctx, NULL)) { debug("%10u: q is not prime", count_in); continue; } debug("%10u: q is almost certainly prime", count_in); if (qfileout(out, QTYPE_SAFE, (in_tests | QTEST_MILLER_RABIN), in_tries, in_size, generator_known, p)) { res = -1; break; } count_out++; } time(&time_stop); xfree(lp); BN_free(p); BN_free(q); BN_CTX_free(ctx); logit("%.24s Found %u safe primes of %u candidates in %ld seconds", ctime(&time_stop), count_out, count_possible, (long) (time_stop - time_start)); return (res);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -