Botan 1.10.17
numthry.cpp
Go to the documentation of this file.
1/*
2* Number Theory Functions
3* (C) 1999-2011 Jack Lloyd
4*
5* Distributed under the terms of the Botan license
6*/
7
8#include <botan/numthry.h>
9#include <botan/reducer.h>
10#include <botan/internal/mp_core.h>
11#include <botan/internal/bit_ops.h>
12#include <algorithm>
13
14namespace Botan {
15
16namespace {
17
18/*
19* Miller-Rabin Primality Tester
20*/
21class MillerRabin_Test
22 {
23 public:
24 bool is_witness(const BigInt& nonce);
25 MillerRabin_Test(const BigInt& num);
26 private:
27 BigInt n, r, n_minus_1;
28 size_t s;
29 Fixed_Exponent_Power_Mod pow_mod;
30 Modular_Reducer reducer;
31 };
32
33/*
34* Miller-Rabin Test, as described in Handbook of Applied Cryptography
35* section 4.24
36*/
37bool MillerRabin_Test::is_witness(const BigInt& a)
38 {
39 if(a < 2 || a >= n_minus_1)
40 throw Invalid_Argument("Bad size for nonce in Miller-Rabin test");
41
42 BigInt y = pow_mod(a);
43 if(y == 1 || y == n_minus_1)
44 return false;
45
46 for(size_t i = 1; i != s; ++i)
47 {
48 y = reducer.square(y);
49
50 if(y == 1) // found a non-trivial square root
51 return true;
52
53 if(y == n_minus_1) // -1, trivial square root, so give up
54 return false;
55 }
56
57 // If we reached here then n fails the Fermat test
58 return true;
59 }
60
61/*
62* Miller-Rabin Constructor
63*/
64MillerRabin_Test::MillerRabin_Test(const BigInt& num)
65 {
66 if(num.is_even() || num < 3)
67 throw Invalid_Argument("MillerRabin_Test: Invalid number for testing");
68
69 n = num;
70 n_minus_1 = n - 1;
71 s = low_zero_bits(n_minus_1);
72 r = n_minus_1 >> s;
73
74 pow_mod = Fixed_Exponent_Power_Mod(r, n);
75 reducer = Modular_Reducer(n);
76 }
77
78/*
79* Miller-Rabin Iterations
80*/
81size_t miller_rabin_test_iterations(size_t bits, size_t level)
82 {
83 struct mapping { size_t bits; size_t verify_iter; size_t check_iter; };
84
85 static const mapping tests[] = {
86 { 50, 55, 25 },
87 { 100, 38, 22 },
88 { 160, 32, 18 },
89 { 163, 31, 17 },
90 { 168, 30, 16 },
91 { 177, 29, 16 },
92 { 181, 28, 15 },
93 { 185, 27, 15 },
94 { 190, 26, 15 },
95 { 195, 25, 14 },
96 { 201, 24, 14 },
97 { 208, 23, 14 },
98 { 215, 22, 13 },
99 { 222, 21, 13 },
100 { 231, 20, 13 },
101 { 241, 19, 12 },
102 { 252, 18, 12 },
103 { 264, 17, 12 },
104 { 278, 16, 11 },
105 { 294, 15, 10 },
106 { 313, 14, 9 },
107 { 334, 13, 8 },
108 { 360, 12, 8 },
109 { 392, 11, 7 },
110 { 430, 10, 7 },
111 { 479, 9, 6 },
112 { 542, 8, 6 },
113 { 626, 7, 5 },
114 { 746, 6, 4 },
115 { 926, 5, 3 },
116 { 1232, 4, 2 },
117 { 1853, 3, 2 },
118 { 0, 0, 0 }
119 };
120
121 for(size_t i = 0; tests[i].bits; ++i)
122 {
123 if(bits <= tests[i].bits)
124 {
125 if(level >= 2)
126 return tests[i].verify_iter;
127 else if(level == 1)
128 return tests[i].check_iter;
129 else if(level == 0)
130 return std::max<size_t>(tests[i].check_iter / 4, 1);
131 }
132 }
133
134 return level > 0 ? 2 : 1; // for large inputs
135 }
136
137}
138
139/*
140* Return the number of 0 bits at the end of n
141*/
142size_t low_zero_bits(const BigInt& n)
143 {
144 size_t low_zero = 0;
145
146 if(n.is_positive() && n.is_nonzero())
147 {
148 for(size_t i = 0; i != n.size(); ++i)
149 {
150 word x = n[i];
151
152 if(x)
153 {
154 low_zero += ctz(x);
155 break;
156 }
157 else
158 low_zero += BOTAN_MP_WORD_BITS;
159 }
160 }
161
162 return low_zero;
163 }
164
165/*
166* Calculate the GCD
167*/
168BigInt gcd(const BigInt& a, const BigInt& b)
169 {
170 if(a.is_zero() || b.is_zero()) return 0;
171 if(a == 1 || b == 1) return 1;
172
173 BigInt x = a, y = b;
175 y.set_sign(BigInt::Positive);
176 size_t shift = std::min(low_zero_bits(x), low_zero_bits(y));
177
178 x >>= shift;
179 y >>= shift;
180
181 while(x.is_nonzero())
182 {
183 x >>= low_zero_bits(x);
184 y >>= low_zero_bits(y);
185 if(x >= y) { x -= y; x >>= 1; }
186 else { y -= x; y >>= 1; }
187 }
188
189 return (y << shift);
190 }
191
192/*
193* Calculate the LCM
194*/
195BigInt lcm(const BigInt& a, const BigInt& b)
196 {
197 return ((a * b) / gcd(a, b));
198 }
199
200namespace {
201
202BigInt ct_inverse_mod_odd_modulus(const BigInt& n, const BigInt& mod)
203 {
204 if(n.is_negative() || mod.is_negative())
205 throw Invalid_Argument("ct_inverse_mod_odd_modulus: arguments must be non-negative");
206 if(mod < 3 || mod.is_even())
207 throw Invalid_Argument("Bad modulus to ct_inverse_mod_odd_modulus");
208
209 /*
210 This uses a modular inversion algorithm designed by Niels Möller
211 and implemented in Nettle. The same algorithm was later also
212 adapted to GMP in mpn_sec_invert.
213
214 It can be easily implemented in a way that does not depend on
215 secret branches or memory lookups, providing resistance against
216 some forms of side channel attack.
217
218 There is also a description of the algorithm in Appendix 5 of "Fast
219 Software Polynomial Multiplication on ARM Processors using the NEON Engine"
220 by Danilo Câmara, Conrado P. L. Gouvêa, Julio López, and Ricardo
221 Dahab in LNCS 8182
222 http://conradoplg.cryptoland.net/files/2010/12/mocrysen13.pdf
223
224 Thanks to Niels for creating the algorithm, explaining some things
225 about it, and the reference to the paper.
226 */
227
228 // todo allow this to be pre-calculated and passed in as arg
229 BigInt mp1o2 = (mod + 1) >> 1;
230
231 const size_t mod_words = mod.sig_words();
232
233 BigInt a = n;
234 BigInt b = mod;
235 BigInt u = 1, v = 0;
236
237 a.grow_to(mod_words);
238 u.grow_to(mod_words);
239 v.grow_to(mod_words);
240 mp1o2.grow_to(mod_words);
241
242 SecureVector<word>& a_w = a.get_reg();
243 SecureVector<word>& b_w = b.get_reg();
244 SecureVector<word>& u_w = u.get_reg();
245 SecureVector<word>& v_w = v.get_reg();
246
247 // Only n.bits() + mod.bits() iterations are required, but avoid leaking the size of n
248 size_t bits = 2 * mod.bits();
249
250 while(bits--)
251 {
252#if 1
253 const word odd = a.is_odd();
254 a -= odd * b;
255 const word underflow = a.is_negative();
256 b += a * underflow;
257 a.set_sign(BigInt::Positive);
258
259 a >>= 1;
260
261 if(underflow)
262 {
263 std::swap(u, v);
264 }
265
266 u -= odd * v;
267 u += u.is_negative() * mod;
268
269 const word odd_u = u.is_odd();
270
271 u >>= 1;
272 u += mp1o2 * odd_u;
273#else
274 const word odd_a = a_w[0] & 1;
275
276 //if(odd_a) a -= b
277 word underflow = bigint_cnd_sub(odd_a, a_w.begin(), b_w.begin(), mod_words);
278
279 //if(underflow) { b -= a; a = abs(a); swap(u, v); }
280 bigint_cnd_add(underflow, b_w.begin(), a_w.begin(), mod_words);
281 bigint_cnd_abs(underflow, a_w.begin(), mod_words);
282 bigint_cnd_swap(underflow, u_w.begin(), v_w.begin(), mod_words);
283
284 // a >>= 1
285 bigint_shr1(a_w.begin(), mod_words, 0, 1);
286
287 //if(odd_a) u -= v;
288 word borrow = bigint_cnd_sub(odd_a, u_w.begin(), v_w.begin(), mod_words);
289
290 // if(borrow) u += p
291 bigint_cnd_add(borrow, u_w.begin(), mod.data(), mod_words);
292
293 const word odd_u = u_w[0] & 1;
294
295 // u >>= 1
296 bigint_shr1(u_w.begin(), mod_words, 0, 1);
297
298 //if(odd_u) u += mp1o2;
299 bigint_cnd_add(odd_u, u_w.begin(), mp1o2.data(), mod_words);
300#endif
301 }
302
303 if(b != 1)
304 return 0;
305
306 return v;
307 }
308
309}
310
311/*
312* Find the Modular Inverse
313*/
314BigInt inverse_mod(const BigInt& n, const BigInt& mod)
315 {
316 if(mod.is_zero())
317 throw BigInt::DivideByZero();
318 if(mod.is_negative() || n.is_negative())
319 throw Invalid_Argument("inverse_mod: arguments must be non-negative");
320
321 if(n.is_zero() || (n.is_even() && mod.is_even()))
322 return 0;
323
324 if(mod.is_odd())
325 return ct_inverse_mod_odd_modulus(n % mod, mod);
326
327 BigInt x = mod, y = n, u = mod, v = n;
328 BigInt A = 1, B = 0, C = 0, D = 1;
329
330 while(u.is_nonzero())
331 {
332 size_t zero_bits = low_zero_bits(u);
333 u >>= zero_bits;
334 for(size_t i = 0; i != zero_bits; ++i)
335 {
336 if(A.is_odd() || B.is_odd())
337 { A += y; B -= x; }
338 A >>= 1; B >>= 1;
339 }
340
341 zero_bits = low_zero_bits(v);
342 v >>= zero_bits;
343 for(size_t i = 0; i != zero_bits; ++i)
344 {
345 if(C.is_odd() || D.is_odd())
346 { C += y; D -= x; }
347 C >>= 1; D >>= 1;
348 }
349
350 if(u >= v) { u -= v; A -= C; B -= D; }
351 else { v -= u; C -= A; D -= B; }
352 }
353
354 if(v != 1)
355 return 0;
356
357 while(D.is_negative()) D += mod;
358 while(D >= mod) D -= mod;
359
360 return D;
361 }
362
363/*
364* Modular Exponentiation
365*/
366BigInt power_mod(const BigInt& base, const BigInt& exp, const BigInt& mod)
367 {
368 Power_Mod pow_mod(mod);
369 pow_mod.set_base(base);
370 pow_mod.set_exponent(exp);
371 return pow_mod.execute();
372 }
373
374/*
375* Test for primaility using Miller-Rabin
376*/
377bool primality_test(const BigInt& n,
379 size_t level)
380 {
381 const size_t PREF_NONCE_BITS = 128;
382
383 if(n == 2)
384 return true;
385 if(n <= 1 || n.is_even())
386 return false;
387
388 // Fast path testing for small numbers (<= 65521)
389 if(n <= PRIMES[PRIME_TABLE_SIZE-1])
390 {
391 const word num = n.word_at(0);
392
393 for(size_t i = 0; PRIMES[i]; ++i)
394 {
395 if(num == PRIMES[i])
396 return true;
397 if(num < PRIMES[i])
398 return false;
399 }
400
401 return false;
402 }
403
404 if(level > 2)
405 level = 2;
406
407 const size_t NONCE_BITS = std::min(n.bits() - 2, PREF_NONCE_BITS);
408
409 MillerRabin_Test mr(n);
410
411 if(mr.is_witness(2))
412 return false;
413
414 const size_t tests = miller_rabin_test_iterations(n.bits(), level);
415
416 for(size_t i = 0; i != tests; ++i)
417 {
418 BigInt nonce;
419 while(nonce < 2 || nonce >= (n-1))
420 nonce.randomize(rng, NONCE_BITS);
421
422 if(mr.is_witness(nonce))
423 return false;
424 }
425
426 return true;
427 }
428
429}
bool is_odd() const
Definition bigint.h:164
size_t size() const
Definition bigint.h:284
word word_at(size_t n) const
Definition bigint.h:238
size_t bits() const
Definition bigint.cpp:254
bool is_even() const
Definition bigint.h:158
void randomize(RandomNumberGenerator &rng, size_t bitsize=0)
Definition big_rand.cpp:29
bool is_zero() const
Definition bigint.h:176
bool is_negative() const
Definition bigint.h:245
bool is_nonzero() const
Definition bigint.h:170
bool is_positive() const
Definition bigint.h:251
void set_sign(Sign sign)
Definition bigint.cpp:292
BigInt square(const BigInt &x) const
Definition reducer.h:39
void set_exponent(const BigInt &) const
Definition pow_mod.cpp:96
BigInt execute() const
Definition pow_mod.cpp:109
void set_base(const BigInt &) const
Definition pow_mod.cpp:83
BigInt lcm(const BigInt &a, const BigInt &b)
Definition numthry.cpp:195
BigInt inverse_mod(const BigInt &n, const BigInt &mod)
Definition numthry.cpp:314
void bigint_shr1(word x[], size_t x_size, size_t word_shift, size_t bit_shift)
Definition mp_shift.cpp:42
size_t ctz(T n)
Definition bit_ops.h:93
void bigint_cnd_swap(word cnd, word x[], word y[], size_t size)
Definition mp_asm.cpp:25
size_t low_zero_bits(const BigInt &n)
Definition numthry.cpp:142
word bigint_cnd_add(word cnd, word x[], const word y[], size_t size)
Definition mp_asm.cpp:42
const size_t PRIME_TABLE_SIZE
Definition numthry.h:220
BigInt power_mod(const BigInt &base, const BigInt &exp, const BigInt &mod)
Definition numthry.cpp:366
word bigint_cnd_sub(word cnd, word x[], const word y[], size_t size)
Definition mp_asm.cpp:64
std::invalid_argument Invalid_Argument
Definition exceptn.h:20
const u16bit BOTAN_DLL PRIMES[]
Definition primes.cpp:12
void bigint_cnd_abs(word cnd, word x[], size_t size)
Definition mp_asm.cpp:78
bool primality_test(const BigInt &n, RandomNumberGenerator &rng, size_t level)
Definition numthry.cpp:377
BigInt gcd(const BigInt &a, const BigInt &b)
Definition numthry.cpp:168
void swap(Botan::MemoryRegion< T > &x, Botan::MemoryRegion< T > &y)
Definition secmem.h:438