lightphe 0.0.6__tar.gz → 0.0.8__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 (47) hide show
  1. {lightphe-0.0.6 → lightphe-0.0.8}/PKG-INFO +86 -22
  2. {lightphe-0.0.6 → lightphe-0.0.8}/README.md +85 -21
  3. {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/__init__.py +2 -2
  4. {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/cryptosystems/ElGamal.py +9 -2
  5. {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/cryptosystems/GoldwasserMicali.py +6 -1
  6. {lightphe-0.0.6 → lightphe-0.0.8}/lightphe.egg-info/PKG-INFO +86 -22
  7. {lightphe-0.0.6 → lightphe-0.0.8}/setup.py +1 -1
  8. {lightphe-0.0.6 → lightphe-0.0.8}/LICENSE +0 -0
  9. {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/commons/__init__.py +0 -0
  10. {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/commons/logger.py +0 -0
  11. {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/commons/phe_utils.py +0 -0
  12. {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/cryptosystems/Benaloh.py +0 -0
  13. {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/cryptosystems/DamgardJurik.py +0 -0
  14. {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/cryptosystems/EllipticCurveElGamal.py +0 -0
  15. {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/cryptosystems/NaccacheStern.py +0 -0
  16. {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/cryptosystems/OkamotoUchiyama.py +0 -0
  17. {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/cryptosystems/Paillier.py +0 -0
  18. {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/cryptosystems/RSA.py +0 -0
  19. {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/cryptosystems/__init__.py +0 -0
  20. {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/elliptic/Weierstrass.py +0 -0
  21. {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/elliptic/__init__.py +0 -0
  22. {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/models/Algorithm.py +0 -0
  23. {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/models/Ciphertext.py +0 -0
  24. {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/models/EllipticCurve.py +0 -0
  25. {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/models/Homomorphic.py +0 -0
  26. {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/models/Tensor.py +0 -0
  27. {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/models/__init__.py +0 -0
  28. {lightphe-0.0.6 → lightphe-0.0.8}/lightphe.egg-info/SOURCES.txt +0 -0
  29. {lightphe-0.0.6 → lightphe-0.0.8}/lightphe.egg-info/dependency_links.txt +0 -0
  30. {lightphe-0.0.6 → lightphe-0.0.8}/lightphe.egg-info/requires.txt +0 -0
  31. {lightphe-0.0.6 → lightphe-0.0.8}/lightphe.egg-info/top_level.txt +0 -0
  32. {lightphe-0.0.6 → lightphe-0.0.8}/requirements.txt +0 -0
  33. {lightphe-0.0.6 → lightphe-0.0.8}/setup.cfg +0 -0
  34. {lightphe-0.0.6 → lightphe-0.0.8}/tests/__init__.py +0 -0
  35. {lightphe-0.0.6 → lightphe-0.0.8}/tests/test_benaloh.py +0 -0
  36. {lightphe-0.0.6 → lightphe-0.0.8}/tests/test_cloud.py +0 -0
  37. {lightphe-0.0.6 → lightphe-0.0.8}/tests/test_damgard.py +0 -0
  38. {lightphe-0.0.6 → lightphe-0.0.8}/tests/test_elgamal.py +0 -0
  39. {lightphe-0.0.6 → lightphe-0.0.8}/tests/test_ellipticcurveelgamal.py +0 -0
  40. {lightphe-0.0.6 → lightphe-0.0.8}/tests/test_exporting_keys.py +0 -0
  41. {lightphe-0.0.6 → lightphe-0.0.8}/tests/test_goldwasser.py +0 -0
  42. {lightphe-0.0.6 → lightphe-0.0.8}/tests/test_naccache.py +0 -0
  43. {lightphe-0.0.6 → lightphe-0.0.8}/tests/test_okamoto.py +0 -0
  44. {lightphe-0.0.6 → lightphe-0.0.8}/tests/test_paillier.py +0 -0
  45. {lightphe-0.0.6 → lightphe-0.0.8}/tests/test_rsa.py +0 -0
  46. {lightphe-0.0.6 → lightphe-0.0.8}/tests/test_salary.py +0 -0
  47. {lightphe-0.0.6 → lightphe-0.0.8}/tests/test_tensors.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lightphe
3
- Version: 0.0.6
3
+ Version: 0.0.8
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
@@ -18,16 +18,19 @@ License-File: LICENSE
18
18
 
19
19
  <div align="center">
20
20
 
21
- [![PyPI Downloads](https://static.pepy.tech/personalized-badge/lightphe?period=total&units=international_system&left_color=grey&right_color=blue&left_text=pypi%20downloads)](https://pepy.tech/project/lightphe)
21
+ [![PyPI Downloads](https://static.pepy.tech/personalized-badge/lightphe?period=total&units=international_system&left_color=grey&right_color=blue&left_text=downloads)](https://pepy.tech/project/lightphe)
22
22
  [![Stars](https://img.shields.io/github/stars/serengil/LightPHE?color=yellow&style=flat&label=%E2%AD%90%20stars)](https://github.com/serengil/LightPHE/stargazers)
23
23
  [![Tests](https://github.com/serengil/LightPHE/actions/workflows/tests.yml/badge.svg)](https://github.com/serengil/LightPHE/actions/workflows/tests.yml)
24
24
  [![License](http://img.shields.io/:license-MIT-green.svg?style=flat)](https://github.com/serengil/LightPHE/blob/master/LICENSE)
25
- [![Support me on Patreon](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fshieldsio-patreon.vercel.app%2Fapi%3Fusername%3Dserengil%26type%3Dpatrons&style=flat)](https://www.patreon.com/serengil?repo=lightphe)
26
- [![GitHub Sponsors](https://img.shields.io/github/sponsors/serengil?logo=GitHub&color=lightgray)](https://github.com/sponsors/serengil)
25
+ [![DOI](http://img.shields.io/:DOI-10.48550/arXiv.2408.05219-blue.svg?style=flat)](https://arxiv.org/abs/2408.05219)
27
26
 
28
27
  [![Blog](https://img.shields.io/:blog-sefiks.com-blue.svg?style=flat&logo=wordpress)](https://sefiks.com)
29
28
  [![YouTube](https://img.shields.io/:youtube-@sefiks-red.svg?style=flat&logo=youtube)](https://www.youtube.com/@sefiks?sub_confirmation=1)
30
- [![Twitter](https://img.shields.io/:follow-@serengil-blue.svg?style=flat&logo=twitter)](https://twitter.com/intent/user?screen_name=serengil)
29
+ [![Twitter](https://img.shields.io/:follow-@serengil-blue.svg?style=flat&logo=x)](https://twitter.com/intent/user?screen_name=serengil)
30
+
31
+ [![Support me on Patreon](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fshieldsio-patreon.vercel.app%2Fapi%3Fusername%3Dserengil%26type%3Dpatrons&style=flat)](https://www.patreon.com/serengil?repo=lightphe)
32
+ [![GitHub Sponsors](https://img.shields.io/github/sponsors/serengil?logo=GitHub&color=lightgray)](https://github.com/sponsors/serengil)
33
+ [![Buy Me a Coffee](https://img.shields.io/badge/-buy_me_a%C2%A0coffee-gray?logo=buy-me-a-coffee)](https://buymeacoffee.com/serengil)
31
34
 
32
35
  </div>
33
36
 
@@ -109,47 +112,99 @@ m = 17
109
112
  # calculate ciphertext
110
113
  c = cs.encrypt(m)
111
114
 
115
+ # proof of work
112
116
  assert cs.decrypt(c) == m
113
117
  ```
114
118
 
115
119
  # Homomorphic Operations
116
120
 
117
- Once you have the ciphertext, you will be able to perform homomorphic operations on encrypted data. For instance, Paillier is homomorphic with respect to the addition. In other words, decryption of the addition of two ciphertexts is equivalent to addition of plaintexts.
121
+ Once you have the ciphertext, you will be able to perform homomorphic operations on encrypted data without holding private key. For instance, Paillier is homomorphic with respect to the addition. In other words, decryption of the addition of two ciphertexts is equivalent to addition of plaintexts.
122
+
123
+ ### On-Prem Encryption
124
+
125
+ This Python code snippet demonstrates how to generate a private-public key pair using the Paillier cryptosystem via the LightPHE library. First, an instance of the LightPHE class is created with the Paillier algorithm. Then, the public key is exported and saved to a file named "public.txt" to build the same cryptosystem with only public key in the cloud side later. The code defines two plaintext values, m1 and m2, respectively. These plaintext values are encrypted to generate ciphertexts c1 and c2 using the public key. Finally, the ciphertexts c1 and c2 are prepared to be sent to a cloud system for secure processing or storage.
118
126
 
119
127
  ```python
128
+ # generate private-public key pair
120
129
  cs = LightPHE(algorithm_name = "Paillier")
121
130
 
131
+ # export public key to build same cryptosystem with only public key in the cloud
132
+ cs.export_keys(target_file = "public.txt", public = True)
133
+
134
+ # export private key to build same cryptosystem on-prem later
135
+ cs.export_keys(target_file = "private.txt", public = False)
136
+
122
137
  # define plaintexts
123
138
  m1 = 17
124
139
  m2 = 23
125
140
 
126
141
  # calculate ciphertexts
127
- c1 = cs.encrypt(m1)
128
- c2 = cs.encrypt(m2)
142
+ c1 = cs.encrypt(m1).value
143
+ c2 = cs.encrypt(m2).value
144
+
145
+ # send c1 and c2 pair to a cloud system
146
+ ```
147
+
148
+ ### Homomorphic Operations on Cloud
149
+
150
+ This Python code snippet illustrates how to handle encrypted data on the cloud side using the Paillier cryptosystem with the LightPHE library. Upon receiving the encrypted values c1 and c2, the cloud system initializes the cryptosystem using the exported public key stored in public.txt. To ensure the security of the data, a test is performed to confirm that the cloud system cannot decrypt c1 and c2 without the private key. This is done using the pytest library, which raises a ValueError if decryption is attempted, verifying that decryption is not possible without the private key. Finally, the code demonstrates homomorphic addition by adding the two ciphertexts, resulting in a new ciphertext c3 that represents the encrypted sum of the original plaintext values.
151
+
152
+ ```python
153
+ # cloud side receives encrypted c1 and c2
154
+
155
+ # restore cryptosystem with the exported public key
156
+ cs = LightPHE(algorithm_name = "Paillier", key_file = "public.txt")
129
157
 
130
- # homomorphic addition - private key is not required!
158
+ # convert c1 and c2 to ciphertext objects
159
+ c1 = cs.create_ciphertext_obj(c1)
160
+ c2 = cs.create_ciphertext_obj(c2)
161
+
162
+ # confirm that cloud cannot decrypt c1
163
+ with pytest.raises(ValueError, match="You must have private key to perform decryption"):
164
+ cs.decrypt(c1)
165
+
166
+ # confirm that cloud cannot decrypt c2
167
+ with pytest.raises(ValueError, match="You must have private key to perform decryption"):
168
+ cs.decrypt(c2)
169
+
170
+ # homomorphic addition - private key not required
131
171
  c3 = c1 + c2
132
172
 
133
- # proof of work
173
+ # confirm that cloud cannot decrypt c3
174
+ with pytest.raises(ValueError, match="You must have private key to perform decryption"):
175
+ cs.decrypt(c3)
176
+ ```
177
+
178
+ ### On-Prem Decryption
179
+
180
+ This Python code snippet demonstrates the final step in a secure computation process using homomorphic encryption with the LightPHE library. After receiving the ciphertext c3 from the cloud, which is the result of homomorphic addition of two ciphertexts c1 and c2, the on-premises system (which has the private key) decrypts c3 to verify the result. The decrypted value is then asserted to be equal to the sum of the original plaintext values m1 and m2. This step ensures the correctness of the homomorphic computation performed by the cloud.
181
+
182
+ ```python
183
+ # on-prem side receives c3 from cloud
184
+
185
+ # restore cryptosystem with the exported private key
186
+ cs = LightPHE(algorithm_name = "Paillier", key_file = "private.txt")
187
+
188
+ # proof of work - private key required
134
189
  assert cs.decrypt(c3) == m1 + m2
135
190
  ```
136
191
 
137
- ⚡ Notice that once can perform `c1 + c2` here without holding private key. However, just the data owner with private key can perform encryption and decryption. This is the basic definition of homomorphic encryption.
192
+ ### Scalar Multiplication
138
193
 
139
- Besides, Paillier is supporting multiplying ciphertexts by a known plain constant. Simply put, decryption of scalar multiplication of ciphertext is equivalent to that constant times plaintext as well.
194
+ Besides, Paillier is supporting multiplying ciphertexts by a known plain constant. This Python code snippet demonstrates how to perform scalar multiplication on encrypted data using homomorphic encryption with the LightPHE library. The factor k is set to 1.05, representing a 5% increase. On the cloud side, this factor is used to multiply the ciphertext c1, resulting in a new ciphertext c4. When the on-premises system, which holds the private key, receives c4, it decrypts it and verifies that the decrypted value matches the original plaintext m1 scaled by k (i.e., 1.05 * m1). This ensures that the homomorphic scalar multiplication was performed correctly on the encrypted data.
140
195
 
141
196
  ```python
142
197
  # increasing something 5%
143
198
  k = 1.05
144
199
 
145
- # scalar multiplication - private key is not required!
200
+ # scalar multiplication - cloud (private key is not required)
146
201
  c4 = k * c1
147
202
 
148
- # proof of work
203
+ # proof of work on-prem - private key is required
149
204
  assert cs.decrypt(c4) == k * m1
150
205
  ```
151
206
 
152
- ⚡ Herein, `k * c1` operation can be performed by anyone without holding private key.
207
+ ### Ciphertext Regeneration
153
208
 
154
209
  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.
155
210
 
@@ -160,6 +215,8 @@ assert cs.decrypt(c1_prime) == m1
160
215
  assert cs.decrypt(c1) == m1
161
216
  ```
162
217
 
218
+ ### Unsupported Operations
219
+
163
220
  Finally, if you try to perform an operation that algorithm does not support, then an exception will be thrown. For instance, Paillier is not homomorphic with respect to the multiplication or xor. To put it simply, you cannot multiply two ciphertexts. If you enforce this calculation, you will have an exception.
164
221
 
165
222
  ```python
@@ -229,23 +286,30 @@ You should be able run `make test` and `make lint` commands successfully before
229
286
 
230
287
  There are many ways to support a project - starring⭐️ the GitHub repo is just one 🙏
231
288
 
232
- You can also support this work on [Patreon](https://www.patreon.com/serengil?repo=lightphe) or [GitHub Sponsors](https://github.com/sponsors/serengil).
289
+ You can also support this work on [Patreon](https://www.patreon.com/serengil?repo=lightphe), [GitHub Sponsors](https://github.com/sponsors/serengil) or [Buy Me a Coffee](https://buymeacoffee.com/serengil).
233
290
 
234
291
  <a href="https://www.patreon.com/serengil?repo=lightphe">
235
292
  <img src="https://raw.githubusercontent.com/serengil/LightPHE/master/icons/patreon.png" width="30%" height="30%">
236
293
  </a>
237
294
 
295
+ <a href="https://buymeacoffee.com/serengil">
296
+ <img src="https://raw.githubusercontent.com/serengil/LightPHE/master/icons/bmc-button.png" width="25%" height="25%">
297
+ </a>
298
+
299
+ Also, your company's logo will be shown on README on GitHub if you become sponsor in gold, silver or bronze tiers.
300
+
238
301
  # Citation
239
302
 
240
303
  Please cite LightPHE in your publications if it helps your research. Here is its BibTex entry:
241
304
 
242
305
  ```BibTeX
243
- @misc{serengil2023lightphe,
244
- abstract = {A Lightweight Partially Homomorphic Encryption Library for Python},
245
- author = {Serengil, Sefik Ilkin},
246
- title = {LightPHE},
247
- howpublished = {https://github.com/serengil/LightPHE},
248
- year = {2023}
306
+ @misc{serengil2024lightphe,
307
+ title = {LightPHE: Integrating Partially Homomorphic Encryption into Python with Extensive Cloud Environment Evaluations},
308
+ author = {Serengil, Sefik Ilkin and Ozpinar, Alper},
309
+ year = {2024},
310
+ publisher = {arXiv},
311
+ url = {https://arxiv.org/abs/2408.05219},
312
+ doi = {10.48550/arXiv.2408.05219}
249
313
  }
250
314
  ```
251
315
 
@@ -2,16 +2,19 @@
2
2
 
3
3
  <div align="center">
4
4
 
5
- [![PyPI Downloads](https://static.pepy.tech/personalized-badge/lightphe?period=total&units=international_system&left_color=grey&right_color=blue&left_text=pypi%20downloads)](https://pepy.tech/project/lightphe)
5
+ [![PyPI Downloads](https://static.pepy.tech/personalized-badge/lightphe?period=total&units=international_system&left_color=grey&right_color=blue&left_text=downloads)](https://pepy.tech/project/lightphe)
6
6
  [![Stars](https://img.shields.io/github/stars/serengil/LightPHE?color=yellow&style=flat&label=%E2%AD%90%20stars)](https://github.com/serengil/LightPHE/stargazers)
7
7
  [![Tests](https://github.com/serengil/LightPHE/actions/workflows/tests.yml/badge.svg)](https://github.com/serengil/LightPHE/actions/workflows/tests.yml)
8
8
  [![License](http://img.shields.io/:license-MIT-green.svg?style=flat)](https://github.com/serengil/LightPHE/blob/master/LICENSE)
9
- [![Support me on Patreon](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fshieldsio-patreon.vercel.app%2Fapi%3Fusername%3Dserengil%26type%3Dpatrons&style=flat)](https://www.patreon.com/serengil?repo=lightphe)
10
- [![GitHub Sponsors](https://img.shields.io/github/sponsors/serengil?logo=GitHub&color=lightgray)](https://github.com/sponsors/serengil)
9
+ [![DOI](http://img.shields.io/:DOI-10.48550/arXiv.2408.05219-blue.svg?style=flat)](https://arxiv.org/abs/2408.05219)
11
10
 
12
11
  [![Blog](https://img.shields.io/:blog-sefiks.com-blue.svg?style=flat&logo=wordpress)](https://sefiks.com)
13
12
  [![YouTube](https://img.shields.io/:youtube-@sefiks-red.svg?style=flat&logo=youtube)](https://www.youtube.com/@sefiks?sub_confirmation=1)
14
- [![Twitter](https://img.shields.io/:follow-@serengil-blue.svg?style=flat&logo=twitter)](https://twitter.com/intent/user?screen_name=serengil)
13
+ [![Twitter](https://img.shields.io/:follow-@serengil-blue.svg?style=flat&logo=x)](https://twitter.com/intent/user?screen_name=serengil)
14
+
15
+ [![Support me on Patreon](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fshieldsio-patreon.vercel.app%2Fapi%3Fusername%3Dserengil%26type%3Dpatrons&style=flat)](https://www.patreon.com/serengil?repo=lightphe)
16
+ [![GitHub Sponsors](https://img.shields.io/github/sponsors/serengil?logo=GitHub&color=lightgray)](https://github.com/sponsors/serengil)
17
+ [![Buy Me a Coffee](https://img.shields.io/badge/-buy_me_a%C2%A0coffee-gray?logo=buy-me-a-coffee)](https://buymeacoffee.com/serengil)
15
18
 
16
19
  </div>
17
20
 
@@ -93,47 +96,99 @@ m = 17
93
96
  # calculate ciphertext
94
97
  c = cs.encrypt(m)
95
98
 
99
+ # proof of work
96
100
  assert cs.decrypt(c) == m
97
101
  ```
98
102
 
99
103
  # Homomorphic Operations
100
104
 
101
- Once you have the ciphertext, you will be able to perform homomorphic operations on encrypted data. For instance, Paillier is homomorphic with respect to the addition. In other words, decryption of the addition of two ciphertexts is equivalent to addition of plaintexts.
105
+ Once you have the ciphertext, you will be able to perform homomorphic operations on encrypted data without holding private key. For instance, Paillier is homomorphic with respect to the addition. In other words, decryption of the addition of two ciphertexts is equivalent to addition of plaintexts.
106
+
107
+ ### On-Prem Encryption
108
+
109
+ This Python code snippet demonstrates how to generate a private-public key pair using the Paillier cryptosystem via the LightPHE library. First, an instance of the LightPHE class is created with the Paillier algorithm. Then, the public key is exported and saved to a file named "public.txt" to build the same cryptosystem with only public key in the cloud side later. The code defines two plaintext values, m1 and m2, respectively. These plaintext values are encrypted to generate ciphertexts c1 and c2 using the public key. Finally, the ciphertexts c1 and c2 are prepared to be sent to a cloud system for secure processing or storage.
102
110
 
103
111
  ```python
112
+ # generate private-public key pair
104
113
  cs = LightPHE(algorithm_name = "Paillier")
105
114
 
115
+ # export public key to build same cryptosystem with only public key in the cloud
116
+ cs.export_keys(target_file = "public.txt", public = True)
117
+
118
+ # export private key to build same cryptosystem on-prem later
119
+ cs.export_keys(target_file = "private.txt", public = False)
120
+
106
121
  # define plaintexts
107
122
  m1 = 17
108
123
  m2 = 23
109
124
 
110
125
  # calculate ciphertexts
111
- c1 = cs.encrypt(m1)
112
- c2 = cs.encrypt(m2)
126
+ c1 = cs.encrypt(m1).value
127
+ c2 = cs.encrypt(m2).value
128
+
129
+ # send c1 and c2 pair to a cloud system
130
+ ```
131
+
132
+ ### Homomorphic Operations on Cloud
133
+
134
+ This Python code snippet illustrates how to handle encrypted data on the cloud side using the Paillier cryptosystem with the LightPHE library. Upon receiving the encrypted values c1 and c2, the cloud system initializes the cryptosystem using the exported public key stored in public.txt. To ensure the security of the data, a test is performed to confirm that the cloud system cannot decrypt c1 and c2 without the private key. This is done using the pytest library, which raises a ValueError if decryption is attempted, verifying that decryption is not possible without the private key. Finally, the code demonstrates homomorphic addition by adding the two ciphertexts, resulting in a new ciphertext c3 that represents the encrypted sum of the original plaintext values.
135
+
136
+ ```python
137
+ # cloud side receives encrypted c1 and c2
138
+
139
+ # restore cryptosystem with the exported public key
140
+ cs = LightPHE(algorithm_name = "Paillier", key_file = "public.txt")
113
141
 
114
- # homomorphic addition - private key is not required!
142
+ # convert c1 and c2 to ciphertext objects
143
+ c1 = cs.create_ciphertext_obj(c1)
144
+ c2 = cs.create_ciphertext_obj(c2)
145
+
146
+ # confirm that cloud cannot decrypt c1
147
+ with pytest.raises(ValueError, match="You must have private key to perform decryption"):
148
+ cs.decrypt(c1)
149
+
150
+ # confirm that cloud cannot decrypt c2
151
+ with pytest.raises(ValueError, match="You must have private key to perform decryption"):
152
+ cs.decrypt(c2)
153
+
154
+ # homomorphic addition - private key not required
115
155
  c3 = c1 + c2
116
156
 
117
- # proof of work
157
+ # confirm that cloud cannot decrypt c3
158
+ with pytest.raises(ValueError, match="You must have private key to perform decryption"):
159
+ cs.decrypt(c3)
160
+ ```
161
+
162
+ ### On-Prem Decryption
163
+
164
+ This Python code snippet demonstrates the final step in a secure computation process using homomorphic encryption with the LightPHE library. After receiving the ciphertext c3 from the cloud, which is the result of homomorphic addition of two ciphertexts c1 and c2, the on-premises system (which has the private key) decrypts c3 to verify the result. The decrypted value is then asserted to be equal to the sum of the original plaintext values m1 and m2. This step ensures the correctness of the homomorphic computation performed by the cloud.
165
+
166
+ ```python
167
+ # on-prem side receives c3 from cloud
168
+
169
+ # restore cryptosystem with the exported private key
170
+ cs = LightPHE(algorithm_name = "Paillier", key_file = "private.txt")
171
+
172
+ # proof of work - private key required
118
173
  assert cs.decrypt(c3) == m1 + m2
119
174
  ```
120
175
 
121
- ⚡ Notice that once can perform `c1 + c2` here without holding private key. However, just the data owner with private key can perform encryption and decryption. This is the basic definition of homomorphic encryption.
176
+ ### Scalar Multiplication
122
177
 
123
- Besides, Paillier is supporting multiplying ciphertexts by a known plain constant. Simply put, decryption of scalar multiplication of ciphertext is equivalent to that constant times plaintext as well.
178
+ Besides, Paillier is supporting multiplying ciphertexts by a known plain constant. This Python code snippet demonstrates how to perform scalar multiplication on encrypted data using homomorphic encryption with the LightPHE library. The factor k is set to 1.05, representing a 5% increase. On the cloud side, this factor is used to multiply the ciphertext c1, resulting in a new ciphertext c4. When the on-premises system, which holds the private key, receives c4, it decrypts it and verifies that the decrypted value matches the original plaintext m1 scaled by k (i.e., 1.05 * m1). This ensures that the homomorphic scalar multiplication was performed correctly on the encrypted data.
124
179
 
125
180
  ```python
126
181
  # increasing something 5%
127
182
  k = 1.05
128
183
 
129
- # scalar multiplication - private key is not required!
184
+ # scalar multiplication - cloud (private key is not required)
130
185
  c4 = k * c1
131
186
 
132
- # proof of work
187
+ # proof of work on-prem - private key is required
133
188
  assert cs.decrypt(c4) == k * m1
134
189
  ```
135
190
 
136
- ⚡ Herein, `k * c1` operation can be performed by anyone without holding private key.
191
+ ### Ciphertext Regeneration
137
192
 
138
193
  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.
139
194
 
@@ -144,6 +199,8 @@ assert cs.decrypt(c1_prime) == m1
144
199
  assert cs.decrypt(c1) == m1
145
200
  ```
146
201
 
202
+ ### Unsupported Operations
203
+
147
204
  Finally, if you try to perform an operation that algorithm does not support, then an exception will be thrown. For instance, Paillier is not homomorphic with respect to the multiplication or xor. To put it simply, you cannot multiply two ciphertexts. If you enforce this calculation, you will have an exception.
148
205
 
149
206
  ```python
@@ -213,23 +270,30 @@ You should be able run `make test` and `make lint` commands successfully before
213
270
 
214
271
  There are many ways to support a project - starring⭐️ the GitHub repo is just one 🙏
215
272
 
216
- You can also support this work on [Patreon](https://www.patreon.com/serengil?repo=lightphe) or [GitHub Sponsors](https://github.com/sponsors/serengil).
273
+ You can also support this work on [Patreon](https://www.patreon.com/serengil?repo=lightphe), [GitHub Sponsors](https://github.com/sponsors/serengil) or [Buy Me a Coffee](https://buymeacoffee.com/serengil).
217
274
 
218
275
  <a href="https://www.patreon.com/serengil?repo=lightphe">
219
276
  <img src="https://raw.githubusercontent.com/serengil/LightPHE/master/icons/patreon.png" width="30%" height="30%">
220
277
  </a>
221
278
 
279
+ <a href="https://buymeacoffee.com/serengil">
280
+ <img src="https://raw.githubusercontent.com/serengil/LightPHE/master/icons/bmc-button.png" width="25%" height="25%">
281
+ </a>
282
+
283
+ Also, your company's logo will be shown on README on GitHub if you become sponsor in gold, silver or bronze tiers.
284
+
222
285
  # Citation
223
286
 
224
287
  Please cite LightPHE in your publications if it helps your research. Here is its BibTex entry:
225
288
 
226
289
  ```BibTeX
227
- @misc{serengil2023lightphe,
228
- abstract = {A Lightweight Partially Homomorphic Encryption Library for Python},
229
- author = {Serengil, Sefik Ilkin},
230
- title = {LightPHE},
231
- howpublished = {https://github.com/serengil/LightPHE},
232
- year = {2023}
290
+ @misc{serengil2024lightphe,
291
+ title = {LightPHE: Integrating Partially Homomorphic Encryption into Python with Extensive Cloud Environment Evaluations},
292
+ author = {Serengil, Sefik Ilkin and Ozpinar, Alper},
293
+ year = {2024},
294
+ publisher = {arXiv},
295
+ url = {https://arxiv.org/abs/2408.05219},
296
+ doi = {10.48550/arXiv.2408.05219}
233
297
  }
234
298
  ```
235
299
 
@@ -229,8 +229,8 @@ class LightPHE:
229
229
  Returns:
230
230
  ciphertext (from lightphe.models.Ciphertext import Ciphertext): encrypted message
231
231
  """
232
- if self.cs.keys.get("private_key") is None:
233
- raise ValueError("You must have private key to perform decryption")
232
+ if self.cs.keys.get("public_key") is None:
233
+ raise ValueError("You must have public key to perform decryption")
234
234
 
235
235
  ciphertext_new = self.cs.reencrypt(ciphertext=ciphertext.value)
236
236
  return Ciphertext(
@@ -1,7 +1,12 @@
1
+ # built-in dependencies
1
2
  import random
2
- import math
3
+ import decimal
3
4
  from typing import Optional
5
+
6
+ # 3rd party dependencies
4
7
  import sympy
8
+
9
+ # project dependencies
5
10
  from lightphe.models.Homomorphic import Homomorphic
6
11
  from lightphe.commons.logger import Logger
7
12
 
@@ -45,7 +50,9 @@ class ElGamal(Homomorphic):
45
50
  p = sympy.randprime(100, 2 ** int(key_size / 2) - 1)
46
51
 
47
52
  # picking a generator g
48
- g = random.randint(2, int(math.sqrt(p)))
53
+ # g = random.randint(2, int(math.sqrt(p))) # reaches int limit for 3072-bit key
54
+ # g = int(random.uniform(2, float(decimal.Decimal(p).sqrt())))
55
+ g = random.randint(2, int(decimal.Decimal(p).sqrt()))
49
56
 
50
57
  # picking a private key x
51
58
  x = random.randint(1, p - 2)
@@ -128,7 +128,12 @@ class GoldwasserMicali(Homomorphic):
128
128
  xp = i % p
129
129
  xq = i % q
130
130
 
131
- if pow(xp, int((p - 1) / 2), p) == 1 and pow(xq, int((q - 1) / 2), q) == 1:
131
+ # reaches int limit for 3072-bit key
132
+ # if pow(xp, int((p - 1) / 2), p) == 1 and pow(xq, int((q - 1) / 2), q) == 1:
133
+ if (
134
+ pow(xp, int((p - 1) // 2), p) == 1
135
+ and pow(xq, int((q - 1) // 2), q) == 1
136
+ ):
132
137
  m_binaries.append("0")
133
138
  else:
134
139
  m_binaries.append("1")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lightphe
3
- Version: 0.0.6
3
+ Version: 0.0.8
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
@@ -18,16 +18,19 @@ License-File: LICENSE
18
18
 
19
19
  <div align="center">
20
20
 
21
- [![PyPI Downloads](https://static.pepy.tech/personalized-badge/lightphe?period=total&units=international_system&left_color=grey&right_color=blue&left_text=pypi%20downloads)](https://pepy.tech/project/lightphe)
21
+ [![PyPI Downloads](https://static.pepy.tech/personalized-badge/lightphe?period=total&units=international_system&left_color=grey&right_color=blue&left_text=downloads)](https://pepy.tech/project/lightphe)
22
22
  [![Stars](https://img.shields.io/github/stars/serengil/LightPHE?color=yellow&style=flat&label=%E2%AD%90%20stars)](https://github.com/serengil/LightPHE/stargazers)
23
23
  [![Tests](https://github.com/serengil/LightPHE/actions/workflows/tests.yml/badge.svg)](https://github.com/serengil/LightPHE/actions/workflows/tests.yml)
24
24
  [![License](http://img.shields.io/:license-MIT-green.svg?style=flat)](https://github.com/serengil/LightPHE/blob/master/LICENSE)
25
- [![Support me on Patreon](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fshieldsio-patreon.vercel.app%2Fapi%3Fusername%3Dserengil%26type%3Dpatrons&style=flat)](https://www.patreon.com/serengil?repo=lightphe)
26
- [![GitHub Sponsors](https://img.shields.io/github/sponsors/serengil?logo=GitHub&color=lightgray)](https://github.com/sponsors/serengil)
25
+ [![DOI](http://img.shields.io/:DOI-10.48550/arXiv.2408.05219-blue.svg?style=flat)](https://arxiv.org/abs/2408.05219)
27
26
 
28
27
  [![Blog](https://img.shields.io/:blog-sefiks.com-blue.svg?style=flat&logo=wordpress)](https://sefiks.com)
29
28
  [![YouTube](https://img.shields.io/:youtube-@sefiks-red.svg?style=flat&logo=youtube)](https://www.youtube.com/@sefiks?sub_confirmation=1)
30
- [![Twitter](https://img.shields.io/:follow-@serengil-blue.svg?style=flat&logo=twitter)](https://twitter.com/intent/user?screen_name=serengil)
29
+ [![Twitter](https://img.shields.io/:follow-@serengil-blue.svg?style=flat&logo=x)](https://twitter.com/intent/user?screen_name=serengil)
30
+
31
+ [![Support me on Patreon](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fshieldsio-patreon.vercel.app%2Fapi%3Fusername%3Dserengil%26type%3Dpatrons&style=flat)](https://www.patreon.com/serengil?repo=lightphe)
32
+ [![GitHub Sponsors](https://img.shields.io/github/sponsors/serengil?logo=GitHub&color=lightgray)](https://github.com/sponsors/serengil)
33
+ [![Buy Me a Coffee](https://img.shields.io/badge/-buy_me_a%C2%A0coffee-gray?logo=buy-me-a-coffee)](https://buymeacoffee.com/serengil)
31
34
 
32
35
  </div>
33
36
 
@@ -109,47 +112,99 @@ m = 17
109
112
  # calculate ciphertext
110
113
  c = cs.encrypt(m)
111
114
 
115
+ # proof of work
112
116
  assert cs.decrypt(c) == m
113
117
  ```
114
118
 
115
119
  # Homomorphic Operations
116
120
 
117
- Once you have the ciphertext, you will be able to perform homomorphic operations on encrypted data. For instance, Paillier is homomorphic with respect to the addition. In other words, decryption of the addition of two ciphertexts is equivalent to addition of plaintexts.
121
+ Once you have the ciphertext, you will be able to perform homomorphic operations on encrypted data without holding private key. For instance, Paillier is homomorphic with respect to the addition. In other words, decryption of the addition of two ciphertexts is equivalent to addition of plaintexts.
122
+
123
+ ### On-Prem Encryption
124
+
125
+ This Python code snippet demonstrates how to generate a private-public key pair using the Paillier cryptosystem via the LightPHE library. First, an instance of the LightPHE class is created with the Paillier algorithm. Then, the public key is exported and saved to a file named "public.txt" to build the same cryptosystem with only public key in the cloud side later. The code defines two plaintext values, m1 and m2, respectively. These plaintext values are encrypted to generate ciphertexts c1 and c2 using the public key. Finally, the ciphertexts c1 and c2 are prepared to be sent to a cloud system for secure processing or storage.
118
126
 
119
127
  ```python
128
+ # generate private-public key pair
120
129
  cs = LightPHE(algorithm_name = "Paillier")
121
130
 
131
+ # export public key to build same cryptosystem with only public key in the cloud
132
+ cs.export_keys(target_file = "public.txt", public = True)
133
+
134
+ # export private key to build same cryptosystem on-prem later
135
+ cs.export_keys(target_file = "private.txt", public = False)
136
+
122
137
  # define plaintexts
123
138
  m1 = 17
124
139
  m2 = 23
125
140
 
126
141
  # calculate ciphertexts
127
- c1 = cs.encrypt(m1)
128
- c2 = cs.encrypt(m2)
142
+ c1 = cs.encrypt(m1).value
143
+ c2 = cs.encrypt(m2).value
144
+
145
+ # send c1 and c2 pair to a cloud system
146
+ ```
147
+
148
+ ### Homomorphic Operations on Cloud
149
+
150
+ This Python code snippet illustrates how to handle encrypted data on the cloud side using the Paillier cryptosystem with the LightPHE library. Upon receiving the encrypted values c1 and c2, the cloud system initializes the cryptosystem using the exported public key stored in public.txt. To ensure the security of the data, a test is performed to confirm that the cloud system cannot decrypt c1 and c2 without the private key. This is done using the pytest library, which raises a ValueError if decryption is attempted, verifying that decryption is not possible without the private key. Finally, the code demonstrates homomorphic addition by adding the two ciphertexts, resulting in a new ciphertext c3 that represents the encrypted sum of the original plaintext values.
151
+
152
+ ```python
153
+ # cloud side receives encrypted c1 and c2
154
+
155
+ # restore cryptosystem with the exported public key
156
+ cs = LightPHE(algorithm_name = "Paillier", key_file = "public.txt")
129
157
 
130
- # homomorphic addition - private key is not required!
158
+ # convert c1 and c2 to ciphertext objects
159
+ c1 = cs.create_ciphertext_obj(c1)
160
+ c2 = cs.create_ciphertext_obj(c2)
161
+
162
+ # confirm that cloud cannot decrypt c1
163
+ with pytest.raises(ValueError, match="You must have private key to perform decryption"):
164
+ cs.decrypt(c1)
165
+
166
+ # confirm that cloud cannot decrypt c2
167
+ with pytest.raises(ValueError, match="You must have private key to perform decryption"):
168
+ cs.decrypt(c2)
169
+
170
+ # homomorphic addition - private key not required
131
171
  c3 = c1 + c2
132
172
 
133
- # proof of work
173
+ # confirm that cloud cannot decrypt c3
174
+ with pytest.raises(ValueError, match="You must have private key to perform decryption"):
175
+ cs.decrypt(c3)
176
+ ```
177
+
178
+ ### On-Prem Decryption
179
+
180
+ This Python code snippet demonstrates the final step in a secure computation process using homomorphic encryption with the LightPHE library. After receiving the ciphertext c3 from the cloud, which is the result of homomorphic addition of two ciphertexts c1 and c2, the on-premises system (which has the private key) decrypts c3 to verify the result. The decrypted value is then asserted to be equal to the sum of the original plaintext values m1 and m2. This step ensures the correctness of the homomorphic computation performed by the cloud.
181
+
182
+ ```python
183
+ # on-prem side receives c3 from cloud
184
+
185
+ # restore cryptosystem with the exported private key
186
+ cs = LightPHE(algorithm_name = "Paillier", key_file = "private.txt")
187
+
188
+ # proof of work - private key required
134
189
  assert cs.decrypt(c3) == m1 + m2
135
190
  ```
136
191
 
137
- ⚡ Notice that once can perform `c1 + c2` here without holding private key. However, just the data owner with private key can perform encryption and decryption. This is the basic definition of homomorphic encryption.
192
+ ### Scalar Multiplication
138
193
 
139
- Besides, Paillier is supporting multiplying ciphertexts by a known plain constant. Simply put, decryption of scalar multiplication of ciphertext is equivalent to that constant times plaintext as well.
194
+ Besides, Paillier is supporting multiplying ciphertexts by a known plain constant. This Python code snippet demonstrates how to perform scalar multiplication on encrypted data using homomorphic encryption with the LightPHE library. The factor k is set to 1.05, representing a 5% increase. On the cloud side, this factor is used to multiply the ciphertext c1, resulting in a new ciphertext c4. When the on-premises system, which holds the private key, receives c4, it decrypts it and verifies that the decrypted value matches the original plaintext m1 scaled by k (i.e., 1.05 * m1). This ensures that the homomorphic scalar multiplication was performed correctly on the encrypted data.
140
195
 
141
196
  ```python
142
197
  # increasing something 5%
143
198
  k = 1.05
144
199
 
145
- # scalar multiplication - private key is not required!
200
+ # scalar multiplication - cloud (private key is not required)
146
201
  c4 = k * c1
147
202
 
148
- # proof of work
203
+ # proof of work on-prem - private key is required
149
204
  assert cs.decrypt(c4) == k * m1
150
205
  ```
151
206
 
152
- ⚡ Herein, `k * c1` operation can be performed by anyone without holding private key.
207
+ ### Ciphertext Regeneration
153
208
 
154
209
  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.
155
210
 
@@ -160,6 +215,8 @@ assert cs.decrypt(c1_prime) == m1
160
215
  assert cs.decrypt(c1) == m1
161
216
  ```
162
217
 
218
+ ### Unsupported Operations
219
+
163
220
  Finally, if you try to perform an operation that algorithm does not support, then an exception will be thrown. For instance, Paillier is not homomorphic with respect to the multiplication or xor. To put it simply, you cannot multiply two ciphertexts. If you enforce this calculation, you will have an exception.
164
221
 
165
222
  ```python
@@ -229,23 +286,30 @@ You should be able run `make test` and `make lint` commands successfully before
229
286
 
230
287
  There are many ways to support a project - starring⭐️ the GitHub repo is just one 🙏
231
288
 
232
- You can also support this work on [Patreon](https://www.patreon.com/serengil?repo=lightphe) or [GitHub Sponsors](https://github.com/sponsors/serengil).
289
+ You can also support this work on [Patreon](https://www.patreon.com/serengil?repo=lightphe), [GitHub Sponsors](https://github.com/sponsors/serengil) or [Buy Me a Coffee](https://buymeacoffee.com/serengil).
233
290
 
234
291
  <a href="https://www.patreon.com/serengil?repo=lightphe">
235
292
  <img src="https://raw.githubusercontent.com/serengil/LightPHE/master/icons/patreon.png" width="30%" height="30%">
236
293
  </a>
237
294
 
295
+ <a href="https://buymeacoffee.com/serengil">
296
+ <img src="https://raw.githubusercontent.com/serengil/LightPHE/master/icons/bmc-button.png" width="25%" height="25%">
297
+ </a>
298
+
299
+ Also, your company's logo will be shown on README on GitHub if you become sponsor in gold, silver or bronze tiers.
300
+
238
301
  # Citation
239
302
 
240
303
  Please cite LightPHE in your publications if it helps your research. Here is its BibTex entry:
241
304
 
242
305
  ```BibTeX
243
- @misc{serengil2023lightphe,
244
- abstract = {A Lightweight Partially Homomorphic Encryption Library for Python},
245
- author = {Serengil, Sefik Ilkin},
246
- title = {LightPHE},
247
- howpublished = {https://github.com/serengil/LightPHE},
248
- year = {2023}
306
+ @misc{serengil2024lightphe,
307
+ title = {LightPHE: Integrating Partially Homomorphic Encryption into Python with Extensive Cloud Environment Evaluations},
308
+ author = {Serengil, Sefik Ilkin and Ozpinar, Alper},
309
+ year = {2024},
310
+ publisher = {arXiv},
311
+ url = {https://arxiv.org/abs/2408.05219},
312
+ doi = {10.48550/arXiv.2408.05219}
249
313
  }
250
314
  ```
251
315
 
@@ -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.6",
11
+ version="0.0.8",
12
12
  author="Sefik Ilkin Serengil",
13
13
  author_email="serengil@gmail.com",
14
14
  description="A Lightweight Partially Homomorphic Encryption Library for Python",
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes