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

randombit / botan / 5079590438

25 May 2023 12:28PM UTC coverage: 92.228% (+0.5%) from 91.723%
5079590438

Pull #3502

github

Pull Request #3502: Apply clang-format to the codebase

75589 of 81959 relevant lines covered (92.23%)

12139530.51 hits per line

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

92.81
/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&) { result.test_success("BigInt::to_u32bit rejected out of range"); }
30✔
67
               }
68

69
               a--;
48✔
70
            }
71
         }
12✔
72

73
         return result;
1✔
74
      }
×
75

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

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

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

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

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

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

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

110
         return result;
1✔
111
      }
2✔
112

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

116
         const BigInt n1(0xffff);
1✔
117
         const BigInt n2(1023);
1✔
118

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

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

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

133
         return result;
1✔
134
      }
6✔
135

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

139
         const size_t rbits = 1024;
1✔
140

141
         const Botan::BigInt r(Test::rng(), rbits);
1✔
142

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

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

150
               const uint32_t cmp = t.to_u32bit();
34,816✔
151

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

156
         return result;
1✔
157
      }
1✔
158

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

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

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

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

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

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

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

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

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

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

211
         return result;
1✔
212
      }
1✔
213
};
214

215
BOTAN_REGISTER_TEST("math", "bigint_unit", BigInt_Unit_Tests);
216

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

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

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

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

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

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

247
         return result;
19✔
248
      }
38✔
249
};
250

251
BOTAN_REGISTER_TEST("math", "bn_cmp", BigInt_Cmp_Test);
252

253
class BigInt_Add_Test final : public Text_Based_Test {
×
254
   public:
255
      BigInt_Add_Test() : Text_Based_Test("bn/add.vec", "In1,In2,Output") {}
2✔
256

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

260
         using Botan::BigInt;
78✔
261

262
         const BigInt a = vars.get_req_bn("In1");
78✔
263
         const BigInt b = vars.get_req_bn("In2");
78✔
264
         const BigInt c = vars.get_req_bn("Output");
78✔
265

266
         result.test_eq("a + b", a + b, c);
156✔
267
         result.test_eq("b + a", b + a, c);
156✔
268

269
         BigInt e = a;
78✔
270
         e += b;
78✔
271
         result.test_eq("a += b", e, c);
78✔
272

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

277
         return result;
78✔
278
      }
312✔
279
};
280

281
BOTAN_REGISTER_TEST("math", "bn_add", BigInt_Add_Test);
282

283
class BigInt_Sub_Test final : public Text_Based_Test {
×
284
   public:
285
      BigInt_Sub_Test() : Text_Based_Test("bn/sub.vec", "In1,In2,Output") {}
2✔
286

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

290
         const BigInt a = vars.get_req_bn("In1");
77✔
291
         const BigInt b = vars.get_req_bn("In2");
77✔
292
         const BigInt c = vars.get_req_bn("Output");
77✔
293

294
         result.test_eq("a - b", a - b, c);
154✔
295

296
         BigInt e = a;
77✔
297
         e -= b;
77✔
298
         result.test_eq("a -= b", e, c);
77✔
299

300
         return result;
77✔
301
      }
308✔
302
};
303

304
BOTAN_REGISTER_TEST("math", "bn_sub", BigInt_Sub_Test);
305

306
class BigInt_Mul_Test final : public Text_Based_Test {
×
307
   public:
308
      BigInt_Mul_Test() : Text_Based_Test("bn/mul.vec", "In1,In2,Output") {}
2✔
309

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

313
         const BigInt a = vars.get_req_bn("In1");
104✔
314
         const BigInt b = vars.get_req_bn("In2");
104✔
315
         const BigInt c = vars.get_req_bn("Output");
104✔
316

317
         result.test_eq("a * b", a * b, c);
208✔
318
         result.test_eq("b * a", b * a, c);
208✔
319

320
         BigInt e = a;
104✔
321
         e *= b;
104✔
322
         result.test_eq("a *= b", e, c);
104✔
323

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

328
         return result;
104✔
329
      }
416✔
330
};
331

332
BOTAN_REGISTER_TEST("math", "bn_mul", BigInt_Mul_Test);
333

