lightphe 0.0.18__tar.gz → 0.0.22__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 (57) hide show
  1. {lightphe-0.0.18 → lightphe-0.0.22}/PKG-INFO +29 -20
  2. {lightphe-0.0.18 → lightphe-0.0.22}/README.md +28 -19
  3. {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/__init__.py +35 -7
  4. {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/commons/phe_utils.py +4 -0
  5. {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/cryptosystems/Benaloh.py +5 -1
  6. lightphe-0.0.22/lightphe/cryptosystems/BonehGohNissim.py +350 -0
  7. {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/cryptosystems/EllipticCurveElGamal.py +22 -2
  8. {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/cryptosystems/GoldwasserMicali.py +28 -12
  9. {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/cryptosystems/NaccacheStern.py +5 -1
  10. {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/cryptosystems/RSA.py +41 -25
  11. lightphe-0.0.22/lightphe/cryptosystems/SanderYoungYung.py +225 -0
  12. {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/models/Algorithm.py +2 -0
  13. {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/models/Ciphertext.py +24 -0
  14. {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/models/Homomorphic.py +33 -10
  15. {lightphe-0.0.18 → lightphe-0.0.22}/lightphe.egg-info/PKG-INFO +29 -20
  16. {lightphe-0.0.18 → lightphe-0.0.22}/lightphe.egg-info/SOURCES.txt +4 -0
  17. lightphe-0.0.22/lightphe.egg-info/requires.txt +3 -0
  18. lightphe-0.0.22/requirements.txt +3 -0
  19. {lightphe-0.0.18 → lightphe-0.0.22}/setup.py +1 -1
  20. {lightphe-0.0.18 → lightphe-0.0.22}/tests/test_benaloh.py +1 -32
  21. lightphe-0.0.22/tests/test_bonehgohnissim.py +180 -0
  22. {lightphe-0.0.18 → lightphe-0.0.22}/tests/test_ciphertexts.py +2 -4
  23. lightphe-0.0.22/tests/test_damgard.py +34 -0
  24. lightphe-0.0.22/tests/test_elgamal.py +64 -0
  25. {lightphe-0.0.18 → lightphe-0.0.22}/tests/test_ellipticcurveelgamal.py +15 -1
  26. {lightphe-0.0.18 → lightphe-0.0.22}/tests/test_exporting_keys.py +1 -1
  27. {lightphe-0.0.18 → lightphe-0.0.22}/tests/test_goldwasser.py +1 -35
  28. {lightphe-0.0.18 → lightphe-0.0.22}/tests/test_keys.py +2 -5
  29. {lightphe-0.0.18 → lightphe-0.0.22}/tests/test_large_keys.py +5 -4
  30. {lightphe-0.0.18 → lightphe-0.0.22}/tests/test_naccache.py +0 -95
  31. lightphe-0.0.22/tests/test_okamoto.py +34 -0
  32. {lightphe-0.0.18 → lightphe-0.0.22}/tests/test_paillier.py +2 -36
  33. {lightphe-0.0.18 → lightphe-0.0.22}/tests/test_rsa.py +1 -31
  34. lightphe-0.0.22/tests/test_salary.py +24 -0
  35. lightphe-0.0.22/tests/test_sanderyoungyung.py +71 -0
  36. {lightphe-0.0.18 → lightphe-0.0.22}/tests/test_tensors.py +25 -11
  37. lightphe-0.0.18/lightphe.egg-info/requires.txt +0 -4
  38. lightphe-0.0.18/requirements.txt +0 -4
  39. lightphe-0.0.18/tests/test_damgard.py +0 -63
  40. lightphe-0.0.18/tests/test_elgamal.py +0 -139
  41. lightphe-0.0.18/tests/test_okamoto.py +0 -61
  42. lightphe-0.0.18/tests/test_salary.py +0 -53
  43. {lightphe-0.0.18 → lightphe-0.0.22}/LICENSE +0 -0
  44. {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/commons/__init__.py +0 -0
  45. {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/commons/logger.py +0 -0
  46. {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/cryptosystems/DamgardJurik.py +0 -0
  47. {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/cryptosystems/ElGamal.py +0 -0
  48. {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/cryptosystems/OkamotoUchiyama.py +0 -0
  49. {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/cryptosystems/Paillier.py +0 -0
  50. {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/cryptosystems/__init__.py +0 -0
  51. {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/models/Tensor.py +0 -0
  52. {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/models/__init__.py +0 -0
  53. {lightphe-0.0.18 → lightphe-0.0.22}/lightphe.egg-info/dependency_links.txt +0 -0
  54. {lightphe-0.0.18 → lightphe-0.0.22}/lightphe.egg-info/top_level.txt +0 -0
  55. {lightphe-0.0.18 → lightphe-0.0.22}/setup.cfg +0 -0
  56. {lightphe-0.0.18 → lightphe-0.0.22}/tests/__init__.py +0 -0
  57. {lightphe-0.0.18 → lightphe-0.0.22}/tests/test_cloud.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lightphe
3
- Version: 0.0.18
3
+ Version: 0.0.22
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/).
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/).
40
40
 
41
41
  # Partially vs Fully Homomorphic Encryption
42
42
 
@@ -67,18 +67,20 @@ from lightphe import LightPHE
67
67
 
68
68
  In summary, LightPHE is covering following algorithms and these are partially homomorphic with respect to the operations mentioned in the following table.
69
69
 
70
- | Algorithm | Multiplicatively<br>Homomorphic | Additively<br>Homomorphic | Scalar Multiplication | Exclusively<br>Homomorphic | Regeneration<br>of Ciphertext |
71
- | --- | --- | --- | --- | --- | --- |
72
- | RSA | ✅ | ❌ | ❌ | ❌ | ❌ |
73
- | ElGamal | ✅ | ❌ | ❌ | ❌ | ✅ |
74
- | Exponential ElGamal | ❌ | ✅ | ✅ | ❌ | ✅ |
75
- | Elliptic Curve ElGamal | ❌ | ✅ | ✅ | ❌ | ❌ |
76
- | Paillier | ❌ | ✅ | ✅ | ❌ | ✅ |
77
- | Damgard-Jurik | ❌ | ✅ | ✅ | ❌ | ✅ |
78
- | Benaloh | ❌ | ✅ | ✅ | ❌ | ✅ |
79
- | Naccache-Stern | ❌ | ✅ | ✅ | ❌ | ✅ |
80
- | Okamoto-Uchiyama | ❌ | ✅ | ✅ | ❌ | ✅ |
81
- | Goldwasser-Micali | ❌ | ❌ | ❌ | ✅ | ❌ |
70
+ | Algorithm | Multiplicatively<br>Homomorphic | Additively<br>Homomorphic | Scalar Multiplication | Bitwise-XOR Homomorphic | Bitwise-AND Homomorphic | Regeneration<br>of Ciphertext |
71
+ | --- | --- | --- | --- | --- | --- | --- |
72
+ | RSA | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
73
+ | ElGamal | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ |
74
+ | Exponential ElGamal | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
75
+ | Elliptic Curve ElGamal | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
76
+ | Paillier | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
77
+ | Damgard-Jurik | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
78
+ | Benaloh | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
79
+ | Naccache-Stern | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
80
+ | Okamoto-Uchiyama | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
81
+ | Goldwasser-Micali | ❌ | ❌ | ❌ | ✅ | ❌ | ✅ |
82
+ | Sander-Young-Yung | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ |
83
+ | Boneh-Goh-Nissim | 1️⃣ | ✅ | ✅ | ❌ | ❌ | ✅ |
82
84
 
83
85
  # Building cryptosystem
84
86
 
@@ -95,7 +97,9 @@ algorithms = [
95
97
  "Benaloh",
96
98
  "Naccache-Stern",
97
99
  "Goldwasser-Micali",
98
- "EllipticCurve-ElGamal"
100
+ "EllipticCurve-ElGamal",
101
+ "Sander-Young-Yung",
102
+ "Boneh-Goh-Nissim",
99
103
  ]
100
104
 
101
105
  cs = LightPHE(algorithm_name = algorithms[0])
@@ -129,7 +133,7 @@ assert cs.decrypt(c3) == m1 + m2
129
133
  assert cs.decrypt(c4) == k * m1
130
134
  ```
131
135
 
132
- On the other hand, if you adopt a multiplicatively homomorphic cryptosyste (e.g. RSA or ElGamal), you can multiply ciphertexts without revealing the private key or the plaintext.
136
+ On the other hand, if you adopt a multiplicatively homomorphic cryptosystem (e.g. RSA or ElGamal), you can multiply ciphertexts without revealing the private key or the plaintext.
133
137
 
134
138
  ```python
135
139
  # build a multiplicatively homomorphic cryptosystem
@@ -152,7 +156,7 @@ assert cs.decrypt(c3) == m1 * m2
152
156
 
153
157
  ### Ciphertext Regeneration
154
158
 
155
- Similar to the most of additively homomorphic algorithms, Paillier lets you to regenerate ciphertext while you are not breaking its plaintext restoration. You may consider to do this re-generation many times to have stronger ciphertexts.
159
+ The most of additively homomorphic algorithms allow you to regenerate ciphertext while you are not breaking its plaintext restoration. You may consider to do this re-generation many times to have stronger ciphertexts.
156
160
 
157
161
  ```python
158
162
  c1_prime = cs.regenerate_ciphertext(c1)
@@ -163,7 +167,7 @@ assert cs.decrypt(c1) == m1
163
167
 
164
168
  ### Elliptic Curve Cryptography
165
169
 
166
- ECC is a powerful public-key cryptosystem based on the algebraic structure of elliptic curves over finite fields. The library supports 3 elliptic curve forms (weierstrass, edwards and koblitz) and 100+ standard elliptic curve configurations.
170
+ ECC is a powerful public-key cryptosystem based on the algebraic structure of elliptic curves over finite fields. The library supports 3 elliptic curve forms (weierstrass (default), edwards and koblitz) and 100+ standard elliptic curve configurations.
167
171
 
168
172
  In LightPHE, the [Elliptic Curve ElGamal](https://sefiks.com/2018/08/21/elliptic-curve-elgamal-encryption/) scheme is implemented, offering a secure and efficient homomorphic encryption option.
169
173
 
@@ -171,7 +175,8 @@ In LightPHE, the [Elliptic Curve ElGamal](https://sefiks.com/2018/08/21/elliptic
171
175
  forms = ["weierstrass", "edwards", "koblitz"]
172
176
  phe = LightPHE(
173
177
  algorithm_name="EllipticCurve-ElGamal",
174
- form=forms[1],
178
+ form="edwards",
179
+ # curve="ed448", # optinally you can specify the curve for given form
175
180
  )
176
181
  ```
177
182
 
@@ -204,12 +209,16 @@ c4 = c1 + c2
204
209
  c5 = 3 * c1
205
210
 
206
211
  # perform element-wise multiplication between an encrypted embedding and plain embedding
207
- c6 = c1 * t3 # Encrypted-plaintext multiplication
212
+ c6 = c1 * t3
213
+
214
+ # encrypted dot product (likewise cosine similarity)
215
+ c7 = c1 @ t3
208
216
 
209
217
  # proof of work
210
218
  assert np.allclose(cs.decrypt(c4), [a + b for a, b in zip(t1, t2)], rtol=1e-2)
211
219
  assert np.allclose(cs.decrypt(c5), [a * 3 for a in t1], rtol=1e-2)
212
220
  assert np.allclose(cs.decrypt(c6), [a * b for a, b in zip(t1, t3)], rtol=1e-2)
221
+ assert np.allclose(cs.decrypt(c7)[0], sum([a * b for a, b in zip(t1, t3)]), rtol=1e-2)
213
222
  ```
214
223
 
215
224
  # Contributing
@@ -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/).
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/).
24
24
 
25
25
  # Partially vs Fully Homomorphic Encryption
26
26
 
@@ -51,18 +51,20 @@ from lightphe import LightPHE
51
51
 
52
52
  In summary, LightPHE is covering following algorithms and these are partially homomorphic with respect to the operations mentioned in the following table.
53
53
 
54
- | Algorithm | Multiplicatively<br>Homomorphic | Additively<br>Homomorphic | Scalar Multiplication | Exclusively<br>Homomorphic | Regeneration<br>of Ciphertext |
55
- | --- | --- | --- | --- | --- | --- |
56
- | RSA | ✅ | ❌ | ❌ | ❌ | ❌ |
57
- | ElGamal | ✅ | ❌ | ❌ | ❌ | ✅ |
58
- | Exponential ElGamal | ❌ | ✅ | ✅ | ❌ | ✅ |
59
- | Elliptic Curve ElGamal | ❌ | ✅ | ✅ | ❌ | ❌ |
60
- | Paillier | ❌ | ✅ | ✅ | ❌ | ✅ |
61
- | Damgard-Jurik | ❌ | ✅ | ✅ | ❌ | ✅ |
62
- | Benaloh | ❌ | ✅ | ✅ | ❌ | ✅ |
63
- | Naccache-Stern | ❌ | ✅ | ✅ | ❌ | ✅ |
64
- | Okamoto-Uchiyama | ❌ | ✅ | ✅ | ❌ | ✅ |
65
- | Goldwasser-Micali | ❌ | ❌ | ❌ | ✅ | ❌ |
54
+ | Algorithm | Multiplicatively<br>Homomorphic | Additively<br>Homomorphic | Scalar Multiplication | Bitwise-XOR Homomorphic | Bitwise-AND Homomorphic | Regeneration<br>of Ciphertext |
55
+ | --- | --- | --- | --- | --- | --- | --- |
56
+ | RSA | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
57
+ | ElGamal | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ |
58
+ | Exponential ElGamal | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
59
+ | Elliptic Curve ElGamal | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
60
+ | Paillier | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
61
+ | Damgard-Jurik | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
62
+ | Benaloh | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
63
+ | Naccache-Stern | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
64
+ | Okamoto-Uchiyama | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
65
+ | Goldwasser-Micali | ❌ | ❌ | ❌ | ✅ | ❌ | ✅ |
66
+ | Sander-Young-Yung | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ |
67
+ | Boneh-Goh-Nissim | 1️⃣ | ✅ | ✅ | ❌ | ❌ | ✅ |
66
68
 
67
69
  # Building cryptosystem
68
70
 
@@ -79,7 +81,9 @@ algorithms = [
79
81
  "Benaloh",
80
82
  "Naccache-Stern",
81
83
  "Goldwasser-Micali",
82
- "EllipticCurve-ElGamal"
84
+ "EllipticCurve-ElGamal",
85
+ "Sander-Young-Yung",
86
+ "Boneh-Goh-Nissim",
83
87
  ]
84
88
 
85
89
  cs = LightPHE(algorithm_name = algorithms[0])
@@ -113,7 +117,7 @@ assert cs.decrypt(c3) == m1 + m2
113
117
  assert cs.decrypt(c4) == k * m1
114
118
  ```
115
119
 
116
- On the other hand, if you adopt a multiplicatively homomorphic cryptosyste (e.g. RSA or ElGamal), you can multiply ciphertexts without revealing the private key or the plaintext.
120
+ On the other hand, if you adopt a multiplicatively homomorphic cryptosystem (e.g. RSA or ElGamal), you can multiply ciphertexts without revealing the private key or the plaintext.
117
121
 
118
122
  ```python
119
123
  # build a multiplicatively homomorphic cryptosystem
@@ -136,7 +140,7 @@ assert cs.decrypt(c3) == m1 * m2
136
140
 
137
141
  ### Ciphertext Regeneration
138
142
 
139
- Similar to the most of additively homomorphic algorithms, Paillier lets you to regenerate ciphertext while you are not breaking its plaintext restoration. You may consider to do this re-generation many times to have stronger ciphertexts.
143
+ The most of additively homomorphic algorithms allow you to regenerate ciphertext while you are not breaking its plaintext restoration. You may consider to do this re-generation many times to have stronger ciphertexts.
140
144
 
141
145
  ```python
142
146
  c1_prime = cs.regenerate_ciphertext(c1)
@@ -147,7 +151,7 @@ assert cs.decrypt(c1) == m1
147
151
 
148
152
  ### Elliptic Curve Cryptography
149
153
 
150
- ECC is a powerful public-key cryptosystem based on the algebraic structure of elliptic curves over finite fields. The library supports 3 elliptic curve forms (weierstrass, edwards and koblitz) and 100+ standard elliptic curve configurations.
154
+ ECC is a powerful public-key cryptosystem based on the algebraic structure of elliptic curves over finite fields. The library supports 3 elliptic curve forms (weierstrass (default), edwards and koblitz) and 100+ standard elliptic curve configurations.
151
155
 
152
156
  In LightPHE, the [Elliptic Curve ElGamal](https://sefiks.com/2018/08/21/elliptic-curve-elgamal-encryption/) scheme is implemented, offering a secure and efficient homomorphic encryption option.
153
157
 
@@ -155,7 +159,8 @@ In LightPHE, the [Elliptic Curve ElGamal](https://sefiks.com/2018/08/21/elliptic
155
159
  forms = ["weierstrass", "edwards", "koblitz"]
156
160
  phe = LightPHE(
157
161
  algorithm_name="EllipticCurve-ElGamal",
158
- form=forms[1],
162
+ form="edwards",
163
+ # curve="ed448", # optinally you can specify the curve for given form
159
164
  )
160
165
  ```
161
166
 
@@ -188,12 +193,16 @@ c4 = c1 + c2
188
193
  c5 = 3 * c1
189
194
 
190
195
  # perform element-wise multiplication between an encrypted embedding and plain embedding
191
- c6 = c1 * t3 # Encrypted-plaintext multiplication
196
+ c6 = c1 * t3
197
+
198
+ # encrypted dot product (likewise cosine similarity)
199
+ c7 = c1 @ t3
192
200
 
193
201
  # proof of work
194
202
  assert np.allclose(cs.decrypt(c4), [a + b for a, b in zip(t1, t2)], rtol=1e-2)
195
203
  assert np.allclose(cs.decrypt(c5), [a * 3 for a in t1], rtol=1e-2)
196
204
  assert np.allclose(cs.decrypt(c6), [a * b for a, b in zip(t1, t3)], rtol=1e-2)
205
+ assert np.allclose(cs.decrypt(c7)[0], sum([a * b for a, b in zip(t1, t3)]), rtol=1e-2)
197
206
  ```
198
207
 
199
208
  # Contributing
@@ -28,13 +28,15 @@ from lightphe.cryptosystems.Benaloh import Benaloh
28
28
  from lightphe.cryptosystems.NaccacheStern import NaccacheStern
29
29
  from lightphe.cryptosystems.GoldwasserMicali import GoldwasserMicali
30
30
  from lightphe.cryptosystems.EllipticCurveElGamal import EllipticCurveElGamal
31
+ from lightphe.cryptosystems.SanderYoungYung import SanderYoungYung
32
+ from lightphe.cryptosystems.BonehGohNissim import BonehGohNissim
31
33
 
32
34
 
33
35
  # pylint: disable=eval-used, simplifiable-if-expression, too-few-public-methods
34
36
 
35
37
  logger = Logger(module="lightphe/__init__.py")
36
38
 
37
- VERSION = "0.0.18"
39
+ VERSION = "0.0.22"
38
40
 
39
41
 
40
42
  class LightPHE:
@@ -50,13 +52,14 @@ class LightPHE:
50
52
  form: Optional[str] = None,
51
53
  curve: Optional[str] = None,
52
54
  plaintext_limit: Optional[int] = None,
55
+ max_tries: int = 10000,
53
56
  ):
54
57
  """
55
58
  Build LightPHE class
56
59
  Args:
57
60
  algorithm_name (str): RSA | ElGamal | Exponential-ElGamal | EllipticCurve-ElGamal
58
61
  | Paillier | Damgard-Jurik | Okamoto-Uchiyama | Benaloh | Naccache-Stern
59
- | Goldwasser-Micali
62
+ | Goldwasser-Micali | Sander-Young-Yung | Boneh-Goh-Nissim
60
63
  keys (dict): optional private-public key pair
61
64
  key_file (str): if keys were exported already, you can load them into cryptosystem
62
65
  key_size (int): key size in bits
@@ -74,6 +77,10 @@ class LightPHE:
74
77
  This parameter is only used if `algorithm_name` is 'EllipticCurve-ElGamal'.
75
78
  plaintext_limit (int, optional): Upper bound for plaintext values.
76
79
  This parameter is only used if `algorithm_name` is 'Benaloh'.
80
+ max_tries (int): maximum attempts to generate keys. Default is 10000.
81
+ RSA, Benaloh, Naccache-Stern and Goldwasser-Micali algorithms
82
+ need multiple attempts to generate valid keys. Will be discarded
83
+ for other algorithms.
77
84
  """
78
85
  self.algorithm_name = algorithm_name
79
86
  self.precision = precision
@@ -90,6 +97,7 @@ class LightPHE:
90
97
  form=form,
91
98
  curve=curve,
92
99
  plaintext_limit=plaintext_limit,
100
+ max_tries=max_tries,
93
101
  )
94
102
 
95
103
  def __build_cryptosystem(
@@ -100,6 +108,7 @@ class LightPHE:
100
108
  form: Optional[str] = None,
101
109
  curve: Optional[str] = None,
102
110
  plaintext_limit: Optional[int] = None,
111
+ max_tries: int = 10000,
103
112
  ) -> Union[
104
113
  RSA,
105
114
  ElGamal,
@@ -109,13 +118,15 @@ class LightPHE:
109
118
  Benaloh,
110
119
  NaccacheStern,
111
120
  EllipticCurveElGamal,
121
+ SanderYoungYung,
122
+ BonehGohNissim,
112
123
  ]:
113
124
  """
114
125
  Build a cryptosystem among partially homomorphic algorithms
115
126
  Args:
116
127
  algorithm_name (str): RSA | ElGamal | Exponential-ElGamal | EllipticCurve-ElGamal
117
128
  | Paillier | Damgard-Jurik | Okamoto-Uchiyama | Benaloh | Naccache-Stern
118
- | Goldwasser-Micali | Edwards-ElGamal
129
+ | Goldwasser-Micali | Edwards-ElGamal | Sander-Young-Yung | Boneh-Goh-Nissim
119
130
  Default is Paillier.
120
131
  keys (dict): optional private-public key pair
121
132
  key_file (str): if keys are exported, you can load them into cryptosystem
@@ -128,12 +139,18 @@ class LightPHE:
128
139
  - ed25519, ed448 for edwards form
129
140
  - secp256k1 for weierstrass form
130
141
  This parameter is only used if `algorithm_name` is 'EllipticCurve-ElGamal'.
142
+ plaintext_limit (int, optional): Upper bound for plaintext values.
143
+ This parameter is only used if `algorithm_name` is 'Benaloh'.
144
+ max_tries (int): maximum attempts to generate keys. Default is 10000.
145
+ RSA, Benaloh, Naccache-Stern and Goldwasser-Micali algorithms
146
+ need multiple attempts to generate valid keys. Will be discarded
147
+ for other algorithms.
131
148
  Returns
132
149
  cryptosystem
133
150
  """
134
151
  # build cryptosystem
135
152
  if algorithm_name == Algorithm.RSA:
136
- cs = RSA(keys=keys, key_size=key_size)
153
+ cs = RSA(keys=keys, key_size=key_size, max_tries=max_tries)
137
154
  elif algorithm_name == Algorithm.ElGamal:
138
155
  cs = ElGamal(keys=keys, key_size=key_size)
139
156
  elif algorithm_name == Algorithm.ExponentialElGamal:
@@ -149,11 +166,22 @@ class LightPHE:
149
166
  elif algorithm_name == Algorithm.OkamotoUchiyama:
150
167
  cs = OkamotoUchiyama(keys=keys, key_size=key_size)
151
168
  elif algorithm_name == Algorithm.Benaloh:
152
- cs = Benaloh(keys=keys, key_size=key_size, plaintext_limit=plaintext_limit)
169
+ cs = Benaloh(
170
+ keys=keys,
171
+ key_size=key_size,
172
+ plaintext_limit=plaintext_limit,
173
+ max_tries=max_tries,
174
+ )
153
175
  elif algorithm_name == Algorithm.NaccacheStern:
154
- cs = NaccacheStern(keys=keys, key_size=key_size)
176
+ cs = NaccacheStern(keys=keys, key_size=key_size, max_tries=max_tries)
155
177
  elif algorithm_name == Algorithm.GoldwasserMicali:
156
- cs = GoldwasserMicali(keys=keys, key_size=key_size)
178
+ cs = GoldwasserMicali(keys=keys, key_size=key_size, max_tries=max_tries)
179
+ elif algorithm_name == Algorithm.SanderYoungYung:
180
+ cs = SanderYoungYung(
181
+ keys=keys, key_size=key_size, plaintext_limit=plaintext_limit
182
+ )
183
+ elif algorithm_name == Algorithm.BonehGohNissim:
184
+ cs = BonehGohNissim(keys=keys, key_size=key_size, max_tries=max_tries)
157
185
  else:
158
186
  raise ValueError(f"unimplemented algorithm - {algorithm_name}")
159
187
  return cs
@@ -23,6 +23,10 @@ def normalize_input(value: Union[int, float], modulo: Union[int, str]) -> int:
23
23
  # elliptic curve elgamal & koblitz curves
24
24
  result = value % int(modulo, 2)
25
25
  elif isinstance(value, int) and isinstance(modulo, int):
26
+ if value > modulo:
27
+ logger.warn(
28
+ f"Value {value} is greater than modulo {modulo}. Normalizing it to be in the range of modulo."
29
+ )
26
30
  result = value % modulo
27
31
  elif isinstance(value, float) and value >= 0:
28
32
  dividend, divisor = fractionize(value=value, modulo=modulo)
@@ -20,6 +20,7 @@ class Benaloh(Homomorphic):
20
20
  keys: Optional[dict] = None,
21
21
  key_size: Optional[int] = None,
22
22
  plaintext_limit: Optional[int] = None,
23
+ max_tries: int = 10000,
23
24
  ):
24
25
  """
25
26
  Args:
@@ -29,9 +30,12 @@ class Benaloh(Homomorphic):
29
30
  plaintext_limit (int, optional): Upper bound for plaintext values.
30
31
  If provided, r is set to the next prime greater than this value;
31
32
  otherwise, r is chosen randomly from a default range.
33
+ max_tries (int): maximum attempts to generate keys.
32
34
  """
33
35
  self.keys = keys or self.generate_keys(
34
- key_size=key_size or 1024, plaintext_limit=plaintext_limit
36
+ key_size=key_size or 1024,
37
+ plaintext_limit=plaintext_limit,
38
+ max_tries=max_tries,
35
39
  )
36
40
  self.plaintext_modulo = self.keys["public_key"]["r"]
37
41
  self.ciphertext_modulo = self.keys["public_key"]["n"]