lightphe 0.0.9__tar.gz → 0.0.11__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 (56) hide show
  1. {lightphe-0.0.9 → lightphe-0.0.11}/PKG-INFO +46 -3
  2. {lightphe-0.0.9 → lightphe-0.0.11}/README.md +45 -2
  3. {lightphe-0.0.9 → lightphe-0.0.11}/lightphe/__init__.py +106 -16
  4. lightphe-0.0.11/lightphe/commons/binary_operations.py +147 -0
  5. {lightphe-0.0.9 → lightphe-0.0.11}/lightphe/commons/phe_utils.py +22 -4
  6. {lightphe-0.0.9 → lightphe-0.0.11}/lightphe/cryptosystems/EllipticCurveElGamal.py +77 -45
  7. lightphe-0.0.11/lightphe/elliptic_curve_forms/edwards.py +89 -0
  8. lightphe-0.0.11/lightphe/elliptic_curve_forms/koblitz.py +166 -0
  9. lightphe-0.0.11/lightphe/elliptic_curve_forms/weierstrass.py +120 -0
  10. {lightphe-0.0.9 → lightphe-0.0.11}/lightphe/models/Ciphertext.py +27 -8
  11. lightphe-0.0.11/lightphe/models/Curve.py +29 -0
  12. lightphe-0.0.11/lightphe/models/EllipticCurve.py +160 -0
  13. {lightphe-0.0.9 → lightphe-0.0.11}/lightphe/models/Tensor.py +13 -5
  14. {lightphe-0.0.9 → lightphe-0.0.11}/lightphe.egg-info/PKG-INFO +46 -3
  15. {lightphe-0.0.9 → lightphe-0.0.11}/lightphe.egg-info/SOURCES.txt +4 -0
  16. {lightphe-0.0.9 → lightphe-0.0.11}/setup.py +1 -1
  17. lightphe-0.0.11/tests/test_ellipticcurve.py +75 -0
  18. lightphe-0.0.11/tests/test_ellipticcurveelgamal.py +263 -0
  19. lightphe-0.0.9/lightphe/elliptic_curve_forms/edwards.py +0 -61
  20. lightphe-0.0.9/lightphe/elliptic_curve_forms/weierstrass.py +0 -75
  21. lightphe-0.0.9/lightphe/models/EllipticCurve.py +0 -45
  22. lightphe-0.0.9/tests/test_ellipticcurveelgamal.py +0 -69
  23. {lightphe-0.0.9 → lightphe-0.0.11}/LICENSE +0 -0
  24. {lightphe-0.0.9 → lightphe-0.0.11}/lightphe/commons/__init__.py +0 -0
  25. {lightphe-0.0.9 → lightphe-0.0.11}/lightphe/commons/logger.py +0 -0
  26. {lightphe-0.0.9 → lightphe-0.0.11}/lightphe/cryptosystems/Benaloh.py +0 -0
  27. {lightphe-0.0.9 → lightphe-0.0.11}/lightphe/cryptosystems/DamgardJurik.py +0 -0
  28. {lightphe-0.0.9 → lightphe-0.0.11}/lightphe/cryptosystems/ElGamal.py +0 -0
  29. {lightphe-0.0.9 → lightphe-0.0.11}/lightphe/cryptosystems/GoldwasserMicali.py +0 -0
  30. {lightphe-0.0.9 → lightphe-0.0.11}/lightphe/cryptosystems/NaccacheStern.py +0 -0
  31. {lightphe-0.0.9 → lightphe-0.0.11}/lightphe/cryptosystems/OkamotoUchiyama.py +0 -0
  32. {lightphe-0.0.9 → lightphe-0.0.11}/lightphe/cryptosystems/Paillier.py +0 -0
  33. {lightphe-0.0.9 → lightphe-0.0.11}/lightphe/cryptosystems/RSA.py +0 -0
  34. {lightphe-0.0.9 → lightphe-0.0.11}/lightphe/cryptosystems/__init__.py +0 -0
  35. {lightphe-0.0.9 → lightphe-0.0.11}/lightphe/elliptic_curve_forms/__init__.py +0 -0
  36. {lightphe-0.0.9 → lightphe-0.0.11}/lightphe/models/Algorithm.py +0 -0
  37. {lightphe-0.0.9 → lightphe-0.0.11}/lightphe/models/Homomorphic.py +0 -0
  38. {lightphe-0.0.9 → lightphe-0.0.11}/lightphe/models/__init__.py +0 -0
  39. {lightphe-0.0.9 → lightphe-0.0.11}/lightphe.egg-info/dependency_links.txt +0 -0
  40. {lightphe-0.0.9 → lightphe-0.0.11}/lightphe.egg-info/requires.txt +0 -0
  41. {lightphe-0.0.9 → lightphe-0.0.11}/lightphe.egg-info/top_level.txt +0 -0
  42. {lightphe-0.0.9 → lightphe-0.0.11}/requirements.txt +0 -0
  43. {lightphe-0.0.9 → lightphe-0.0.11}/setup.cfg +0 -0
  44. {lightphe-0.0.9 → lightphe-0.0.11}/tests/__init__.py +0 -0
  45. {lightphe-0.0.9 → lightphe-0.0.11}/tests/test_benaloh.py +0 -0
  46. {lightphe-0.0.9 → lightphe-0.0.11}/tests/test_cloud.py +0 -0
  47. {lightphe-0.0.9 → lightphe-0.0.11}/tests/test_damgard.py +0 -0
  48. {lightphe-0.0.9 → lightphe-0.0.11}/tests/test_elgamal.py +0 -0
  49. {lightphe-0.0.9 → lightphe-0.0.11}/tests/test_exporting_keys.py +0 -0
  50. {lightphe-0.0.9 → lightphe-0.0.11}/tests/test_goldwasser.py +0 -0
  51. {lightphe-0.0.9 → lightphe-0.0.11}/tests/test_naccache.py +0 -0
  52. {lightphe-0.0.9 → lightphe-0.0.11}/tests/test_okamoto.py +0 -0
  53. {lightphe-0.0.9 → lightphe-0.0.11}/tests/test_paillier.py +0 -0
  54. {lightphe-0.0.9 → lightphe-0.0.11}/tests/test_rsa.py +0 -0
  55. {lightphe-0.0.9 → lightphe-0.0.11}/tests/test_salary.py +0 -0
  56. {lightphe-0.0.9 → lightphe-0.0.11}/tests/test_tensors.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lightphe