334
class BigInt_Sqr_Test final : public Text_Based_Test {
×
335
   public:
336
      BigInt_Sqr_Test() : Text_Based_Test("bn/sqr.vec", "Input,Output") {}
2✔
337

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

341
         const BigInt input = vars.get_req_bn("Input");
21✔
342
         const BigInt output = vars.get_req_bn("Output");
21✔
343

344
         result.test_eq("a * a", input * input, output);
42✔
345
         result.test_eq("sqr(a)", square(input), output);
42✔
346

347
         return result;
21✔
348
      }
42✔
349
};
350

351
BOTAN_REGISTER_TEST("math", "bn_sqr", BigInt_Sqr_Test);
352

353
class BigInt_Div_Test final : public Text_Based_Test {
×
354
   public:
355
      BigInt_Div_Test() : Text_Based_Test("bn/divide.vec", "In1,In2,Output") {}
2✔
356

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

360
         const BigInt a = vars.get_req_bn("In1");
783✔
361
         const BigInt b = vars.get_req_bn("In2");
783✔
362
         const BigInt c = vars.get_req_bn("Output");
783✔
363

364
         result.test_eq("a / b", a / b, c);
1,566✔
365

366
         BigInt e = a;
783✔
367
         e /= b;
783✔
368
         result.test_eq("a /= b", e, c);
783✔
369

370
         if(b.sig_words() == 1) {
783✔
371
            const Botan::word bw = b.word_at(0);
404✔
372
            result.test_eq("bw ok", Botan::BigInt::from_word(bw), b);
808✔
373

374
            Botan::BigInt ct_q;
404✔
375
            Botan::word ct_r;
404✔
376
            Botan::ct_divide_word(a, bw, ct_q, ct_r);
404✔
377
            result.test_eq("ct_divide_word q", ct_q, c);
404✔
378
            result.test_eq("ct_divide_word r", ct_q * b + ct_r, a);
2,020✔
379
         }
404✔
380

381
         Botan::BigInt ct_q, ct_r;
783✔
382
         Botan::ct_divide(a, b, ct_q, ct_r);
783✔
383
         result.test_eq("ct_divide q", ct_q, c);
783✔
384
         result.test_eq("ct_divide r", ct_q * b + ct_r, a);
2,349✔
385

386
         return result;
783✔
387
      }
4,696✔
388
};
389

390
BOTAN_REGISTER_TEST("math", "bn_div", BigInt_Div_Test);
391

392
class BigInt_Mod_Test final : public Text_Based_Test {
×
393
   public:
394
      BigInt_Mod_Test() : Text_Based_Test("bn/mod.vec", "In1,In2,Output") {}
2✔
395

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

399
         const BigInt a = vars.get_req_bn("In1");
76✔
400
         const BigInt b = vars.get_req_bn("In2");
76✔
401
         const BigInt expected = vars.get_req_bn("Output");
76✔
402

403
         result.test_eq("a % b", a % b, expected);
152✔
404

405
         BigInt e = a;
76✔
406
         e %= b;
76✔
407
         result.test_eq("a %= b", e, expected);
76✔
408

409
         const Botan::Modular_Reducer mod_b(b);
76✔
410
         result.test_eq("Barrett", mod_b.reduce(a), expected);
152✔
411

412
         // if b fits into a Botan::word test %= operator for words
413
         if(b.sig_words() == 1) {
76✔
414
            const Botan::word b_word = b.word_at(0);
30✔
415

416
            e = a;
30✔
417
            e %= b_word;
30✔
418
            result.test_eq("a %= b (as word)", e, expected);
30✔
419

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

422
            Botan::BigInt ct_q;
30✔
423
            Botan::word ct_r;
30✔
424
            Botan::ct_divide_word(a, b.word_at(0), ct_q, ct_r);
60✔
425
            result.test_eq("ct_divide_u8 r", ct_r, expected);
82✔
426
         }
30✔
427

428
         Botan::BigInt ct_q, ct_r;
76✔
429
         Botan::ct_divide(a, b, ct_q, ct_r);
76✔
430
         result.test_eq("ct_divide r", ct_r, expected);
76✔
431

432
         return result;
76✔
433
      }
