openGPMP
Open Source Mathematics Package
logarithms.cpp
Go to the documentation of this file.
1 /*************************************************************************
2  *
3  * Project
4  * _____ _____ __ __ _____
5  * / ____| __ \| \/ | __ \
6  * ___ _ __ ___ _ __ | | __| |__) | \ / | |__) |
7  * / _ \| '_ \ / _ \ '_ \| | |_ | ___/| |\/| | ___/
8  *| (_) | |_) | __/ | | | |__| | | | | | | |
9  * \___/| .__/ \___|_| |_|\_____|_| |_| |_|_|
10  * | |
11  * |_|
12  *
13  * Copyright (C) Akiel Aries, <akiel@akiel.org>, et al.
14  *
15  * This software is licensed as described in the file LICENSE, which
16  * you should have received as part of this distribution. The terms
17  * among other details are referenced in the official documentation
18  * seen here : https://akielaries.github.io/openGPMP/ along with
19  * important files seen in this project.
20  *
21  * You may opt to use, copy, modify, merge, publish, distribute
22  * and/or sell copies of the Software, and permit persons to whom
23  * the Software is furnished to do so, under the terms of the
24  * LICENSE file. As this is an Open Source effort, all implementations
25  * must be of the same methodology.
26  *
27  *
28  *
29  * This software is distributed on an AS IS basis, WITHOUT
30  * WARRANTY OF ANY KIND, either express or implied.
31  *
32  ************************************************************************/
33 
34 /*
35  * Some core concepts seen in Number Theory specifically
36  * Discrete Logarithms
37  */
38 #include <algorithm>
39 #include <cmath>
40 #include <cstdlib>
41 #include <cstring>
42 #include <iostream>
43 #include <numeric>
44 #include <openGPMP/arithmetic.hpp>
47 #include <string>
48 #include <unordered_map>
49 
50 // primes object for this Logarithms file
52 
53 // OSX uses srand() opposed to rand()
54 #ifdef __APPLE__
55 #define USE_SRAND
56 #endif
57 
58 uint64_t gpmp::Logarithms::pollard_rho_log(uint64_t g, uint64_t y, uint64_t p) {
59  uint64_t x = rand() % (p - 1) + 1;
60 
61 #ifdef USE_SRAND
62  srand(time(NULL));
63  x = rand() % (p - 1) + 1;
64 #endif
65 
66  uint64_t y1 = y;
67  uint64_t y2 = y;
68  uint64_t d = 1;
69  std::unordered_map<uint64_t, uint64_t> values;
70 
71  // Compute the iterated values of the sequence x_n = g^x_n-1 mod p
72  // until a collision is found
73  while (d == 1) {
74  x = (x * x + 1) % p;
75  y1 = (y1 * g) % p;
76  y2 = (y2 * g) % p;
77  y2 = (y2 * g) % p;
78  d = std::gcd(std::llabs(y2 - y1), p);
79  values[x] = y1;
80  }
81 
82  // Compute the discrete logarithm using the collision point
83  if (d == p) {
84  return -1;
85  } else {
86  uint64_t x0 = std::llabs(y2 - y1) / d;
87  uint64_t y0 = values[x0];
88  uint64_t k = 1;
89  while (y0 != y) {
90  y0 = (y0 * g) % p;
91  k++;
92  }
93  return k * x0 % (p - 1);
94  }
95 }
96 
97 /* Baby-Step Giant-Step */
98 uint64_t gpmp::Logarithms::BSGS(uint64_t a, uint64_t b, uint64_t m) {
99  uint64_t n = (uint64_t)sqrt(m) + 1;
100 
101  std::unordered_map<uint64_t, uint64_t> value;
102 
103  // store all values of a^(n*i) of LHS
104  for (uint64_t i = n; i >= 1; --i) {
105  value[__LOG_PRIMES__.mod_pow(a, i * n, m)] = i;
106  }
107 
108  for (uint64_t j = 0; j < n; ++j) {
109  // calculate (a ^ j) * b and check
110  uint64_t cur = (__LOG_PRIMES__.mod_pow(a, j, m) * b) % m;
111 
112  // If collision occurs i.e., LHS = RHS
113  if (value[cur]) {
114  uint64_t ans = value[cur] * n - j;
115  // Check whether ans lies below m or not
116  if (ans < m) {
117  return ans;
118  }
119  }
120  }
121  return -1;
122 }
User API for openGPMP ARITHMETIC MODULE.
uint64_t BSGS(uint64_t a, uint64_t b, uint64_t m)
Definition: logarithms.cpp:98
uint64_t pollard_rho_log(uint64_t a, uint64_t b, uint64_t m)
Definition: logarithms.cpp:58
uint64_t mod_pow(uint64_t a, uint64_t b, uint64_t m)
Definition: prime_test.cpp:72
gpmp::PrimalityTest __LOG_PRIMES__
Definition: logarithms.cpp:51