• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 5134090420

31 May 2023 03:12PM UTC coverage: 91.721% (-0.3%) from 91.995%
5134090420

push

github

randombit
Merge GH #3565 Disable noisy/pointless pylint warnings

76048 of 82912 relevant lines covered (91.72%)

11755290.1 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.84
/src/tests/test_bigint.cpp
1
/*
2
* (C) 2009,2015,2016 Jack Lloyd
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6

7
#include "tests.h"
8

9
#if defined(BOTAN_HAS_NUMBERTHEORY)
10
   #include "test_rng.h"
11
   #include <botan/bigint.h>
12
   #include <botan/numthry.h>
13
   #include <botan/reducer.h>
14
   #include <botan/internal/divide.h>
15
   #include <botan/internal/parsing.h>
16
   #include <botan/internal/primality.h>
17
#endif
18

19
namespace Botan_Tests {
20

21
namespace {
22

23
#if defined(BOTAN_HAS_NUMBERTHEORY)
24

25
using Botan::BigInt;
26

27
class BigInt_Unit_Tests final : public Test {
×
28
   public:
29
      std::vector<Test::Result> run() override {
1✔
30
         std::vector<Test::Result> results;
1✔
31

32
         results.push_back(test_bigint_sizes());
2✔
33
         results.push_back(test_random_prime());
2✔
34
         results.push_back(test_encode());
2✔
35
         results.push_back(test_bigint_io());
2✔
36
         results.push_back(test_get_substring());
2✔
37

38
         return results;
1✔
39
      }
×
40

41
   private:
42
      static Test::Result test_bigint_sizes() {
1✔
43
         Test::Result result("BigInt size functions");
1✔
44

45
         for(size_t bit : {1, 8, 16, 31, 32, 64, 97, 128, 179, 192, 512, 521}) {
13✔
46
            BigInt a;
12✔
47

48
            a.set_bit(bit);
12✔
49

50
            // Test 2^n and 2^n-1
51
            for(size_t i = 0; i != 2; ++i) {
36✔
52
               const size_t exp_bits = bit + 1 - i;
24✔
53
               result.test_eq("BigInt::bits", a.bits(), exp_bits);
24✔
54
               result.test_eq(
24✔
55
                  "BigInt::bytes", a.bytes(), (exp_bits % 8 == 0) ? (exp_bits / 8) : (exp_bits + 8 - exp_bits % 8) / 8);
24✔
56

57
               if(bit == 1 && i == 1) {
24✔
58
                  result.test_is_eq("BigInt::to_u32bit zero", a.to_u32bit(), static_cast<uint32_t>(1));
2✔
59
               } else if(bit <= 31 || (bit == 32 && i == 1)) {
23✔
60
                  result.test_is_eq(
8✔
61
                     "BigInt::to_u32bit", a.to_u32bit(), static_cast<uint32_t>((uint64_t(1) << bit) - i));
16✔
62
               } else {
63
                  try {
15✔
64
                     a.to_u32bit();
15✔
65
                     result.test_failure("BigInt::to_u32bit roundtripped out of range value");
×
66
                  } catch(std::exception&) {
15✔
67
                     result.test_success("BigInt::to_u32bit rejected out of range");
15✔
68
                  }
15✔
69
               }
70

71
               a--;
48✔
72
            }
73
         }
12✔
74

75
         return result;
1✔
76
      }
×
77

78
      static Test::Result test_random_prime() {
1✔
79
         Test::Result result("BigInt prime generation");
1✔
80

81
         result.test_throws("Invalid bit size", "random_prime: Can't make a prime of 0 bits", []() {
3✔
82
            Botan::random_prime(Test::rng(), 0);
1✔
83
         });
×
84
         result.test_throws("Invalid bit size", "random_prime: Can't make a prime of 1 bits", []() {
3✔
85
            Botan::random_prime(Test::rng(), 1);
1✔
86
         });
×
87
         result.test_throws("Invalid arg", "random_prime Invalid value for equiv/modulo", []() {
3✔
88
            Botan::random_prime(Test::rng(), 2, 1, 0, 2);
1✔
89
         });
×
90

91
         BigInt p = Botan::random_prime(Test::rng(), 2);
1✔
92
         result.confirm("Only two 2-bit primes", p == 2 || p == 3);
2✔
93

94
         p = Botan::random_prime(Test::rng(), 3);
2✔
95
         result.confirm("Only two 3-bit primes", p == 5 || p == 7);
2✔
96

97
         p = Botan::random_prime(Test::rng(), 4);
2✔
98
         result.confirm("Only two 4-bit primes", p == 11 || p == 13);
4✔
99

100
         for(size_t bits = 5; bits <= 32; ++bits) {
29✔
101
            p = Botan::random_prime(Test::rng(), bits);
56✔
102
            result.test_eq("Expected bit size", p.bits(), bits);
28✔
103
            result.test_eq("P is prime", Botan::is_prime(p, Test::rng()), true);
56✔
104
         }
105

106
         const size_t safe_prime_bits = 65;
1✔
107
         const BigInt safe_prime = Botan::random_safe_prime(Test::rng(), safe_prime_bits);
1✔
108
         result.test_eq("Safe prime size", safe_prime.bits(), safe_prime_bits);
1✔
109
         result.confirm("P is prime", Botan::is_prime(safe_prime, Test::rng()));
2✔
110
         result.confirm("(P-1)/2 is prime", Botan::is_prime((safe_prime - 1) / 2, Test::rng()));
4✔
111

112
         return result;
1✔
113
      }
2✔
114

115
      static Test::Result test_encode() {
1✔
116
         Test::Result result("BigInt encoding functions");
1✔
117

118
         const BigInt n1(0xffff);
1✔
119
         const BigInt n2(1023);
1✔
120

121
         Botan::secure_vector<uint8_t> encoded_n1 = BigInt::encode_1363(n1, 256);
1✔
122
         Botan::secure_vector<uint8_t> encoded_n2 = BigInt::encode_1363(n2, 256);
1✔
123
         Botan::secure_vector<uint8_t> expected = encoded_n1;
1✔
124
         expected += encoded_n2;
1✔
125

126
         Botan::secure_vector<uint8_t> encoded_n1_n2 = BigInt::encode_fixed_length_int_pair(n1, n2, 256);
1✔
127
         result.test_eq("encode_fixed_length_int_pair", encoded_n1_n2, expected);
1✔
128

129
         for(size_t i = 0; i < 256 - n1.bytes(); ++i) {
255✔
130
            if(encoded_n1[i] != 0) {
254✔
131
               result.test_failure("encode_1363", "no zero byte");
×
132
            }
133
         }
134

135
         return result;
1✔
136
      }
6✔
137

138
      static Test::Result test_get_substring() {
1✔
139
         Test::Result result("BigInt get_substring");
1✔
140

141
         const size_t rbits = 1024;
1✔
142

143
         const Botan::BigInt r(Test::rng(), rbits);
1✔
144

145
         for(size_t wlen = 1; wlen <= 32; ++wlen) {
33✔
146
            for(size_t offset = 0; offset != rbits + 64; ++offset) {
34,848✔
147
               const uint32_t val = r.get_substring(offset, wlen);
34,816✔
148

149
               Botan::BigInt t = r >> offset;
34,816✔
150
               t.mask_bits(wlen);
34,816✔
151

152
               const uint32_t cmp = t.to_u32bit();
34,816✔
153

154
               result.test_eq("Same value", size_t(val), size_t(cmp));
69,632✔
155
            }
34,816✔
156
         }
157

158
         return result;
1✔
159
      }
1✔
160

161
      static Test::Result test_bigint_io() {
1✔
162
         Test::Result result("BigInt IO operators");
1✔
163

164
         const std::map<std::string, Botan::BigInt> str_to_val = {{"-13", -Botan::BigInt(13)},
2✔
165
                                                                  {"0", Botan::BigInt(0)},
2✔
166
                                                                  {"0x13", Botan::BigInt(0x13)},
2✔
167
                                                                  {"1", Botan::BigInt(1)},
2✔
168
                                                                  {"4294967297", Botan::BigInt(2147483648) * 2 + 1}};
13✔
169

170
         for(const auto& vec : str_to_val) {
6✔
171
            Botan::BigInt n;
5✔
172
            std::istringstream iss;
5✔
173

174
            iss.str(vec.first);
5✔
175
            iss >> n;
5✔
176
            result.test_eq("input '" + vec.first + "'", n, vec.second);
10✔
177
         }
10✔
178

179
         auto check_bigint_formatting = [&](const Botan::BigInt& n,
6✔
180
                                            const std::string& dec,
181
                                            const std::string& hex,
182
                                            const std::string& neg_dec,
183
                                            const std::string& neg_hex) {
184
            std::ostringstream oss;
5✔
185
            oss << n;
5✔
186
            result.test_eq("output decimal", oss.str(), dec);
10✔
187

188
            oss.str("");
10✔
189
            oss << (-n);
5✔
190
            result.test_eq("output negative decimal", oss.str(), neg_dec);
10✔
191

192
            oss.str("");
10✔
193
            oss << std::hex << n;
5✔
194
            result.test_eq("output hex", oss.str(), hex);
10✔
195

196
            oss.str("");
10✔
197
            oss << std::hex << (-n);
5✔
198
            result.test_eq("output negative hex", oss.str(), neg_hex);
10✔
199
         };
5✔
200

201
         check_bigint_formatting(Botan::BigInt(33), "33", "0x21", "-33", "-0x21");
2✔
202
         check_bigint_formatting(Botan::BigInt::from_s32(-33), "-33", "-0x21", "33", "0x21");
2✔
203
         check_bigint_formatting(Botan::BigInt(255), "255", "0xFF", "-255", "-0xFF");
2✔
204
         check_bigint_formatting(Botan::BigInt(0), "0", "0x00", "0", "0x00");
2✔
205
         check_bigint_formatting(Botan::BigInt(5), "5", "0x05", "-5", "-0x05");
2✔
206

207
         result.test_throws("octal output not supported", [&]() {
2✔
208
            Botan::BigInt n(5);
1✔
209
            std::ostringstream oss;
1✔
210
            oss << std::oct << n;
1✔
211
         });
1✔
212

213
         return result;
1✔
214
      }
1✔
215
};
216

217
BOTAN_REGISTER_TEST("math", "bigint_unit", BigInt_Unit_Tests);
218

219
class BigInt_Cmp_Test final : public Text_Based_Test {
×
220
   public:
221
      BigInt_Cmp_Test() : Text_Based_Test("bn/cmp.vec", "X,Y,R") {}
2✔
222

223
      Test::Result run_one_test(const std::string& op, const VarMap& vars) override {
19✔
224
         Test::Result result("BigInt Comparison " + op);
19✔
225

226
         const BigInt x = vars.get_req_bn("X");
19✔
227
         const BigInt y = vars.get_req_bn("Y");
19✔
228
         const bool expected = vars.get_req_bool("R");
19✔
229

230
         if(op == "EQ") {
19✔
231
            result.confirm("Values equal", x == y, expected);
12✔
232
         } else if(op == "LT") {
13✔
233
            result.confirm("Values LT", x < y, expected);
12✔
234

235
            if(expected) {
6✔
236
               result.confirm("If LT then reverse is GT", y >= x);
6✔
237
            } else {
238
               result.confirm("If not LT then GTE", x >= y);
12✔
239
            }
240
         } else if(op == "LTE") {
7✔
241
            result.confirm("Values LTE", x <= y, expected);
14✔
242

243
            if(expected) {
7✔
244
               result.confirm("If LTE then either LT or EQ", x < y || x == y);
14✔
245
            } else {
246
               result.confirm("If not LTE then GT", x > y);
9✔
247
            }
248
         } else {
249
            throw Test_Error("Unknown BigInt comparison type " + op);
×
250
         }
251

252
         return result;
19✔
253
      }
38✔
254
};
255

256
BOTAN_REGISTER_TEST("math", "bn_cmp", BigInt_Cmp_Test);
257

258
class BigInt_Add_Test final : public Text_Based_Test {
×
259
   public:
260
      BigInt_Add_Test() : Text_Based_Test("bn/add.vec", "In1,In2,Output") {}
2✔
261

262
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
78✔
263
         Test::Result result("BigInt Addition");
78✔
264

265
         using Botan::BigInt;
78✔
266

267
         const BigInt a = vars.get_req_bn("In1");
78✔
268
         const BigInt b = vars.get_req_bn("In2");
78✔
269
         const BigInt c = vars.get_req_bn("Output");
78✔
270

271
         result.test_eq("a + b", a + b, c);
156✔
272
         result.test_eq("b + a", b + a, c);
156✔
273

274
         BigInt e = a;
78✔
275
         e += b;
78✔
276
         result.test_eq("a += b", e, c);
78✔
277

278
         e = b;
78✔
279
         e += a;
78✔
280
         result.test_eq("b += a", e, c);
78✔
281

282
         return result;
78✔
283
      }
312✔
284
};
285

286
BOTAN_REGISTER_TEST("math", "bn_add", BigInt_Add_Test);
287

288
class BigInt_Sub_Test final : public Text_Based_Test {
×
289
   public:
290
      BigInt_Sub_Test() : Text_Based_Test("bn/sub.vec", "In1,In2,Output") {}
2✔
291

292
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
77✔
293
         Test::Result result("BigInt Subtraction");
77✔
294

295
         const BigInt a = vars.get_req_bn("In1");
77✔
296
         const BigInt b = vars.get_req_bn("In2");
77✔
297
         const BigInt c = vars.get_req_bn("Output");
77✔
298

299
         result.test_eq("a - b", a - b, c);
154✔
300

301
         BigInt e = a;
77✔
302
         e -= b;
77✔
303
         result.test_eq("a -= b", e, c);
77✔
304

305
         return result;
77✔
306
      }
308✔
307
};
308

309
BOTAN_REGISTER_TEST("math", "bn_sub", BigInt_Sub_Test);
310

311
class BigInt_Mul_Test final : public Text_Based_Test {
×
312
   public:
313
      BigInt_Mul_Test() : Text_Based_Test("bn/mul.vec", "In1,In2,Output") {}
2✔
314

315
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
104✔
316
         Test::Result result("BigInt Multiply");
104✔
317

318
         const BigInt a = vars.get_req_bn("In1");
104✔
319
         const BigInt b = vars.get_req_bn("In2");
104✔
320
         const BigInt c = vars.get_req_bn("Output");
104✔
321

322
         result.test_eq("a * b", a * b, c);
208✔
323
         result.test_eq("b * a", b * a, c);
208✔
324

325
         BigInt e = a;
104✔
326
         e *= b;
104✔
327
         result.test_eq("a *= b", e, c);
104✔
328

329
         e = b;
104✔
330
         e *= a;
104✔
331
         result.test_eq("b *= a", e, c);
104✔
332

333
         return result;
104✔
334
      }
416✔
335
};
336

337
BOTAN_REGISTER_TEST("math", "bn_mul", BigInt_Mul_Test);
338

339
class BigInt_Sqr_Test final : public Text_Based_Test {
×
340
   public:
341
      BigInt_Sqr_Test() : Text_Based_Test("bn/sqr.vec", "Input,Output") {}
2✔
342

343
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
21✔
344
         Test::Result result("BigInt Square");
21✔
345

346
         const BigInt input = vars.get_req_bn("Input");
21✔
347
         const BigInt output = vars.get_req_bn("Output");
21✔
348

349
         result.test_eq("a * a", input * input, output);
42✔
350
         result.test_eq("sqr(a)", square(input), output);
42✔
351

352
         return result;
21✔
353
      }
42✔
354
};
355

356
BOTAN_REGISTER_TEST("math", "bn_sqr", BigInt_Sqr_Test);
357

358
class BigInt_Div_Test final : public Text_Based_Test {
×
359
   public:
360
      BigInt_Div_Test() : Text_Based_Test("bn/divide.vec", "In1,In2,Output") {}
2✔
361

362
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
783✔
363
         Test::Result result("BigInt Divide");
783✔
364

365
         const BigInt a = vars.get_req_bn("In1");
783✔
366
         const BigInt b = vars.get_req_bn("In2");
783✔
367
         const BigInt c = vars.get_req_bn("Output");
783✔
368

369
         result.test_eq("a / b", a / b, c);
1,566✔
370

371
         BigInt e = a;
783✔
372
         e /= b;
783✔
373
         result.test_eq("a /= b", e, c);
783✔
374

375
         if(b.sig_words() == 1) {
783✔
376
            const Botan::word bw = b.word_at(0);
404✔
377
            result.test_eq("bw ok", Botan::BigInt::from_word(bw), b);
808✔
378

379
            Botan::BigInt ct_q;
404✔
380
            Botan::word ct_r;
404✔
381
            Botan::ct_divide_word(a, bw, ct_q, ct_r);
404✔
382
            result.test_eq("ct_divide_word q", ct_q, c);
404✔
383
            result.test_eq("ct_divide_word r", ct_q * b + ct_r, a);
2,020✔
384
         }
404✔
385

386
         Botan::BigInt ct_q, ct_r;
783✔
387
         Botan::ct_divide(a, b, ct_q, ct_r);
783✔
388
         result.test_eq("ct_divide q", ct_q, c);
783✔
389
         result.test_eq("ct_divide r", ct_q * b + ct_r, a);
2,349✔
390

391
         return result;
783✔
392
      }
4,696✔
393
};
394

395
BOTAN_REGISTER_TEST("math", "bn_div", BigInt_Div_Test);
396

397
class BigInt_Mod_Test final : public Text_Based_Test {
×
398
   public:
399
      BigInt_Mod_Test() : Text_Based_Test("bn/mod.vec", "In1,In2,Output") {}
2✔
400

401
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
76✔
402
         Test::Result result("BigInt Mod");
76✔
403

404
         const BigInt a = vars.get_req_bn("In1");
76✔
405
         const BigInt b = vars.get_req_bn("In2");
76✔
406
         const BigInt expected = vars.get_req_bn("Output");
76✔
407

408
         result.test_eq("a % b", a % b, expected);
152✔
409

410
         BigInt e = a;
76✔
411
         e %= b;
76✔
412
         result.test_eq("a %= b", e, expected);
76✔
413

414
         const Botan::Modular_Reducer mod_b(b);
76✔
415
         result.test_eq("Barrett", mod_b.reduce(a), expected);
152✔
416

417
         // if b fits into a Botan::word test %= operator for words
418
         if(b.sig_words() == 1) {
76✔
419
            const Botan::word b_word = b.word_at(0);
30✔
420

421
            e = a;
30✔
422
            e %= b_word;
30✔
423
            result.test_eq("a %= b (as word)", e, expected);
30✔
424

425
            result.test_eq("a % b (as word)", a % b_word, expected);
60✔
426

427
            Botan::BigInt ct_q;
30✔
428
            Botan::word ct_r;
30✔
429
            Botan::ct_divide_word(a, b.word_at(0), ct_q, ct_r);
60✔
430
            result.test_eq("ct_divide_u8 r", ct_r, expected);
82✔
431
         }
30✔
432

433
         Botan::BigInt ct_q, ct_r;
76✔
434
         Botan::ct_divide(a, b, ct_q, ct_r);
76✔
435
         result.test_eq("ct_divide r", ct_r, expected);
76✔
436

437
         return result;
76✔
438
      }
453✔
439
};
440

441
BOTAN_REGISTER_TEST("math", "bn_mod", BigInt_Mod_Test);
442

443
class BigInt_GCD_Test final : public Text_Based_Test {
×
444
   public:
445
      BigInt_GCD_Test() : Text_Based_Test("bn/gcd.vec", "X,Y,GCD") {}
2✔
446

447
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
181✔
448
         Test::Result result("BigInt GCD");
181✔
449

450
         const BigInt x = vars.get_req_bn("X");
181✔
451
         const BigInt y = vars.get_req_bn("Y");
181✔
452
         const BigInt expected = vars.get_req_bn("GCD");
181✔
453

454
         const BigInt g1 = Botan::gcd(x, y);
181✔
455
         result.test_eq("gcd", g1, expected);
181✔
456

457
         const BigInt g2 = Botan::gcd(y, x);
181✔
458
         result.test_eq("gcd", g2, expected);
181✔
459

460
         return result;
181✔
461
      }
905✔
462
};
463

464
BOTAN_REGISTER_TEST("math", "bn_gcd", BigInt_GCD_Test);
465

466
class BigInt_Jacobi_Test final : public Text_Based_Test {
×
467
   public:
468
      BigInt_Jacobi_Test() : Text_Based_Test("bn/jacobi.vec", "A,N,J") {}
2✔
469

470
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
698✔
471
         Test::Result result("BigInt Jacobi");
698✔
472

473
         const BigInt a = vars.get_req_bn("A");
698✔
474
         const BigInt n = vars.get_req_bn("N");
698✔
475
         const std::string expected = vars.get_req_str("J");
698✔
476

477
         const int32_t j = Botan::jacobi(a, n);
698✔
478

479
         if(j == 0) {
698✔
480
            result.test_eq("jacobi", expected, "0");
314✔
481
         } else if(j == -1) {
541✔
482
            result.test_eq("jacobi", expected, "-1");
614✔
483
         } else {
484
            result.test_eq("jacobi", expected, "1");
468✔
485
         }
486

487
         return result;
698✔
488
      }
2,094✔
489
};
490

491
BOTAN_REGISTER_TEST("math", "bn_jacobi", BigInt_Jacobi_Test);
492

493
class BigInt_Lshift_Test final : public Text_Based_Test {
×
494
   public:
495
      BigInt_Lshift_Test() : Text_Based_Test("bn/lshift.vec", "Value,Shift,Output") {}
3✔
496

497
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
50✔
498
         Test::Result result("BigInt Lshift");
50✔
499

500
         const BigInt value = vars.get_req_bn("Value");
50✔
501
         const size_t shift = vars.get_req_bn("Shift").to_u32bit();
100✔
502
         const BigInt output = vars.get_req_bn("Output");
50✔
503

504
         result.test_eq("a << s", value << shift, output);
100✔
505

506
         BigInt e = value;
50✔
507
         e <<= shift;
50✔
508
         result.test_eq("a <<= s", e, output);
50✔
509

510
         return result;
50✔
511
      }
150✔
512
};
513

514
BOTAN_REGISTER_TEST("math", "bn_lshift", BigInt_Lshift_Test);
515

516
class BigInt_Rshift_Test final : public Text_Based_Test {
×
517
   public:
518
      BigInt_Rshift_Test() : Text_Based_Test("bn/rshift.vec", "Value,Shift,Output") {}
3✔
519

520
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
53✔
521
         Test::Result result("BigInt Rshift");
53✔
522

523
         const BigInt value = vars.get_req_bn("Value");
53✔
524
         const size_t shift = vars.get_req_bn("Shift").to_u32bit();
106✔
525
         const BigInt output = vars.get_req_bn("Output");
53✔
526

527
         result.test_eq("a >> s", value >> shift, output);
106✔
528

529
         BigInt e = value;
53✔
530
         e >>= shift;
53✔
531
         result.test_eq("a >>= s", e, output);
53✔
532

533
         return result;
53✔
534
      }
159✔
535
};
536

537
BOTAN_REGISTER_TEST("math", "bn_rshift", BigInt_Rshift_Test);
538

539
class BigInt_Powmod_Test final : public Text_Based_Test {
×
540
   public:
541
      BigInt_Powmod_Test() : Text_Based_Test("bn/powmod.vec", "Base,Exponent,Modulus,Output") {}
3✔
542

543
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
47✔
544
         Test::Result result("BigInt Powmod");
47✔
545

546
         const BigInt base = vars.get_req_bn("Base");
47✔
547
         const BigInt exponent = vars.get_req_bn("Exponent");
47✔
548
         const BigInt modulus = vars.get_req_bn("Modulus");
47✔
549
         const BigInt expected = vars.get_req_bn("Output");
47✔
550

551
         result.test_eq("power_mod", Botan::power_mod(base, exponent, modulus), expected);
94✔
552
         return result;
47✔
553
      }
188✔
554
};
555

556
BOTAN_REGISTER_TEST("math", "bn_powmod", BigInt_Powmod_Test);
557

558
class BigInt_IsPrime_Test final : public Text_Based_Test {
×
559
   public:
560
      BigInt_IsPrime_Test() : Text_Based_Test("bn/isprime.vec", "X") {}
2✔
561

562
      Test::Result run_one_test(const std::string& header, const VarMap& vars) override {
132✔
563
         if(header != "Prime" && header != "NonPrime") {
132✔
564
            throw Test_Error("Bad header for prime test " + header);
×
565
         }
566

567
         const BigInt value = vars.get_req_bn("X");
132✔
568
         const bool is_prime = (header == "Prime");
132✔
569

570
         Test::Result result("BigInt Test " + header);
132✔
571
         result.test_eq("is_prime", Botan::is_prime(value, Test::rng()), is_prime);
132✔
572

573
         return result;
132✔
574
      }
132✔
575
};
576

577
BOTAN_REGISTER_TEST("math", "bn_isprime", BigInt_IsPrime_Test);
578

579
class BigInt_IsSquare_Test final : public Text_Based_Test {
×
580
   public:
581
      BigInt_IsSquare_Test() : Text_Based_Test("bn/perfect_square.vec", "X,R") {}
2✔
582

583
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
7✔
584
         const BigInt value = vars.get_req_bn("X");
7✔
585
         const BigInt expected = vars.get_req_bn("R");
7✔
586
         const BigInt computed = Botan::is_perfect_square(value);
7✔
587

588
         Test::Result result("BigInt IsSquare");
7✔
589
         result.test_eq("is_perfect_square", computed, expected);
7✔
590
         return result;
7✔
591
      }
21✔
592
};
593

594
BOTAN_REGISTER_TEST("math", "bn_issquare", BigInt_IsSquare_Test);
595

596
class BigInt_Sqrt_Modulo_Prime_Test final : public Text_Based_Test {
×
597
   public:
598
      BigInt_Sqrt_Modulo_Prime_Test() : Text_Based_Test("bn/sqrt_modulo_prime.vec", "Input,Modulus,Output") {}
3✔
599

600
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
17✔
601
         Test::Result result("BigInt Sqrt Modulo Prime");
17✔
602

603
         const Botan::BigInt a = vars.get_req_bn("Input");
17✔
604
         const Botan::BigInt p = vars.get_req_bn("Modulus");
17✔
605
         const Botan::BigInt exp = vars.get_req_bn("Output");
17✔
606

607
         const Botan::BigInt a_sqrt = Botan::sqrt_modulo_prime(a, p);
17✔
608

609
         result.test_eq("sqrt_modulo_prime", a_sqrt, exp);
17✔
610

611
         if(a_sqrt > 1) {
17✔
612
            const Botan::BigInt a_sqrt2 = (a_sqrt * a_sqrt) % p;
8✔
613
            result.test_eq("square correct", a_sqrt2, a);
16✔
614
         }
8✔
615

616
         return result;
17✔
617
      }
68✔
618
};
619

620
BOTAN_REGISTER_TEST("math", "bn_sqrt_modulo_prime", BigInt_Sqrt_Modulo_Prime_Test);
621

622
class BigInt_InvMod_Test final : public Text_Based_Test {
×
623
   public:
624
      BigInt_InvMod_Test() : Text_Based_Test("bn/invmod.vec", "Input,Modulus,Output") {}
3✔
625

626
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
138✔
627
         Test::Result result("BigInt InvMod");
138✔
628

629
         const Botan::BigInt a = vars.get_req_bn("Input");
138✔
630
         const Botan::BigInt mod = vars.get_req_bn("Modulus");
138✔
631
         const Botan::BigInt expected = vars.get_req_bn("Output");
138✔
632

633
         const Botan::BigInt a_inv = Botan::inverse_mod(a, mod);
138✔
634

635
         result.test_eq("inverse_mod", a_inv, expected);
138✔
636

637
         if(a_inv > 1) {
138✔
638
            result.test_eq("inverse ok", (a * a_inv) % mod, 1);
415✔
639
         }
640
         /*
641
         else if((a % mod) > 0)
642
            {
643
            result.confirm("no inverse with gcd > 1", gcd(a, mod) > 1);
644
            }
645
         */