3
- Version: 0.0.9
3
+ Version: 0.0.11
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
@@ -22,7 +22,8 @@ License-File: LICENSE
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
- [![DOI](http://img.shields.io/:DOI-10.48550/arXiv.2408.05219-blue.svg?style=flat)](https://arxiv.org/abs/2408.05219)
25
+ [![arXiv](https://img.shields.io/badge/arXiv-2408.05219-b31b1b.svg?logo=arXiv)](https://arxiv.org/abs/2408.05219)
26
+ <!-- [![DOI](http://img.shields.io/:DOI-10.48550/arXiv.2408.05219-blue.svg?style=flat)](https://arxiv.org/abs/2408.05219) -->
26
27
 
27
28
  [![Blog](https://img.shields.io/:blog-sefiks.com-blue.svg?style=flat&logo=wordpress)](https://sefiks.com)
28
29
  [![YouTube](https://img.shields.io/:youtube-@sefiks-red.svg?style=flat&logo=youtube)](https://www.youtube.com/@sefiks?sub_confirmation=1)
@@ -36,7 +37,7 @@ License-File: LICENSE
36
37
 
37
38
  <p align="center"><img src="https://raw.githubusercontent.com/serengil/LightPHE/master/icons/phi.png" width="200" height="240"></p>
38
39
 
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/) 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/).
40
+ 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/).
40
41
 
41
42
  # Partially vs Fully Homomorphic Encryption
42
43
 
@@ -245,6 +246,48 @@ with pytest.raises(ValueError, match="Paillier is not homomorphic with respect t
245
246
 
246
247
  However, if you tried to multiply ciphertexts with RSA, or xor ciphertexts with Goldwasser-Micali, these will be succeeded because those cryptosystems support those homomorphic operations.
247
248
 
249
+ ### Elliptic Curve Cryptography
250
+
251
+ 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.
252
+
253
+ Building an elliptic curve with LightPHE is very straightforward. Once the curve is initialized, you can perform operations such as point addition and scalar multiplication.
254
+
255
+ ```python
256
+ from lightphe import ECC
257
+
258
+ forms = ["weierstrass", "edwards", "koblitz"]
259
+
260
+ # construct an elliptic curve
261
+ ed = ECC(form_name="edwards")
262
+
263
+ # Base Point
264
+ G = ed.G
265
+
266
+ _2G = G + G
267
+ _3G = _2G + G
268
+ _5G = _3G + _2G
269
+
270
+ _20G = 4 * G
271
+ _19G = _20G - G
272
+ ```
273
+
274
+ 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.
275
+
276
+ ```python
277
+ forms = ["weierstass", "edwards", "koblitz"]
278
+
279
+ phe = LightPHE(
280
+ algorithm_name="EllipticCurve-ElGamal",
281
+ form=forms[1],
282
+ )
283
+ ```
284
+
285
+ One of the crucial factors that define the security level of an elliptic curve cryptosystem is the order of the curve. The order of a curve is the number of points on the curve, and it directly influences the strength of the encryption. A higher order typically corresponds to a stronger cryptosystem, making it more resistant to cryptographic attacks.
286
+
287
+ Each curve in LightPHE has a specific order, which is carefully chosen to balance performance and security. By selecting an elliptic curve with a larger order, you increase the security of your cryptographic system, but this may come with a trade-off in computational efficiency. Therefore, choosing the appropriate curve order is a crucial decision based on your application’s security and performance requirements.
288
+
289
+ See [`curves`](https://github.com/serengil/LightPHE/tree/master/lightphe/elliptic_curve_forms) page for a list of all supported forms, curves and their details.
290
+
248
291
  # Contributing
249
292
 
250
293
  All PRs are more than welcome! If you are planning to contribute a large patch, please create an issue first to get any upfront questions or design decisions out of the way first.
@@ -6,7 +6,8 @@
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
- [![DOI](http://img.shields.io/:DOI-10.48550/arXiv.2408.05219-blue.svg?style=flat)](https://arxiv.org/abs/2408.05219)
9
+ [![arXiv](https://img.shields.io/badge/arXiv-2408.05219-b31b1b.svg?logo=arXiv)](https://arxiv.org/abs/2408.05219)
10
+ <!-- [![DOI](http://img.shields.io/:DOI-10.48550/arXiv.2408.05219-blue.svg?style=flat)](https://arxiv.org/abs/2408.05219) -->
10
11
 
11
12
  [![Blog](https://img.shields.io/:blog-sefiks.com-blue.svg?style=flat&logo=wordpress)](https://sefiks.com)
12
13
  [![YouTube](https://img.shields.io/:youtube-@sefiks-red.svg?style=flat&logo=youtube)](https://www.youtube.com/@sefiks?sub_confirmation=1)
@@ -20,7 +21,7 @@
20
21
 
21
22
  <p align="center"><img src="https://raw.githubusercontent.com/serengil/LightPHE/master/icons/phi.png" width="200" height="240"></p>
22
23
 
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/) 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/).
24
+ 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/).
24
25
 
25
26
  # Partially vs Fully Homomorphic Encryption
26
27
 
@@ -229,6 +230,48 @@ with pytest.raises(ValueError, match="Paillier is not homomorphic with respect t
229
230
 
230
231
  However, if you tried to multiply ciphertexts with RSA, or xor ciphertexts with Goldwasser-Micali, these will be succeeded because those cryptosystems support those homomorphic operations.
231
232
 
233
+ ### Elliptic Curve Cryptography
234
+
235
+ 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.
236
+
237
+ Building an elliptic curve with LightPHE is very straightforward. Once the curve is initialized, you can perform operations such as point addition and scalar multiplication.
238
+
239
+ ```python
240
+ from lightphe import ECC
241
+
242
+ forms = ["weierstrass", "edwards", "koblitz"]
243
+
244
+ # construct an elliptic curve
245
+ ed = ECC(form_name="edwards")
246
+
247
+ # Base Point
248
+ G = ed.G
249
+
250
+ _2G = G + G
251
+ _3G = _2G + G
252
+ _5G = _3G + _2G
253
+
254
+ _20G = 4 * G
255
+ _19G = _20G - G
256
+ ```
257
+
258
+ 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.
259
+
260
+ ```python
261
+ forms = ["weierstass", "edwards", "koblitz"]
262
+
263
+ phe = LightPHE(
264
+ algorithm_name="EllipticCurve-ElGamal",
265
+ form=forms[1],
266
+ )
267
+ ```
268
+
269
+ One of the crucial factors that define the security level of an elliptic curve cryptosystem is the order of the curve. The order of a curve is the number of points on the curve, and it directly influences the strength of the encryption. A higher order typically corresponds to a stronger cryptosystem, making it more resistant to cryptographic attacks.
270
+
271
+ Each curve in LightPHE has a specific order, which is carefully chosen to balance performance and security. By selecting an elliptic curve with a larger order, you increase the security of your cryptographic system, but this may come with a trade-off in computational efficiency. Therefore, choosing the appropriate curve order is a crucial decision based on your application’s security and performance requirements.
272
+
273
+ See [`curves`](https://github.com/serengil/LightPHE/tree/master/lightphe/elliptic_curve_forms) page for a list of all supported forms, curves and their details.
274
+
232
275
  # Contributing
233
276
 
234
277
  All PRs are more than welcome! If you are planning to contribute a large patch, please create an issue first to get any upfront questions or design decisions out of the way first.
@@ -1,10 +1,17 @@
1
+ # built-in dependencies
1
2
  import json
2
3
  from typing import Optional, Union, List
3
4
 
5
+ # project dependencies
4
6
  from lightphe.models.Homomorphic import Homomorphic
5
7
  from lightphe.models.Ciphertext import Ciphertext
6
8
  from lightphe.models.Algorithm import Algorithm
7
9
  from lightphe.models.Tensor import Fraction, EncryptedTensor
10
+ from lightphe.models.EllipticCurve import EllipticCurvePoint
11
+ from lightphe.commons import phe_utils
12
+ from lightphe.commons.logger import Logger
13
+
14
+ # cryptosystems
8
15
  from lightphe.cryptosystems.RSA import RSA
9
16
  from lightphe.cryptosystems.ElGamal import ElGamal
10
17
  from lightphe.cryptosystems.Paillier import Paillier
@@ -14,16 +21,21 @@ from lightphe.cryptosystems.Benaloh import Benaloh
14
21
  from lightphe.cryptosystems.NaccacheStern import NaccacheStern
15
22
  from lightphe.cryptosystems.GoldwasserMicali import GoldwasserMicali
16
23
  from lightphe.cryptosystems.EllipticCurveElGamal import EllipticCurveElGamal
17
- from lightphe.commons import phe_utils
18
- from lightphe.commons.logger import Logger
24
+ from lightphe.elliptic_curve_forms.weierstrass import Weierstrass
25
+ from lightphe.elliptic_curve_forms.edwards import TwistedEdwards
26
+ from lightphe.elliptic_curve_forms.koblitz import Koblitz
27
+
19
28
 
20
- # pylint: disable=eval-used, simplifiable-if-expression
29
+ # pylint: disable=eval-used, simplifiable-if-expression, too-few-public-methods
21
30
 
22
31
  logger = Logger(module="lightphe/__init__.py")
23
32
 
33
+ VERSION = "0.0.11"
34
+
24
35
 
25
36
  class LightPHE:
26
- __version__ = "0.0.9"
37
+ __version__ = VERSION
38
+
27
39
  def __init__(
28
40
  self,
29
41
  algorithm_name: str,
@@ -31,7 +43,8 @@ class LightPHE:
31
43
  key_file: Optional[str] = None,
32
44
  key_size: Optional[int] = None,
33
45
  precision: int = 5,
34
- form: str = "weierstrass",
46
+ form: Optional[str] = None,
47
+ curve: Optional[str] = None,
35
48
  ):
36
49
  """
37
50
  Build LightPHE class
@@ -43,19 +56,32 @@ class LightPHE:
43
56
  key_file (str): if keys are exported, you can load them into cryptosystem
44
57
  key_size (int): key size in bits
45
58
  precision (int): precision for homomorphic operations on tensors
46
- form (str): specifies the form of the elliptic curve.
47
- Options: 'weierstrass' (default), 'edwards'.
59
+ form (str): specifies the form of the elliptic curve.
60
+ Options: 'weierstrass' (default), 'edwards', 'koblitz'.
61
+ This parameter is only used if `algorithm_name` is 'EllipticCurve-ElGamal'.
62
+ curve (str): specifies the elliptic curve to use.
63
+ Options:
64
+ - e.g. ed25519, ed448 for edwards form
65
+ - e.g. secp256k1 for weierstrass form
66
+ - e.g. k-409 for koblitz form
67
+ List of all available curves:
68
+ github.com/serengil/LightPHE/blob/master/lightphe/elliptic_curve_forms/README.md
48
69
  This parameter is only used if `algorithm_name` is 'EllipticCurve-ElGamal'.
49
70
  """
50
71
  self.algorithm_name = algorithm_name
51
72
  self.precision = precision
52
73
  self.form = form
74
+ self.curve = curve
53
75
 
54
76
  if key_file is not None:
55
77
  keys = self.restore_keys(target_file=key_file)
56
78
 
57
79
  self.cs: Homomorphic = self.__build_cryptosystem(
58
- algorithm_name=algorithm_name, keys=keys, key_size=key_size, form=form,
80
+ algorithm_name=algorithm_name,
81
+ keys=keys,
82
+ key_size=key_size,
83
+ form=form,
84
+ curve=curve,
59
85
  )
60
86
 
61
87
  def __build_cryptosystem(
@@ -64,6 +90,7 @@ class LightPHE:
64
90
  keys: Optional[dict] = None,
65
91
  key_size: Optional[int] = None,
66
92
  form: Optional[str] = None,
93
+ curve: Optional[str] = None,
67
94
  ) -> Union[
68
95
  RSA,
69
96
  ElGamal,
@@ -83,9 +110,14 @@ class LightPHE:
83
110
  keys (dict): optional private-public key pair
84
111
  key_file (str): if keys are exported, you can load them into cryptosystem
85
112
  key_size (int): key size in bits
86
- form (str): specifies the form of the elliptic curve.
113
+ form (str): specifies the form of the elliptic curve.
87
114
  Options: 'weierstrass' (default), 'edwards'.
88
115
  This parameter is only used if `algorithm_name` is 'EllipticCurve-ElGamal'.
116
+ curve (str): specifies the elliptic curve to use.
117
+ Options:
118
+ - ed25519, ed448 for edwards form
119
+ - secp256k1 for weierstrass form
120
+ This parameter is only used if `algorithm_name` is 'EllipticCurve-ElGamal'.
89
121
  Returns
90
122
  cryptosystem
91
123
  """
@@ -97,7 +129,9 @@ class LightPHE:
97
129
  elif algorithm_name == Algorithm.ExponentialElGamal:
98
130
  cs = ElGamal(keys=keys, key_size=key_size, exponential=True)
99
131
  elif algorithm_name == Algorithm.EllipticCurveElGamal:
100
- cs = EllipticCurveElGamal(keys=keys, key_size=key_size, form=form)
132
+ cs = EllipticCurveElGamal(
133
+ keys=keys, key_size=key_size, form=form, curve=curve
134
+ )
101
135
  elif algorithm_name == Algorithm.Paillier:
102
136
  cs = Paillier(keys=keys, key_size=key_size)
103
137
  elif algorithm_name == Algorithm.DamgardJurik:
@@ -114,7 +148,9 @@ class LightPHE:
114
148
  raise ValueError(f"unimplemented algorithm - {algorithm_name}")
115
149
  return cs
116
150
 
117
- def encrypt(self, plaintext: Union[int, float, list]) -> Union[Ciphertext, EncryptedTensor]:
151
+ def encrypt(
152
+ self, plaintext: Union[int, float, list]
153
+ ) -> Union[Ciphertext, EncryptedTensor]:
118
154
  """
119
155
  Encrypt a plaintext with a built cryptosystem
120
156
  Args:
@@ -130,9 +166,17 @@ class LightPHE:
130
166
  return self.__encrypt_tensors(tensor=plaintext)
131
167
 
132
168
  ciphertext = self.cs.encrypt(
133
- plaintext=phe_utils.parse_int(value=plaintext, modulo=self.cs.plaintext_modulo)
169
+ plaintext=phe_utils.normalize_input(
170
+ value=plaintext, modulo=self.cs.plaintext_modulo
171
+ )
172
+ )
173
+ return Ciphertext(
174
+ algorithm_name=self.algorithm_name,
175
+ keys=self.cs.keys,
176
+ value=ciphertext,
177
+ form=self.form,
178
+ curve=self.curve,
134
179
  )
135
- return Ciphertext(algorithm_name=self.algorithm_name, keys=self.cs.keys, value=ciphertext, form=self.form)
136
180
 
137
181
  def decrypt(
138
182
  self, ciphertext: Union[Ciphertext, EncryptedTensor]
@@ -171,7 +215,8 @@ class LightPHE:
171
215
  plaintext=(m % self.cs.plaintext_modulo) * pow(10, self.precision)
172
216
  )
173
217
  abs_dividend_encrypted = self.cs.encrypt(
174
- plaintext=(abs(m) % self.cs.plaintext_modulo) * pow(10, self.precision)
218
+ plaintext=(abs(m) % self.cs.plaintext_modulo)
219
+ * pow(10, self.precision)
175
220
  )
176
221
  divisor_encrypted = self.cs.encrypt(plaintext=pow(10, self.precision))
177
222
  c = Fraction(
@@ -205,7 +250,9 @@ class LightPHE:
205
250
  encrypted_tensor.append(c)
206
251
  return EncryptedTensor(fractions=encrypted_tensor, cs=self.cs)
207
252
 
208
- def __decrypt_tensors(self, encrypted_tensor: EncryptedTensor) -> Union[List[int], List[float]]:
253
+ def __decrypt_tensors(
254
+ self, encrypted_tensor: EncryptedTensor
255
+ ) -> Union[List[int], List[float]]:
209
256
  """
210
257
  Decrypt a given encrypted tensor
211
258
  Args:
@@ -304,4 +351,47 @@ class LightPHE:
304
351
  Returns:
305
352
  Ciphertext
306
353
  """
307
- return Ciphertext(algorithm_name=self.algorithm_name, keys=self.cs.keys, value=ciphertext)
354
+ return Ciphertext(
355
+ algorithm_name=self.algorithm_name, keys=self.cs.keys, value=ciphertext
356
+ )
357
+
358
+
359
+ class ECC:
360
+ __version__ = VERSION
361
+
362
+ def __init__(
363
+ self, form_name: Optional[str] = None, curve_name: Optional[str] = None
364
+ ):
365
+ """
366
+ Construct an Elliptic Curve over a finite field (prime or binary)
367
+ Args:
368
+ form_name (str): specifies the form of the elliptic curve.
369
+ Options: 'weierstrass' (default), 'edwards', 'koblitz'.
370
+ curve_name (str): specifies the elliptic curve to use.
371
+ Options:
372
+ - e.g. ed25519, ed448 for edwards form
373
+ - e.g. secp256k1 for weierstrass form
374
+ - e.g. k-409 for koblitz form
375
+ List of all available curves:
376
+ github.com/serengil/LightPHE/blob/master/lightphe/elliptic_curve_forms/README.md
377
+ """
378
+ if form_name is None or form_name == "weierstrass":
379
+ self.curve = Weierstrass(curve=curve_name)
380
+ elif form_name in "edwards":
381
+ self.curve = TwistedEdwards(curve=curve_name)
382
+ elif form_name in "koblitz":
383
+ self.curve = Koblitz(curve=curve_name)
384
+ else:
385
+ raise ValueError(f"unimplemented curve form - {form_name}")
386
+
387
+ # base point
388
+ self.G = EllipticCurvePoint(self.curve.G[0], self.curve.G[1], self.curve)
389
+
390
+ # order of the curve
391
+ self.n = self.curve.n
392
+
393
+ # point at infinity or neutral / identity element
394
+ self.O = EllipticCurvePoint(self.curve.O[0], self.curve.O[1], self.curve)
395
+
396
+ # modulo
397
+ self.modulo = self.curve.modulo
@@ -0,0 +1,147 @@
1
+ """
2
+ This module is heavily inspired by repo github.com/dimitrijray/ecc-binary-field/blob/master/binop.py
3
+ """
4
+
5
+
6
+ def divide(a: int, b: int, p: int) -> int:
7
+ """
8
+ Returns a_bin * (b_bin)^-1 (mod p)
9
+ Args:
10
+ a (int): nominator
11
+ b (int): denominator
12
+ p (int): modulo
13
+ Returns:
14
+ result (int): (a_bin * (b_bin)^-1 (mod p)) mod p
15
+ """
16
+ result = mod(multi(a, inverse(b, p)), p)
17
+ return result
18
+
19
+
20
+ def multi(a: int, b: int) -> int:
21
+ """
22
+ Multiply two binary numbers in GF(2).
23
+ Args:
24
+ a (int): first number
25
+ b (int): second number
26
+ Returns:
27
+ result (int): carry-less multiplication between a and b
28
+ """
29
+ result = 0
30
+ shift = 0
31
+
32
+ while b > 0:
33
+ if b & 1: # Check if the least significant bit of b is 1
34
+ result ^= a << shift
35
+ shift += 1
36
+ b >>= 1 # Shift b to the right by 1
37
+
38
+ return result
39
+
40
+
41
+ def power_mod(num: int, exp: int, modulo: int) -> int:
42
+ """
43
+ Calculate num^exp (mod m) in GF(2).
44
+ Args:
45
+ num (int): base
46
+ exp (int): exponent
47
+ modulo (int): modulo
48
+ Returns:
49
+ result (int): num^exp (mod m)
50
+ """
51
+ result = 1
52
+ base = num % modulo
53
+
54
+ while exp > 0:
55
+ if exp & 1: # Check if the least significant bit of exp is 1
56
+ result = multi(base, result) # multiply result by base
57
+ result = mod(result, modulo) # apply modulo
58
+
59
+ base = square(base) # square the base
60
+ exp >>= 1 # right shift exp by 1
61
+
62
+ return result
63
+
64
+
65
+ def square(num: int) -> int:
66
+ """
67
+ Square a binary number in GF(2).
68
+ Args:
69
+ num (int): number
70
+ Returns:
71
+ result (int): square of num
72
+ """
73
+ result = 0
74
+ shift = 0
75
+
76
+ while num > 0:
77
+ if num & 1: # Check if the least significant bit of num is 1
78
+ result ^= 1 << (2 * shift) # Set the appropriate bit in the result
79
+
80
+ num >>= 1 # Right shift num by 1
81
+ shift += 1
82
+
83
+ return result
84
+
85
+
86
+ def mod(num: int, modulo: int) -> int:
87
+ """
88
+ Perform modulo operation for binary numbers in GF(2).
89
+ Args:
90
+ num (int): number
91
+ modulo (int): modulo
92
+ Returns:
93
+ result (int): num mod modulo
94
+ """
95
+ degP = num.bit_length() - 1
96
+ degR = modulo.bit_length() - 1
97
+
98
+ while degP >= degR and degR != 0:
99
+ shift = degP - degR
100
+ num ^= modulo << shift # Perform XOR to reduce the degree of num
101
+ degP = num.bit_length() - 1 # Update the degree of num
102
+
103
+ return num
104
+
105
+
106
+ def div(num: int, modulo: int) -> int:
107
+ """
108
+ Return the quotient of the polynomial division num / modulo in GF(2).
109
+ Args:
110
+ num (int): numerator
111
+ modulo (int): denominator
112
+ Returns:
113
+ result (int): quotient
114
+ """
115
+ deg_p = num.bit_length() - 1
116
+ deg_r = modulo.bit_length() - 1
117
+ q = 0
118
+
119
+ while deg_p >= deg_r:
120
+ shift = deg_p - deg_r
121
+ q |= 1 << shift # Set the corresponding bit in the quotient
122
+ num ^= modulo << shift # Perform XOR to reduce the degree of num
123
+ deg_p = num.bit_length() - 1 # Update the degree of num
124
+
125
+ return q
126
+
127
+
128
+ def inverse(num: int, modulo: int) -> int:
129
+ """
130
+ Calculate the inverse of a binary number modulo a polynomial in GF(2).
131
+ Args:
132
+ num (int): number
133
+ modulo (int): modulo
134
+ Returns:
135
+ result (int): inverse of num mod modulo
136
+ """
137
+ a, b = num, modulo
138
+ p1, p2 = 1, 0
139
+
140
+ while b != 1:
141
+ q = div(a, b)
142
+ r = mod(a, b)
143
+ a, b = b, r
144
+ p_a = p1 ^ multi(q, p2)
145
+ p1, p2 = p2, p_a
146
+
147
+ return p2
@@ -1,5 +1,8 @@
1
+ # built-in dependencies
1
2
  from typing import Union, Tuple, Optional
2
3
  from decimal import Decimal, getcontext
4
+
5
+ # project dependencies
3
6
  from lightphe.commons.logger import Logger
4
7
 
5
8
  logger = Logger(module="lightphe/commons/phe_utils.py")
@@ -7,8 +10,19 @@ logger = Logger(module="lightphe/commons/phe_utils.py")
7
10
  # pylint: disable=no-else-return, no-else-break
8
11
 
9
12
 
10
- def parse_int(value: Union[int, float], modulo: int) -> int:
11
- if isinstance(value, int):
13
+ def normalize_input(value: Union[int, float], modulo: Union[int, str]) -> int:
14
+ """
15
+ Normaliz given value to be in the range of modulo
16
+ Args:
17
+ value (int, float): the value to be normalized
18
+ modulo (int): the modulo value
19
+ Returns:
20
+ result (int, str): the normalized value
21
+ """
22
+ if isinstance(value, int) and isinstance(modulo, str):
23
+ # elliptic curve elgamal & koblitz curves
24
+ result = value % int(modulo, 2)
25
+ elif isinstance(value, int) and isinstance(modulo, int):
12
26
  result = value % modulo
13
27
  elif isinstance(value, float) and value >= 0:
14
28
  dividend, divisor = fractionize(value=value, modulo=modulo)
@@ -23,7 +37,9 @@ def parse_int(value: Union[int, float], modulo: int) -> int:
23
37
  return result
24
38
 
25
39
 
26
- def fractionize(value: float, modulo: int, precision: Optional[int] = None) -> Tuple[int, int]:
40
+ def fractionize(
41
+ value: float, modulo: int, precision: Optional[int] = None
42
+ ) -> Tuple[int, int]:
27
43
  getcontext().prec = 50
28
44
 
29
45
  if precision is None:
@@ -40,7 +56,9 @@ def fractionize(value: float, modulo: int, precision: Optional[int] = None) -> T
40
56
 
41
57
  if scaling_factor > 10**precision:
42
58
  # If scaling factor is too large, discard excess part of integer value
43
- integer_value = int(integer_value / (10 ** (scaling_factor - 10**precision)))
59
+ integer_value = int(
60
+ integer_value / (10 ** (scaling_factor - 10**precision))
61
+ )
44
62
  break
45
63
  elif scaling_factor < 10 ** (precision - 1):
46
64
  # If scaling factor is too small, multiply dividend and divisor 10 times