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