646

647
         return result;
138✔
648
      }
552✔
649
};
650

651
BOTAN_REGISTER_TEST("math", "bn_invmod", BigInt_InvMod_Test);
652

653
class BigInt_Rand_Test final : public Text_Based_Test {
×
654
   public:
655
      BigInt_Rand_Test() : Text_Based_Test("bn/random.vec", "Seed,Min,Max,Output") {}
3✔
656

657
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
3✔
658
         Test::Result result("BigInt Random");
3✔
659

660
         const std::vector<uint8_t> seed = vars.get_req_bin("Seed");
3✔
661
         const Botan::BigInt min = vars.get_req_bn("Min");
3✔
662
         const Botan::BigInt max = vars.get_req_bn("Max");
3✔
663
         const Botan::BigInt expected = vars.get_req_bn("Output");
3✔
664

665
         Fixed_Output_RNG rng(seed);
3✔
666
         Botan::BigInt generated = BigInt::random_integer(rng, min, max);
3✔
667

668
         result.test_eq("random_integer KAT", generated, expected);
3✔
669

670
         return result;
3✔
671
      }
15✔
672
};
673

674
BOTAN_REGISTER_TEST("math", "bn_rand", BigInt_Rand_Test);
675

676
class Lucas_Primality_Test final : public Test {
×
677
   public:
678
      std::vector<Test::Result> run() override {
1✔
679
         const uint32_t lucas_max = (Test::run_long_tests() ? 100000 : 6000);
1✔
680

681
         // OEIS A217120
682
         std::set<uint32_t> lucas_pp{
1✔
683
            323,   377,   1159,  1829,  3827,  5459,  5777,  9071,  9179,  10877, 11419, 11663, 13919, 14839, 16109,
684
            16211, 18407, 18971, 19043, 22499, 23407, 24569, 25199, 25877, 26069, 27323, 32759, 34943, 35207, 39059,
685
            39203, 39689, 40309, 44099, 46979, 47879, 50183, 51983, 53663, 56279, 58519, 60377, 63881, 69509, 72389,
686
            73919, 75077, 77219, 79547, 79799, 82983, 84419, 86063, 90287, 94667, 97019, 97439,
687
         };
1✔
688

689
         Test::Result result("Lucas primality test");
1✔
690

691
         for(uint32_t i = 3; i <= lucas_max; i += 2) {
50,000✔
692
            Botan::Modular_Reducer mod_i(i);
49,999✔
693
            const bool passes_lucas = Botan::is_lucas_probable_prime(i, mod_i);
49,999✔
694
            const bool is_prime = Botan::is_prime(i, Test::rng());
49,999✔
695

696
            const bool is_lucas_pp = (is_prime == false && passes_lucas == true);
49,999✔
697

698
            if(is_lucas_pp) {
49,999✔
699
               result.confirm("Lucas pseudoprime is in list", lucas_pp.count(i) == 1);
228✔
700
            } else {
701
               result.confirm("Lucas non-pseudoprime is not in list", !lucas_pp.contains(i));
199,768✔
702
            }
703
         }
49,999✔
704

705
         return {result};
2✔
706
      }
1✔
707
};
708