453✔
434
};
435

436
BOTAN_REGISTER_TEST("math", "bn_mod", BigInt_Mod_Test);
437

438
class BigInt_GCD_Test final : public Text_Based_Test {
×
439
   public:
440
      BigInt_GCD_Test() : Text_Based_Test("bn/gcd.vec", "X,Y,GCD") {}
2✔
441

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

445
         const BigInt x = vars.get_req_bn("X");
181✔
446
         const BigInt y = vars.get_req_bn("Y");
181✔
447
         const BigInt expected = vars.get_req_bn("GCD");
181✔
448

449
         const BigInt g1 = Botan::gcd(x, y);
181✔
450
         result.test_eq("gcd", g1, expected);
181✔
451

452
         const BigInt g2 = Botan::gcd(y, x);
181✔
453
         result.test_eq("gcd", g2, expected);
181✔
454

455
         return result;
181✔
456
      }
905✔
457
};
458

459
BOTAN_REGISTER_TEST("math", "bn_gcd", BigInt_GCD_Test);
460

461
class BigInt_Jacobi_Test final : public Text_Based_Test {
×
462
   public:
463
      BigInt_Jacobi_Test() : Text_Based_Test("bn/jacobi.vec", "A,N,J") {}
2✔
464

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

468
         const BigInt a = vars.get_req_bn("A");
698✔
469
         const BigInt n = vars.get_req_bn("N");
698✔
470
         const std::string expected = vars.get_req_str("J");
698✔
471

472
         const int32_t j = Botan::jacobi(a, n);
698✔
473

474
         if(j == 0)
698✔
475
            result.test_eq("jacobi", expected, "0");
314✔
476
         else if(j == -1)
541✔
477
            result.test_eq("jacobi", expected, "-1");
614✔
478
         else
479
            result.test_eq("jacobi", expected, "1");
468✔
480

481
         return result;
698✔
482
      }
2,094✔
483
};
484

485
BOTAN_REGISTER_TEST("math", "bn_jacobi", BigInt_Jacobi_Test);
486

487
class BigInt_Lshift_Test final : public Text_Based_Test {
×
488
   public:
489
      BigInt_Lshift_Test() : Text_Based_Test("bn/lshift.vec", "Value,Shift,Output") {}
3✔
490

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

494
         const BigInt value = vars.get_req_bn("Value");
50✔
495
         const size_t shift = vars.get_req_bn("Shift").to_u32bit();
100✔
496
         const BigInt output = vars.get_req_bn("Output");
50✔
497

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

500
         BigInt e = value;
50✔
501
         e <<= shift;
50✔
502
         result.test_eq("a <<= s", e, output);
50✔
503

504
         return result;
50✔
505
      }
150✔
506
};
507

508
BOTAN_REGISTER_TEST("math", "bn_lshift", BigInt_Lshift_Test);
509

510
class BigInt_Rshift_Test final : public Text_Based_Test {
×
511
   public:
512
      BigInt_Rshift_Test() : Text_Based_Test("bn/rshift.vec", "Value,Shift,Output") {}
3✔
513

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

517
         const BigInt value = vars.get_req_bn("Value");
53✔
518
         const size_t shift = vars.get_req_bn("Shift").to_u32bit();
106✔
519
         const BigInt output = vars.get_req_bn("Output");
53✔
520

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

523
         BigInt e = value;
53✔
524
         e >>= shift;
53✔
525
         result.test_eq("a >>= s", e, output);
53✔
526

527
         return result;
53✔
528
      }
159✔
529
};
530

531
BOTAN_REGISTER_TEST("math", "bn_rshift", BigInt_Rshift_Test);
532

533
class BigInt_Powmod_Test final : public Text_Based_Test {
×
534
   public:
535
      BigInt_Powmod_Test() : Text_Based_Test("bn/powmod.vec", "Base,Exponent,Modulus,Output") {}
3✔
536

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

540
         const BigInt base = vars.get_req_bn("Base");
47✔
541
         const BigInt exponent = vars.get_req_bn("Exponent");
47✔
542
         const BigInt modulus = vars.get_req_bn("Modulus");
47✔
543
         const BigInt expected = vars.get_req_bn("Output");
47✔
544

545
         result.test_eq("power_mod", Botan::power_mod(base, exponent, modulus), expected);
94✔
546
         return result;
47✔
547
      }
