lightphe 0.0.13__tar.gz → 0.0.15__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 (55) hide show
  1. {lightphe-0.0.13 → lightphe-0.0.15}/PKG-INFO +46 -23
  2. {lightphe-0.0.13 → lightphe-0.0.15}/README.md +45 -22
  3. {lightphe-0.0.13 → lightphe-0.0.15}/lightphe/__init__.py +7 -47
  4. {lightphe-0.0.13 → lightphe-0.0.15}/lightphe/cryptosystems/Benaloh.py +0 -6
  5. {lightphe-0.0.13 → lightphe-0.0.15}/lightphe/cryptosystems/DamgardJurik.py +0 -6
  6. {lightphe-0.0.13 → lightphe-0.0.15}/lightphe/cryptosystems/ElGamal.py +0 -3
  7. {lightphe-0.0.13 → lightphe-0.0.15}/lightphe/cryptosystems/EllipticCurveElGamal.py +5 -18
  8. {lightphe-0.0.13 → lightphe-0.0.15}/lightphe/cryptosystems/GoldwasserMicali.py +0 -6
  9. {lightphe-0.0.13 → lightphe-0.0.15}/lightphe/cryptosystems/NaccacheStern.py +0 -6
  10. {lightphe-0.0.13 → lightphe-0.0.15}/lightphe/cryptosystems/OkamotoUchiyama.py +0 -10
  11. {lightphe-0.0.13 → lightphe-0.0.15}/lightphe/cryptosystems/Paillier.py +0 -6
  12. {lightphe-0.0.13 → lightphe-0.0.15}/lightphe/cryptosystems/RSA.py +0 -12
  13. {lightphe-0.0.13 → lightphe-0.0.15}/lightphe/models/Homomorphic.py +15 -10
  14. {lightphe-0.0.13 → lightphe-0.0.15}/lightphe.egg-info/PKG-INFO +46 -23
  15. {lightphe-0.0.13 → lightphe-0.0.15}/lightphe.egg-info/SOURCES.txt +0 -8
  16. lightphe-0.0.13/requirements.txt → lightphe-0.0.15/lightphe.egg-info/requires.txt +2 -1
  17. lightphe-0.0.13/lightphe.egg-info/requires.txt → lightphe-0.0.15/requirements.txt +1 -0
  18. {lightphe-0.0.13 → lightphe-0.0.15}/setup.py +1 -1
  19. lightphe-0.0.15/tests/test_ellipticcurveelgamal.py +134 -0
  20. {lightphe-0.0.13 → lightphe-0.0.15}/tests/test_okamoto.py +1 -1
  21. lightphe-0.0.13/lightphe/commons/binary_operations.py +0 -147
  22. lightphe-0.0.13/lightphe/elliptic_curve_forms/edwards.py +0 -89
  23. lightphe-0.0.13/lightphe/elliptic_curve_forms/koblitz.py +0 -166
  24. lightphe-0.0.13/lightphe/elliptic_curve_forms/weierstrass.py +0 -120
  25. lightphe-0.0.13/lightphe/models/Curve.py +0 -29
  26. lightphe-0.0.13/lightphe/models/EllipticCurve.py +0 -196
  27. lightphe-0.0.13/tests/__init__.py +0 -0
  28. lightphe-0.0.13/tests/test_ellipticcurve.py +0 -75
  29. lightphe-0.0.13/tests/test_ellipticcurveelgamal.py +0 -263
  30. {lightphe-0.0.13 → lightphe-0.0.15}/LICENSE +0 -0
  31. {lightphe-0.0.13 → lightphe-0.0.15}/lightphe/commons/__init__.py +0 -0
  32. {lightphe-0.0.13 → lightphe-0.0.15}/lightphe/commons/logger.py +0 -0
  33. {lightphe-0.0.13 → lightphe-0.0.15}/lightphe/commons/phe_utils.py +0 -0
  34. {lightphe-0.0.13 → lightphe-0.0.15}/lightphe/cryptosystems/__init__.py +0 -0
  35. {lightphe-0.0.13 → lightphe-0.0.15}/lightphe/models/Algorithm.py +0 -0
  36. {lightphe-0.0.13 → lightphe-0.0.15}/lightphe/models/Ciphertext.py +0 -0
  37. {lightphe-0.0.13 → lightphe-0.0.15}/lightphe/models/Tensor.py +0 -0
  38. {lightphe-0.0.13/lightphe/elliptic_curve_forms → lightphe-0.0.15/lightphe/models}/__init__.py +0 -0
  39. {lightphe-0.0.13 → lightphe-0.0.15}/lightphe.egg-info/dependency_links.txt +0 -0
  40. {lightphe-0.0.13 → lightphe-0.0.15}/lightphe.egg-info/top_level.txt +0 -0
  41. {lightphe-0.0.13 → lightphe-0.0.15}/setup.cfg +0 -0
  42. {lightphe-0.0.13/lightphe/models → lightphe-0.0.15/tests}/__init__.py +0 -0
  43. {lightphe-0.0.13 → lightphe-0.0.15}/tests/test_benaloh.py +0 -0
  44. {lightphe-0.0.13 → lightphe-0.0.15}/tests/test_ciphertexts.py +0 -0
  45. {lightphe-0.0.13 → lightphe-0.0.15}/tests/test_cloud.py +0 -0
  46. {lightphe-0.0.13 → lightphe-0.0.15}/tests/test_damgard.py +0 -0
  47. {lightphe-0.0.13 → lightphe-0.0.15}/tests/test_elgamal.py +0 -0
  48. {lightphe-0.0.13 → lightphe-0.0.15}/tests/test_exporting_keys.py +0 -0
  49. {lightphe-0.0.13 → lightphe-0.0.15}/tests/test_goldwasser.py +0 -0
  50. {lightphe-0.0.13 → lightphe-0.0.15}/tests/test_keys.py +0 -0
  51. {lightphe-0.0.13 → lightphe-0.0.15}/tests/test_naccache.py +0 -0
  52. {lightphe-0.0.13 → lightphe-0.0.15}/tests/test_paillier.py +0 -0
  53. {lightphe-0.0.13 → lightphe-0.0.15}/tests/test_rsa.py +0 -0
  54. {lightphe-0.0.13 → lightphe-0.0.15}/tests/test_salary.py +0 -0
  55. {lightphe-0.0.13 → lightphe-0.0.15}/tests/test_tensors.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lightphe
