mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-07-30 02:37:28 +02:00
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:
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
Reference in New Issue
Block a user