188✔
548
};
549

550
BOTAN_REGISTER_TEST("math", "bn_powmod", BigInt_Powmod_Test);
551

552
class BigInt_IsPrime_Test final : public Text_Based_Test {
×
553
   public:
554
      BigInt_IsPrime_Test() : Text_Based_Test("bn/isprime.vec", "X") {}
2✔
555

556
      Test::Result run_one_test(const std::string& header, const VarMap& vars) override {
132✔
557
         if(header != "Prime" && header != "NonPrime") {
132✔
558
            throw Test_Error("Bad header for prime test " + header);
×
559
         }
560

561
         const BigInt value = vars.get_req_bn("X");
132✔
562
         const bool is_prime = (header == "Prime");
132✔
563

564
         Test::Result result("BigInt Test " + header);
132✔
565
         result.test_eq("is_prime", Botan::is_prime(value, Test::rng()), is_prime);
132✔
566

567
         return result;
132✔
568
      }
132✔
569
};
570

571
BOTAN_REGISTER_TEST("math", "bn_isprime", BigInt_IsPrime_Test);
572

573
class BigInt_IsSquare_Test final : public Text_Based_Test {
×
574
   public:
575
      BigInt_IsSquare_Test() : Text_Based_Test("bn/perfect_square.vec", "X,R") {}
2✔
576

577
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
7✔
578
         const BigInt value = vars.get_req_bn("X");
7✔
579
         const BigInt expected = vars.get_req_bn("R");
7✔
580
         const BigInt computed = Botan::is_perfect_square(value);
7✔
581

582
         Test::Result result("BigInt IsSquare");
7✔
583
         result.test_eq("is_perfect_square", computed, expected);
7✔
584
         return result;
7✔
585
      }
21✔
586
};
587

588
BOTAN_REGISTER_TEST("math", "bn_issquare", BigInt_IsSquare_Test);
589

590
class BigInt_Sqrt_Modulo_Prime_Test final : public Text_Based_Test {
×
591
   public:
592
      BigInt_Sqrt_Modulo_Prime_Test() : Text_Based_Test("bn/sqrt_modulo_prime.vec", "Input,Modulus,Output") {}
3✔
593

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

597
         const Botan::BigInt a = vars.get_req_bn("Input");
17✔
598
         const Botan::BigInt p = vars.get_req_bn("Modulus");
17✔
599
         const Botan::BigInt exp = vars.get_req_bn("Output");
17✔
600

601
         const Botan::BigInt a_sqrt = Botan::sqrt_modulo_prime(a, p);
17✔
602

603
         result.test_eq("sqrt_modulo_prime", a_sqrt, exp);
17✔
604

605
         if(a_sqrt > 1) {
17✔
606
            const Botan::BigInt a_sqrt2 = (a_sqrt * a_sqrt) % p;
8✔
607
            result.test_eq("square correct", a_sqrt2, a);
16✔
608
         }
8✔
609

610
         return result;
17✔
611
      }
68✔
612
};
613

614
BOTAN_REGISTER_TEST("math", "bn_sqrt_modulo_prime", BigInt_Sqrt_Modulo_Prime_Test);
615

616
class BigInt_InvMod_Test final : public Text_Based_Test {
×
617
   public:
618
      BigInt_InvMod_Test() : Text_Based_Test("bn/invmod.vec", "Input,Modulus,Output") {}
3✔
619

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

623
         const Botan::BigInt a = vars.get_req_bn("Input");
138✔
624
         const Botan::BigInt mod = vars.get_req_bn("Modulus");
138✔
625
         const Botan::BigInt expected = vars.get_req_bn("Output");
138✔
626

627
         const Botan::BigInt a_inv = Botan::inverse_mod(a, mod);
138✔
628

629
         result.test_eq("inverse_mod", a_inv, expected);
138✔
630

631
         if(a_inv > 1) {
138✔
632
            result.test_eq("inverse ok", (a * a_inv) % mod, 1);
415✔
633
         }
634
         /*
635
         else if((a % mod) > 0)
636
            {
637
            result.confirm("no inverse with gcd > 1", gcd(a, mod) > 1);
638
            }
639
         */
640

641
         return result;
138✔
642
      }