709
BOTAN_REGISTER_TEST("math", "bn_lucas", Lucas_Primality_Test);
710

711
class DSA_ParamGen_Test final : public Text_Based_Test {
×
712
   public:
713
      DSA_ParamGen_Test() : Text_Based_Test("bn/dsa_gen.vec", "P,Q,Counter,Seed") {}
3✔
714

715
      Test::Result run_one_test(const std::string& header, const VarMap& vars) override {
20✔
716
         const std::vector<uint8_t> seed = vars.get_req_bin("Seed");
20✔
717
         const size_t offset = vars.get_req_sz("Counter");
20✔
718

719
         const Botan::BigInt exp_P = vars.get_req_bn("P");
20✔
720
         const Botan::BigInt exp_Q = vars.get_req_bn("Q");
20✔
721

722
         const std::vector<std::string> header_parts = Botan::split_on(header, ',');
20✔
723

724
         if(header_parts.size() != 2) {
20✔
725
            throw Test_Error("Unexpected header '" + header + "' in DSA param gen test");
×
726
         }
727

728
         const size_t p_bits = Botan::to_u32bit(header_parts[1]);
20✔
729
         const size_t q_bits = Botan::to_u32bit(header_parts[0]);
20✔
730

731
         Test::Result result("DSA Parameter Generation");
20✔
732

733
         try {
20✔
734
            Botan::BigInt gen_P, gen_Q;
20✔
735
            if(Botan::generate_dsa_primes(Test::rng(), gen_P, gen_Q, p_bits, q_bits, seed, offset)) {
20✔
736
               result.test_eq("P", gen_P, exp_P);
20✔
737
               result.test_eq("Q", gen_Q, exp_Q);
40✔
738
            } else {
739
               result.test_failure("Seed did not generate a DSA parameter");
×
740
            }
741
         } catch(Botan::Lookup_Error&) {}
40✔
742

743
         return result;
40✔
744
      }
80✔
745
};
746

747
BOTAN_REGISTER_TEST("math", "dsa_param", DSA_ParamGen_Test);
748

749
#endif
750

751
}  // namespace
752

753
}  // namespace Botan_Tests
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc