Я реализовал следующую функцию GMP для программы RSA. В принципе, программа генерирует случайные номера mpz*t
пока одна из них не вернет true
для этой функции.
bool isPrime(const mpz_t bignum)
{
mpz_t modnum; mpz_init(modnum);
if(mpz_cmp_ui(bignum,4)<0 && mpz_cmp_si(bignum,0)>=0) {
fprintf(stderr,"Trivially prime.\n");
return false;
}
else if(mpz_mod_ui(modnum,bignum,2)==0)
return false;
mpz_clear(modnum);
mpz_t i,rootnum;
mpz_inits(i,modnum,rootnum,NULL);
mpz_sqrt(rootnum,bignum);
mpz_set_str(i,"3",10);
for(;mpz_cmp(rootnum,i)>0; mpz_add_ui(i,i,2)) {
mpz_mod(modnum,bignum,i);
if(mpz_cmp(modnum,i)==0)
return false;
}
mpz_clears(modnum,i,rootnum,NULL);
return true;
}
Вот функция, которая вызывает isPrime()
в качестве подпрограммы:
void generate_pq(mpz_t& p, mpz_t& q)
{
gmp_randstate_t rstate;
gmp_randinit_default(rstate);
gmp_randseed_ui(rstate,time(NULL));
printf("\nGenerating keys...\n");
do {
mpz_urandomb(p,rstate,32);
} while(!isPrime(p));
printf("\n***** p *****\n");
gmp_printf(" %Zd\n",p);
do {
mpz_urandomb(q,rstate,32);
} while(!isPrime(q));
gmp_randclear(rstate);
printf("\n***** q *****\n");
gmp_printf(" %Zd\n",q);
}
Программа компилируется и не создает никаких проблем. Однако генерируемые числа не являются isPrime()
и все же isPrime()
прежнему возвращает true для них. Может ли кто-нибудь указать на недостаток в алгоритме моего теста на первичность? Вот регулярная версия int
моей функции isPrime()
, если вы хотите сравнить:
bool isPrime(uint64_t n)
{
//waste of time
if(n < 4) {
fprintf(stderr,"Trivially prime.\n");
return true;
}
//even #, not prime
else if(n%2==0) {
return false;
}
//check if divisible by all odd #s < sqrt(n)
for(uint64_t i=3; i<(uint64_t)sqrt(n+1); i+=2) {
if(n%i==0) {
return false;
}
}
return true;
}
Ошибка была в моем for-loop.
for(;mpz_cmp(rootnum,i)>0; mpz_add_ui(i,i,2)) {
mpz_mod(modnum,bignum,i);
if(mpz_cmp(modnum,i)==0) // <-----not supposed to do if(modnum==i)
return false;
Правильная версия этого for-loop находится здесь:
for(;mpz_cmp(rootnum,i)>0; mpz_add_ui(i,i,2)) {
mpz_mod(modnum,bignum,i);
if(mpz_cmp_ui(modnum,0)==0) // <-- if bignum % modnum == 0, return false
return false;