3
- Version: 0.0.13
3
+ Version: 0.0.15
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
@@ -23,8 +23,6 @@ License-File: LICENSE
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
25
  [![arXiv](https://img.shields.io/badge/arXiv-2408.05219-b31b1b.svg?logo=arXiv)](https://arxiv.org/abs/2408.05219)
26
- [![Hacker News](https://img.shields.io/badge/dynamic/json?color=orange&label=Hacker%20News&query=score&url=https%3A%2F%2Fhacker-news.firebaseio.com%2Fv0%2Fitem%2F43024283.json&logo=y-combinator)](https://news.ycombinator.com/item?id=43024283)
27
- <!-- [![DOI](http://img.shields.io/:DOI-10.48550/arXiv.2408.05219-blue.svg?style=flat)](https://arxiv.org/abs/2408.05219) -->
28
26
 
29
27
  [![Blog](https://img.shields.io/:blog-sefiks.com-blue.svg?style=flat&logo=wordpress)](https://sefiks.com)
30
28
  [![YouTube](https://img.shields.io/:youtube-@sefiks-red.svg?style=flat&logo=youtube)](https://www.youtube.com/@sefiks?sub_confirmation=1)
@@ -254,11 +252,9 @@ ECC is a powerful public-key cryptosystem based on the algebraic structure of el
254
252
  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.
255
253
 
256
254
  ```python
257
- forms = ["weierstass", "edwards", "koblitz"]
258
-
259
255
  phe = LightPHE(
260
256
  algorithm_name="EllipticCurve-ElGamal",
261
- form=forms[1],
257
+ form="edwards", # or weierstrass, koblitz
262
258
  )
263
259
  ```
264
260
 
@@ -266,7 +262,7 @@ One of the crucial factors that define the security level of an elliptic curve c
266
262
 
267
263
  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.
268
264
 
269
- 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.
265
+ See [`curves`](https://github.com/serengil/LightECC) page for a list of all supported forms, curves and their details.
270
266
 
271
267
  ### Vector Embeddings and Tensors
272
268
 
@@ -345,24 +341,42 @@ Many machine learning models rely on a two-tower architecture, including facial
345
341
  For example, suppose all facial embeddings in your database are encrypted on-prem in advance. When verifying an identity, the attempted facial embedding is generated on an edge device or in the cloud. You can compute the encrypted similarity by performing a dot product between the encrypted vector and the plain vector, ensuring secure comparison without decrypting sensitive data. Only additively homomorphic cryptosystems offer encrypted similarity calculation.
346
342
 
347
343
  ```python
348
- # build an additively homomorphic cryptosystem (e.g. Paillier)
349
- cs = LightPHE("Paillier")
350
-
351
- # define plain vectors - suppose those are l2 normalized already
344
+ # define a plain vectors for source and target
352
345
  alpha = [7.1, 5.2, 5.3, 2.4, 3.5, 4.6] # On-prem vector (user tower)
353
346
  beta = [5.6, 3.7, 2.8, 4, 0, 5.9] # Cloud vector (item tower)
347
+ expected_similarity = sum(x * y for x, y in zip(alpha, beta))
354
348
 
355
- # encrypt embedding
349
+ # build an additively homomorphic cryptosystem (e.g. Paillier) on-prem
350
+ cs = LightPHE(algorithm_name = "Paillier", precision = 19)
351
+
352
+ # export keys
353
+ cs.export_keys("secret.txt")
354
+ cs.export_keys("public.txt", public=True)
355
+
356
+ # encrypt source embedding
356
357
  encrypted_alpha = cs.encrypt(alpha)
357
358
 
358
- # dot product of encrypted embedding and plain embedding
359
+ # remove cryptosystem and plain alpha not to be leaked in cloud
360
+ del cs, alpha
361
+
362
+ # restore the cryptosystem in cloud with only public key
363
+ cloud_cs = LightPHE(algorithm_name = "Paillier", precision = 19, key_file = "public.txt")
364
+
365
+ # dot product of encrypted and plain embedding pair
359
366
  encrypted_cosine_similarity = encrypted_alpha @ beta
360
367
 
361
- # decrypt similarity
362
- cosine_similarity = cs.decrypt(encrypted_cosine_similarity)[0]
368
+ # computed by the cloud but cloud cannot decrypt it
369
+ with pytest.raises(ValueError, match="must have private key"):
370
+ cloud_cs.decrypt(encrypted_cosine_similarity)
371
+
372
+ # restore the cryptosystem on-prem with secret key
373
+ cs = LightPHE(algorithm_name = "Paillier", precision = 19, key_file = "secret.txt")
374
+
375
+ # decrypt similarity (on prem)
376
+ calculated_similarity = cs.decrypt(encrypted_cosine_similarity)[0]
363
377
 
364
378
  # proof of work
365
- assert abs(cosine_similarity - sum(x * y for x, y in zip(alpha, beta))) < 1e-2
379
+ assert abs(calculated_similarity - expected_similarity) < 1e-2
366
380
  ```
367
381
 
368
382
  # Contributing
@@ -392,13 +406,22 @@ Also, your company's logo will be shown on README on GitHub if you become sponso
392
406
  Please cite LightPHE in your publications if it helps your research. Here is its BibTex entry:
393
407
 
394
408
  ```BibTeX
395
- @misc{serengil2024lightphe,
396
- title = {LightPHE: Integrating Partially Homomorphic Encryption into Python with Extensive Cloud Environment Evaluations},
397
- author = {Serengil, Sefik Ilkin and Ozpinar, Alper},
398
- year = {2024},
399
- publisher = {arXiv},
400
- url = {https://arxiv.org/abs/2408.05219},
401
- doi = {10.48550/arXiv.2408.05219}
409
+ @article{serengil2024lightphe,
410
+ title={LightPHE: Integrating Partially Homomorphic Encryption into Python with Extensive Cloud Environment Evaluations},
411
+ author={Serengil, Sefik Ilkin and Ozpinar, Alper},
412
+ journal={arXiv preprint arXiv:2408.05219},
413
+ note={doi: 10.48550/arXiv.2408.05219. [Online]. Available: \url{https://arxiv.org/abs/2408.05219}},
414
+ year={2025}
415
+ }
416
+ ```
417
+
418
+ ```BibTeX
419
+ @article{serengil2025vectorsimilarity,
420
+ title={Encrypted Vector Similarity Computations Using Partially Homomorphic Encryption: Applications and Performance Analysis},
421
+ author={Serengil, Sefik and Ozpinar, Alper},
422
+ journal={arXiv preprint arXiv:2503.05850},
423
+ note={doi: 10.48550/arXiv.2503.05850. [Online]. Available: \url{https://arxiv.org/abs/2503.05850}},
424
+ year={2025}
402
425
  }
403
426
  ```
404
427
 
@@ -7,8 +7,6 @@
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
9
  [![arXiv](https://img.shields.io/badge/arXiv-2408.05219-b31b1b.svg?logo=arXiv)](https://arxiv.org/abs/2408.05219)
10
- [![Hacker News](https://img.shields.io/badge/dynamic/json?color=orange&label=Hacker%20News&query=score&url=https%3A%2F%2Fhacker-news.firebaseio.com%2Fv0%2Fitem%2F43024283.json&logo=y-combinator)](https://news.ycombinator.com/item?id=43024283)
11
- <!-- [![DOI](http://img.shields.io/:DOI-10.48550/arXiv.2408.05219-blue.svg?style=flat)](https://arxiv.org/abs/2408.05219) -->
12
10
 
13
11
  [![Blog](https://img.shields.io/:blog-sefiks.com-blue.svg?style=flat&logo=wordpress)](https://sefiks.com)
14
12
  [![YouTube](https://img.shields.io/:youtube-@sefiks-red.svg?style=flat&logo=youtube)](https://www.youtube.com/@sefiks?sub_confirmation=1)
@@ -238,11 +236,9 @@ ECC is a powerful public-key cryptosystem based on the algebraic structure of el
238
236
  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.
239
237
 
240
238
  ```python
241
- forms = ["weierstass", "edwards", "koblitz"]
242
-
243
239
  phe = LightPHE(
244
240
  algorithm_name="EllipticCurve-ElGamal",
245
- form=forms[1],
241
+ form="edwards", # or weierstrass, koblitz
246
242
  )
247
243
  ```
248
244
 
@@ -250,7 +246,7 @@ One of the crucial factors that define the security level of an elliptic curve c
250
246
 
251
247
  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.
252
248
 
253
- 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.
249
+ See [`curves`](https://github.com/serengil/LightECC) page for a list of all supported forms, curves and their details.
254
250
 
255
251
  ### Vector Embeddings and Tensors
256
252
 
@@ -329,24 +325,42 @@ Many machine learning models rely on a two-tower architecture, including facial
329
325
  For example, suppose all facial embeddings in your database are encrypted on-prem in advance. When verifying an identity, the attempted facial embedding is generated on an edge device or in the cloud. You can compute the encrypted similarity by performing a dot product between the encrypted vector and the plain vector, ensuring secure comparison without decrypting sensitive data. Only additively homomorphic cryptosystems offer encrypted similarity calculation.
330
326
 
331
327
  ```python
332
- # build an additively homomorphic cryptosystem (e.g. Paillier)
333
- cs = LightPHE("Paillier")
334
-
335
- # define plain vectors - suppose those are l2 normalized already
328
+ # define a plain vectors for source and target
336
329
  alpha = [7.1, 5.2, 5.3, 2.4, 3.5, 4.6] # On-prem vector (user tower)
337
330
  beta = [5.6, 3.7, 2.8, 4, 0, 5.9] # Cloud vector (item tower)
331
+ expected_similarity = sum(x * y for x, y in zip(alpha, beta))
338
332
 
339
- # encrypt embedding
333
+ # build an additively homomorphic cryptosystem (e.g. Paillier) on-prem
334
+ cs = LightPHE(algorithm_name = "Paillier", precision = 19)
335
+
336
+ # export keys
337
+ cs.export_keys("secret.txt")
338
+ cs.export_keys("public.txt", public=True)
339
+
340
+ # encrypt source embedding
340
341
  encrypted_alpha = cs.encrypt(alpha)
341
342
 
342
- # dot product of encrypted embedding and plain embedding
343
+ # remove cryptosystem and plain alpha not to be leaked in cloud
344
+ del cs, alpha
345
+
346
+ # restore the cryptosystem in cloud with only public key
347
+ cloud_cs = LightPHE(algorithm_name = "Paillier", precision = 19, key_file = "public.txt")
348
+
349
+ # dot product of encrypted and plain embedding pair
343
350
  encrypted_cosine_similarity = encrypted_alpha @ beta
344
351
 
345
- # decrypt similarity
346
- cosine_similarity = cs.decrypt(encrypted_cosine_similarity)[0]
352
+ # computed by the cloud but cloud cannot decrypt it
353
+ with pytest.raises(ValueError, match="must have private key"):
354
+ cloud_cs.decrypt(encrypted_cosine_similarity)
355
+
356
+ # restore the cryptosystem on-prem with secret key
357
+ cs = LightPHE(algorithm_name = "Paillier", precision = 19, key_file = "secret.txt")
358
+
359
+ # decrypt similarity (on prem)
360
+ calculated_similarity = cs.decrypt(encrypted_cosine_similarity)[0]
347
361
 
348
362
  # proof of work
349
- assert abs(cosine_similarity - sum(x * y for x, y in zip(alpha, beta))) < 1e-2
363
+ assert abs(calculated_similarity - expected_similarity) < 1e-2
350
364
  ```
351
365
 
352
366
  # Contributing
@@ -376,13 +390,22 @@ Also, your company's logo will be shown on README on GitHub if you become sponso
376
390
  Please cite LightPHE in your publications if it helps your research. Here is its BibTex entry:
377
391
 
378
392
  ```BibTeX
379
- @misc{serengil2024lightphe,
380
- title = {LightPHE: Integrating Partially Homomorphic Encryption into Python with Extensive Cloud Environment Evaluations},
381
- author = {Serengil, Sefik Ilkin and Ozpinar, Alper},
382
- year = {2024},
383
- publisher = {arXiv},
384
- url = {https://arxiv.org/abs/2408.05219},
385
- doi = {10.48550/arXiv.2408.05219}
393
+ @article{serengil2024lightphe,
394
+ title={LightPHE: Integrating Partially Homomorphic Encryption into Python with Extensive Cloud Environment Evaluations},
395
+ author={Serengil, Sefik Ilkin and Ozpinar, Alper},
396
+ journal={arXiv preprint arXiv:2408.05219},
397
+ note={doi: 10.48550/arXiv.2408.05219. [Online]. Available: \url{https://arxiv.org/abs/2408.05219}},
398
+ year={2025}
399
+ }
400
+ ```
401
+
402
+ ```BibTeX
403
+ @article{serengil2025vectorsimilarity,
404
+ title={Encrypted Vector Similarity Computations Using Partially Homomorphic Encryption: Applications and Performance Analysis},
405
+ author={Serengil, Sefik and Ozpinar, Alper},
406
+ journal={arXiv preprint arXiv:2503.05850},
407
+ note={doi: 10.48550/arXiv.2503.05850. [Online]. Available: \url{https://arxiv.org/abs/2503.05850}},
408
+ year={2025}
386
409
  }
387
410
  ```
388
411
 
@@ -9,13 +9,16 @@ import copy
9
9
 
10
10
  # 3rd party dependencies
11
11
  from tqdm import tqdm
12
+ from lightecc.interfaces.elliptic_curve import EllipticCurvePoint
13
+ from lightecc.forms.weierstrass import Weierstrass
14
+ from lightecc.forms.edwards import TwistedEdwards
15
+ from lightecc.forms.koblitz import Koblitz
12
16
 
13
17
  # project dependencies
14
18
  from lightphe.models.Homomorphic import Homomorphic
15
19
  from lightphe.models.Ciphertext import Ciphertext
16
20
  from lightphe.models.Algorithm import Algorithm
17
21
  from lightphe.models.Tensor import Fraction, EncryptedTensor
18
- from lightphe.models.EllipticCurve import EllipticCurvePoint
19
22
  from lightphe.commons import phe_utils
20
23
  from lightphe.commons.logger import Logger
21
24
 
@@ -29,16 +32,13 @@ from lightphe.cryptosystems.Benaloh import Benaloh
29
32
  from lightphe.cryptosystems.NaccacheStern import NaccacheStern
30
33
  from lightphe.cryptosystems.GoldwasserMicali import GoldwasserMicali
31
34
  from lightphe.cryptosystems.EllipticCurveElGamal import EllipticCurveElGamal
32
- from lightphe.elliptic_curve_forms.weierstrass import Weierstrass
33
- from lightphe.elliptic_curve_forms.edwards import TwistedEdwards
34
- from lightphe.elliptic_curve_forms.koblitz import Koblitz
35
35
 
36
36
 
37
37
  # pylint: disable=eval-used, simplifiable-if-expression, too-few-public-methods
38
38
 
39
39
  logger = Logger(module="lightphe/__init__.py")
40
40
 
41
- VERSION = "0.0.13"
41
+ VERSION = "0.0.15"
42
42
 
43
43
 
44
44
  class LightPHE:
@@ -94,7 +94,7 @@ class LightPHE:
94
94
 
95
95
  def __build_cryptosystem(
96
96
  self,
97
- algorithm_name: str,
97
+ algorithm_name: str = "Paillier",
98
98
  keys: Optional[dict] = None,
99
99
  key_size: Optional[int] = None,
100
100
  form: Optional[str] = None,
@@ -115,6 +115,7 @@ class LightPHE:
115
115
  algorithm_name (str): RSA | ElGamal | Exponential-ElGamal | EllipticCurve-ElGamal
116
116
  | Paillier | Damgard-Jurik | Okamoto-Uchiyama | Benaloh | Naccache-Stern
117
117
  | Goldwasser-Micali | Edwards-ElGamal
118
+ Default is Paillier.
118
119
  keys (dict): optional private-public key pair
119
120
  key_file (str): if keys are exported, you can load them into cryptosystem
120
121
  key_size (int): key size in bits
@@ -464,44 +465,3 @@ def encrypt_float(
464
465
  logger.error(f"Exception while running encrypt_float: {str(err)}")
465
466
  logger.error(traceback.format_exc())
466
467
  raise err
467
-
468
-
469
- class ECC:
470
- __version__ = VERSION
471
-
472
- def __init__(
473
- self, form_name: Optional[str] = None, curve_name: Optional[str] = None
474
- ):
475
- """
476
- Construct an Elliptic Curve over a finite field (prime or binary)
477
- Args:
478
- form_name (str): specifies the form of the elliptic curve.
479
- Options: 'weierstrass' (default), 'edwards', 'koblitz'.
480
- curve_name (str): specifies the elliptic curve to use.
481
- Options:
482
- - e.g. ed25519, ed448 for edwards form
483
- - e.g. secp256k1 for weierstrass form
484
- - e.g. k-409 for koblitz form
485
- List of all available curves:
486
- github.com/serengil/LightPHE/blob/master/lightphe/elliptic_curve_forms/README.md
487
- """
488
- if form_name is None or form_name == "weierstrass":
489
- self.curve = Weierstrass(curve=curve_name)
490
- elif form_name in "edwards":
491
- self.curve = TwistedEdwards(curve=curve_name)
492
- elif form_name in "koblitz":
493
- self.curve = Koblitz(curve=curve_name)
494
- else:
495
- raise ValueError(f"unimplemented curve form - {form_name}")
496
-
497
- # base point
498
- self.G = EllipticCurvePoint(self.curve.G[0], self.curve.G[1], self.curve)
499
-
500
- # order of the curve
501
- self.n = self.curve.n
502
-
503
- # point at infinity or neutral / identity element
504
- self.O = EllipticCurvePoint(self.curve.O[0], self.curve.O[1], self.curve)
505
-
506
- # modulo
507
- self.modulo = self.curve.modulo
@@ -169,12 +169,6 @@ class Benaloh(Homomorphic):
169
169
  n = self.keys["public_key"]["n"]
170
170
  return (ciphertext1 * ciphertext2) % n
171
171
 
172
- def multiply(self, ciphertext1: int, ciphertext2: int) -> int:
173
- raise ValueError("Benaloh is not homomorphic with respect to the multiplication")
174
-
175
- def xor(self, ciphertext1: int, ciphertext2: int) -> int:
176
- raise ValueError("Benaloh is not homomorphic with respect to the exclusive or")
177
-
178
172
  def multiply_by_contant(self, ciphertext: int, constant: int) -> int:
179
173
  """
180
174
  Multiply a ciphertext with a plain constant.
@@ -125,12 +125,6 @@ class DamgardJurik(Homomorphic):
125
125
  modulo = pow(n, s + 1)
126
126
  return (ciphertext1 * ciphertext2) % modulo
127
127
 
128
- def multiply(self, ciphertext1: int, ciphertext2: int) -> int:
129
- raise ValueError("Damgard-Jurik is not homomorphic with respect to the multiplication")
130
-
131
- def xor(self, ciphertext1: int, ciphertext2: int) -> int:
132
- raise ValueError("Damgard-Jurik is not homomorphic with respect to the exclusive or")
133
-
134
128
  def multiply_by_contant(self, ciphertext: int, constant: int) -> int:
135
129
  """
136
130
  Multiply a ciphertext by a known plain constant
@@ -169,9 +169,6 @@ class ElGamal(Homomorphic):
169
169
  p = self.keys["public_key"]["p"]
170
170
  return (ciphertext1[0] * ciphertext2[0]) % p, (ciphertext1[1] * ciphertext2[1]) % p
171
171
 
172
- def xor(self, ciphertext1: tuple, ciphertext2: tuple) -> int:
173
- raise ValueError("ElGamal is not homomorphic with respect to the exclusive or")
174
-
175
172
  def multiply_by_contant(self, ciphertext: tuple, constant: int) -> tuple:
176
173
  if self.exponential is False:
177
174
  raise ValueError("ElGamal is not supporting multiplying ciphertext by a known constant")
@@ -2,9 +2,12 @@
2
2
  import random
3
3
  from typing import Optional
4
4
 
5
+ # 3rd party dependencies
6
+ from lightecc import LightECC as ECC
7
+ from lightecc.interfaces.elliptic_curve import EllipticCurvePoint
8
+
5
9
  # project dependencies
6
10
  from lightphe.models.Homomorphic import Homomorphic
7
- from lightphe.models.EllipticCurve import EllipticCurvePoint
8
11
  from lightphe.commons.logger import Logger
9
12
 
10
13
  logger = Logger(module="lightphe/cryptosystems/EllipticCurveElGamal.py")
@@ -40,9 +43,6 @@ class EllipticCurveElGamal(Homomorphic):
40
43
  - secp256k1 for weierstrass form
41
44
  This parameter is only used if `algorithm_name` is 'EllipticCurve-ElGamal'.
42
45
  """
43
- # to avoid circular import, import ECC class here
44
- from lightphe import ECC
45
-
46
46
  self.ecc = ECC(form_name=form, curve_name=curve)
47
47
 
48
48
  self.keys = keys or self.generate_keys(key_size or self.ecc.n.bit_length())
@@ -142,11 +142,6 @@ class EllipticCurveElGamal(Homomorphic):
142
142
 
143
143
  return s_prime / self.ecc.G
144
144
 
145
- def multiply(self, ciphertext1: tuple, ciphertext2: tuple) -> tuple:
146
- raise ValueError(
147
- "Elliptic Curve ElGamal is not homomorphic with respect to the multiplication"
148
- )
149
-
150
145
  def add(self, ciphertext1: tuple, ciphertext2: tuple) -> tuple:
151
146
  """
152
147
  Perform homomorphic addition on encrypted data
@@ -171,10 +166,7 @@ class EllipticCurveElGamal(Homomorphic):
171
166
 
172
167
  return a.get_point(), b.get_point()
173
168
 
174
- def xor(self, ciphertext1: tuple, ciphertext2: tuple) -> int:
175
- raise ValueError(
176
- "Elliptic Curve ElGamal is not homomorphic with respect to the exclusive or"
177
- )
169
+
178
170
 
179
171
  def multiply_by_contant(self, ciphertext: tuple, constant: int) -> tuple:
180
172
  """
@@ -198,8 +190,3 @@ class EllipticCurveElGamal(Homomorphic):
198
190
  Q_prime = Q * constant
199
191
 
200
192
  return P_prime.get_point(), Q_prime.get_point()
201
-
202
- def reencrypt(self, ciphertext: tuple) -> tuple:
203
- raise ValueError(
204
- "Elliptic Curve ElGamal does not support regeneration of ciphertext"
205
- )
@@ -193,9 +193,3 @@ class GoldwasserMicali(Homomorphic):
193
193
  ciphertext3.append((c1 * c2) % self.ciphertext_modulo)
194
194
 
195
195
  return ciphertext3
196
-
197
- def multiply_by_contant(self, ciphertext: int, constant: int):
198
- raise ValueError("Goldwasser-Micali does not support multiplying with constant")
199
-
200
- def reencrypt(self, ciphertext: int):
201
- raise ValueError("Goldwasser-Micali does not support re-encryption")
@@ -257,12 +257,6 @@ class NaccacheStern(Homomorphic):
257
257
  """
258
258
  return (ciphertext1 * ciphertext2) % self.ciphertext_modulo
259
259
 
260
- def multiply(self, ciphertext1: int, ciphertext2: int) -> int:
261
- raise ValueError("Naccache-Stern is not homomorphic with respect to the multiplication")
262
-
263
- def xor(self, ciphertext1: int, ciphertext2: int) -> int:
264
- raise ValueError("Naccache-Stern is not homomorphic with respect to the exclusive or")
265
-
266
260
  def multiply_by_contant(self, ciphertext: int, constant: int) -> int:
267
261
  """
268
262
  Multiply a ciphertext with a plain constant.
@@ -127,16 +127,6 @@ class OkamotoUchiyama(Homomorphic):
127
127
  n = self.keys["public_key"]["n"]
128
128
  return (ciphertext1 * ciphertext2) % n
129
129
 
130
- def multiply(self, ciphertext1: int, ciphertext2: int) -> int:
131
- raise ValueError(
132
- "Okamoto-Uchiyama is not homomorphic with respect to the multiplication"
133
- )
134
-
135
- def xor(self, ciphertext1: int, ciphertext2: int) -> int:
136
- raise ValueError(
137
- "Okamoto-Uchiyama is not homomorphic with respect to the exclusive or"
138
- )
139
-
140
130
  def multiply_by_contant(self, ciphertext: int, constant: int) -> int:
141
131
  """
142
132
  Multiply a ciphertext with a plain constant.
@@ -112,12 +112,6 @@ class Paillier(Homomorphic):
112
112
  n = self.keys["public_key"]["n"]
113
113
  return (ciphertext1 * ciphertext2) % (n * n)
114
114
 
115
- def multiply(self, ciphertext1: int, ciphertext2: int) -> int:
116
- raise ValueError("Paillier is not homomorphic with respect to the multiplication")
117
-
118
- def xor(self, ciphertext1: int, ciphertext2: int) -> int:
119
- raise ValueError("Paillier is not homomorphic with respect to the exclusive or")
120
-
121
115
  def multiply_by_contant(self, ciphertext: int, constant: int) -> int:
122
116
  """
123
117
  Multiply a ciphertext with a plain constant.
@@ -129,15 +129,3 @@ class RSA(Homomorphic):
129
129
  """
130
130
  n = self.keys["public_key"]["n"]
131
131
  return (ciphertext1 * ciphertext2) % n
132
-
133
- def add(self, ciphertext1: int, ciphertext2: int) -> int:
134
- raise ValueError("RSA is not homomorphic with respect to the addition")
135
-
136
- def xor(self, ciphertext1: int, ciphertext2: int) -> int:
137
- raise ValueError("RSA is not homomorphic with respect to the exclusive or")
138
-
139
- def multiply_by_contant(self, ciphertext: int, constant: int) -> int:
140
- raise ValueError("RSA is not supporting multiplying ciphertext by a known constant")
141
-
142
- def reencrypt(self, ciphertext: int) -> int:
143
- raise ValueError("RSA does not support re-encryption")
@@ -1,6 +1,10 @@
1
+ # built-in dependencies
1
2
  from typing import Optional, Union
2
3
  from abc import ABC, abstractmethod
3
4
 
5
+ # project dependencies
6
+ from lightphe.models.Algorithm import Algorithm
7
+
4
8
  # Signature for supported cryptosystems
5
9
 
6
10
 
@@ -27,26 +31,27 @@ class Homomorphic(ABC):
27
31
  def decrypt(self, ciphertext: Union[int, tuple, list]) -> int:
28
32
  pass
29
33
 
30
- @abstractmethod
31
34
  def add(
32
35
  self, ciphertext1: Union[int, tuple, list], ciphertext2: Union[int, tuple, list]
33
36
  ) -> Union[int, tuple, list]:
34
- pass
37
+ raise ValueError(f"{self.get_algorithm_name()} is not homomorphic with respect to the addition")
35
38
 
36
- @abstractmethod
37
39
  def multiply(
38
40
  self, ciphertext1: Union[int, tuple, list], ciphertext2: Union[int, tuple, list]
39
41
  ) -> Union[int, tuple]:
40
- pass
42
+ raise ValueError(f"{self.get_algorithm_name()} is not homomorphic with respect to the multiplication")
41
43
 
42
- @abstractmethod
43
44
  def xor(self, ciphertext1: list, ciphertext2: list) -> list:
44
- pass
45
+ raise ValueError(f"{self.get_algorithm_name()} is not homomorphic with respect to the exclusive or")
45
46
 
46
- @abstractmethod
47
47
  def multiply_by_contant(self, ciphertext: Union[int, tuple, list], constant: int) -> int:
48
- pass
48
+ raise ValueError(f"{self.get_algorithm_name()} is not supporting multiplying ciphertext by a known constant")
49
49
 
50
- @abstractmethod
51
50
  def reencrypt(self, ciphertext: Union[int, tuple, list]) -> Union[int, tuple, list]:
52
- pass
51
+ raise ValueError(f"{self.get_algorithm_name()} does not support re-encryption")
52
+
53
+ def get_algorithm_name(self) -> str:
54
+ class_name = self.__class__.__name__
55
+ algorithm_name = getattr(Algorithm, class_name, None)
56
+ assert isinstance(algorithm_name, str), f"Algorithm name for {class_name} is not defined"
57
+ return algorithm_name