-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Ciphertext.py
119 lines (104 loc) · 5.02 KB
/
Ciphertext.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
from typing import Union
from lightphe.models.Homomorphic import Homomorphic
from lightphe.models.Algorithm import Algorithm
from lightphe.cryptosystems.RSA import RSA
from lightphe.cryptosystems.ElGamal import ElGamal
from lightphe.cryptosystems.Paillier import Paillier
from lightphe.cryptosystems.DamgardJurik import DamgardJurik
from lightphe.cryptosystems.OkamotoUchiyama import OkamotoUchiyama
from lightphe.cryptosystems.Benaloh import Benaloh
from lightphe.cryptosystems.NaccacheStern import NaccacheStern
from lightphe.cryptosystems.GoldwasserMicali import GoldwasserMicali
from lightphe.cryptosystems.EllipticCurveElGamal import EllipticCurveElGamal
from lightphe.commons import phe_utils
from lightphe.commons.logger import Logger
logger = Logger(module="lightphe/models/Ciphertext.py")
# pylint: disable=too-few-public-methods, no-else-return
class Ciphertext:
def __init__(self, algorithm_name: str, keys: dict, value: Union[int, tuple, list]):
self.algorithm_name = algorithm_name
self.keys = keys
self.value = value
if algorithm_name == Algorithm.RSA:
cs = RSA(keys=keys)
elif algorithm_name == Algorithm.ElGamal:
cs = ElGamal(keys=keys)
elif algorithm_name == Algorithm.ExponentialElGamal:
cs = ElGamal(keys=keys, exponential=True)
elif algorithm_name == Algorithm.EllipticCurveElGamal:
cs = EllipticCurveElGamal(keys=keys)
elif algorithm_name == Algorithm.Paillier:
cs = Paillier(keys=keys)
elif algorithm_name == Algorithm.DamgardJurik:
cs = DamgardJurik(keys=keys)
elif algorithm_name == Algorithm.OkamotoUchiyama:
cs = OkamotoUchiyama(keys=keys)
elif algorithm_name == Algorithm.Benaloh:
cs = Benaloh(keys=keys)
elif algorithm_name == Algorithm.NaccacheStern:
cs = NaccacheStern(keys=keys)
elif algorithm_name == Algorithm.GoldwasserMicali:
cs = GoldwasserMicali(keys=keys)
else:
raise ValueError(f"unimplemented algorithm - {algorithm_name}")
self.cs: Homomorphic = cs
def __str__(self) -> str:
return f"Ciphertext({self.value})"
def __repr__(self) -> str:
return f"Ciphertext({self.value})"
def __add__(self, other: "Ciphertext") -> "Ciphertext":
"""
Perform homomorphic addition methods
Args:
other (Ciperhtext): some other ciphertext
Returns:
ciphertext (Ciphertext): homomorphic addition of ciphertext
"""
if self.cs.keys.get("public_key") is None:
raise ValueError("You must have public key to perform homomorphic addition")
result = self.cs.add(ciphertext1=self.value, ciphertext2=other.value)
return Ciphertext(algorithm_name=self.algorithm_name, keys=self.keys, value=result)
def __mul__(self, other: Union["Ciphertext", int, float]) -> "Ciphertext":
"""
Perform homomorphic multiplication or multiply a ciphertext with a known constant
Args:
other (int | float | Ciphertext): a known plain constant of some other ciphertext
Returns
homomorphic multiplication of ciphertexts | scalar multiplication of ciphertext
"""
if self.cs.keys.get("public_key") is None:
raise ValueError("You must have public key to perform homomorphic multiplication")
if isinstance(other, Ciphertext):
# Handle multiplication with another EncryptedObject
result = self.cs.multiply(ciphertext1=self.value, ciphertext2=other.value)
elif isinstance(other, int):
result = self.cs.multiply_by_contant(ciphertext=self.value, constant=other)
elif isinstance(other, float):
constant = phe_utils.parse_int(value=other, modulo=self.cs.plaintext_modulo)
result = self.cs.multiply_by_contant(ciphertext=self.value, constant=constant)
else:
raise ValueError(
f"A ciphertext can be multiplied by either ciphertext itself or a scalar but it is {type(other)}"
)
return Ciphertext(algorithm_name=self.algorithm_name, keys=self.keys, value=result)
def __rmul__(self, constant: Union[int, float]) -> "Ciphertext":
"""
Multiply a ciphertext with a known constant
Args:
constant (int | float): a known plain constant
Returns
scalar multiplication of ciphertext
"""
return self.__mul__(other=constant)
def __xor__(self, other: "Ciphertext") -> "Ciphertext":
"""
Perform homomorphic xor
Args:
other (| Ciphertext): some other ciphertext
Returns
homomorphic xor of ciphertexts
"""
if self.cs.keys.get("public_key") is None:
raise ValueError("You must have public key to perform homomorphic xor")
result = self.cs.xor(ciphertext1=self.value, ciphertext2=other.value)
return Ciphertext(algorithm_name=self.algorithm_name, keys=self.keys, value=result)