Coverage Report

Created: 2020-10-17 06:46

/src/botan/src/lib/math/numbertheory/ressol.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
* Shanks-Tonnelli (RESSOL)
3
* (C) 2007-2008 Falko Strenzke, FlexSecure GmbH
4
* (C) 2008 Jack Lloyd
5
*
6
* Botan is released under the Simplified BSD License (see license.txt)
7
*/
8
9
#include <botan/numthry.h>
10
#include <botan/reducer.h>
11
12
namespace Botan {
13
14
/*
15
* Shanks-Tonnelli algorithm
16
*/
17
BigInt ressol(const BigInt& a, const BigInt& p)
18
23.4k
   {
19
23.4k
   if(a == 0)
20
1
      return 0;
21
23.4k
   else if(a < 0)
22
0
      throw Invalid_Argument("ressol: value to solve for must be positive");
23
23.4k
   else if(a >= p)
24
2
      throw Invalid_Argument("ressol: value to solve for must be less than p");
25
23.4k
26
23.4k
   if(p == 2)
27
0
      return a;
28
23.4k
   else if(p <= 1)
29
0
      throw Invalid_Argument("ressol: prime must be > 1 a");
30
23.4k
   else if(p.is_even())
31
0
      throw Invalid_Argument("ressol: invalid prime");
32
23.4k
33
23.4k
   if(jacobi(a, p) != 1) // not a quadratic residue
34
5.53k
      return -BigInt(1);
35
17.9k
36
17.9k
   if(p % 4 == 3)
37
16.6k
      return power_mod(a, ((p+1) >> 2), p);
38
1.25k
39
1.25k
   size_t s = low_zero_bits(p - 1);
40
1.25k
   BigInt q = p >> s;
41
1.25k
42
1.25k
   q -= 1;
43
1.25k
   q >>= 1;
44
1.25k
45
1.25k
   Modular_Reducer mod_p(p);
46
1.25k
47
1.25k
   BigInt r = power_mod(a, q, p);
48
1.25k
   BigInt n = mod_p.multiply(a, mod_p.square(r));
49
1.25k
   r = mod_p.multiply(r, a);
50
1.25k
51
1.25k
   if(n == 1)
52
59
      return r;
53
1.19k
54
   // find random non quadratic residue z
55
1.19k
   BigInt z = 2;
56
11.2k
   while(jacobi(z, p) == 1) // while z quadratic residue
57
10.0k
      ++z;
58
1.19k
59
1.19k
   BigInt c = power_mod(z, (q << 1) + 1, p);
60
1.19k
61
55.1k
   while(n > 1)
62
53.9k
      {
63
53.9k
      q = n;
64
53.9k
65
53.9k
      size_t i = 0;
66
2.83M
      while(q != 1)
67
2.77M
         {
68
2.77M
         q = mod_p.square(q);
69
2.77M
         ++i;
70
2.77M
71
2.77M
         if(i >= s)
72
0
            {
73
0
            return -BigInt(1);
74
0
            }
75
2.77M
         }
76
53.9k
77
53.9k
      c = power_mod(c, BigInt::power_of_2(s-i-1), p);
78
53.9k
      r = mod_p.multiply(r, c);
79
53.9k
      c = mod_p.square(c);
80
53.9k
      n = mod_p.multiply(n, c);
81
53.9k
      s = i;
82
53.9k
      }
83
1.19k
84
1.19k
   return r;
85
1.19k
   }
86
87
}