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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
/*
* Prime Generation
* (C) 1999-2007 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
#include <botan/numthry.h>
#include <botan/rng.h>
#include <algorithm>
namespace Botan {
/*
* Generate a random prime
*/
BigInt random_prime(RandomNumberGenerator& rng,
size_t bits, const BigInt& coprime,
size_t equiv, size_t modulo)
{
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");
}
// Handle small values:
if(bits <= 1)
{
throw Invalid_Argument("random_prime: Can't make a prime of " +
std::to_string(bits) + " bits");
}
else if(bits == 2)
{
return ((rng.next_byte() % 2) ? 2 : 3);
}
else if(bits == 3)
{
return ((rng.next_byte() % 2) ? 5 : 7);
}
else if(bits == 4)
{
return ((rng.next_byte() % 2) ? 11 : 13);
}
while(true)
{
BigInt p(rng, bits);
// Force lowest and two top bits on
p.set_bit(bits - 1);
p.set_bit(bits - 2);
p.set_bit(0);
if(p % modulo != equiv)
p += (modulo - p % modulo) + equiv;
const size_t sieve_size = std::min(bits / 2, PRIME_TABLE_SIZE);
secure_vector<uint16_t> sieve(sieve_size);
for(size_t j = 0; j != sieve.size(); ++j)
sieve[j] = static_cast<uint16_t>(p % PRIMES[j]);
size_t counter = 0;
while(true)
{
++counter;
if(counter >= 4096)
{
break; // don't try forever, choose a new starting point
}
p += modulo;
if(p.bits() > bits)
break;
bool passes_sieve = true;
for(size_t j = 0; j != sieve.size(); ++j)
{
sieve[j] = (sieve[j] + modulo) % PRIMES[j];
if(sieve[j] == 0)
{
passes_sieve = false;
break;
}
}
if(!passes_sieve)
continue;
if(gcd(p - 1, coprime) != 1)
continue;
if(is_prime(p, rng, 128, true))
{
return p;
}
}
}
}
/*
* Generate a random safe prime
*/
BigInt random_safe_prime(RandomNumberGenerator& rng, size_t bits)
{
if(bits <= 64)
throw Invalid_Argument("random_safe_prime: Can't make a prime of " +
std::to_string(bits) + " bits");
BigInt p;
do
p = (random_prime(rng, bits - 1) << 1) + 1;
while(!is_prime(p, rng, 128, true));
return p;
}
}
|