lightphe 0.0.22__tar.gz → 0.0.23__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. {lightphe-0.0.22 → lightphe-0.0.23}/PKG-INFO +2 -2
  2. {lightphe-0.0.22 → lightphe-0.0.23}/README.md +1 -1
  3. {lightphe-0.0.22 → lightphe-0.0.23}/lightphe/__init__.py +1 -1
  4. {lightphe-0.0.22 → lightphe-0.0.23}/lightphe/cryptosystems/BonehGohNissim.py +33 -8
  5. {lightphe-0.0.22 → lightphe-0.0.23}/lightphe.egg-info/PKG-INFO +2 -2
  6. {lightphe-0.0.22 → lightphe-0.0.23}/setup.py +1 -1
  7. {lightphe-0.0.22 → lightphe-0.0.23}/tests/test_bonehgohnissim.py +71 -0
  8. {lightphe-0.0.22 → lightphe-0.0.23}/LICENSE +0 -0
  9. {lightphe-0.0.22 → lightphe-0.0.23}/lightphe/commons/__init__.py +0 -0
  10. {lightphe-0.0.22 → lightphe-0.0.23}/lightphe/commons/logger.py +0 -0
  11. {lightphe-0.0.22 → lightphe-0.0.23}/lightphe/commons/phe_utils.py +0 -0
  12. {lightphe-0.0.22 → lightphe-0.0.23}/lightphe/cryptosystems/Benaloh.py +0 -0
  13. {lightphe-0.0.22 → lightphe-0.0.23}/lightphe/cryptosystems/DamgardJurik.py +0 -0
  14. {lightphe-0.0.22 → lightphe-0.0.23}/lightphe/cryptosystems/ElGamal.py +0 -0
  15. {lightphe-0.0.22 → lightphe-0.0.23}/lightphe/cryptosystems/EllipticCurveElGamal.py +0 -0
  16. {lightphe-0.0.22 → lightphe-0.0.23}/lightphe/cryptosystems/GoldwasserMicali.py +0 -0
  17. {lightphe-0.0.22 → lightphe-0.0.23}/lightphe/cryptosystems/NaccacheStern.py +0 -0
  18. {lightphe-0.0.22 → lightphe-0.0.23}/lightphe/cryptosystems/OkamotoUchiyama.py +0 -0
  19. {lightphe-0.0.22 → lightphe-0.0.23}/lightphe/cryptosystems/Paillier.py +0 -0
  20. {lightphe-0.0.22 → lightphe-0.0.23}/lightphe/cryptosystems/RSA.py +0 -0
  21. {lightphe-0.0.22 → lightphe-0.0.23}/lightphe/cryptosystems/SanderYoungYung.py +0 -0
  22. {lightphe-0.0.22 → lightphe-0.0.23}/lightphe/cryptosystems/__init__.py +0 -0
  23. {lightphe-0.0.22 → lightphe-0.0.23}/lightphe/models/Algorithm.py +0 -0
  24. {lightphe-0.0.22 → lightphe-0.0.23}/lightphe/models/Ciphertext.py +0 -0
  25. {lightphe-0.0.22 → lightphe-0.0.23}/lightphe/models/Homomorphic.py +0 -0
  26. {lightphe-0.0.22 → lightphe-0.0.23}/lightphe/models/Tensor.py +0 -0
  27. {lightphe-0.0.22 → lightphe-0.0.23}/lightphe/models/__init__.py +0 -0
  28. {lightphe-0.0.22 → lightphe-0.0.23}/lightphe.egg-info/SOURCES.txt +0 -0
  29. {lightphe-0.0.22 → lightphe-0.0.23}/lightphe.egg-info/dependency_links.txt +0 -0
  30. {lightphe-0.0.22 → lightphe-0.0.23}/lightphe.egg-info/requires.txt +0 -0
  31. {lightphe-0.0.22 → lightphe-0.0.23}/lightphe.egg-info/top_level.txt +0 -0
  32. {lightphe-0.0.22 → lightphe-0.0.23}/requirements.txt +0 -0
  33. {lightphe-0.0.22 → lightphe-0.0.23}/setup.cfg +0 -0
  34. {lightphe-0.0.22 → lightphe-0.0.23}/tests/__init__.py +0 -0
  35. {lightphe-0.0.22 → lightphe-0.0.23}/tests/test_benaloh.py +0 -0
  36. {lightphe-0.0.22 → lightphe-0.0.23}/tests/test_ciphertexts.py +0 -0
  37. {lightphe-0.0.22 → lightphe-0.0.23}/tests/test_cloud.py +0 -0
  38. {lightphe-0.0.22 → lightphe-0.0.23}/tests/test_damgard.py +0 -0
  39. {lightphe-0.0.22 → lightphe-0.0.23}/tests/test_elgamal.py +0 -0
  40. {lightphe-0.0.22 → lightphe-0.0.23}/tests/test_ellipticcurveelgamal.py +0 -0
  41. {lightphe-0.0.22 → lightphe-0.0.23}/tests/test_exporting_keys.py +0 -0
  42. {lightphe-0.0.22 → lightphe-0.0.23}/tests/test_goldwasser.py +0 -0
  43. {lightphe-0.0.22 → lightphe-0.0.23}/tests/test_keys.py +0 -0
  44. {lightphe-0.0.22 → lightphe-0.0.23}/tests/test_large_keys.py +0 -0
  45. {lightphe-0.0.22 → lightphe-0.0.23}/tests/test_naccache.py +0 -0
  46. {lightphe-0.0.22 → lightphe-0.0.23}/tests/test_okamoto.py +0 -0
  47. {lightphe-0.0.22 → lightphe-0.0.23}/tests/test_paillier.py +0 -0
  48. {lightphe-0.0.22 → lightphe-0.0.23}/tests/test_rsa.py +0 -0
  49. {lightphe-0.0.22 → lightphe-0.0.23}/tests/test_salary.py +0 -0
  50. {lightphe-0.0.22 → lightphe-0.0.23}/tests/test_sanderyoungyung.py +0 -0
  51. {lightphe-0.0.22 → lightphe-0.0.23}/tests/test_tensors.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lightphe
