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.
- {lightphe-0.0.18 → lightphe-0.0.22}/PKG-INFO +29 -20
- {lightphe-0.0.18 → lightphe-0.0.22}/README.md +28 -19
- {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/__init__.py +35 -7
- {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/commons/phe_utils.py +4 -0
- {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/cryptosystems/Benaloh.py +5 -1
- lightphe-0.0.22/lightphe/cryptosystems/BonehGohNissim.py +350 -0
- {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/cryptosystems/EllipticCurveElGamal.py +22 -2
- {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/cryptosystems/GoldwasserMicali.py +28 -12
- {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/cryptosystems/NaccacheStern.py +5 -1
- {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/cryptosystems/RSA.py +41 -25
- lightphe-0.0.22/lightphe/cryptosystems/SanderYoungYung.py +225 -0
- {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/models/Algorithm.py +2 -0
- {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/models/Ciphertext.py +24 -0
- {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/models/Homomorphic.py +33 -10
- {lightphe-0.0.18 → lightphe-0.0.22}/lightphe.egg-info/PKG-INFO +29 -20
- {lightphe-0.0.18 → lightphe-0.0.22}/lightphe.egg-info/SOURCES.txt +4 -0
- lightphe-0.0.22/lightphe.egg-info/requires.txt +3 -0
- lightphe-0.0.22/requirements.txt +3 -0
- {lightphe-0.0.18 → lightphe-0.0.22}/setup.py +1 -1
- {lightphe-0.0.18 → lightphe-0.0.22}/tests/test_benaloh.py +1 -32
- lightphe-0.0.22/tests/test_bonehgohnissim.py +180 -0
- {lightphe-0.0.18 → lightphe-0.0.22}/tests/test_ciphertexts.py +2 -4
- lightphe-0.0.22/tests/test_damgard.py +34 -0
- lightphe-0.0.22/tests/test_elgamal.py +64 -0
- {lightphe-0.0.18 → lightphe-0.0.22}/tests/test_ellipticcurveelgamal.py +15 -1
- {lightphe-0.0.18 → lightphe-0.0.22}/tests/test_exporting_keys.py +1 -1
- {lightphe-0.0.18 → lightphe-0.0.22}/tests/test_goldwasser.py +1 -35
- {lightphe-0.0.18 → lightphe-0.0.22}/tests/test_keys.py +2 -5
- {lightphe-0.0.18 → lightphe-0.0.22}/tests/test_large_keys.py +5 -4
- {lightphe-0.0.18 → lightphe-0.0.22}/tests/test_naccache.py +0 -95
- lightphe-0.0.22/tests/test_okamoto.py +34 -0
- {lightphe-0.0.18 → lightphe-0.0.22}/tests/test_paillier.py +2 -36
- {lightphe-0.0.18 → lightphe-0.0.22}/tests/test_rsa.py +1 -31
- lightphe-0.0.22/tests/test_salary.py +24 -0
- lightphe-0.0.22/tests/test_sanderyoungyung.py +71 -0
- {lightphe-0.0.18 → lightphe-0.0.22}/tests/test_tensors.py +25 -11
- lightphe-0.0.18/lightphe.egg-info/requires.txt +0 -4
- lightphe-0.0.18/requirements.txt +0 -4
- lightphe-0.0.18/tests/test_damgard.py +0 -63
- lightphe-0.0.18/tests/test_elgamal.py +0 -139
- lightphe-0.0.18/tests/test_okamoto.py +0 -61
- lightphe-0.0.18/tests/test_salary.py +0 -53
- {lightphe-0.0.18 → lightphe-0.0.22}/LICENSE +0 -0
- {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/commons/__init__.py +0 -0
- {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/commons/logger.py +0 -0
- {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/cryptosystems/DamgardJurik.py +0 -0
- {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/cryptosystems/ElGamal.py +0 -0
- {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/cryptosystems/OkamotoUchiyama.py +0 -0
- {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/cryptosystems/Paillier.py +0 -0
- {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/cryptosystems/__init__.py +0 -0
- {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/models/Tensor.py +0 -0
- {lightphe-0.0.18 → lightphe-0.0.22}/lightphe/models/__init__.py +0 -0
- {lightphe-0.0.18 → lightphe-0.0.22}/lightphe.egg-info/dependency_links.txt +0 -0
- {lightphe-0.0.18 → lightphe-0.0.22}/lightphe.egg-info/top_level.txt +0 -0
- {lightphe-0.0.18 → lightphe-0.0.22}/setup.cfg +0 -0
- {lightphe-0.0.18 → lightphe-0.0.22}/tests/__init__.py +0 -0
- {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.
|
|
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 |
|
|
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
|
|
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
|
-
|
|
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=
|
|
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
|
|
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 |
|
|
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
|
|
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
|
-
|
|
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=
|
|
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
|
|
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.
|
|
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(
|
|
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,
|
|
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"]
|