Prime Number Testing

Made modifications to the primality testing so that the Miller-Rabin tests check against up to 40 random numbers rather than a fixed list of small primes.
This commit is contained in:
John Safranek
2018-07-05 17:23:01 -07:00
parent 87499aa7bd
commit f1c3098bdc
4 changed files with 127 additions and 2 deletions

View File

@ -4529,7 +4529,9 @@ int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap)
}
/* test */
if ((err = mp_prime_is_prime(N, 8, &res)) != MP_OKAY) {
/* Running Miller-Rabin up to 40 times gives us a 2^{-80} chance
* of a candidate being a false positive. */
if ((err = mp_prime_is_prime_ex(N, 40, &res, rng)) != MP_OKAY) {
XFREE(buf, heap, DYNAMIC_TYPE_RSA);
return err;
}
@ -4602,6 +4604,74 @@ LBL_B:mp_clear (&b);
}
/*
* Sets result to 1 if probably prime, 0 otherwise
*/
int mp_prime_is_prime_ex (mp_int * a, int t, int *result, WC_RNG *rng)
{
mp_int b;
int ix, err, res;
byte scratch[16];
/* default to no */
*result = MP_NO;
/* valid value of t? */
if (t <= 0 || t > PRIME_SIZE) {
return MP_VAL;
}
/* is the input equal to one of the primes in the table? */
for (ix = 0; ix < PRIME_SIZE; ix++) {
if (mp_cmp_d(a, ltm_prime_tab[ix]) == MP_EQ) {
*result = MP_YES;
return MP_OKAY;
}
}
/* first perform trial division */
if ((err = mp_prime_is_divisible (a, &res)) != MP_OKAY) {
return err;
}
/* return if it was trivially divisible */
if (res == MP_YES) {
return MP_OKAY;
}
/* now perform the miller-rabin rounds */
if ((err = mp_init (&b)) != MP_OKAY) {
return err;
}
/* now do a miller rabin with up to t random numbers, this should
* give a (1/4)^t chance of a false prime. */
for (ix = 0; ix < t; ix++) {
/* Set a test candidate. */
if ((err = wc_RNG_GenerateBlock(rng, scratch, sizeof(scratch))) != 0) {
goto LBL_B;
}
if ((err = mp_read_unsigned_bin(&b, scratch, sizeof(scratch))) != MP_OKAY) {
goto LBL_B;
}
if ((err = mp_prime_miller_rabin (a, &b, &res)) != MP_OKAY) {
goto LBL_B;
}
if (res == MP_NO) {
goto LBL_B;
}
}
/* passed the test */
*result = MP_YES;
LBL_B:mp_clear (&b);
return err;
}
/* computes least common multiple as |a*b|/(a, b) */
int mp_lcm (mp_int * a, mp_int * b, mp_int * c)
{

View File

@ -2945,10 +2945,60 @@ int fp_isprime(fp_int *a)
return fp_isprime_ex(a, 8);
}
int mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng)
{
int ret = FP_YES;
if (a == NULL || result == NULL || rng == NULL)
return FP_VAL;
/* do trial division */
if (ret == FP_YES) {
fp_digit d;
int r;
for (r = 0; r < FP_PRIME_SIZE; r++) {
if (fp_mod_d(a, primes[r], &d) == MP_OKAY) {
if (d == 0)
ret = FP_NO;
}
else
return FP_VAL;
}
}
/* now do a miller rabin with up to t random numbers, this should
* give a (1/4)^t chance of a false prime. */
if (ret == FP_YES) {
byte scratch[16];
fp_int b;
fp_init(&b);
while (t > 0) {
wc_RNG_GenerateBlock(rng, scratch, sizeof(scratch));
fp_read_unsigned_bin(&b, scratch, sizeof(scratch));
fp_prime_miller_rabin(a, &b, &ret);
if (ret == FP_NO)
break;
fp_zero(&b);
t--;
}
fp_clear(&b);
}
*result = ret;
return FP_OKAY;
}
int fp_randprime(fp_int* N, int len, WC_RNG* rng, void* heap)
{
static const int USE_BBS = 1;
int err, type;
int isPrime = FP_YES;
/* Assume the candidate is probably prime and then test until
* it is proven composite. */
byte* buf;
/* get type */
@ -2991,7 +3041,10 @@ int fp_randprime(fp_int* N, int len, WC_RNG* rng, void* heap)
fp_read_unsigned_bin(N, buf, len);
/* test */
} while (fp_isprime(N) == FP_NO);
/* Running Miller-Rabin up to 40 times gives us a 2^{-80} chance
* of a candidate being a false positive. */
mp_prime_is_prime_ex(N, 40, &isPrime, rng);
} while (isPrime == FP_NO);
XMEMSET(buf, 0, len);
XFREE(buf, heap, DYNAMIC_TYPE_TMP_BUFFER);

View File

@ -372,6 +372,7 @@ MP_API int mp_radix_size (mp_int * a, int radix, int *size);
#ifdef WOLFSSL_KEY_GEN
MP_API int mp_prime_is_prime (mp_int * a, int t, int *result);
MP_API int mp_prime_is_prime_ex (mp_int * a, int t, int *result, WC_RNG*);
MP_API int mp_gcd (mp_int * a, mp_int * b, mp_int * c);
MP_API int mp_lcm (mp_int * a, mp_int * b, mp_int * c);
MP_API int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap);

View File

@ -732,6 +732,7 @@ MP_API int mp_radix_size (mp_int * a, int radix, int *size);
MP_API int mp_gcd(fp_int *a, fp_int *b, fp_int *c);
MP_API int mp_lcm(fp_int *a, fp_int *b, fp_int *c);
MP_API int mp_prime_is_prime(mp_int* a, int t, int* result);
MP_API int mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng);
MP_API int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap);
MP_API int mp_exch(mp_int *a, mp_int *b);
#endif /* WOLFSSL_KEY_GEN */