3
- Version: 0.0.22
3
+ Version: 0.0.23
4
4
  Summary: A Lightweight Partially Homomorphic Encryption Library for Python
5
5
  Home-page: https://github.com/serengil/LightPHE
6
6
  Author: Sefik Ilkin Serengil
@@ -36,7 +36,7 @@ License-File: LICENSE
36
36
 
37
37
  <p align="center"><img src="https://raw.githubusercontent.com/serengil/LightPHE/master/icons/phi.png" width="200" height="240"></p>
38
38
 
39
- LightPHE is a lightweight partially homomorphic encryption library for python. It is a hybrid homomoprhic encryption library wrapping many schemes such as [`RSA`](https://sefiks.com/2023/03/06/a-step-by-step-partially-homomorphic-encryption-example-with-rsa-in-python/), [`ElGamal`](https://sefiks.com/2023/03/27/a-step-by-step-partially-homomorphic-encryption-example-with-elgamal-in-python/), [`Exponential ElGamal`](https://sefiks.com/2023/03/27/a-step-by-step-partially-homomorphic-encryption-example-with-elgamal-in-python/), [`Elliptic Curve ElGamal`](https://sefiks.com/2018/08/21/elliptic-curve-elgamal-encryption/) ([`Weierstrass`](https://sefiks.com/2016/03/13/the-math-behind-elliptic-curve-cryptography/), [`Koblitz`](sefiks.com/2016/03/13/the-math-behind-elliptic-curves-over-binary-field/) and [`Edwards`](https://sefiks.com/2018/12/19/a-gentle-introduction-to-edwards-curves/) forms), [`Paillier`](https://sefiks.com/2023/04/03/a-step-by-step-partially-homomorphic-encryption-example-with-paillier-in-python/), [`Damgard-Jurik`](https://sefiks.com/2023/10/20/a-step-by-step-partially-homomorphic-encryption-example-with-damgard-jurik-in-python/), [`Okamoto–Uchiyama`](https://sefiks.com/2023/10/20/a-step-by-step-partially-homomorphic-encryption-example-with-okamoto-uchiyama-in-python/), [`Benaloh`](https://sefiks.com/2023/10/06/a-step-by-step-partially-homomorphic-encryption-example-with-benaloh-in-python-from-scratch/), [`Naccache–Stern`](https://sefiks.com/2023/10/26/a-step-by-step-partially-homomorphic-encryption-example-with-naccache-stern-in-python/), [`Goldwasser–Micali`](https://sefiks.com/2023/10/27/a-step-by-step-partially-homomorphic-encryption-example-with-goldwasser-micali-in-python/), [`Sander-Young-Yung`](https://sefiks.com/2026/04/02/a-step-by-step-partially-homomorphic-sander-young-yung-example-in-python/), [`Boneh-Goh-Nissim`](https://sefiks.com/2026/04/02/a-step-by-step-somewhat-homomorphic-encryption-example-with-boneh-goh-nissim-in-python/).
39
+ LightPHE is a lightweight homomorphic encryption library for python supporting various partially and somewhat homomorphic encryptions schemes such as [`RSA`](https://sefiks.com/2023/03/06/a-step-by-step-partially-homomorphic-encryption-example-with-rsa-in-python/), [`ElGamal`](https://sefiks.com/2023/03/27/a-step-by-step-partially-homomorphic-encryption-example-with-elgamal-in-python/), [`Exponential ElGamal`](https://sefiks.com/2023/03/27/a-step-by-step-partially-homomorphic-encryption-example-with-elgamal-in-python/), [`Elliptic Curve ElGamal`](https://sefiks.com/2018/08/21/elliptic-curve-elgamal-encryption/) ([`Weierstrass`](https://sefiks.com/2016/03/13/the-math-behind-elliptic-curve-cryptography/), [`Koblitz`](sefiks.com/2016/03/13/the-math-behind-elliptic-curves-over-binary-field/) and [`Edwards`](https://sefiks.com/2018/12/19/a-gentle-introduction-to-edwards-curves/) forms), [`Paillier`](https://sefiks.com/2023/04/03/a-step-by-step-partially-homomorphic-encryption-example-with-paillier-in-python/), [`Damgard-Jurik`](https://sefiks.com/2023/10/20/a-step-by-step-partially-homomorphic-encryption-example-with-damgard-jurik-in-python/), [`Okamoto–Uchiyama`](https://sefiks.com/2023/10/20/a-step-by-step-partially-homomorphic-encryption-example-with-okamoto-uchiyama-in-python/), [`Benaloh`](https://sefiks.com/2023/10/06/a-step-by-step-partially-homomorphic-encryption-example-with-benaloh-in-python-from-scratch/), [`Naccache–Stern`](https://sefiks.com/2023/10/26/a-step-by-step-partially-homomorphic-encryption-example-with-naccache-stern-in-python/), [`Goldwasser–Micali`](https://sefiks.com/2023/10/27/a-step-by-step-partially-homomorphic-encryption-example-with-goldwasser-micali-in-python/), [`Sander-Young-Yung`](https://sefiks.com/2026/04/02/a-step-by-step-partially-homomorphic-sander-young-yung-example-in-python/), [`Boneh-Goh-Nissim`](https://sefiks.com/2026/04/02/a-step-by-step-somewhat-homomorphic-encryption-example-with-boneh-goh-nissim-in-python/).
40
40
 
41
41
  # Partially vs Fully Homomorphic Encryption
42
42
 
@@ -20,7 +20,7 @@
20
20
 
21
21
  <p align="center"><img src="https://raw.githubusercontent.com/serengil/LightPHE/master/icons/phi.png" width="200" height="240"></p>
22
22
 
23
- LightPHE is a lightweight partially homomorphic encryption library for python. It is a hybrid homomoprhic encryption library wrapping many schemes such as [`RSA`](https://sefiks.com/2023/03/06/a-step-by-step-partially-homomorphic-encryption-example-with-rsa-in-python/), [`ElGamal`](https://sefiks.com/2023/03/27/a-step-by-step-partially-homomorphic-encryption-example-with-elgamal-in-python/), [`Exponential ElGamal`](https://sefiks.com/2023/03/27/a-step-by-step-partially-homomorphic-encryption-example-with-elgamal-in-python/), [`Elliptic Curve ElGamal`](https://sefiks.com/2018/08/21/elliptic-curve-elgamal-encryption/) ([`Weierstrass`](https://sefiks.com/2016/03/13/the-math-behind-elliptic-curve-cryptography/), [`Koblitz`](sefiks.com/2016/03/13/the-math-behind-elliptic-curves-over-binary-field/) and [`Edwards`](https://sefiks.com/2018/12/19/a-gentle-introduction-to-edwards-curves/) forms), [`Paillier`](https://sefiks.com/2023/04/03/a-step-by-step-partially-homomorphic-encryption-example-with-paillier-in-python/), [`Damgard-Jurik`](https://sefiks.com/2023/10/20/a-step-by-step-partially-homomorphic-encryption-example-with-damgard-jurik-in-python/), [`Okamoto–Uchiyama`](https://sefiks.com/2023/10/20/a-step-by-step-partially-homomorphic-encryption-example-with-okamoto-uchiyama-in-python/), [`Benaloh`](https://sefiks.com/2023/10/06/a-step-by-step-partially-homomorphic-encryption-example-with-benaloh-in-python-from-scratch/), [`Naccache–Stern`](https://sefiks.com/2023/10/26/a-step-by-step-partially-homomorphic-encryption-example-with-naccache-stern-in-python/), [`Goldwasser–Micali`](https://sefiks.com/2023/10/27/a-step-by-step-partially-homomorphic-encryption-example-with-goldwasser-micali-in-python/), [`Sander-Young-Yung`](https://sefiks.com/2026/04/02/a-step-by-step-partially-homomorphic-sander-young-yung-example-in-python/), [`Boneh-Goh-Nissim`](https://sefiks.com/2026/04/02/a-step-by-step-somewhat-homomorphic-encryption-example-with-boneh-goh-nissim-in-python/).
23
+ LightPHE is a lightweight homomorphic encryption library for python supporting various partially and somewhat homomorphic encryptions schemes such as [`RSA`](https://sefiks.com/2023/03/06/a-step-by-step-partially-homomorphic-encryption-example-with-rsa-in-python/), [`ElGamal`](https://sefiks.com/2023/03/27/a-step-by-step-partially-homomorphic-encryption-example-with-elgamal-in-python/), [`Exponential ElGamal`](https://sefiks.com/2023/03/27/a-step-by-step-partially-homomorphic-encryption-example-with-elgamal-in-python/), [`Elliptic Curve ElGamal`](https://sefiks.com/2018/08/21/elliptic-curve-elgamal-encryption/) ([`Weierstrass`](https://sefiks.com/2016/03/13/the-math-behind-elliptic-curve-cryptography/), [`Koblitz`](sefiks.com/2016/03/13/the-math-behind-elliptic-curves-over-binary-field/) and [`Edwards`](https://sefiks.com/2018/12/19/a-gentle-introduction-to-edwards-curves/) forms), [`Paillier`](https://sefiks.com/2023/04/03/a-step-by-step-partially-homomorphic-encryption-example-with-paillier-in-python/), [`Damgard-Jurik`](https://sefiks.com/2023/10/20/a-step-by-step-partially-homomorphic-encryption-example-with-damgard-jurik-in-python/), [`Okamoto–Uchiyama`](https://sefiks.com/2023/10/20/a-step-by-step-partially-homomorphic-encryption-example-with-okamoto-uchiyama-in-python/), [`Benaloh`](https://sefiks.com/2023/10/06/a-step-by-step-partially-homomorphic-encryption-example-with-benaloh-in-python-from-scratch/), [`Naccache–Stern`](https://sefiks.com/2023/10/26/a-step-by-step-partially-homomorphic-encryption-example-with-naccache-stern-in-python/), [`Goldwasser–Micali`](https://sefiks.com/2023/10/27/a-step-by-step-partially-homomorphic-encryption-example-with-goldwasser-micali-in-python/), [`Sander-Young-Yung`](https://sefiks.com/2026/04/02/a-step-by-step-partially-homomorphic-sander-young-yung-example-in-python/), [`Boneh-Goh-Nissim`](https://sefiks.com/2026/04/02/a-step-by-step-somewhat-homomorphic-encryption-example-with-boneh-goh-nissim-in-python/).
24
24
 
25
25
  # Partially vs Fully Homomorphic Encryption
26
26
 
@@ -36,7 +36,7 @@ from lightphe.cryptosystems.BonehGohNissim import BonehGohNissim
36
36
 
37
37
  logger = Logger(module="lightphe/__init__.py")
38
38
 
39
- VERSION = "0.0.22"
39
+ VERSION = "0.0.23"
40
40
 
41
41
 
42
42
  class LightPHE:
@@ -54,7 +54,10 @@ class BonehGohNissim(Homomorphic):
54
54
  },
55
55
  )
56
56
 
57
- self.plaintext_modulo = self.ec.modulo
57
+ if "private_key" in self.keys and "q2" in self.keys["private_key"]:
58
+ self.plaintext_modulo = self.keys["private_key"]["q2"]
59
+ else:
60
+ self.plaintext_modulo = self.keys["public_key"]["curve"]["n"]
58
61
  self.ciphertext_modulo = self.ec.modulo
59
62
 
60
63
  def generate_keys(
@@ -160,14 +163,28 @@ class BonehGohNissim(Homomorphic):
160
163
 
161
164
  raise Exception(f"Failed to find a generator after {max_tries} attempts")
162
165
 
166
+ def _has_private_key(self) -> bool:
167
+ return "private_key" in self.keys and "q2" in self.keys["private_key"]
168
+
163
169
  def generate_random_key(self) -> int:
164
170
  """
165
171
  Boneh-Goh-Nissim requires to generate one-time random key per encryption
166
172
  Returns:
167
173
  random key (int): one time random key for encryption
168
174
  """
169
- q2 = self.keys["private_key"]["q2"]
170
- return random.randint(1, q2 - 1)
175
+ if self._has_private_key():
176
+ q2 = self.keys["private_key"]["q2"]
177
+ return random.randint(1, q2 - 1)
178
+
179
+ n = self.keys["public_key"]["curve"]["n"]
180
+ logger.warn(
181
+ "Private key is not available. Random key will be bounded by n"
182
+ " instead of q2. Encryption will work for small plaintexts,"
183
+ " but negative number encoding via plaintext_modulo will not"
184
+ " round-trip correctly because plaintext_modulo is set to n"
185
+ " (public) instead of q2 (private)."
186
+ )
187
+ return random.randint(1, n - 1)
171
188
 
172
189
  def encrypt(
173
190
  self, plaintext: int, random_key: Optional[int] = None
@@ -200,23 +217,28 @@ class BonehGohNissim(Homomorphic):
200
217
  plaintext (int): restored message
201
218
  """
202
219
  q1 = self.keys["private_key"]["q1"]
220
+ q2 = self.keys["private_key"]["q2"]
203
221
 
204
222
  if isinstance(ciphertext, tuple):
205
- return self._decrypt_gt(ciphertext, q1)
223
+ return self._decrypt_gt(ciphertext, q1, q2)
206
224
 
207
225
  G = self.ec.G
208
226
 
209
227
  mP = ciphertext * q1
210
228
  P = G * q1
211
229
 
212
- for i in range(1, q1 + 1):
230
+ # P has order q2, so DLP result is in [0, q2)
231
+ if mP == self.ec.O:
232
+ return 0
233
+
234
+ for i in range(1, q2):
213
235
  iP = P * i
214
236
  if iP == mP:
215
237
  return i
216
238
 
217
239
  raise Exception("Decryption failed")
218
240
 
219
- def _decrypt_gt(self, ciphertext: tuple, q1: int) -> int:
241
+ def _decrypt_gt(self, ciphertext: tuple, q1: int, q2: int) -> int:
220
242
  """
221
243
  Decrypt a G_T ciphertext (result of homomorphic multiplication).
222
244
 
@@ -241,9 +263,12 @@ class BonehGohNissim(Homomorphic):
241
263
  base = _fp2_pow(e_gg, q1, p)
242
264
  target = _fp2_pow(ciphertext, q1, p)
243
265
 
244
- # brute-force DLP in G_T
266
+ # brute-force DLP in G_T — result is in [0, q2)
267
+ if target == (1, 0):
268
+ return 0
269
+
245
270
  acc = (1, 0)
246
- for i in range(1, q1 + 1):
271
+ for i in range(1, q2):
247
272
  acc = _fp2_mul(acc, base, p)
248
273
  if acc == target:
249
274
  return i
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lightphe
3
- Version: 0.0.22
3
+ Version: 0.0.23
4
4
  Summary: A Lightweight Partially Homomorphic Encryption Library for Python
5
5
  Home-page: https://github.com/serengil/LightPHE
6
6
  Author: Sefik Ilkin Serengil
@@ -36,7 +36,7 @@ License-File: LICENSE
36
36
 
37
37
  <p align="center"><img src="https://raw.githubusercontent.com/serengil/LightPHE/master/icons/phi.png" width="200" height="240"></p>
38
38
 
39
- LightPHE is a lightweight partially homomorphic encryption library for python. It is a hybrid homomoprhic encryption library wrapping many schemes such as [`RSA`](https://sefiks.com/2023/03/06/a-step-by-step-partially-homomorphic-encryption-example-with-rsa-in-python/), [`ElGamal`](https://sefiks.com/2023/03/27/a-step-by-step-partially-homomorphic-encryption-example-with-elgamal-in-python/), [`Exponential ElGamal`](https://sefiks.com/2023/03/27/a-step-by-step-partially-homomorphic-encryption-example-with-elgamal-in-python/), [`Elliptic Curve ElGamal`](https://sefiks.com/2018/08/21/elliptic-curve-elgamal-encryption/) ([`Weierstrass`](https://sefiks.com/2016/03/13/the-math-behind-elliptic-curve-cryptography/), [`Koblitz`](sefiks.com/2016/03/13/the-math-behind-elliptic-curves-over-binary-field/) and [`Edwards`](https://sefiks.com/2018/12/19/a-gentle-introduction-to-edwards-curves/) forms), [`Paillier`](https://sefiks.com/2023/04/03/a-step-by-step-partially-homomorphic-encryption-example-with-paillier-in-python/), [`Damgard-Jurik`](https://sefiks.com/2023/10/20/a-step-by-step-partially-homomorphic-encryption-example-with-damgard-jurik-in-python/), [`Okamoto–Uchiyama`](https://sefiks.com/2023/10/20/a-step-by-step-partially-homomorphic-encryption-example-with-okamoto-uchiyama-in-python/), [`Benaloh`](https://sefiks.com/2023/10/06/a-step-by-step-partially-homomorphic-encryption-example-with-benaloh-in-python-from-scratch/), [`Naccache–Stern`](https://sefiks.com/2023/10/26/a-step-by-step-partially-homomorphic-encryption-example-with-naccache-stern-in-python/), [`Goldwasser–Micali`](https://sefiks.com/2023/10/27/a-step-by-step-partially-homomorphic-encryption-example-with-goldwasser-micali-in-python/), [`Sander-Young-Yung`](https://sefiks.com/2026/04/02/a-step-by-step-partially-homomorphic-sander-young-yung-example-in-python/), [`Boneh-Goh-Nissim`](https://sefiks.com/2026/04/02/a-step-by-step-somewhat-homomorphic-encryption-example-with-boneh-goh-nissim-in-python/).
39
+ LightPHE is a lightweight homomorphic encryption library for python supporting various partially and somewhat homomorphic encryptions schemes such as [`RSA`](https://sefiks.com/2023/03/06/a-step-by-step-partially-homomorphic-encryption-example-with-rsa-in-python/), [`ElGamal`](https://sefiks.com/2023/03/27/a-step-by-step-partially-homomorphic-encryption-example-with-elgamal-in-python/), [`Exponential ElGamal`](https://sefiks.com/2023/03/27/a-step-by-step-partially-homomorphic-encryption-example-with-elgamal-in-python/), [`Elliptic Curve ElGamal`](https://sefiks.com/2018/08/21/elliptic-curve-elgamal-encryption/) ([`Weierstrass`](https://sefiks.com/2016/03/13/the-math-behind-elliptic-curve-cryptography/), [`Koblitz`](sefiks.com/2016/03/13/the-math-behind-elliptic-curves-over-binary-field/) and [`Edwards`](https://sefiks.com/2018/12/19/a-gentle-introduction-to-edwards-curves/) forms), [`Paillier`](https://sefiks.com/2023/04/03/a-step-by-step-partially-homomorphic-encryption-example-with-paillier-in-python/), [`Damgard-Jurik`](https://sefiks.com/2023/10/20/a-step-by-step-partially-homomorphic-encryption-example-with-damgard-jurik-in-python/), [`Okamoto–Uchiyama`](https://sefiks.com/2023/10/20/a-step-by-step-partially-homomorphic-encryption-example-with-okamoto-uchiyama-in-python/), [`Benaloh`](https://sefiks.com/2023/10/06/a-step-by-step-partially-homomorphic-encryption-example-with-benaloh-in-python-from-scratch/), [`Naccache–Stern`](https://sefiks.com/2023/10/26/a-step-by-step-partially-homomorphic-encryption-example-with-naccache-stern-in-python/), [`Goldwasser–Micali`](https://sefiks.com/2023/10/27/a-step-by-step-partially-homomorphic-encryption-example-with-goldwasser-micali-in-python/), [`Sander-Young-Yung`](https://sefiks.com/2026/04/02/a-step-by-step-partially-homomorphic-sander-young-yung-example-in-python/), [`Boneh-Goh-Nissim`](https://sefiks.com/2026/04/02/a-step-by-step-somewhat-homomorphic-encryption-example-with-boneh-goh-nissim-in-python/).
40
40
 
41
41
  # Partially vs Fully Homomorphic Encryption
42
42
 
@@ -8,7 +8,7 @@ with open("requirements.txt", "r", encoding="utf-8") as f:
8
8
 
9
9
  setuptools.setup(
10
10
  name="lightphe",
11
- version="0.0.22",
11
+ version="0.0.23",
12
12
  author="Sefik Ilkin Serengil",
13
13
  author_email="serengil@gmail.com",
14
14
  description="A Lightweight Partially Homomorphic Encryption Library for Python",
@@ -108,6 +108,77 @@ def test_linear_regression():
108
108
  )
109
109
 
110
110
 
111
+ def test_cosine_similarity():
112
+ tic = time.time()
113
+ i1 = 5
114
+ i2 = 2
115
+ i3 = 8
116
+
117
+ # v2 = [1, 1, 2]
118
+ j1 = 1
119
+ j2 = 1
120
+ j3 = 2
121
+
122
+ i1_enc = cs.encrypt(i1)
123
+ i2_enc = cs.encrypt(i2)
124
+ i3_enc = cs.encrypt(i3)
125
+
126
+ j1_enc = cs.encrypt(j1)
127
+ j2_enc = cs.encrypt(j2)
128
+ j3_enc = cs.encrypt(j3)
129
+
130
+ # homomorphic operation
131
+ cosine_sim_enc = i1_enc * j1_enc + i2_enc * j2_enc + i3_enc * j3_enc
132
+
133
+ # proof of work
134
+ assert cs.decrypt(cosine_sim_enc) == i1 * j1 + i2 * j2 + i3 * j3
135
+
136
+ logger.info(
137
+ f"✅ Boneh-God-Nissim cosine similarity test succeeded "
138
+ f"({security_level} bit ECC security level)"
139
+ f" in {time.time() - tic:.2f} seconds"
140
+ )
141
+
142
+
143
+ def test_euclidean_distance():
144
+ tic = time.time()
145
+
146
+ # v1 = [5, 2, 3]
147
+ i1 = 5
148
+ i2 = 2
149
+ i3 = 8
150
+
151
+ # v2 = [1, 1, 2]
152
+ j1 = 1
153
+ j2 = 1
154
+ j3 = 2
155
+
156
+ i1_enc = cs.encrypt(i1)
157
+ i2_enc = cs.encrypt(i2)
158
+ i3_enc = cs.encrypt(i3)
159
+
160
+ j1_enc = cs.encrypt(-j1)
161
+ j2_enc = cs.encrypt(-j2)
162
+ j3_enc = cs.encrypt(-j3)
163
+
164
+ euclidean_sqrt_enc = (
165
+ (i1_enc + j1_enc) * (i1_enc + j1_enc)
166
+ + (i2_enc + j2_enc) * (i2_enc + j2_enc)
167
+ + (i3_enc + j3_enc) * (i3_enc + j3_enc)
168
+ )
169
+
170
+ assert (
171
+ cs.decrypt(euclidean_sqrt_enc)
172
+ == (i1 - j1) ** 2 + (i2 - j2) ** 2 + (i3 - j3) ** 2
173
+ )
174
+
175
+ logger.info(
176
+ f"✅ Boneh-God-Nissim euclidean distance test succeeded "
177
+ f"({security_level} bit ECC security level)"
178
+ f" in {time.time() - tic:.2f} seconds"
179
+ )
180
+
181
+
111
182
  def test_api_with_predefined_keys():
112
183
  keys = {
113
184
  "private_key": {"q1": 1260048562698661, "q2": 1495813357973021},
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes