test_serial_cc.py 9.0 KB

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