mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-07-31 03:07:29 +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 */
|
/* 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);
|
XFREE(buf, heap, DYNAMIC_TYPE_RSA);
|
||||||
return err;
|
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) */
|
/* computes least common multiple as |a*b|/(a, b) */
|
||||||
int mp_lcm (mp_int * a, mp_int * b, mp_int * c)
|
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);
|
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)
|
int fp_randprime(fp_int* N, int len, WC_RNG* rng, void* heap)
|
||||||
{
|
{
|
||||||
static const int USE_BBS = 1;
|
static const int USE_BBS = 1;
|
||||||
int err, type;
|
int err, type;
|
||||||
|
int isPrime = FP_YES;
|
||||||
|
/* Assume the candidate is probably prime and then test until
|
||||||
|
* it is proven composite. */
|
||||||
byte* buf;
|
byte* buf;
|
||||||
|
|
||||||
/* get type */
|
/* 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);
|
fp_read_unsigned_bin(N, buf, len);
|
||||||
|
|
||||||
/* test */
|
/* 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);
|
XMEMSET(buf, 0, len);
|
||||||
XFREE(buf, heap, DYNAMIC_TYPE_TMP_BUFFER);
|
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
|
#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 (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_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_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);
|
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_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_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(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_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap);
|
||||||
MP_API int mp_exch(mp_int *a, mp_int *b);
|
MP_API int mp_exch(mp_int *a, mp_int *b);
|
||||||
#endif /* WOLFSSL_KEY_GEN */
|
#endif /* WOLFSSL_KEY_GEN */
|
||||||
|
Reference in New Issue
Block a user