Code base obscuration (for images) 1.0
It implements different obscuration methods on portable images (.pgm and .ppm)
Loading...
Searching...
No Matches
Paillier.hpp
Go to the documentation of this file.
1
11#define BITSETSIZE 64
12
13#ifndef PAILLIER_CRYPTOSYSTEM
14#define PAILLIER_CRYPTOSYSTEM
15
16#include <iostream>
17#include <bitset>
18#include <vector>
19#include <random> //Randomdevice and mt19937
20
21using namespace std;
22
31template <typename T_in, typename T_out>
33{
34public:
41
49
59 uint64_t random64(uint64_t min, uint64_t max)
60 {
61 static std::random_device rd;
62 static std::mt19937 gen(rd());
63 std::uniform_int_distribution<std::uint64_t> dis(min, max);
64 return dis(gen);
65 }
66
77 uint64_t fastMod_64t(uint64_t x, uint64_t e, uint64_t n)
78 {
79 uint64_t c = 1;
80 bitset<BITSETSIZE> bits = bitset<BITSETSIZE>(e);
81
82 for (int i = BITSETSIZE - 1; i >= 0; i--)
83 {
84 c = c * c % n;
85 if (bits[i] & 1)
86 c = c * x % n;
87 }
88
89 return c;
90 };
91
101 uint64_t gcd_64t(uint64_t a, uint64_t b)
102 {
103 if (b == 0)
104 {
105 return a;
106 }
107 return gcd_64t(b, a % b);
108 };
109
119 std::vector<uint64_t> calc_set_same_remainder_divide_euclide_64t(uint64_t n)
120 {
121 std::vector<uint64_t> result;
122 for (uint64_t i = 0; i < n; i++)
123 {
124 if (gcd_64t(i, n) == 1)
125 {
126 result.push_back(i);
127 }
128 }
129 return result;
130 };
131
142 std::vector<uint64_t> calc_set_same_remainder_divide_euclide_64t_v2(uint64_t n, const uint64_t &lambda)
143 {
144 std::vector<uint64_t> result;
145
146 uint64_t x, r = 0, mu = 0;
147 for (uint64_t g = 0; g < n; g++)
148 {
149 if (gcd_64t(g, n) == 1)
150 {
151 uint64_t u = fastMod_64t(g, lambda, n * n);
152 uint64_t l = (u - 1) / n;
153 r = (x - 1) % n; // Vérifier si x est entier.
154 mu = modInverse_64t(l, n);
155 if (mu != 0)
156 {
157 result.push_back(g);
158 }
159 }
160 }
161 return result;
162 };
163
175 uint64_t choose_g_in_vec_64t(std::vector<uint64_t> &set, const uint64_t &n, const uint64_t &lambda)
176 {
177 uint64_t x;
178 int i_position = 0;
179 uint64_t g = 0, r = 1, r2 = 1, mu = 0;
180 while (r != 0 && r2 != 0 && mu == 0)
181 {
182 i_position = rand() % set.size();
183 g = set.at(i_position);
184 x = fastMod_64t(g, lambda, n * n);
185 r = (x - 1) % n; // Vérifier si L(x) est entier.
186 r2 = (x - 1) / n; // Vérifier si L(x) est entier.
187 mu = modInverse_64t(r2, n); // Calculer μ en utilisant la formule donnée et la fonction modular_inverse pour calculer l'inverse modulaire
188 }
189 return g;
190 };
191
201 uint64_t choose_g_in_vec_64t_v2(std::vector<uint64_t> &set)
202 {
203 int i_position = rand() % set.size();
204 return set.at(i_position);
205 };
206
215 uint64_t L_64t(uint64_t x, uint64_t n)
216 {
217 return (x - 1) / n;
218 };
219
228 uint64_t lcm_64t(uint64_t a, uint64_t b)
229 {
230 return a * b / gcd_64t(a, b);
231 };
232
241 uint64_t modInverse_64t(uint64_t a, uint64_t n)
242 {
243 a = a % n;
244 for (uint64_t x = 1; x < n; x++)
245 {
246 if ((a * x) % n == 1)
247 return x;
248 }
249
250 return 0;
251 };
252
262 uint64_t pow_uint64_t(uint64_t x, uint64_t n)
263 {
264 if (n == 0)
265 {
266 return 1;
267 }
268 return x * pow_uint64_t(x, n - 1);
269 };
270
281 uint64_t randomZNStar(uint64_t n)
282 {
283 uint64_t r = 0;
284 do
285 {
286 r = random64(1, n);
287 } while (r >= 1 && gcd_64t(r, n) != 1);
288 return r;
289 };
290
299 std::vector<uint64_t> get_set_ZNZStar(uint64_t n)
300 {
301 std::vector<uint64_t> ZNZStar;
302 for (uint64_t i = 1; i < n; i++)
303 {
304 if (gcd_64t(i, n) == 1)
305 {
306 ZNZStar.push_back(i);
307 }
308 }
309 return ZNZStar;
310 }
311
321 std::vector<uint64_t> get_set_ZN2ZStar(uint64_t n, uint64_t lambda)
322 {
323 std::vector<uint64_t> ZN2ZStar;
324 for (uint64_t g = 1; g < n * n; g++)
325 {
326 uint64_t u, l;
327 u = fastMod_64t(g, lambda, n * n);
328 l = L_64t(u, n);
329 if (gcd_64t(l, n) == 1)
330 {
331 ZN2ZStar.push_back(g);
332 }
333 }
334 return ZN2ZStar;
335 }
336
347 uint64_t generate_g_64t(uint64_t n, uint64_t lambda)
348 {
349 uint64_t g, u, l;
350 do
351 {
352 g = randomZNStar(n * n); // generate g, a random integer in Z*_{n^2}
353 u = fastMod_64t(g, lambda, n * n);
354 l = L_64t(u, n);
355 } while (gcd_64t(l, n) != 1);
356 return g;
357 };
358
369 void generateMu_64t(uint64_t &mu, const uint64_t &g, const uint64_t &lambda, const uint64_t &n)
370 {
371 uint64_t u = fastMod_64t(g, lambda, n * n);
372 uint64_t l = (u - 1) / n;
373 mu = modInverse_64t(l, n);
374 };
375
387 void generatePrivateKey_64t(uint64_t &lambda, uint64_t &mu, const uint64_t &p, const uint64_t &q, const uint64_t &n, const uint64_t &g)
388 {
389 lambda = lcm_64t(p - 1, q - 1);
390
391 generateMu_64t(mu, g, lambda, n);
392 };
393
394 //================ Overload and Generic programming ================//
395
407 T_out paillierEncryption(uint64_t n, uint64_t g, T_in m)
408 {
409 if (m >= std::numeric_limits<uint64_t>::max())
410 {
411 throw std::runtime_error("Erreur m ne peut pas être stocké dans 64 bits.");
412 }
413 uint64_t m_64 = static_cast<uint64_t>(m);
414
415 uint64_t c;
416 // uint64_t r = random64(0,n);
417 // while (gcd_64t(r, n) != 1 || r == 0)
418 // {
419 // r = random64(0,n);
420 // }
421 uint64_t r = randomZNStar(n);
422
423 // fprintf(stdout, "r : %" PRIu64 "\n", r);
424
425 uint64_t fm1 = fastMod_64t(g, m_64, n * n);
426 uint64_t fm2 = fastMod_64t(r, n, n * n);
427 c = (fm1 * fm2) % (n * n);
428
429 if (c >= std::numeric_limits<T_out>::max())
430 {
431 throw std::runtime_error("Erreur le résultat ne peut pas être stocké dans n*2 bits.");
432 }
433 return static_cast<T_out>(c);
434 };
435
448 T_out paillierEncryption(uint64_t n, uint64_t g, T_in m, uint64_t r)
449 {
450 if (m >= std::numeric_limits<uint64_t>::max())
451 {
452 throw std::runtime_error("Erreur m ne peut pas être stocké dans 64 bits.");
453 }
454 uint64_t m_64 = static_cast<uint64_t>(m);
455
456 uint64_t c;
457 uint64_t fm1 = fastMod_64t(g, m_64, n * n);
458 uint64_t fm2 = fastMod_64t(r, n, n * n);
459 c = (fm1 * fm2) % (n * n);
460
461 if (c >= std::numeric_limits<T_out>::max())
462 {
463 throw std::runtime_error("Erreur le résultat ne peut pas être stocké dans n*2 bits.");
464 }
465 return static_cast<T_out>(c);
466 };
467
480 T_in paillierDecryption(uint64_t n, uint64_t lambda, uint64_t mu, T_out c)
481 {
482 if (c >= std::numeric_limits<uint64_t>::max())
483 {
484 throw std::runtime_error("Erreur m ne peut pas être stocké dans 64 bits.");
485 }
486 uint64_t c_64 = static_cast<uint64_t>(c);
487
488 // uint64_t result = (((fastMod_64t(c_64, lambda, n * n) - 1) / n) * mu) % n;
489 uint64_t result = ((fastMod_64t(c_64, lambda, n * n) - 1) / n) * mu % n;
490
491 if (result >= std::numeric_limits<T_in>::max())
492 {
493 throw std::runtime_error("Erreur le résultat ne peut pas être stocké dans 8 bits.");
494 }
495 return static_cast<T_in>(result);
496 };
497};
498
499#endif // PAILLIER_CRYPTOSYSTEM
#define BITSETSIZE
Definition Paillier.hpp:11
This class implements the Paillier cryptosystem.
Definition Paillier.hpp:33
std::vector< uint64_t > get_set_ZN2ZStar(uint64_t n, uint64_t lambda)
Return the set Z/n²Z* that satisfy the condition gcd(L(g^lambda mod n²), n) = 1 as a vector.
Definition Paillier.hpp:321
uint64_t choose_g_in_vec_64t(std::vector< uint64_t > &set, const uint64_t &n, const uint64_t &lambda)
Choose g from the set of elements in (Z/n²Z)* that satisfy the condition L(x) = (x-1)/n where x is a ...
Definition Paillier.hpp:175
void generatePrivateKey_64t(uint64_t &lambda, uint64_t &mu, const uint64_t &p, const uint64_t &q, const uint64_t &n, const uint64_t &g)
Generate private key for Paillier cryptosystem.
Definition Paillier.hpp:387
T_out paillierEncryption(uint64_t n, uint64_t g, T_in m)
Encrypt a message using Paillier cryptosystem.
Definition Paillier.hpp:407
uint64_t lcm_64t(uint64_t a, uint64_t b)
Calculate the least common multiple (LCM) of two 64-bit unsigned integers.
Definition Paillier.hpp:228
uint64_t L_64t(uint64_t x, uint64_t n)
Calculate L(x).
Definition Paillier.hpp:215
uint64_t fastMod_64t(uint64_t x, uint64_t e, uint64_t n)
Calculate the modular exponentiation of a base raised to a power modulo a modulus.
Definition Paillier.hpp:77
std::vector< uint64_t > calc_set_same_remainder_divide_euclide_64t_v2(uint64_t n, const uint64_t &lambda)
Calculate the set of elements in (Z/n²Z)* that satisfy the condition L(x) = (x-1)/n where x is a posi...
Definition Paillier.hpp:142
uint64_t pow_uint64_t(uint64_t x, uint64_t n)
Calculate the power of a 64-bit unsigned integer.
Definition Paillier.hpp:262
std::vector< uint64_t > calc_set_same_remainder_divide_euclide_64t(uint64_t n)
Calculate the set of elements in (Z/n²Z)*.
Definition Paillier.hpp:119
uint64_t modInverse_64t(uint64_t a, uint64_t n)
Calculate the modular inverse of a 64-bit unsigned integer modulo a modulus.
Definition Paillier.hpp:241
Paillier()
Construct a new Paillier object.
Definition Paillier.hpp:40
uint64_t choose_g_in_vec_64t_v2(std::vector< uint64_t > &set)
Choose g from the set of elements in (Z/n²Z)*.
Definition Paillier.hpp:201
T_in paillierDecryption(uint64_t n, uint64_t lambda, uint64_t mu, T_out c)
Decrypt a ciphertext using Paillier cryptosystem.
Definition Paillier.hpp:480
uint64_t generate_g_64t(uint64_t n, uint64_t lambda)
Generate g for Paillier cryptosystem.
Definition Paillier.hpp:347
uint64_t random64(uint64_t min, uint64_t max)
Generate a random 64-bit unsigned integer.
Definition Paillier.hpp:59
uint64_t gcd_64t(uint64_t a, uint64_t b)
Calculate the greatest common divisor (GCD) of two 64-bit unsigned integers.
Definition Paillier.hpp:101
std::vector< uint64_t > get_set_ZNZStar(uint64_t n)
Return the set Z/nZ* as a vector.
Definition Paillier.hpp:299
T_out paillierEncryption(uint64_t n, uint64_t g, T_in m, uint64_t r)
Encrypt a message using Paillier cryptosystem with a given random value.
Definition Paillier.hpp:448
~Paillier()
Destroy the Paillier object.
Definition Paillier.hpp:48
uint64_t randomZNStar(uint64_t n)
Choose a random element from the set Z/nZ*.
Definition Paillier.hpp:281
void generateMu_64t(uint64_t &mu, const uint64_t &g, const uint64_t &lambda, const uint64_t &n)
Generate Mu for Paillier cryptosystem.
Definition Paillier.hpp:369