552✔
643
};
644

645
BOTAN_REGISTER_TEST("math", "bn_invmod", BigInt_InvMod_Test);
646

647
class BigInt_Rand_Test final : public Text_Based_Test {
×
648
   public:
649
      BigInt_Rand_Test() : Text_Based_Test("bn/random.vec", "Seed,Min,Max,Output") {}
3✔
650

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

654
         const std::vector<uint8_t> seed = vars.get_req_bin("Seed");
3✔
655
         const Botan::BigInt min = vars.get_req_bn("Min");
3✔
656
         const Botan::BigInt max = vars.get_req_bn("Max");
3✔
657
         const Botan::BigInt expected = vars.get_req_bn("Output");
3✔
658

659
         Fixed_Output_RNG rng(seed);
3✔
660
         Botan::BigInt generated = BigInt::random_integer(rng, min, max);
3✔
661

662
         result.test_eq("random_integer KAT", generated, expected);
3✔
663

664
         return result;
3✔
665
      }
15✔
666
};
667

668
BOTAN_REGISTER_TEST("math", "bn_rand", BigInt_Rand_Test);
669

670
class Lucas_Primality_Test final : public Test {
×
671
   public:
672
      std::vector<Test::Result> run() override {
1✔
673
         const uint32_t lucas_max = (Test::run_long_tests() ? 100000 : 6000);
1✔
674

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

683
         Test::Result result("Lucas primality test");
1✔
684

685
         for(uint32_t i = 3; i <= lucas_max; i += 2) {
50,000✔
686
            Botan::Modular_Reducer mod_i(i);
49,999✔
687
            const bool passes_lucas = Botan::is_lucas_probable_prime(i, mod_i);
49,999✔
688
            const bool is_prime = Botan::is_prime(i, Test::rng());
49,999✔
689

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

692
            if(is_lucas_pp)
49,999✔
693
               result.confirm("Lucas pseudoprime is in list", lucas_pp.count(i) == 1);
228✔
694
            else
695
               result.confirm("Lucas non-pseudoprime is not in list", !lucas_pp.contains(i));
199,768✔
696
         }
49,999✔
697

698
         return {result};
2✔
699
      }
1✔
700
};
701

702
BOTAN_REGISTER_TEST("math", "bn_lucas", Lucas_Primality_Test);
703

704
class DSA_ParamGen_Test final : public Text_Based_Test {
×
705
   public:
706
      DSA_ParamGen_Test() : Text_Based_Test("bn/dsa_gen.vec", "P,Q,Counter,Seed") {}
3✔
707

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

712
         const Botan::BigInt exp_P = vars.get_req_bn("P");
20✔
713
         const Botan::BigInt exp_Q = vars.get_req_bn("Q");
20✔
714

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

717
         if(header_parts.size() != 2) {
20✔
718
            throw Test_Error("Unexpected header '" + header + "' in DSA param gen test");
×
719
         }
720

721
         const size_t p_bits = Botan::to_u32bit(header_parts[1]);
20✔
722
         const size_t q_bits = Botan::to_u32bit(header_parts[0]);
20✔
723

724
         Test::Result result("DSA Parameter Generation");
20✔
725

726
         try {
20✔
727
            Botan::BigInt gen_P, gen_Q;
20✔
728
            if(Botan::generate_dsa_primes(Test::rng(), gen_P, gen_Q, p_bits, q_bits, seed, offset)) {
20✔
729
               result.test_eq("P", gen_P, exp_P);
20✔
730
               result.test_eq("Q", gen_Q, exp_Q);
40✔
731
            } else {
732
               result.test_failure("Seed did not generate a DSA parameter");
×
733
            }
734
         } catch(Botan::Lookup_Error&) {}
40✔
735

736
         return result;
40✔
737
      }
80✔
738
};
739

740
BOTAN_REGISTER_TEST("math", "dsa_param", DSA_ParamGen_Test);
741

742
#endif
743

744
}
745

746
}
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