mp_err make_prime(mp_int *p, int nr) { mp_err res; if(mp_iseven(p)) { mp_add_d(p, 1, p); } do { mp_digit which = prime_tab_size; /* First test for divisibility by a few small primes */ if((res = mpp_divis_primes(p, &which)) == MP_YES) continue; else if(res != MP_NO) goto CLEANUP; /* If that passes, try one iteration of Fermat's test */ if((res = mpp_fermat(p, 2)) == MP_NO) continue; else if(res != MP_YES) goto CLEANUP; /* If that passes, run Rabin-Miller as often as requested */ if((res = mpp_pprime(p, nr)) == MP_YES) break; else if(res != MP_NO) goto CLEANUP; } while((res = mp_add_d(p, 2, p)) == MP_OKAY); CLEANUP: return res; } /* end make_prime() */
mp_err rsa_is_prime(mp_int *p) { int res; /* run a Fermat test */ res = mpp_fermat(p, 2); if (res != MP_OKAY) { return res; } /* If that passed, run some Miller-Rabin tests */ res = mpp_pprime(p, 2); return res; }
int main(int argc, char *argv[]) { int ix; mp_digit num; mp_int a; srand(time(NULL)); if(argc < 2) { fprintf(stderr, "Usage: %s <a>\n", argv[0]); return 1; } printf("Test 8: Probabilistic primality testing\n\n"); mp_init(&a); mp_read_radix(&a, argv[1], 10); printf("a = "); mp_print(&a, stdout); fputc('\n', stdout); printf("\nChecking for divisibility by small primes ... \n"); num = 170; if(mpp_divis_primes(&a, &num) == MP_YES) { printf("it is not prime\n"); goto CLEANUP; } printf("Passed that test (not divisible by any small primes).\n"); for(ix = 0; ix < 10; ix++) { printf("\nPerforming Rabin-Miller test, iteration %d\n", ix + 1); if(mpp_pprime(&a, 5) == MP_NO) { printf("it is not prime\n"); goto CLEANUP; } } printf("All tests passed; a is probably prime\n"); CLEANUP: mp_clear(&a); return 0; }
mp_err mpp_make_prime(mp_int *start, mp_size nBits, mp_size strong, unsigned long * nTries) { mp_digit np; mp_err res; int i = 0; mp_int trial; mp_int q; mp_size num_tests; unsigned char *sieve; ARGCHK(start != 0, MP_BADARG); ARGCHK(nBits > 16, MP_RANGE); sieve = malloc(SIEVE_SIZE); ARGCHK(sieve != NULL, MP_MEM); MP_DIGITS(&trial) = 0; MP_DIGITS(&q) = 0; MP_CHECKOK( mp_init(&trial) ); MP_CHECKOK( mp_init(&q) ); /* values taken from table 4.4, HandBook of Applied Cryptography */ if (nBits >= 1300) { num_tests = 2; } else if (nBits >= 850) { num_tests = 3; } else if (nBits >= 650) { num_tests = 4; } else if (nBits >= 550) { num_tests = 5; } else if (nBits >= 450) { num_tests = 6; } else if (nBits >= 400) { num_tests = 7; } else if (nBits >= 350) { num_tests = 8; } else if (nBits >= 300) { num_tests = 9; } else if (nBits >= 250) { num_tests = 12; } else if (nBits >= 200) { num_tests = 15; } else if (nBits >= 150) { num_tests = 18; } else if (nBits >= 100) { num_tests = 27; } else num_tests = 50; if (strong) --nBits; MP_CHECKOK( mpl_set_bit(start, nBits - 1, 1) ); MP_CHECKOK( mpl_set_bit(start, 0, 1) ); for (i = mpl_significant_bits(start) - 1; i >= nBits; --i) { MP_CHECKOK( mpl_set_bit(start, i, 0) ); } /* start sieveing with prime value of 3. */ MP_CHECKOK(mpp_sieve(start, prime_tab + 1, prime_tab_size - 1, sieve, SIEVE_SIZE) ); #ifdef DEBUG_SIEVE res = 0; for (i = 0; i < SIEVE_SIZE; ++i) { if (!sieve[i]) ++res; } fprintf(stderr,"sieve found %d potential primes.\n", res); #define FPUTC(x,y) fputc(x,y) #else #define FPUTC(x,y) #endif res = MP_NO; for(i = 0; i < SIEVE_SIZE; ++i) { if (sieve[i]) /* this number is composite */ continue; MP_CHECKOK( mp_add_d(start, 2 * i, &trial) ); FPUTC('.', stderr); /* run a Fermat test */ res = mpp_fermat(&trial, 2); if (res != MP_OKAY) { if (res == MP_NO) continue; /* was composite */ goto CLEANUP; } FPUTC('+', stderr); /* If that passed, run some Miller-Rabin tests */ res = mpp_pprime(&trial, num_tests); if (res != MP_OKAY) { if (res == MP_NO) continue; /* was composite */ goto CLEANUP; } FPUTC('!', stderr); if (!strong) break; /* success !! */ /* At this point, we have strong evidence that our candidate is itself prime. If we want a strong prime, we need now to test q = 2p + 1 for primality... */ MP_CHECKOK( mp_mul_2(&trial, &q) ); MP_CHECKOK( mp_add_d(&q, 1, &q) ); /* Test q for small prime divisors ... */ np = prime_tab_size; res = mpp_divis_primes(&q, &np); if (res == MP_YES) { /* is composite */ mp_clear(&q); continue; } if (res != MP_NO) goto CLEANUP; /* And test with Fermat, as with its parent ... */ res = mpp_fermat(&q, 2); if (res != MP_YES) { mp_clear(&q); if (res == MP_NO) continue; /* was composite */ goto CLEANUP; } /* And test with Miller-Rabin, as with its parent ... */ res = mpp_pprime(&q, num_tests); if (res != MP_YES) { mp_clear(&q); if (res == MP_NO) continue; /* was composite */ goto CLEANUP; } /* If it passed, we've got a winner */ mp_exch(&q, &trial); mp_clear(&q); break; } /* end of loop through sieved values */ if (res == MP_YES) mp_exch(&trial, start); CLEANUP: mp_clear(&trial); mp_clear(&q); if (nTries) *nTries += i; if (sieve != NULL) { memset(sieve, 0, SIEVE_SIZE); free (sieve); } return res; }
int main(int argc, char *argv[]) { unsigned char *raw, *out; int rawlen, bits, outlen, ngen, ix, jx; mp_int testval, q, ntries; mp_err res; mp_digit np; clock_t start, end; #ifdef MACOS argc = ccommand(&argv); #endif /* We'll just use the C library's rand() for now, although this won't be good enough for cryptographic purposes */ if((out = (unsigned char *)getenv("SEED")) == NULL) { srand((unsigned int)time(NULL)); } else { srand((unsigned int)atoi((char *)out)); } if(argc < 2) { fprintf(stderr, "Usage: %s <bits> [<count> [strong]]\n", argv[0]); return 1; } if((bits = abs(atoi(argv[1]))) < CHAR_BIT) { fprintf(stderr, "%s: please request at least %d bits.\n", argv[0], CHAR_BIT); return 1; } /* If optional third argument is given, use that as the number of primes to generate; otherwise generate one prime only. */ if(argc < 3) { ngen = 1; } else { ngen = abs(atoi(argv[2])); } /* If fourth argument is given, and is the word "strong", we'll generate strong (Sophie Germain) primes. */ if(argc > 3 && strcmp(argv[3], "strong") == 0) g_strong = 1; /* testval - candidate being tested ntries - number tried so far q - used in finding strong primes */ if((res = mp_init(&testval)) != MP_OKAY || (res = mp_init(&ntries)) != MP_OKAY || (res = mp_init(&q)) != MP_OKAY) { fprintf(stderr, "%s: error: %s\n", argv[0], mp_strerror(res)); return 1; } if(g_strong) { printf("Requested %d strong prime values of at least %d bits.\n", ngen, bits); } else { printf("Requested %d prime values of at least %d bits.\n", ngen, bits); } rawlen = (bits / CHAR_BIT) + ((bits % CHAR_BIT) ? 1 : 0); if((raw = calloc(rawlen, sizeof(unsigned char))) == NULL) { fprintf(stderr, "%s: out of memory, sorry.\n", argv[0]); return 1; } /* This loop is one for each prime we need to generate */ for(jx = 0; jx < ngen; jx++) { /* Pack the initializer with random bytes */ for(ix = 0; ix < rawlen; ix++) raw[ix] = (rand() * rand()) & UCHAR_MAX; raw[0] |= 0x80; /* set high-order bit of test value */ if(g_strong) raw[rawlen - 1] |= 7; /* set low-order 3 bits of test value */ else raw[rawlen - 1] |= 1; /* set low-order bit of test value */ /* Make an mp_int out of the initializer */ mp_read_unsigned_bin(&testval, raw, rawlen); /* If we asked for a strong prime, shift down one bit so that when we double, we're still within the right range of bits ... this is why we OR'd with 7 instead of 1 above (leaves two bits set so that the value remains congruent to 3 (mod 4)). */ if(g_strong) { mp_copy(&testval, &q); mp_div_2(&testval, &testval); } /* Initialize candidate counter */ mp_zero(&ntries); mp_add_d(&ntries, 1, &ntries); start = clock(); /* time generation for this prime */ for(;;) { /* Test for divisibility by small primes (of which there is a table conveniently stored in mpprime.c) */ np = prime_tab_size; if(mpp_divis_primes(&testval, &np) == MP_NO) { /* If we're trying for a strong prime, test 2p+1 before running other primality tests */ if(g_strong) { np = prime_tab_size; if(mpp_divis_primes(&q, &np) == MP_YES) goto NEXT_CANDIDATE; } /* If that passed, run a Fermat test */ res = mpp_fermat(&testval, 2); switch(res) { case MP_NO: /* composite */ goto NEXT_CANDIDATE; case MP_YES: /* may be prime */ break; default: goto CLEANUP; /* some other error */ } /* If that passed, run some Miller-Rabin tests */ res = mpp_pprime(&testval, NUM_TESTS); switch(res) { case MP_NO: /* composite */ goto NEXT_CANDIDATE; case MP_YES: /* may be prime */ break; default: goto CLEANUP; /* some other error */ } /* At this point, we have strong evidence that our candidate is itself prime. If we want a strong prime, we need now to test q = 2p + 1 for primality... */ if(g_strong) { if(res == MP_YES) { fputc('.', stderr); /* If we get here, we've already tested q against small prime divisors, so we can just do the regular primality testing */ /* Fermat, as with its parent ... */ res = mpp_fermat(&q, 2); switch(res) { case MP_NO: /* composite */ goto NEXT_CANDIDATE; case MP_YES: /* may be prime */ break; default: goto CLEANUP; /* some other error */ } /* And, with Miller-Rabin, as with its parent ... */ res = mpp_pprime(&q, NUM_TESTS); switch(res) { case MP_NO: /* composite */ goto NEXT_CANDIDATE; case MP_YES: /* may be prime */ break; default: goto CLEANUP; /* some other error */ } /* If it passed, we've got a winner */ if(res == MP_YES) { fputc('\n', stderr); mp_copy(&q, &testval); break; } } /* end if(res == MP_YES) */ } else { /* We get here if g_strong is false */ if(res == MP_YES) break; } } /* end if(not divisible by small primes) */ /* If we're testing strong primes, skip to the next odd value congruent to 3 (mod 4). Otherwise, just skip to the next odd value */ NEXT_CANDIDATE: if(g_strong) { mp_add_d(&q, 4, &q); mp_div_2(&q, &testval); } else mp_add_d(&testval, 2, &testval); mp_add_d(&ntries, 1, &ntries); } /* end of loop to generate a single prime */ end = clock(); printf("After %d tests, the following value is still probably prime:\n", NUM_TESTS); outlen = mp_radix_size(&testval, 10); out = calloc(outlen, sizeof(unsigned char)); mp_toradix(&testval, out, 10); printf("10: %s\n", (char *)out); mp_toradix(&testval, out, 16); printf("16: %s\n\n", (char *)out); free(out); printf("Number of candidates tried: "); outlen = mp_radix_size(&ntries, 10); out = calloc(outlen, sizeof(unsigned char)); mp_toradix(&ntries, out, 10); printf("%s\n", (char *)out); free(out); printf("This computation took %ld clock ticks (%.2f seconds)\n", (end - start), ((double)(end - start) / CLOCKS_PER_SEC)); fputc('\n', stdout); } /* end of loop to generate all requested primes */ CLEANUP: if(res != MP_OKAY) fprintf(stderr, "%s: error: %s\n", argv[0], mp_strerror(res)); free(raw); mp_clear(&testval); mp_clear(&q); mp_clear(&ntries); return 0; }
int main(int argc, char *argv[]) { mp_int a; mp_digit np = prime_tab_size; /* from mpprime.h */ int res = 0; g_prog = argv[0]; if(argc < 2) { fprintf(stderr, "Usage: %s <a>, where <a> is a decimal integer\n" "Use '0x' prefix for a hexadecimal value\n", g_prog); return 1; } /* Read number of tests from environment, if present */ { char *tmp; if((tmp = getenv("RM_TESTS")) != NULL) { if((g_tests = atoi(tmp)) <= 0) g_tests = RM_TESTS; } } mp_init(&a); if(argv[1][0] == '0' && argv[1][1] == 'x') mp_read_radix(&a, argv[1] + 2, 16); else mp_read_radix(&a, argv[1], 10); if(mp_cmp_d(&a, MINIMUM) <= 0) { fprintf(stderr, "%s: please use a value greater than %d\n", g_prog, MINIMUM); mp_clear(&a); return 1; } /* Test for divisibility by small primes */ if(mpp_divis_primes(&a, &np) != MP_NO) { printf("Not prime (divisible by small prime %d)\n", np); res = 2; goto CLEANUP; } /* Test with Fermat's test, using 2 as a witness */ if(mpp_fermat(&a, 2) != MP_YES) { printf("Not prime (failed Fermat test)\n"); res = 2; goto CLEANUP; } /* Test with Rabin-Miller probabilistic test */ if(mpp_pprime(&a, g_tests) == MP_NO) { printf("Not prime (failed pseudoprime test)\n"); res = 2; goto CLEANUP; } printf("Probably prime, 1 in 4^%d chance of false positive\n", g_tests); CLEANUP: mp_clear(&a); return res; }