test_serial_cc.py 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. import logging
  2. import pytest
  3. import openfhe as fhe
  4. pytestmark = pytest.mark.skipif(fhe.get_native_int() == 32, reason="Doesn't work for NATIVE_INT=32")
  5. LOGGER = logging.getLogger("test_serial_cc")
  6. def test_serial_cryptocontext(tmp_path):
  7. parameters = fhe.CCParamsBFVRNS()
  8. parameters.SetPlaintextModulus(65537)
  9. parameters.SetMultiplicativeDepth(2)
  10. cryptoContext = fhe.GenCryptoContext(parameters)
  11. cryptoContext.Enable(fhe.PKESchemeFeature.PKE)
  12. keypair = cryptoContext.KeyGen()
  13. vectorOfInts1 = list(range(12))
  14. plaintext1 = cryptoContext.MakePackedPlaintext(vectorOfInts1)
  15. ciphertext1 = cryptoContext.Encrypt(keypair.publicKey, plaintext1)
  16. assert fhe.SerializeToFile(str(tmp_path / "cryptocontext.json"), cryptoContext, fhe.JSON)
  17. LOGGER.debug("The cryptocontext has been serialized.")
  18. assert fhe.SerializeToFile(str(tmp_path / "ciphertext1.json"), ciphertext1, fhe.JSON)
  19. fhe.ClearEvalMultKeys()
  20. cryptoContext.ClearEvalAutomorphismKeys()
  21. fhe.ReleaseAllContexts()
  22. cc, success = fhe.DeserializeCryptoContext(str(tmp_path / "cryptocontext.json"), fhe.JSON)
  23. assert success
  24. assert isinstance(cc, fhe.CryptoContext)
  25. assert fhe.SerializeToFile(str(tmp_path / "cryptocontext2.json"), cc, fhe.JSON)
  26. LOGGER.debug("The cryptocontext has been serialized.")
  27. ct1, success = fhe.DeserializeCiphertext(str(tmp_path / "ciphertext1.json"), fhe.JSON)
  28. assert success
  29. assert isinstance(ct1, fhe.Ciphertext)
  30. LOGGER.debug("Cryptocontext deserializes to %s %s", success, ct1)
  31. assert fhe.SerializeToFile(str(tmp_path / "ciphertext12.json"), ct1, fhe.JSON)
  32. VECTOR1_ROTATION = 1
  33. VECTOR2_ROTATION = 2
  34. VECTOR3_ROTATION = -1
  35. VECTOR4_ROTATION = -2
  36. @pytest.mark.parametrize("mode", [fhe.JSON, fhe.BINARY])
  37. def test_serial_cryptocontext_str(mode):
  38. parameters = fhe.CCParamsBFVRNS()
  39. parameters.SetPlaintextModulus(65537)
  40. parameters.SetMultiplicativeDepth(2)
  41. cryptoContext = fhe.GenCryptoContext(parameters)
  42. cryptoContext.Enable(fhe.PKE)
  43. cryptoContext.Enable(fhe.KEYSWITCH)
  44. cryptoContext.Enable(fhe.LEVELEDSHE)
  45. cryptoContext.Enable(fhe.PKESchemeFeature.PRE)
  46. keypair = cryptoContext.KeyGen()
  47. # First plaintext vector is encoded
  48. vectorOfInts1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
  49. plaintext1 = cryptoContext.MakePackedPlaintext(vectorOfInts1)
  50. # Second plaintext vector is encoded
  51. vectorOfInts2 = [3, 2, 1, 4, 5, 6, 7, 8, 9, 10, 11, 12]
  52. plaintext2 = cryptoContext.MakePackedPlaintext(vectorOfInts2)
  53. # Third plaintext vector is encoded
  54. vectorOfInts3 = [1, 2, 5, 2, 5, 6, 7, 8, 9, 10, 11, 12]
  55. plaintext3 = cryptoContext.MakePackedPlaintext(vectorOfInts3)
  56. # Create a final array adding the three vectors
  57. initialPlaintextAddResult = [vectorOfInts1[i] + vectorOfInts2[i] + vectorOfInts3[i] for i in range(len(vectorOfInts1))]
  58. initialPlaintextAddResult = cryptoContext.MakePackedPlaintext(initialPlaintextAddResult)
  59. # Multiply the values
  60. initialPlaintextMultResult = [vectorOfInts1[i] * vectorOfInts2[i] * vectorOfInts3[i] for i in range(len(vectorOfInts1))]
  61. initialPlaintextMultResult = cryptoContext.MakePackedPlaintext(initialPlaintextMultResult)
  62. # Rotate the values
  63. initialPlaintextRot1 = rotate_vector(vectorOfInts1, VECTOR1_ROTATION)
  64. initialPlaintextRot1 = cryptoContext.MakePackedPlaintext(initialPlaintextRot1)
  65. initialPlaintextRot2 = rotate_vector(vectorOfInts2, VECTOR2_ROTATION)
  66. initialPlaintextRot2 = cryptoContext.MakePackedPlaintext(initialPlaintextRot2)
  67. initialPlaintextRot3 = rotate_vector(vectorOfInts3, VECTOR3_ROTATION)
  68. initialPlaintextRot3 = cryptoContext.MakePackedPlaintext(initialPlaintextRot3)
  69. initialPlaintextRot4 = rotate_vector(vectorOfInts3, VECTOR4_ROTATION)
  70. initialPlaintextRot4 = cryptoContext.MakePackedPlaintext(initialPlaintextRot4)
  71. # The encoded vectors are encrypted
  72. ciphertext1 = cryptoContext.Encrypt(keypair.publicKey, plaintext1)
  73. ciphertext2 = cryptoContext.Encrypt(keypair.publicKey, plaintext2)
  74. ciphertext3 = cryptoContext.Encrypt(keypair.publicKey, plaintext3)
  75. evalKey = cryptoContext.ReKeyGen(keypair.secretKey, keypair.publicKey)
  76. cryptoContext.EvalMultKeyGen(keypair.secretKey)
  77. cryptoContext.EvalRotateKeyGen(keypair.secretKey, [VECTOR1_ROTATION, VECTOR2_ROTATION, VECTOR3_ROTATION, VECTOR4_ROTATION])
  78. cryptoContext_ser = fhe.Serialize(cryptoContext, mode)
  79. LOGGER.debug("The cryptocontext has been serialized.")
  80. publickey_ser = fhe.Serialize(keypair.publicKey, mode)
  81. LOGGER.debug("The public key has been serialized.")
  82. secretkey_ser = fhe.Serialize(keypair.secretKey, mode)
  83. LOGGER.debug("The private key has been serialized.")
  84. ciphertext1_ser = fhe.Serialize(ciphertext1, mode)
  85. LOGGER.debug("The ciphertext 1 has been serialized.")
  86. ciphertext2_ser = fhe.Serialize(ciphertext2, mode)
  87. LOGGER.debug("The ciphertext 2 has been serialized.")
  88. ciphertext3_ser = fhe.Serialize(ciphertext3, mode)
  89. LOGGER.debug("The ciphertext 3 has been serialized.")
  90. evalKey_ser = fhe.Serialize(evalKey, mode)
  91. LOGGER.debug("The evaluation key has been serialized.")
  92. multKey_ser = fhe.SerializeEvalMultKeyString(mode, "")
  93. LOGGER.debug("The relinearization key has been serialized.")
  94. automorphismKey_ser = fhe.SerializeEvalAutomorphismKeyString(mode, "")
  95. LOGGER.debug("The rotation evaluation keys have been serialized.")
  96. fhe.ClearEvalMultKeys()
  97. cryptoContext.ClearEvalAutomorphismKeys()
  98. fhe.ReleaseAllContexts()
  99. cc = fhe.DeserializeCryptoContextString(cryptoContext_ser, mode)
  100. assert isinstance(cc, fhe.CryptoContext)
  101. LOGGER.debug("The cryptocontext has been deserialized.")
  102. pk = fhe.DeserializePublicKeyString(publickey_ser, mode)
  103. assert isinstance(pk, fhe.PublicKey)
  104. LOGGER.debug("The public key has been deserialized.")
  105. sk = fhe.DeserializePrivateKeyString(secretkey_ser, mode)
  106. assert isinstance(sk, fhe.PrivateKey)
  107. LOGGER.debug("The private key has been deserialized.")
  108. ct1 = fhe.DeserializeCiphertextString(ciphertext1_ser, mode)
  109. assert isinstance(ct1, fhe.Ciphertext)
  110. LOGGER.debug("The ciphertext 1 has been reserialized.")
  111. ct2 = fhe.DeserializeCiphertextString(ciphertext2_ser, mode)
  112. assert isinstance(ct2, fhe.Ciphertext)
  113. LOGGER.debug("The ciphertext 2 has been reserialized.")
  114. ct3 = fhe.DeserializeCiphertextString(ciphertext3_ser, mode)
  115. assert isinstance(ct3, fhe.Ciphertext)
  116. LOGGER.debug("The ciphertext 3 has been reserialized.")
  117. ek = fhe.DeserializeEvalKeyString(evalKey_ser, mode)
  118. assert isinstance(ek, fhe.EvalKey)
  119. LOGGER.debug("The evaluation key has been deserialized.")
  120. fhe.DeserializeEvalMultKeyString(multKey_ser, mode)
  121. LOGGER.debug("The relinearization key has been deserialized.")
  122. fhe.DeserializeEvalAutomorphismKeyString(automorphismKey_ser, mode)
  123. LOGGER.debug("The rotation evaluation keys have been deserialized.")
  124. # Homomorphic addition
  125. ciphertextAdd12 = cc.EvalAdd(ct1, ct2)
  126. ciphertextAddResult = cc.EvalAdd(ciphertextAdd12, ct3)
  127. # Homomorphic multiplication
  128. ciphertextMult12 = cc.EvalMult(ct1, ct2)
  129. ciphertextMultResult = cc.EvalMult(ciphertextMult12, ct3)
  130. # Homomorphic rotation
  131. ciphertextRot1 = cc.EvalRotate(ct1, VECTOR1_ROTATION)
  132. ciphertextRot2 = cc.EvalRotate(ct2, VECTOR2_ROTATION)
  133. ciphertextRot3 = cc.EvalRotate(ct3, VECTOR3_ROTATION)
  134. ciphertextRot4 = cc.EvalRotate(ct3, VECTOR4_ROTATION)
  135. # Decrypt the result of additions
  136. plaintextAddResult = cc.Decrypt(sk, ciphertextAddResult)
  137. # Decrypt the result of multiplications
  138. plaintextMultResult = cc.Decrypt(sk, ciphertextMultResult)
  139. # Decrypt the result of rotations
  140. plaintextRot1 = cc.Decrypt(sk, ciphertextRot1)
  141. plaintextRot2 = cc.Decrypt(sk, ciphertextRot2)
  142. plaintextRot3 = cc.Decrypt(sk, ciphertextRot3)
  143. plaintextRot4 = cc.Decrypt(sk, ciphertextRot4)
  144. # Shows only the same number of elements as in the original plaintext vector
  145. # By default it will show all coefficients in the BFV-encoded polynomial
  146. plaintextRot1.SetLength(len(vectorOfInts1))
  147. plaintextRot2.SetLength(len(vectorOfInts1))
  148. plaintextRot3.SetLength(len(vectorOfInts1))
  149. plaintextRot4.SetLength(len(vectorOfInts1))
  150. assert str(plaintextAddResult) == str(initialPlaintextAddResult)
  151. assert str(plaintextMultResult) == str(initialPlaintextMultResult)
  152. assert str(plaintextRot1) == str(initialPlaintextRot1)
  153. assert str(plaintextRot2) == str(initialPlaintextRot2)
  154. assert str(plaintextRot3) == str(initialPlaintextRot3)
  155. assert str(plaintextRot4) == str(initialPlaintextRot4)
  156. def rotate_vector(vector, rotation):
  157. """
  158. Rotate a vector by a specified number of positions.
  159. Positive values rotate left, negative values rotate right.
  160. :param vector: List[int], the vector to rotate.
  161. :param rotation: int, the number of positions to rotate.
  162. :return: List[int], the rotated vector.
  163. """
  164. n = len(vector)
  165. if rotation > 0:
  166. rotated = vector[rotation:] + [0] * rotation
  167. elif rotation < 0:
  168. rotation = abs(rotation)
  169. rotated = [0] * rotation + vector[:n - rotation]
  170. else:
  171. rotated = vector
  172. return rotated