Botan 3.0.0 Crypto and TLS for C&
primality.cpp
Go to the documentation of this file.
1/*
2* (C) 2016,2018 Jack Lloyd
3*
5*/
6
7#include <botan/internal/primality.h>
8#include <botan/internal/monty_exp.h>
9#include <botan/bigint.h>
10#include <botan/internal/monty.h>
11#include <botan/reducer.h>
12#include <botan/rng.h>
13#include <algorithm>
14
15namespace Botan {
16
18 {
19 if(C == 2 || C == 3 || C == 5 || C == 7 || C == 11 || C == 13)
20 return true;
21
22 if(C <= 1 || C.is_even())
23 return false;
24
26
27 for(;;)
28 {
29 int32_t j = jacobi(D, C);
30 if(j == 0)
31 return false;
32
33 if(j == -1)
34 break;
35
36 // Check 5, -7, 9, -11, 13, -15, 17, ...
37 if(D.is_negative())
38 {
39 D.flip_sign();
40 D += 2;
41 }
42 else
43 {
44 D += 2;
45 D.flip_sign();
46 }
47
48 if(D == 17 && is_perfect_square(C).is_nonzero())
49 return false;
50 }
51
52 const BigInt K = C + 1;
53 const size_t K_bits = K.bits() - 1;
54
55 BigInt U = BigInt::one();
56 BigInt V = BigInt::one();
57
58 BigInt Ut, Vt, U2, V2;
59
60 for(size_t i = 0; i != K_bits; ++i)
61 {
62 const bool k_bit = K.get_bit(K_bits - 1 - i);
63
64 Ut = mod_C.multiply(U, V);
65
66 Vt = mod_C.reduce(mod_C.square(V) + mod_C.multiply(D, mod_C.square(U)));
68 Vt >>= 1;
69 Vt = mod_C.reduce(Vt);
70
71 U = Ut;
72 V = Vt;
73
74 U2 = mod_C.reduce(Ut + Vt);
76 U2 >>= 1;
77
78 V2 = mod_C.reduce(Vt + Ut*D);
80 V2 >>= 1;
81
82 U.ct_cond_assign(k_bit, U2);
83 V.ct_cond_assign(k_bit, V2);
84 }
85
86 return (U == 0);
87 }
88
90 {
91 if(n == 2)
92 return true;
93 else if(n <= 1 || n.is_even())
94 return false;
95
96 auto monty_n = std::make_shared<Montgomery_Params>(n, mod_n);
97 const auto base = BigInt::from_word(2);
98 return passes_miller_rabin_test(n, mod_n, monty_n, base) && is_lucas_probable_prime(n, mod_n);
99 }
100
102 {
103 Modular_Reducer mod_n(n);
104 return is_bailie_psw_probable_prime(n, mod_n);
105 }
106
108 const Modular_Reducer& mod_n,
109 const std::shared_ptr<Montgomery_Params>& monty_n,
110 const BigInt& a)
111 {
112 if(n < 3 || n.is_even())
113 return false;
114
115 BOTAN_ASSERT_NOMSG(n > 1);
116
117 const BigInt n_minus_1 = n - 1;
118 const size_t s = low_zero_bits(n_minus_1);
119 const BigInt nm1_s = n_minus_1 >> s;
120 const size_t n_bits = n.bits();
121
122 const size_t powm_window = 4;
123
124 auto powm_a_n = monty_precompute(monty_n, a, powm_window);
125
126 BigInt y = monty_execute(*powm_a_n, nm1_s, n_bits);
127
128 if(y == 1 || y == n_minus_1)
129 return true;
130
131 for(size_t i = 1; i != s; ++i)
132 {
133 y = mod_n.square(y);
134
135 if(y == 1) // found a non-trivial square root
136 return false;
137
138 /*
139 -1 is the trivial square root of unity, so ``a`` is not a
140 witness for this number - give up
141 */
142 if(y == n_minus_1)
143 return true;
144 }
145
146 return false;
147 }
148
150 const Modular_Reducer& mod_n,
152 size_t test_iterations)
153 {
154 if(n < 3 || n.is_even())
155 return false;
156
157 auto monty_n = std::make_shared<Montgomery_Params>(n, mod_n);
158
159 for(size_t i = 0; i != test_iterations; ++i)
160 {
161 const BigInt a = BigInt::random_integer(rng, BigInt::from_word(2), n);
162
163 if(!passes_miller_rabin_test(n, mod_n, monty_n, a))
164 return false;
165 }
166
167 // Failed to find a counterexample
168 return true;
169 }
170
171
172size_t miller_rabin_test_iterations(size_t n_bits, size_t prob, bool random)
173 {
174 const size_t base = (prob + 2) / 2; // worst case 4^-t error rate
175
176 /*
177 * If the candidate prime was maliciously constructed, we can't rely
178 * on arguments based on p being random.
179 */
180 if(random == false)
181 return base;
182
183 /*
184 * For randomly chosen numbers we can use the estimates from
185 * http://www.math.dartmouth.edu/~carlp/PDF/paper88.pdf
186 *
187 * These values are derived from the inequality for p(k,t) given on
188 * the second page.
189 */
190 if(prob <= 128)
191 {
192 if(n_bits >= 1536)
193 return 4; // < 2^-133
194 if(n_bits >= 1024)
195 return 6; // < 2^-133
196 if(n_bits >= 512)
197 return 12; // < 2^-129
198 if(n_bits >= 256)
199 return 29; // < 2^-128
200 }
201
202 /*
203 If the user desires a smaller error probability than we have
204 precomputed error estimates for, just fall back to using the worst
205 case error rate.
206 */
207 return base;
208 }
209
210}
static SIMD_4x64 y
#define BOTAN_ASSERT_NOMSG(expr)
Definition: assert.h:67
void ct_cond_add(bool predicate, const BigInt &value)
Definition: bigint.cpp:454
bool is_odd() const
Definition: bigint.h:422
static BigInt random_integer(RandomNumberGenerator &rng, const BigInt &min, const BigInt &max)
Definition: big_rand.cpp:45
void ct_cond_assign(bool predicate, const BigInt &other)
Definition: bigint.cpp:487
void flip_sign()
Definition: bigint.h:583
static BigInt one()
Definition: bigint.h:50
size_t bits() const
Definition: bigint.cpp:312
bool is_even() const
Definition: bigint.h:416
static BigInt from_word(word n)
Definition: bigint.cpp:43
bool is_negative() const
Definition: bigint.h:556
bool get_bit(size_t n) const
Definition: bigint.h:483
BigInt square(const BigInt &x) const
Definition: reducer.h:46
BigInt multiply(const BigInt &x, const BigInt &y) const
Definition: reducer.h:31
BigInt reduce(const BigInt &x) const
Definition: reducer.cpp:37
Definition: alg_id.cpp:12
size_t low_zero_bits(const BigInt &n)
Definition: numthry.cpp:181
bool passes_miller_rabin_test(const BigInt &n, const Modular_Reducer &mod_n, const std::shared_ptr< Montgomery_Params > &monty_n, const BigInt &a)
Definition: primality.cpp:107
bool is_miller_rabin_probable_prime(const BigInt &n, const Modular_Reducer &mod_n, RandomNumberGenerator &rng, size_t test_iterations)
Definition: primality.cpp:149
bool is_bailie_psw_probable_prime(const BigInt &n, const Modular_Reducer &mod_n)
Definition: primality.cpp:89
BigInt is_perfect_square(const BigInt &C)
Definition: numthry.cpp:338
size_t miller_rabin_test_iterations(size_t n_bits, size_t prob, bool random)
Definition: primality.cpp:172
int32_t jacobi(const BigInt &a, const BigInt &n)
Definition: numthry.cpp:130
bool is_lucas_probable_prime(const BigInt &C, const Modular_Reducer &mod_C)
Definition: primality.cpp:17
BigInt monty_execute(const Montgomery_Exponentation_State &precomputed_state, const BigInt &k, size_t max_k_bits)
Definition: monty_exp.cpp:162
std::shared_ptr< const Montgomery_Exponentation_State > monty_precompute(const std::shared_ptr< const Montgomery_Params > &params, const BigInt &g, size_t window_bits, bool const_time)
Definition: monty_exp.cpp:154