blob: 7d399b8259ee1cb342c030ca271b3a5a2fc3c5ec (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
/*************************************************
* Prime Generation Source File *
* (C) 1999-2007 Jack Lloyd *
*************************************************/
#include <botan/numthry.h>
#include <botan/parsing.h>
#include <algorithm>
namespace Botan {
/*************************************************
* Generate a random prime *
*************************************************/
BigInt random_prime(RandomNumberGenerator& rng,
u32bit bits, const BigInt& coprime,
u32bit equiv, u32bit modulo)
{
if(bits < 48)
throw Invalid_Argument("random_prime: Can't make a prime of " +
to_string(bits) + " bits");
if(coprime <= 0)
throw Invalid_Argument("random_prime: coprime must be > 0");
if(modulo % 2 == 1 || modulo == 0)
throw Invalid_Argument("random_prime: Invalid modulo value");
if(equiv >= modulo || equiv % 2 == 0)
throw Invalid_Argument("random_prime: equiv must be < modulo, and odd");
while(true)
{
BigInt p = random_integer(rng, bits);
p.set_bit(bits - 2);
p.set_bit(0);
if(p % modulo != equiv)
p += (modulo - p % modulo) + equiv;
const u32bit sieve_size = std::min(bits / 2, PRIME_TABLE_SIZE);
SecureVector<u32bit> sieve(sieve_size);
for(u32bit j = 0; j != sieve.size(); ++j)
sieve[j] = p % PRIMES[j];
u32bit counter = 0;
while(true)
{
if(counter == 4096 || p.bits() > bits)
break;
bool passes_sieve = true;
++counter;
p += modulo;
for(u32bit j = 0; j != sieve.size(); ++j)
{
sieve[j] = (sieve[j] + modulo) % PRIMES[j];
if(sieve[j] == 0)
passes_sieve = false;
}
if(!passes_sieve || gcd(p - 1, coprime) != 1)
continue;
if(passes_mr_tests(rng, p))
return p;
}
}
}
}
|