@@ -40,34 +40,82 @@ def test_serial_cryptocontext(tmp_path):
4040 assert fhe .SerializeToFile (str (tmp_path / "ciphertext12.json" ), ct1 , fhe .JSON )
4141
4242
43+ VECTOR1_ROTATION = 1
44+ VECTOR2_ROTATION = 2
45+ VECTOR3_ROTATION = - 1
46+ VECTOR4_ROTATION = - 2
47+
4348@pytest .mark .parametrize ("mode" , [fhe .JSON , fhe .BINARY ])
4449def test_serial_cryptocontext_str (mode ):
4550 parameters = fhe .CCParamsBFVRNS ()
4651 parameters .SetPlaintextModulus (65537 )
4752 parameters .SetMultiplicativeDepth (2 )
4853
4954 cryptoContext = fhe .GenCryptoContext (parameters )
50- cryptoContext .Enable (fhe .PKESchemeFeature .PKE )
55+ cryptoContext .Enable (fhe .PKE )
56+ cryptoContext .Enable (fhe .KEYSWITCH )
57+ cryptoContext .Enable (fhe .LEVELEDSHE )
5158 cryptoContext .Enable (fhe .PKESchemeFeature .PRE )
5259
5360 keypair = cryptoContext .KeyGen ()
54- vectorOfInts = list (range (12 ))
55- plaintext = cryptoContext .MakePackedPlaintext (vectorOfInts )
56- ciphertext = cryptoContext .Encrypt (keypair .publicKey , plaintext )
57- evalKey = cryptoContext .ReKeyGen (keypair .secretKey , keypair .publicKey )
5861
62+ # First plaintext vector is encoded
63+ vectorOfInts1 = [1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 ]
64+ plaintext1 = cryptoContext .MakePackedPlaintext (vectorOfInts1 )
65+
66+ # Second plaintext vector is encoded
67+ vectorOfInts2 = [3 , 2 , 1 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 ]
68+ plaintext2 = cryptoContext .MakePackedPlaintext (vectorOfInts2 )
69+
70+ # Third plaintext vector is encoded
71+ vectorOfInts3 = [1 , 2 , 5 , 2 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 ]
72+ plaintext3 = cryptoContext .MakePackedPlaintext (vectorOfInts3 )
73+
74+ # Create a final array adding the three vectors
75+ initialPlaintextAddResult = [vectorOfInts1 [i ] + vectorOfInts2 [i ] + vectorOfInts3 [i ] for i in range (len (vectorOfInts1 ))]
76+ initialPlaintextAddResult = cryptoContext .MakePackedPlaintext (initialPlaintextAddResult )
77+
78+ # Multiply the values
79+ initialPlaintextMultResult = [vectorOfInts1 [i ] * vectorOfInts2 [i ] * vectorOfInts3 [i ] for i in range (len (vectorOfInts1 ))]
80+ initialPlaintextMultResult = cryptoContext .MakePackedPlaintext (initialPlaintextMultResult )
81+
82+ # Rotate the values
83+ initialPlaintextRot1 = rotate_vector (vectorOfInts1 , VECTOR1_ROTATION )
84+ initialPlaintextRot1 = cryptoContext .MakePackedPlaintext (initialPlaintextRot1 )
85+ initialPlaintextRot2 = rotate_vector (vectorOfInts2 , VECTOR2_ROTATION )
86+ initialPlaintextRot2 = cryptoContext .MakePackedPlaintext (initialPlaintextRot2 )
87+ initialPlaintextRot3 = rotate_vector (vectorOfInts3 , VECTOR3_ROTATION )
88+ initialPlaintextRot3 = cryptoContext .MakePackedPlaintext (initialPlaintextRot3 )
89+ initialPlaintextRot4 = rotate_vector (vectorOfInts3 , VECTOR4_ROTATION )
90+ initialPlaintextRot4 = cryptoContext .MakePackedPlaintext (initialPlaintextRot4 )
91+
92+ # The encoded vectors are encrypted
93+ ciphertext1 = cryptoContext .Encrypt (keypair .publicKey , plaintext1 )
94+ ciphertext2 = cryptoContext .Encrypt (keypair .publicKey , plaintext2 )
95+ ciphertext3 = cryptoContext .Encrypt (keypair .publicKey , plaintext3 )
96+
97+ evalKey = cryptoContext .ReKeyGen (keypair .secretKey , keypair .publicKey )
98+ cryptoContext .EvalMultKeyGen (keypair .secretKey )
99+ cryptoContext .EvalRotateKeyGen (keypair .secretKey , [VECTOR1_ROTATION , VECTOR2_ROTATION , VECTOR3_ROTATION , VECTOR4_ROTATION ])
59100
60101 cryptoContext_ser = fhe .Serialize (cryptoContext , mode )
61102 LOGGER .debug ("The cryptocontext has been serialized." )
62103 publickey_ser = fhe .Serialize (keypair .publicKey , mode )
63104 LOGGER .debug ("The public key has been serialized." )
64105 secretkey_ser = fhe .Serialize (keypair .secretKey , mode )
65106 LOGGER .debug ("The private key has been serialized." )
66- ciphertext_ser = fhe .Serialize (ciphertext , mode )
67- LOGGER .debug ("The ciphertext has been serialized." )
107+ ciphertext1_ser = fhe .Serialize (ciphertext1 , mode )
108+ LOGGER .debug ("The ciphertext 1 has been serialized." )
109+ ciphertext2_ser = fhe .Serialize (ciphertext2 , mode )
110+ LOGGER .debug ("The ciphertext 2 has been serialized." )
111+ ciphertext3_ser = fhe .Serialize (ciphertext3 , mode )
112+ LOGGER .debug ("The ciphertext 3 has been serialized." )
68113 evalKey_ser = fhe .Serialize (evalKey , mode )
69114 LOGGER .debug ("The evaluation key has been serialized." )
70-
115+ multKey_ser = fhe .SerializeEvalMultKeyString (mode , "" )
116+ LOGGER .debug ("The relinearization key has been serialized." )
117+ automorphismKey_ser = fhe .SerializeEvalAutomorphismKeyString (mode , "" )
118+ LOGGER .debug ("The rotation evaluation keys have been serialized." )
71119
72120 cryptoContext .ClearEvalMultKeys ()
73121 cryptoContext .ClearEvalAutomorphismKeys ()
@@ -85,10 +133,84 @@ def test_serial_cryptocontext_str(mode):
85133 assert isinstance (sk , fhe .PrivateKey )
86134 LOGGER .debug ("The private key has been deserialized." )
87135
88- ct = fhe .DeserializeCiphertextString (ciphertext_ser , mode )
89- assert isinstance (ct , fhe .Ciphertext )
90- LOGGER .debug ("The ciphertext has been reserialized." )
136+ ct1 = fhe .DeserializeCiphertextString (ciphertext1_ser , mode )
137+ assert isinstance (ct1 , fhe .Ciphertext )
138+ LOGGER .debug ("The ciphertext 1 has been reserialized." )
139+
140+ ct2 = fhe .DeserializeCiphertextString (ciphertext2_ser , mode )
141+ assert isinstance (ct2 , fhe .Ciphertext )
142+ LOGGER .debug ("The ciphertext 2 has been reserialized." )
143+
144+ ct3 = fhe .DeserializeCiphertextString (ciphertext3_ser , mode )
145+ assert isinstance (ct3 , fhe .Ciphertext )
146+ LOGGER .debug ("The ciphertext 3 has been reserialized." )
91147
92148 ek = fhe .DeserializeEvalKeyString (evalKey_ser , mode )
93149 assert isinstance (ek , fhe .EvalKey )
94150 LOGGER .debug ("The evaluation key has been deserialized." )
151+
152+ fhe .DeserializeEvalMultKeyString (multKey_ser , mode )
153+ LOGGER .debug ("The relinearization key has been deserialized." )
154+
155+ fhe .DeserializeEvalAutomorphismKeyString (automorphismKey_ser , mode )
156+ LOGGER .debug ("The rotation evaluation keys have been deserialized." )
157+
158+ # Homomorphic addition
159+
160+ ciphertextAdd12 = cc .EvalAdd (ct1 , ct2 )
161+ ciphertextAddResult = cc .EvalAdd (ciphertextAdd12 , ct3 )
162+
163+ # Homomorphic multiplication
164+ ciphertextMult12 = cc .EvalMult (ct1 , ct2 )
165+ ciphertextMultResult = cc .EvalMult (ciphertextMult12 , ct3 )
166+
167+ # Homomorphic rotation
168+ ciphertextRot1 = cc .EvalRotate (ct1 , VECTOR1_ROTATION )
169+ ciphertextRot2 = cc .EvalRotate (ct2 , VECTOR2_ROTATION )
170+ ciphertextRot3 = cc .EvalRotate (ct3 , VECTOR3_ROTATION )
171+ ciphertextRot4 = cc .EvalRotate (ct3 , VECTOR4_ROTATION )
172+
173+ # Decrypt the result of additions
174+ plaintextAddResult = cc .Decrypt (sk , ciphertextAddResult )
175+
176+ # Decrypt the result of multiplications
177+ plaintextMultResult = cc .Decrypt (sk , ciphertextMultResult )
178+
179+ # Decrypt the result of rotations
180+ plaintextRot1 = cc .Decrypt (sk , ciphertextRot1 )
181+ plaintextRot2 = cc .Decrypt (sk , ciphertextRot2 )
182+ plaintextRot3 = cc .Decrypt (sk , ciphertextRot3 )
183+ plaintextRot4 = cc .Decrypt (sk , ciphertextRot4 )
184+
185+ # Shows only the same number of elements as in the original plaintext vector
186+ # By default it will show all coefficients in the BFV-encoded polynomial
187+ plaintextRot1 .SetLength (len (vectorOfInts1 ))
188+ plaintextRot2 .SetLength (len (vectorOfInts1 ))
189+ plaintextRot3 .SetLength (len (vectorOfInts1 ))
190+ plaintextRot4 .SetLength (len (vectorOfInts1 ))
191+
192+ assert str (plaintextAddResult ) == str (initialPlaintextAddResult )
193+ assert str (plaintextMultResult ) == str (initialPlaintextMultResult )
194+ assert str (plaintextRot1 ) == str (initialPlaintextRot1 )
195+ assert str (plaintextRot2 ) == str (initialPlaintextRot2 )
196+ assert str (plaintextRot3 ) == str (initialPlaintextRot3 )
197+ assert str (plaintextRot4 ) == str (initialPlaintextRot4 )
198+
199+ def rotate_vector (vector , rotation ):
200+ """
201+ Rotate a vector by a specified number of positions.
202+ Positive values rotate left, negative values rotate right.
203+
204+ :param vector: List[int], the vector to rotate.
205+ :param rotation: int, the number of positions to rotate.
206+ :return: List[int], the rotated vector.
207+ """
208+ n = len (vector )
209+ if rotation > 0 :
210+ rotated = vector [rotation :] + [0 ] * rotation
211+ elif rotation < 0 :
212+ rotation = abs (rotation )
213+ rotated = [0 ] * rotation + vector [:n - rotation ]
214+ else :
215+ rotated = vector
216+ return rotated
0 commit comments