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.
- {lightphe-0.0.6 → lightphe-0.0.8}/PKG-INFO +86 -22
- {lightphe-0.0.6 → lightphe-0.0.8}/README.md +85 -21
- {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/__init__.py +2 -2
- {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/cryptosystems/ElGamal.py +9 -2
- {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/cryptosystems/GoldwasserMicali.py +6 -1
- {lightphe-0.0.6 → lightphe-0.0.8}/lightphe.egg-info/PKG-INFO +86 -22
- {lightphe-0.0.6 → lightphe-0.0.8}/setup.py +1 -1
- {lightphe-0.0.6 → lightphe-0.0.8}/LICENSE +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/commons/__init__.py +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/commons/logger.py +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/commons/phe_utils.py +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/cryptosystems/Benaloh.py +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/cryptosystems/DamgardJurik.py +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/cryptosystems/EllipticCurveElGamal.py +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/cryptosystems/NaccacheStern.py +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/cryptosystems/OkamotoUchiyama.py +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/cryptosystems/Paillier.py +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/cryptosystems/RSA.py +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/cryptosystems/__init__.py +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/elliptic/Weierstrass.py +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/elliptic/__init__.py +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/models/Algorithm.py +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/models/Ciphertext.py +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/models/EllipticCurve.py +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/models/Homomorphic.py +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/models/Tensor.py +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/lightphe/models/__init__.py +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/lightphe.egg-info/SOURCES.txt +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/lightphe.egg-info/dependency_links.txt +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/lightphe.egg-info/requires.txt +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/lightphe.egg-info/top_level.txt +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/requirements.txt +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/setup.cfg +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/tests/__init__.py +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/tests/test_benaloh.py +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/tests/test_cloud.py +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/tests/test_damgard.py +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/tests/test_elgamal.py +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/tests/test_ellipticcurveelgamal.py +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/tests/test_exporting_keys.py +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/tests/test_goldwasser.py +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/tests/test_naccache.py +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/tests/test_okamoto.py +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/tests/test_paillier.py +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/tests/test_rsa.py +0 -0
- {lightphe-0.0.6 → lightphe-0.0.8}/tests/test_salary.py +0 -0
- {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.
|
|
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
|
-
[](https://pepy.tech/project/lightphe)
|
|
22
22
|
[](https://github.com/serengil/LightPHE/stargazers)
|
|
23
23
|
[](https://github.com/serengil/LightPHE/actions/workflows/tests.yml)
|
|
24
24
|
[](https://github.com/serengil/LightPHE/blob/master/LICENSE)
|
|
25
|
-
[](https://github.com/sponsors/serengil)
|
|
25
|
+
[](https://arxiv.org/abs/2408.05219)
|
|
27
26
|
|
|
28
27
|
[](https://sefiks.com)
|
|
29
28
|
[](https://www.youtube.com/@sefiks?sub_confirmation=1)
|
|
30
|
-
[](https://twitter.com/intent/user?screen_name=serengil)
|
|
30
|
+
|
|
31
|
+
[](https://www.patreon.com/serengil?repo=lightphe)
|
|
32
|
+
[](https://github.com/sponsors/serengil)
|
|
33
|
+
[](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
|
-
#
|
|
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
|
-
#
|
|
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
|
-
|
|
192
|
+
### Scalar Multiplication
|
|
138
193
|
|
|
139
|
-
Besides, Paillier is supporting multiplying ciphertexts by a known plain constant.
|
|
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
|
-
|
|
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)
|
|
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{
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
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
|
-
[](https://pepy.tech/project/lightphe)
|
|
6
6
|
[](https://github.com/serengil/LightPHE/stargazers)
|
|
7
7
|
[](https://github.com/serengil/LightPHE/actions/workflows/tests.yml)
|
|
8
8
|
[](https://github.com/serengil/LightPHE/blob/master/LICENSE)
|
|
9
|
-
[](https://github.com/sponsors/serengil)
|
|
9
|
+
[](https://arxiv.org/abs/2408.05219)
|
|
11
10
|
|
|
12
11
|
[](https://sefiks.com)
|
|
13
12
|
[](https://www.youtube.com/@sefiks?sub_confirmation=1)
|
|
14
|
-
[](https://twitter.com/intent/user?screen_name=serengil)
|
|
14
|
+
|
|
15
|
+
[](https://www.patreon.com/serengil?repo=lightphe)
|
|
16
|
+
[](https://github.com/sponsors/serengil)
|
|
17
|
+
[](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
|
-
#
|
|
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
|
-
#
|
|
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
|
-
|
|
176
|
+
### Scalar Multiplication
|
|
122
177
|
|
|
123
|
-
Besides, Paillier is supporting multiplying ciphertexts by a known plain constant.
|
|
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
|
-
|
|
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)
|
|
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{
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
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("
|
|
233
|
-
raise ValueError("You must have
|
|
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
|
|
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
|
-
|
|
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.
|
|
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
|
-
[](https://pepy.tech/project/lightphe)
|
|
22
22
|
[](https://github.com/serengil/LightPHE/stargazers)
|
|
23
23
|
[](https://github.com/serengil/LightPHE/actions/workflows/tests.yml)
|
|
24
24
|
[](https://github.com/serengil/LightPHE/blob/master/LICENSE)
|
|
25
|
-
[](https://github.com/sponsors/serengil)
|
|
25
|
+
[](https://arxiv.org/abs/2408.05219)
|
|
27
26
|
|
|
28
27
|
[](https://sefiks.com)
|
|
29
28
|
[](https://www.youtube.com/@sefiks?sub_confirmation=1)
|
|
30
|
-
[](https://twitter.com/intent/user?screen_name=serengil)
|
|
30
|
+
|
|
31
|
+
[](https://www.patreon.com/serengil?repo=lightphe)
|
|
32
|
+
[](https://github.com/sponsors/serengil)
|
|
33
|
+
[](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
|
-
#
|
|
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
|
-
#
|
|
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
|
-
|
|
192
|
+
### Scalar Multiplication
|
|
138
193
|
|
|
139
|
-
Besides, Paillier is supporting multiplying ciphertexts by a known plain constant.
|
|
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
|
-
|
|
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)
|
|
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{
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
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.
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|