Kaynağa Gözat

Fix Serialization/Deserialization API and examples (#63)

* temporary fix for deserialization

* Deserial: testing different workaround

* test tuple impl

* test seria file

* testing ownership problem

* temporary fix for deserialization

* Deserial: testing different workaround

* test tuple impl

* test seria file

* testing ownership problem

* add debug functions

* serialization works for ckks, added missing serialization methods, privatekey has constructor now

* resolve merge conflicts

* Fix DeserializeFromFile bug

* simple-real-numbers-serial

* real numbers fix

* fix bindings file

* fix merge conflicts

* typo

---------

Co-authored-by: Gergo, Petrik <gergo.petrik@xtendr.io>
Rener Oliveira 1 yıl önce
ebeveyn
işleme
ca2271d5e6

+ 5 - 2
.gitignore

@@ -2,9 +2,12 @@ build/
 .vscode/
 .idea
 .png
-.json
-.txt
+*.json
+*.txt
 .cproject
 .project
+.html
+*.pyc
 .settings/
+docs/
 demoData/

+ 61 - 36
examples/pke/simple-integers-serial-bgvrns.py

@@ -3,7 +3,7 @@ from openfhe import *
 # import openfhe.PKESchemeFeature as Feature
 
 datafolder = 'demoData'
-
+serType = BINARY # BINARY or JSON 
 print("This program requres the subdirectory `" + datafolder + "' to exist, otherwise you will get an error writing serializations.")
 
 # Sample Program: Step 1: Set CryptoContext
@@ -18,7 +18,7 @@ cryptoContext.Enable(PKESchemeFeature.KEYSWITCH)
 cryptoContext.Enable(PKESchemeFeature.LEVELEDSHE)
 
 # Serialize cryptocontext
-if not SerializeToFile(datafolder + "/cryptocontext.txt", cryptoContext, BINARY):
+if not SerializeToFile(datafolder + "/cryptocontext.txt", cryptoContext, serType):
    raise Exception("Error writing serialization of the crypto context to cryptocontext.txt")
 print("The cryptocontext has been serialized.")
 
@@ -29,13 +29,13 @@ keypair = cryptoContext.KeyGen()
 print("The keypair has been generated.")
 
 # Serialize the public key
-if not SerializeToFile(datafolder + "/key-public.txt", keypair.publicKey, BINARY):
+if not SerializeToFile(datafolder + "/key-public.txt", keypair.publicKey, serType):
    raise Exception("Error writing serialization of the public key to key-public.txt")
 print("The public key has been serialized.")
 
 # Serialize the secret key
-if not SerializeToFile(datafolder + "/key-secret.txt", keypair.secretKey, BINARY):
-   raise Exception("Error writing serialization of the secret key to key-secret.txt")
+if not SerializeToFile(datafolder + "/key-private.txt", keypair.secretKey, serType):
+   raise Exception("Error writing serialization of the secret key to key-private.txt")
 print("The secret key has been serialized.")
 
 # Generate the relinearization key
@@ -43,7 +43,7 @@ cryptoContext.EvalMultKeyGen(keypair.secretKey)
 print("The relinearization key has been generated.")
 
 # Serialize the relinearization key
-if not cryptoContext.SerializeEvalMultKey(datafolder + "/key-eval-mult.txt",BINARY):
+if not cryptoContext.SerializeEvalMultKey(datafolder + "/key-eval-mult.txt",serType):
    raise Exception("Error writing serialization of the eval mult keys to \"key-eval-mult.txt\"")
 print("The relinearization key has been serialized.")
 
@@ -52,7 +52,7 @@ cryptoContext.EvalRotateKeyGen(keypair.secretKey, [1, 2, -1, -2])
 print("The rotation evaluation keys have been generated.")
 
 # Serialize the rotation evaluation keys
-if not cryptoContext.SerializeEvalAutomorphismKey(datafolder + "/key-eval-rot.txt",BINARY):
+if not cryptoContext.SerializeEvalAutomorphismKey(datafolder + "/key-eval-rot.txt",serType):
    raise Exception("Error writing serialization of the eval rotate keys to \"key-eval-rot.txt\"")
 print("The rotation evaluation keys have been serialized.")
 
@@ -77,15 +77,15 @@ ciphertext2 = cryptoContext.Encrypt(keypair.publicKey, plaintext2)
 ciphertext3 = cryptoContext.Encrypt(keypair.publicKey, plaintext3)
 print("The plaintexts have been encrypted.")
 
-if not SerializeToFile(datafolder + "/ciphertext1.txt", ciphertext1, BINARY):
+if not SerializeToFile(datafolder + "/ciphertext1.txt", ciphertext1, serType):
    raise Exception("Error writing serialization of ciphertext 1 to ciphertext1.txt")
 print("The first ciphertext has been serialized.")
 
-if not SerializeToFile(datafolder + "/ciphertext2.txt", ciphertext2, BINARY):
+if not SerializeToFile(datafolder + "/ciphertext2.txt", ciphertext2, serType):
    raise Exception("Error writing serialization of ciphertext2 to ciphertext2.txt")
 print("The second ciphertext has been serialized.")
 
-if not SerializeToFile(datafolder + "/ciphertext3.txt", ciphertext3, BINARY):   
+if not SerializeToFile(datafolder + "/ciphertext3.txt", ciphertext3, serType):   
    raise Exception("Error writing serialization of ciphertext3 to ciphertext3.txt")
 print("The third ciphertext has been serialized.")
 
@@ -101,49 +101,45 @@ cryptoContext.ClearEvalAutomorphismKeys()
 ReleaseAllContexts()
 
 # Deserialize the crypto context
-cc = CryptoContext()
 
-if not DeserializeFromFile(datafolder + "/cryptocontext.txt", cc, BINARY):
+cc, res = DeserializeCryptoContext(datafolder + "/cryptocontext.txt", serType)
+if not res:
    raise Exception("Error reading serialization of the crypto context from cryptocontext.txt")
 print("The cryptocontext has been deserialized.")
 
 # Deserialize the public key
-pk = PublicKey()
+pk, res = DeserializePublicKey(datafolder + "/key-public.txt", serType)
 
-if not DeserializeFromFile(datafolder + "/key-public.txt", pk, BINARY):
+if not res:
    raise Exception("Error reading serialization of the public key from key-public.txt")
-
 print("The public key has been deserialized.")
 
-# if cryptoContext.DeserializeEvalMultKey(datafolder + "/key-eval-mult.txt",BINARY):
-#    raise Exception("Could not deserialize the eval mult key file")
+if not cc.DeserializeEvalMultKey(datafolder + "/key-eval-mult.txt",serType):
+   raise Exception("Could not deserialize the eval mult key file")
 
-# print("The relinearization key has been deserialized.")
+print("The relinearization key has been deserialized.")
 
-# if cryptoContext.DeserializeEvalAutomorphismKey(datafolder + "/key-eval-rot.txt",BINARY):
-#    raise Exception("Could not deserialize the eval rotation key file")
+if not cc.DeserializeEvalAutomorphismKey(datafolder + "/key-eval-rot.txt",serType):
+   raise Exception("Could not deserialize the eval rotation key file")
 
-# print("Deserialized the eval rotation keys.")
+print("Deserialized the eval rotation keys.")
 
 # Deserialize the ciphertexts
+ct1, res =  DeserializeCiphertext(datafolder + "/ciphertext1.txt", serType)
 
-ct1 = Ciphertext()
-ct2 = Ciphertext()
-ct3 = Ciphertext()
-
-if not DeserializeFromFile(datafolder + "/ciphertext1.txt", ct1, BINARY):
+if not res:
     raise Exception("Could not read the ciphertext")
-
 print("The first ciphertext has been deserialized.")
 
-if not DeserializeFromFile(datafolder + "/ciphertext2.txt", ct2, BINARY):
-    raise Exception("Could not read the ciphertext")
+ct2, res = DeserializeCiphertext(datafolder + "/ciphertext2.txt", serType)
 
+if not res:
+    raise Exception("Could not read the ciphertext")
 print("The second ciphertext has been deserialized.")
 
-if not DeserializeFromFile(datafolder + "/ciphertext3.txt", ct3, BINARY):   
+ct3, res = DeserializeCiphertext(datafolder + "/ciphertext3.txt", serType)
+if not res:   
     raise Exception("Could not read the ciphertext")
-
 print("The third ciphertext has been deserialized.")
 
 # Homomorphic addition
@@ -161,8 +157,37 @@ ciphertextRot2 = cc.EvalRotate(ct2, 2)
 ciphertextRot3 = cc.EvalRotate(ct3, -1)
 ciphertextRot4 = cc.EvalRotate(ct3, -2)
 
-
-
-
-
-
+# Sample Program: Step 5: Decryption
+
+sk, res = DeserializePrivateKey(datafolder + "/key-private.txt", serType)
+if not res:
+      raise Exception("Could not read secret key")
+print("The secret key has been deserialized.")
+
+# Decrypt the result of additions
+plaintextAddResult = cc.Decrypt(sk, ciphertextAddResult)
+
+# Decrypt the result of multiplications
+plaintextMultResult = cc.Decrypt(sk, ciphertextMultResult)
+
+# Decrypt the result of rotations
+plaintextRot1 = cc.Decrypt(sk, ciphertextRot1)
+plaintextRot2 = cc.Decrypt(sk, ciphertextRot2)
+plaintextRot3 = cc.Decrypt(sk, ciphertextRot3)
+plaintextRot4 = cc.Decrypt(sk, ciphertextRot4)
+
+# Shows only the same number of elements as in the original plaintext vector
+# By default it will show all coefficients in the BFV-encoded polynomial
+plaintextRot1.SetLength(len(vectorOfInts1))
+plaintextRot2.SetLength(len(vectorOfInts1))
+plaintextRot3.SetLength(len(vectorOfInts1))
+plaintextRot4.SetLength(len(vectorOfInts1))
+
+# Output results
+print("\nResults of homomorphic computations")
+print("#1 + #2 + #3: " + str(plaintextAddResult))
+print("#1 * #2 * #3: " + str(plaintextMultResult))
+print("Left rotation of #1 by 1: " + str(plaintextRot1))
+print("Left rotation of #1 by 2: " + str(plaintextRot2))
+print("Right rotation of #1 by 1: " + str(plaintextRot3))
+print("Right rotation of #1 by 2: " + str(plaintextRot4))

+ 57 - 32
examples/pke/simple-integers-serial.py

@@ -3,7 +3,7 @@ from openfhe import *
 # import openfhe.PKESchemeFeature as Feature
 
 datafolder = 'demoData'
-
+serType = BINARY # BINARY or JSON 
 print("This program requres the subdirectory `" + datafolder + "' to exist, otherwise you will get an error writing serializations.")
 
 # Sample Program: Step 1: Set CryptoContext
@@ -18,7 +18,7 @@ cryptoContext.Enable(PKESchemeFeature.KEYSWITCH)
 cryptoContext.Enable(PKESchemeFeature.LEVELEDSHE)
 
 # Serialize cryptocontext
-if not SerializeToFile(datafolder + "/cryptocontext.txt", cryptoContext, BINARY):
+if not SerializeToFile(datafolder + "/cryptocontext.txt", cryptoContext, serType):
    raise Exception("Error writing serialization of the crypto context to cryptocontext.txt")
 print("The cryptocontext has been serialized.")
 
@@ -29,13 +29,13 @@ keypair = cryptoContext.KeyGen()
 print("The keypair has been generated.")
 
 # Serialize the public key
-if not SerializeToFile(datafolder + "/key-public.txt", keypair.publicKey, BINARY):
+if not SerializeToFile(datafolder + "/key-public.txt", keypair.publicKey, serType):
    raise Exception("Error writing serialization of the public key to key-public.txt")
 print("The public key has been serialized.")
 
 # Serialize the secret key
-if not SerializeToFile(datafolder + "/key-secret.txt", keypair.secretKey, BINARY):
-   raise Exception("Error writing serialization of the secret key to key-secret.txt")
+if not SerializeToFile(datafolder + "/key-private.txt", keypair.secretKey, serType):
+   raise Exception("Error writing serialization of the secret key to key-private.txt")
 print("The secret key has been serialized.")
 
 # Generate the relinearization key
@@ -43,7 +43,7 @@ cryptoContext.EvalMultKeyGen(keypair.secretKey)
 print("The relinearization key has been generated.")
 
 # Serialize the relinearization key
-if not cryptoContext.SerializeEvalMultKey(datafolder + "/key-eval-mult.txt",BINARY):
+if not cryptoContext.SerializeEvalMultKey(datafolder + "/key-eval-mult.txt",serType):
    raise Exception("Error writing serialization of the eval mult keys to \"key-eval-mult.txt\"")
 print("The relinearization key has been serialized.")
 
@@ -52,7 +52,7 @@ cryptoContext.EvalRotateKeyGen(keypair.secretKey, [1, 2, -1, -2])
 print("The rotation evaluation keys have been generated.")
 
 # Serialize the rotation evaluation keys
-if not cryptoContext.SerializeEvalAutomorphismKey(datafolder + "/key-eval-rot.txt",BINARY):
+if not cryptoContext.SerializeEvalAutomorphismKey(datafolder + "/key-eval-rot.txt",serType):
    raise Exception("Error writing serialization of the eval rotate keys to \"key-eval-rot.txt\"")
 print("The rotation evaluation keys have been serialized.")
 
@@ -77,15 +77,15 @@ ciphertext2 = cryptoContext.Encrypt(keypair.publicKey, plaintext2)
 ciphertext3 = cryptoContext.Encrypt(keypair.publicKey, plaintext3)
 print("The plaintexts have been encrypted.")
 
-if not SerializeToFile(datafolder + "/ciphertext1.txt", ciphertext1, BINARY):
+if not SerializeToFile(datafolder + "/ciphertext1.txt", ciphertext1, serType):
    raise Exception("Error writing serialization of ciphertext 1 to ciphertext1.txt")
 print("The first ciphertext has been serialized.")
 
-if not SerializeToFile(datafolder + "/ciphertext2.txt", ciphertext2, BINARY):
+if not SerializeToFile(datafolder + "/ciphertext2.txt", ciphertext2, serType):
    raise Exception("Error writing serialization of ciphertext2 to ciphertext2.txt")
 print("The second ciphertext has been serialized.")
 
-if not SerializeToFile(datafolder + "/ciphertext3.txt", ciphertext3, BINARY):   
+if not SerializeToFile(datafolder + "/ciphertext3.txt", ciphertext3, serType):   
    raise Exception("Error writing serialization of ciphertext3 to ciphertext3.txt")
 print("The third ciphertext has been serialized.")
 
@@ -101,49 +101,45 @@ cryptoContext.ClearEvalAutomorphismKeys()
 ReleaseAllContexts()
 
 # Deserialize the crypto context
-cc = CryptoContext()
 
-if not DeserializeFromFile(datafolder + "/cryptocontext.txt", cc, BINARY):
+cc, res = DeserializeCryptoContext(datafolder + "/cryptocontext.txt", serType)
+if not res:
    raise Exception("Error reading serialization of the crypto context from cryptocontext.txt")
 print("The cryptocontext has been deserialized.")
 
 # Deserialize the public key
-pk = PublicKey()
+pk, res = DeserializePublicKey(datafolder + "/key-public.txt", serType)
 
-if not DeserializeFromFile(datafolder + "/key-public.txt", pk, BINARY):
+if not res:
    raise Exception("Error reading serialization of the public key from key-public.txt")
-
 print("The public key has been deserialized.")
 
-if cryptoContext.DeserializeEvalMultKey(datafolder + "/key-eval-mult.txt",BINARY):
+if not cc.DeserializeEvalMultKey(datafolder + "/key-eval-mult.txt",serType):
    raise Exception("Could not deserialize the eval mult key file")
 
 print("The relinearization key has been deserialized.")
 
-if cryptoContext.DeserializeEvalAutomorphismKey(datafolder + "/key-eval-rot.txt",BINARY):
+if not cc.DeserializeEvalAutomorphismKey(datafolder + "/key-eval-rot.txt",serType):
    raise Exception("Could not deserialize the eval rotation key file")
 
 print("Deserialized the eval rotation keys.")
 
 # Deserialize the ciphertexts
+ct1, res =  DeserializeCiphertext(datafolder + "/ciphertext1.txt", serType)
 
-ct1 = Ciphertext()
-ct2 = Ciphertext()
-ct3 = Ciphertext()
-
-if not DeserializeFromFile(datafolder + "/ciphertext1.txt", ct1, BINARY):
+if not res:
     raise Exception("Could not read the ciphertext")
-
 print("The first ciphertext has been deserialized.")
 
-if not DeserializeFromFile(datafolder + "/ciphertext2.txt", ct2, BINARY):
-    raise Exception("Could not read the ciphertext")
+ct2, res = DeserializeCiphertext(datafolder + "/ciphertext2.txt", serType)
 
+if not res:
+    raise Exception("Could not read the ciphertext")
 print("The second ciphertext has been deserialized.")
 
-if not DeserializeFromFile(datafolder + "/ciphertext3.txt", ct3, BINARY):   
+ct3, res = DeserializeCiphertext(datafolder + "/ciphertext3.txt", serType)
+if not res:   
     raise Exception("Could not read the ciphertext")
-
 print("The third ciphertext has been deserialized.")
 
 # Homomorphic addition
@@ -161,8 +157,37 @@ ciphertextRot2 = cc.EvalRotate(ct2, 2)
 ciphertextRot3 = cc.EvalRotate(ct3, -1)
 ciphertextRot4 = cc.EvalRotate(ct3, -2)
 
-
-
-
-
-
+# Sample Program: Step 5: Decryption
+
+sk, res = DeserializePrivateKey(datafolder + "/key-private.txt", serType)
+if not res:
+      raise Exception("Could not read secret key")
+print("The secret key has been deserialized.")
+
+# Decrypt the result of additions
+plaintextAddResult = cc.Decrypt(sk, ciphertextAddResult)
+
+# Decrypt the result of multiplications
+plaintextMultResult = cc.Decrypt(sk, ciphertextMultResult)
+
+# Decrypt the result of rotations
+plaintextRot1 = cc.Decrypt(sk, ciphertextRot1)
+plaintextRot2 = cc.Decrypt(sk, ciphertextRot2)
+plaintextRot3 = cc.Decrypt(sk, ciphertextRot3)
+plaintextRot4 = cc.Decrypt(sk, ciphertextRot4)
+
+# Shows only the same number of elements as in the original plaintext vector
+# By default it will show all coefficients in the BFV-encoded polynomial
+plaintextRot1.SetLength(len(vectorOfInts1))
+plaintextRot2.SetLength(len(vectorOfInts1))
+plaintextRot3.SetLength(len(vectorOfInts1))
+plaintextRot4.SetLength(len(vectorOfInts1))
+
+# Output results
+print("\nResults of homomorphic computations")
+print("#1 + #2 + #3: " + str(plaintextAddResult))
+print("#1 * #2 * #3: " + str(plaintextMultResult))
+print("Left rotation of #1 by 1: " + str(plaintextRot1))
+print("Left rotation of #1 by 2: " + str(plaintextRot2))
+print("Right rotation of #1 by 1: " + str(plaintextRot3))
+print("Right rotation of #1 by 2: " + str(plaintextRot4))

+ 287 - 0
examples/pke/simple-real-numbers-serial.py

@@ -0,0 +1,287 @@
+from openfhe import *
+
+
+# NOTE:
+# If running locally, you may want to replace the "hardcoded" datafolder with
+# the datafolder location below which gets the current working directory
+
+# Save-Load locations for keys
+datafolder = 'demoData'
+ccLocation = '/cryptocontext.txt'
+pubKeyLocation = '/key_pub.txt' # Pub key
+multKeyLocation = '/key_mult.txt' # relinearization key
+rotKeyLocation = '/key_rot.txt' # automorphism / rotation key
+
+# Save-load locations for RAW ciphertexts
+cipherOneLocation = '/ciphertext1.txt'
+cipherTwoLocation = '/ciphertext2.txt'
+
+# Save-load locations for evaluated ciphertexts
+cipherMultLocation = '/ciphertextMult.txt'
+cipherAddLocation = '/ciphertextAdd.txt'
+cipherRotLocation = '/ciphertextRot.txt'
+cipherRotNegLocation = '/ciphertextRotNegLocation.txt'
+clientVectorLocation = '/clientVectorFromClient.txt'
+
+# Demarcate - Visual separator between the sections of code
+def demarcate(msg):
+    print("**************************************************\n")
+    print(msg)
+    print("**************************************************\n")
+
+"""
+serverSetupAndWrite(multDepth, scaleModSize, batchSize)
+    simulates a server at startup where we generate a cryptocontext and keys.
+    then, we generate some data (akin to loading raw data on an enclave)
+    before encrypting the data
+    :param multDepth: multiplication depth
+    :param scaleModSize: number of bits to use in the scale factor (not the
+    scale factor itself)
+    :param batchSize: batch size to use
+    :return Tuple<cryptoContext, keyPair>
+"""
+def serverSetupAndWrite(multDepth, scaleModSize, batchSize):
+
+    parameters = CCParamsCKKSRNS()
+    parameters.SetMultiplicativeDepth(multDepth)
+    parameters.SetScalingModSize(scaleModSize)
+    parameters.SetBatchSize(batchSize)
+
+    serverCC = GenCryptoContext(parameters)
+
+    serverCC.Enable(PKE)
+    serverCC.Enable(KEYSWITCH)
+    serverCC.Enable(LEVELEDSHE)
+
+    print("Cryptocontext generated")
+
+    serverKP = serverCC.KeyGen()
+    print("Keypair generated")
+
+    serverCC.EvalMultKeyGen(serverKP.secretKey)
+    print("Eval Mult Keys/ Relinearization keys have been generated")
+
+    serverCC.EvalRotateKeyGen(serverKP.secretKey, [1, 2, -1, -2])
+    print("Rotation keys generated")
+
+    vec1 = [1.0, 2.0, 3.0, 4.0]
+    vec2 = [12.5, 13.5, 14.5, 15.5]
+    vec3 = [10.5, 11.5, 12.5, 13.5]
+    print("\nDisplaying first data vector: ")
+    print(vec1)
+    print("\n")
+
+    serverP1 = serverCC.MakeCKKSPackedPlaintext(vec1)
+    serverP2 = serverCC.MakeCKKSPackedPlaintext(vec2)
+    serverP3 = serverCC.MakeCKKSPackedPlaintext(vec3)
+
+    print("Plaintext version of first vector: "+ str(serverP1))
+
+    print("Plaintexts have been generated from complex-double vectors")
+
+    serverC1 = serverCC.Encrypt(serverKP.publicKey, serverP1)
+    serverC2 = serverCC.Encrypt(serverKP.publicKey, serverP2)
+    serverC3 = serverCC.Encrypt(serverKP.publicKey, serverP3)
+
+    print("Ciphertexts have been generated from plaintexts")
+
+    ###
+    #    Part 2:
+    #    We serialize the following:
+    #      Cryptocontext
+    #      Public key
+    #      relinearization (eval mult keys)
+    #      rotation keys
+    #      Some of the ciphertext
+    #    
+    #      We serialize all of them to files
+    ###
+    demarcate("Part 2: Data Serialization (server)")
+
+    if not SerializeToFile(datafolder + ccLocation, serverCC, BINARY):
+        raise Exception("Exception writing cryptocontext to cryptocontext.txt")
+    print("Cryptocontext serialized")
+
+    if not SerializeToFile(datafolder + pubKeyLocation, serverKP.publicKey, BINARY):
+        raise Exception("Exception writing public key to pubkey.txt")
+    print("Public key has been serialized")
+
+    if not serverCC.SerializeEvalMultKey(datafolder + multKeyLocation, BINARY):
+        raise Exception("Error writing eval mult keys")
+    print("EvalMult/ relinearization keys have been serialized")
+
+    if not serverCC.SerializeEvalAutomorphismKey(datafolder + rotKeyLocation, BINARY):
+        raise Exception("Error writing rotation keys")
+    print("Rotation keys have been serialized")
+
+    if not SerializeToFile(datafolder + cipherOneLocation, serverC1, BINARY):
+        raise Exception("Error writing ciphertext 1")
+    
+    if not SerializeToFile(datafolder + cipherTwoLocation, serverC2, BINARY):
+        raise Exception("Error writing ciphertext 2")
+    
+    return (serverCC, serverKP, len(vec1))
+
+###
+ # clientProcess
+ #  - deserialize data from a file which simulates receiving data from a server
+ # after making a request
+ #  - we then process the data by doing operations (multiplication, addition,
+ # rotation, etc)
+ #  - !! We also create an object and encrypt it in this function before sending
+ # it off to the server to be decrypted
+###
+
+def clientProcess():
+    # clientCC = CryptoContext()
+    # clientCC.ClearEvalMultKeys()
+    # clientCC.ClearEvalAutomorphismKeys()
+    ReleaseAllContexts()
+
+    clientCC, res = DeserializeCryptoContext(datafolder + ccLocation, BINARY)
+    if not res:
+        raise Exception(f"I cannot deserialize the cryptocontext from {datafolder+ccLocation}")
+
+    print("Client CC deserialized")
+
+    #clientKP = KeyPair()
+    # We do NOT have a secret key. The client
+    # should not have access to this
+    clientPuclicKey, res = DeserializePublicKey(datafolder + pubKeyLocation, BINARY)
+    if not res:
+        raise Exception(f"I cannot deserialize the public key from {datafolder+pubKeyLocation}")
+    print("Client KP deserialized\n")
+
+    if not clientCC.DeserializeEvalMultKey(datafolder + multKeyLocation, BINARY):
+        raise Exception(f"Cannot deserialize eval mult keys from {datafolder+multKeyLocation}")
+    print("Deserialized eval mult keys\n")
+
+    if not clientCC.DeserializeEvalAutomorphismKey(datafolder + rotKeyLocation, BINARY):
+        raise Exception(f"Cannot deserialize eval automorphism keys from {datafolder+rotKeyLocation}")
+    
+    clientC1, res = DeserializeCiphertext(datafolder + cipherOneLocation, BINARY)
+    if not res:
+        raise Exception(f"Cannot deserialize the ciphertext from {datafolder+cipherOneLocation}")
+    print("Deserialized ciphertext 1\n")
+
+    clientC2, res = DeserializeCiphertext(datafolder + cipherTwoLocation, BINARY)
+    if not res:
+        raise Exception(f"Cannot deserialize the ciphertext from {datafolder+cipherTwoLocation}")
+    print("Deserialized ciphertext 2\n")
+
+    clientCiphertextMult = clientCC.EvalMult(clientC1, clientC2)
+    clientCiphertextAdd = clientCC.EvalAdd(clientC1, clientC2)
+    clientCiphertextRot = clientCC.EvalRotate(clientC1, 1)
+    clientCiphertextRotNeg = clientCC.EvalRotate(clientC1, -1)
+
+    # Now, we want to simulate a client who is encrypting data for the server to
+    # decrypt. E.g weights of a machine learning algorithm
+    demarcate("Part 3.5: Client Serialization of data that has been operated on")
+
+    clientVector1 = [1.0, 2.0, 3.0, 4.0]
+    clientPlaintext1 = clientCC.MakeCKKSPackedPlaintext(clientVector1)
+    clientInitializedEncryption = clientCC.Encrypt(clientPuclicKey, clientPlaintext1)
+    SerializeToFile(datafolder + cipherMultLocation, clientCiphertextMult, BINARY)
+    SerializeToFile(datafolder + cipherAddLocation, clientCiphertextAdd, BINARY)
+    SerializeToFile(datafolder + cipherRotLocation, clientCiphertextRot, BINARY)
+    SerializeToFile(datafolder + cipherRotNegLocation, clientCiphertextRotNeg, BINARY)
+    SerializeToFile(datafolder + clientVectorLocation, clientInitializedEncryption, BINARY)
+
+    print("Serialized all ciphertexts from client\n")
+
+###
+#  serverVerification
+#  - deserialize data from the client.
+#  - Verify that the results are as we expect
+# @param cc cryptocontext that was previously generated
+# @param kp keypair that was previously generated
+# @param vectorSize vector size of the vectors supplied
+# @return
+#  5-tuple of the plaintexts of various operations
+##
+def serverVerification(cc,kp,vectorSize):
+    
+    serverCiphertextFromClient_Mult, res = DeserializeCiphertext(datafolder + cipherMultLocation, BINARY)
+    serverCiphertextFromClient_Add, res = DeserializeCiphertext(datafolder + cipherAddLocation, BINARY)
+    serverCiphertextFromClient_Rot, res = DeserializeCiphertext(datafolder + cipherRotLocation, BINARY)
+    serverCiphertextFromClient_RotNeg, res = DeserializeCiphertext(datafolder + cipherRotNegLocation, BINARY)
+    serverCiphertextFromClient_Vec, res = DeserializeCiphertext(datafolder + clientVectorLocation, BINARY)
+    print("Deserialized all data from client on server\n")
+
+    print("Part 5: Correctness Verification")
+
+    serverPlaintextFromClient_Mult = cc.Decrypt(kp.secretKey, serverCiphertextFromClient_Mult)
+    serverPlaintextFromClient_Add = cc.Decrypt(kp.secretKey, serverCiphertextFromClient_Add)
+    serverPlaintextFromClient_Rot = cc.Decrypt(kp.secretKey, serverCiphertextFromClient_Rot)
+    serverPlaintextFromClient_RotNeg = cc.Decrypt(kp.secretKey, serverCiphertextFromClient_RotNeg)
+    serverPlaintextFromClient_Vec = cc.Decrypt(kp.secretKey, serverCiphertextFromClient_Vec)
+
+    serverPlaintextFromClient_Mult.SetLength(vectorSize)
+    serverPlaintextFromClient_Add.SetLength(vectorSize)
+    serverPlaintextFromClient_Vec.SetLength(vectorSize)
+    serverPlaintextFromClient_Rot.SetLength(vectorSize + 1)
+    serverPlaintextFromClient_RotNeg.SetLength(vectorSize + 1)
+
+    return (serverPlaintextFromClient_Mult, 
+            serverPlaintextFromClient_Add, 
+            serverPlaintextFromClient_Vec, 
+            serverPlaintextFromClient_Rot, 
+            serverPlaintextFromClient_RotNeg)
+
+def main():
+    print(f"This program requires the subdirectory `{datafolder}' to exist, otherwise you will get\n an error writing serializations.")
+
+    # Set main params
+    multDepth = 5
+    scaleModSize = 40
+    batchSize = 32
+
+    cryptoContextIdx = 0
+    keyPairIdx = 1
+    vectorSizeIdx = 2
+
+    cipherMultResIdx = 0
+    cipherAddResIdx = 1
+    cipherVecResIdx = 2
+    cipherRotResIdx = 3
+    cipherRotNegResIdx = 4
+
+    demarcate("Part 1: Cryptocontext generation, key generation, data encryption \n(server)")
+
+    tupleCryptoContext_KeyPair = serverSetupAndWrite(multDepth, scaleModSize, batchSize)
+    cc = tupleCryptoContext_KeyPair[cryptoContextIdx]
+    kp = tupleCryptoContext_KeyPair[keyPairIdx]
+    vectorSize = tupleCryptoContext_KeyPair[vectorSizeIdx]
+
+    demarcate("Part 3: Client deserialize all data")
+    clientProcess()
+
+    demarcate("Part 4: Server deserialization of data from client. ")
+
+    tupleRes = serverVerification(cc, kp, vectorSize)
+    multRes = tupleRes[cipherMultResIdx]
+    addRes = tupleRes[cipherAddResIdx]
+    vecRes = tupleRes[cipherVecResIdx]
+    rotRes = tupleRes[cipherRotResIdx]
+    rotNegRes = tupleRes[cipherRotNegResIdx]
+
+    # vec1: [1,2,3,4]
+    # vec2: [12.5, 13.5, 14.5, 15.5]
+
+    print(multRes)  # EXPECT: 12.5, 27.0, 43.5, 62
+    print(addRes)   # EXPECT: 13.5, 15.5, 17.5, 19.5
+    print(vecRes)   # EXPECT:  [1,2,3,4]
+
+    print("Displaying 5 elements of a 4-element vector to illustrate rotation")
+    print(rotRes)     # EXPECT: [2, 3, 4, noise, noise]
+    print(rotNegRes)  # EXPECT: [noise, 1, 2, 3, 4]
+
+if __name__ == "__main__":
+    main()
+
+
+
+
+
+
+

+ 1 - 1
src/include/docstrings/ciphertext_docs.h

@@ -45,7 +45,7 @@ const char* ctx_SetLevel_docs = R"pbdoc(
 )pbdoc";
 
 //KeyPair Docs
-kp_good_docs = R"pbdoc(
+const char* kp_good_docs = R"pbdoc(
     Checks whether both public key and secret key are non-null, or correctly initialized.
 
     :return: Result.

+ 9 - 0
src/include/pke/serialization.h

@@ -29,9 +29,18 @@
 #define OPENFHE_SERIALIZATION_BINDINGS_H
 
 #include <pybind11/pybind11.h>
+#include "openfhe.h"
+#include "bindings.h"
+
 using namespace lbcrypto;
 
 template <typename ST>
 bool SerializeEvalMultKeyWrapper(const std::string& filename, const ST& sertype, std::string id);
 
+template <typename ST>
+bool SerializeEvalAutomorphismKeyWrapper(const std::string& filename, const ST& sertype, std::string id);
+
+template <typename ST>
+bool DeserializeEvalMultKeyWrapper(const std::string& filename, const ST& sertype);
+
 #endif // OPENFHE_SERIALIZATION_BINDINGS_H

+ 64 - 11
src/lib/bindings.cpp

@@ -15,6 +15,7 @@
 #include "cryptocontext_docs.h"
 #include "plaintext_docs.h"
 #include "ciphertext_docs.h"
+#include "serialization.h"
 
 using namespace lbcrypto;
 namespace py = pybind11;
@@ -101,13 +102,14 @@ void bind_crypto_context(py::module &m)
         .def("GetKeyGenLevel", &CryptoContextImpl<DCRTPoly>::GetKeyGenLevel, cc_GetKeyGenLevel_docs)
         .def("SetKeyGenLevel", &CryptoContextImpl<DCRTPoly>::SetKeyGenLevel, cc_SetKeyGenLevel_docs,
              py::arg("level"))
+        .def("get_ptr", [](const CryptoContext<DCRTPoly> &self)
+             { std::cout << "CC shared ptr (python cc)" << self << std::endl; })
         //.def("GetScheme",&CryptoContextImpl<DCRTPoly>::GetScheme)
         //.def("GetCryptoParameters", &CryptoContextImpl<DCRTPoly>::GetCryptoParameters)
         .def("GetRingDimension", &CryptoContextImpl<DCRTPoly>::GetRingDimension, cc_GetRingDimension_docs)
         .def("GetPlaintextModulus", &GetPlaintextModulusWrapper, cc_GetPlaintextModulus_docs)
         .def("GetModulus", &GetModulusWrapper, cc_GetModulus_docs)
         .def("GetCyclotomicOrder", &CryptoContextImpl<DCRTPoly>::GetCyclotomicOrder, cc_GetCyclotomicOrder_docs)
-        // .def("GetModulus", &CryptoContextImpl<DCRTPoly>::GetModulus, cc_GetModulus_docs)
         .def("Enable", static_cast<void (CryptoContextImpl<DCRTPoly>::*)(PKESchemeFeature)>(&CryptoContextImpl<DCRTPoly>::Enable), cc_Enable_docs,
              py::arg("feature"))
         .def("KeyGen", &CryptoContextImpl<DCRTPoly>::KeyGen, cc_KeyGen_docs)
@@ -546,6 +548,7 @@ void bind_crypto_context(py::module &m)
              py::arg("ciphertext"),
              py::arg("numIterations") = 1,
              py::arg("precision") = 0)
+        //TODO (Oliveira, R.): Solve pointer handling bug when returning EvalKeyMap objects for the next functions
         .def("EvalAutomorphismKeyGen", &EvalAutomorphismKeyGenWrapper, 
             cc_EvalAutomorphismKeyGen_docs,
             py::arg("privateKey"),
@@ -592,7 +595,17 @@ void bind_crypto_context(py::module &m)
                 return res; },
             cc_SerializeEvalMultKey_docs,
             py::arg("filename"), py::arg("sertype"), py::arg("id") = "")
-        .def_static(
+        .def_static( // SerializeEvalMultKey - JSON
+            "SerializeEvalMultKey", [](const std::string &filename, const SerType::SERJSON &sertype, std::string id = "")
+            {
+                std::ofstream outfile(filename,std::ios::out | std::ios::binary);
+                bool res;
+                res = CryptoContextImpl<DCRTPoly>::SerializeEvalMultKey<SerType::SERJSON>(outfile, sertype, id);
+                outfile.close();
+                return res; },
+            cc_SerializeEvalMultKey_docs,
+            py::arg("filename"), py::arg("sertype"), py::arg("id") = "")
+        .def_static( // SerializeEvalAutomorphismKey - Binary
             "SerializeEvalAutomorphismKey", [](const std::string &filename, const SerType::SERBINARY &sertype, std::string id = "")
             {
                 std::ofstream outfile(filename,std::ios::out | std::ios::binary);
@@ -602,29 +615,65 @@ void bind_crypto_context(py::module &m)
                 return res; },
             cc_SerializeEvalAutomorphismKey_docs,
             py::arg("filename"), py::arg("sertype"), py::arg("id") = "")
-        .def_static("DeserializeEvalMultKey", [](std::shared_ptr<CryptoContextImpl<DCRTPoly>> &self, const std::string &filename, const SerType::SERBINARY &sertype)
+        .def_static( // SerializeEvalAutomorphismKey - JSON
+            "SerializeEvalAutomorphismKey", [](const std::string &filename, const SerType::SERJSON &sertype, std::string id = "")
+            {
+                std::ofstream outfile(filename,std::ios::out | std::ios::binary);
+                bool res;
+                res = CryptoContextImpl<DCRTPoly>::SerializeEvalAutomorphismKey<SerType::SERJSON>(outfile, sertype, id);
+                outfile.close();
+                return res; },
+            cc_SerializeEvalAutomorphismKey_docs,
+            py::arg("filename"), py::arg("sertype"), py::arg("id") = "")
+        .def_static("DeserializeEvalMultKey", // DeserializeEvalMultKey - Binary
+        [](const std::string &filename, const SerType::SERBINARY &sertype)
                     {
                         std::ifstream emkeys(filename, std::ios::in | std::ios::binary);
                          if (!emkeys.is_open()) {
                             std::cerr << "I cannot read serialization from " << filename << std::endl;
                          }
                         bool res;
-                        res = self->DeserializeEvalMultKey<SerType::SERBINARY>(emkeys, sertype);
+                        res = CryptoContextImpl<DCRTPoly>::DeserializeEvalMultKey<SerType::SERBINARY>(emkeys, sertype);
+                        return res; 
+                        
+                        },
+                        cc_DeserializeEvalMultKey_docs,
+                        py::arg("filename"), py::arg("sertype"))
+        .def_static("DeserializeEvalMultKey", // DeserializeEvalMultKey - JSON
+        [](const std::string &filename, const SerType::SERJSON &sertype)
+                    {
+                        std::ifstream emkeys(filename, std::ios::in | std::ios::binary);
+                         if (!emkeys.is_open()) {
+                            std::cerr << "I cannot read serialization from " << filename << std::endl;
+                         }
+                        bool res;
+                        res = CryptoContextImpl<DCRTPoly>::DeserializeEvalMultKey<SerType::SERJSON>(emkeys, sertype);
                         return res; },
                         cc_DeserializeEvalMultKey_docs,
-                        py::arg("self"),
                         py::arg("filename"), py::arg("sertype"))
-        .def_static("DeserializeEvalAutomorphismKey", [](std::shared_ptr<CryptoContextImpl<DCRTPoly>> &self, const std::string &filename, const SerType::SERBINARY &sertype)
+        .def_static("DeserializeEvalAutomorphismKey", // DeserializeEvalAutomorphismKey - Binary
+        [](const std::string &filename, const SerType::SERBINARY &sertype)
                     {
                         std::ifstream erkeys(filename, std::ios::in | std::ios::binary);
                          if (!erkeys.is_open()) {
                             std::cerr << "I cannot read serialization from " << filename << std::endl;
                          }
                         bool res;
-                        res = self->DeserializeEvalAutomorphismKey<SerType::SERBINARY>(erkeys, sertype);
+                        res = CryptoContextImpl<DCRTPoly>::DeserializeEvalAutomorphismKey<SerType::SERBINARY>(erkeys, sertype);
+                        return res; },
+                        cc_DeserializeEvalAutomorphismKey_docs,
+                        py::arg("filename"), py::arg("sertype"))
+        .def_static("DeserializeEvalAutomorphismKey", // DeserializeEvalAutomorphismKey - JSON
+        [](const std::string &filename, const SerType::SERJSON &sertype)
+                    {
+                        std::ifstream erkeys(filename, std::ios::in | std::ios::binary);
+                         if (!erkeys.is_open()) {
+                            std::cerr << "I cannot read serialization from " << filename << std::endl;
+                         }
+                        bool res;
+                        res = CryptoContextImpl<DCRTPoly>::DeserializeEvalAutomorphismKey<SerType::SERJSON>(erkeys, sertype);
                         return res; },
                         cc_DeserializeEvalAutomorphismKey_docs,
-                        py::arg("self"),
                         py::arg("filename"), py::arg("sertype"));
 
     // Generator Functions
@@ -635,6 +684,7 @@ void bind_crypto_context(py::module &m)
     m.def("GenCryptoContext", &GenCryptoContext<CryptoContextCKKSRNS>,
         py::arg("params"));
     m.def("ReleaseAllContexts", &CryptoContextFactory<DCRTPoly>::ReleaseAllContexts);
+    m.def("GetAllContexts", &CryptoContextFactory<DCRTPoly>::GetAllContexts);
 }
 
 int get_native_int(){
@@ -789,6 +839,7 @@ void bind_enums_and_constants(py::module &m)
     //NATIVEINT function
     m.def("get_native_int", &get_native_int);
   
+    
 }
 
 void bind_keys(py::module &m)
@@ -806,7 +857,7 @@ void bind_keys(py::module &m)
         .def_readwrite("secretKey", &KeyPair<DCRTPoly>::secretKey)
         .def("good", &KeyPair<DCRTPoly>::good,kp_good_docs);
     py::class_<EvalKeyImpl<DCRTPoly>, std::shared_ptr<EvalKeyImpl<DCRTPoly>>>(m, "EvalKey")
-        .def(py::init<>())
+    .def(py::init<>())
         .def("GetKeyTag", &EvalKeyImpl<DCRTPoly>::GetKeyTag)
         .def("SetKeyTag", &EvalKeyImpl<DCRTPoly>::SetKeyTag);
     py::class_<std::map<usint, EvalKey<DCRTPoly>>, std::shared_ptr<std::map<usint, EvalKey<DCRTPoly>>>>(m, "EvalKeyMap")
@@ -865,7 +916,9 @@ void bind_ciphertext(py::module &m)
         ctx_GetLevel_docs)
      .def("SetLevel", &CiphertextImpl<DCRTPoly>::SetLevel,
         ctx_SetLevel_docs,
-        py::arg("level"));
+        py::arg("level"))
+    .def("get_ptr",[](const Ciphertext<DCRTPoly> &self){
+        std::cout<< "cryptoparameters shared ptr (python)" << self->GetCryptoContext().get() << std::endl;});
     // .def("GetHopLevel", &CiphertextImpl<DCRTPoly>::GetHopLevel)
     // .def("SetHopLevel", &CiphertextImpl<DCRTPoly>::SetHopLevel)
     // .def("GetScalingFactor", &CiphertextImpl<DCRTPoly>::GetScalingFactor)
@@ -903,4 +956,4 @@ PYBIND11_MODULE(openfhe, m)
     bind_binfhe_context(m);
     bind_binfhe_keys(m);
     bind_binfhe_ciphertext(m);
-}
+}

+ 77 - 22
src/lib/pke/serialization.cpp

@@ -28,17 +28,23 @@
 #include <pybind11/pybind11.h>
 #include <pybind11/stl.h>
 #include "openfhe.h"
-#include "scheme/bfvrns/bfvrns-ser.h"
-#include "scheme/bgvrns/bgvrns-ser.h"
-#include "cryptocontext-ser.h"
 #include "bindings.h"
+#include "utils/exception.h"
+// header files needed for serialization
 #include "serialization.h"
+#include "metadata-ser.h"
+#include "ciphertext-ser.h"
+#include "cryptocontext-ser.h"
+#include "key/key-ser.h"
+#include "scheme/bfvrns/bfvrns-ser.h"
+#include "scheme/bgvrns/bgvrns-ser.h"
+#include "scheme/ckksrns/ckksrns-ser.h"
 
 using namespace lbcrypto;
 namespace py = pybind11;
 
 template <typename ST>
-bool SerializeEvalMultKeyWrapper(const std::string& filename, const ST& sertype, std::string id)
+bool SerializeEvalMultKeyWrapper(const std::string &filename, const ST &sertype, std::string id)
 {
     std::ofstream outfile(filename, std::ios::out | std::ios::binary);
     bool res;
@@ -47,27 +53,76 @@ bool SerializeEvalMultKeyWrapper(const std::string& filename, const ST& sertype,
     return res;
 }
 
+template <typename ST>
+bool SerializeEvalAutomorphismKeyWrapper(const std::string& filename, const ST& sertype, std::string id)
+{
+    std::ofstream outfile(filename, std::ios::out | std::ios::binary);
+    bool res;
+    res = CryptoContextImpl<DCRTPoly>::SerializeEvalAutomorphismKey<ST>(outfile, sertype, id);
+    outfile.close();
+    return res;
+}
+
+template <typename ST>
+bool DeserializeEvalMultKeyWrapper(const std::string &filename, const ST &sertype)
+{
+    std::ifstream emkeys(filename, std::ios::in | std::ios::binary);
+    if (!emkeys.is_open())
+    {
+        std::cerr << "I cannot read serialization from " << filename << std::endl;
+    }
+    bool res;
+    res = CryptoContextImpl<DCRTPoly>::DeserializeEvalMultKey<ST>(emkeys, sertype);
+    return res; }
+
+template <typename T, typename ST>
+std::tuple<T, bool> DeserializeFromFileWrapper(const std::string& filename, const ST& sertype) {
+    T newob;
+    bool result = Serial::DeserializeFromFile<T>(filename, newob, sertype);
+    return std::make_tuple(newob, result);
+}
+template <typename ST>
+std::tuple<CryptoContext<DCRTPoly>, bool> DeserializeCCWrapper(const std::string& filename, const ST& sertype) {
+    CryptoContext<DCRTPoly> newob;
+    bool result = Serial::DeserializeFromFile<DCRTPoly>(filename, newob, sertype);
+    return std::make_tuple(newob, result);
+}
+
 void bind_serialization(pybind11::module &m) {
     // Json Serialization
-    m.def("SerializeToFile", static_cast<bool (*)(const std::string&, const CryptoContext<DCRTPoly>&, const SerType::SERJSON&)>(&Serial::SerializeToFile<DCRTPoly>), py::arg("filename"), py::arg("obj"), py::arg("sertype"));
-    m.def("DeserializeFromFile", static_cast<bool (*)(const std::string&, CryptoContext<DCRTPoly>& ,const SerType::SERJSON&)>(&Serial::DeserializeFromFile<DCRTPoly>), py::arg("filename"), py::arg("obj"), py::arg("sertype"));
-    m.def("SerializeToFile", static_cast<bool (*)(const std::string&, const PublicKey<DCRTPoly>&, const SerType::SERJSON&)>(&Serial::SerializeToFile<PublicKey<DCRTPoly>>), py::arg("filename"), py::arg("obj"), py::arg("sertype"));
-    m.def("DeserializeFromFile", static_cast<bool (*)(const std::string&, PublicKey<DCRTPoly>& ,const SerType::SERJSON&)>(&Serial::DeserializeFromFile<PublicKey<DCRTPoly>>), py::arg("filename"), py::arg("obj"), py::arg("sertype"));
-    m.def("SerializeToFile", static_cast<bool (*)(const std::string&, const PrivateKey<DCRTPoly>&, const SerType::SERJSON&)>(&Serial::SerializeToFile<PrivateKey<DCRTPoly>>), py::arg("filename"), py::arg("obj"), py::arg("sertype"));
-    m.def("DeserializeFromFile", static_cast<bool (*)(const std::string&, PrivateKey<DCRTPoly>& ,const SerType::SERJSON&)>(&Serial::DeserializeFromFile<PrivateKey<DCRTPoly>>), py::arg("filename"), py::arg("obj"), py::arg("sertype"));
-    m.def("SerializeToFile", static_cast<bool (*)(const std::string&, const Ciphertext<DCRTPoly>&, const SerType::SERJSON&)>(&Serial::SerializeToFile<Ciphertext<DCRTPoly>>), py::arg("filename"), py::arg("obj"), py::arg("sertype"));
-    m.def("DeserializeFromFile", static_cast<bool (*)(const std::string&, Ciphertext<DCRTPoly>& ,const SerType::SERJSON&)>(&Serial::DeserializeFromFile<Ciphertext<DCRTPoly>>), py::arg("filename"), py::arg("obj"), py::arg("sertype"));
+    m.def("SerializeToFile", static_cast<bool (*)(const std::string &, const CryptoContext<DCRTPoly> &, const SerType::SERJSON &)>(&Serial::SerializeToFile<DCRTPoly>),
+          py::arg("filename"), py::arg("obj"), py::arg("sertype"));
+    m.def("DeserializeCryptoContext", static_cast<std::tuple<CryptoContext<DCRTPoly>, bool> (*)(const std::string &, const SerType::SERJSON &)>(&DeserializeCCWrapper<SerType::SERJSON>),
+          py::arg("filename"), py::arg("sertype"));
+    m.def("SerializeToFile", static_cast<bool (*)(const std::string &, const PublicKey<DCRTPoly> &, const SerType::SERJSON &)>(&Serial::SerializeToFile<PublicKey<DCRTPoly>>),
+          py::arg("filename"), py::arg("obj"), py::arg("sertype"));
+    m.def("DeserializePublicKey", static_cast<std::tuple<PublicKey<DCRTPoly>,bool> (*)(const std::string&, const SerType::SERJSON&)>(&DeserializeFromFileWrapper<PublicKey<DCRTPoly>, SerType::SERJSON>),
+          py::arg("filename"), py::arg("sertype"));
+    m.def("SerializeToFile", static_cast<bool (*)(const std::string&, const PrivateKey<DCRTPoly>&, const SerType::SERJSON&)>(&Serial::SerializeToFile<PrivateKey<DCRTPoly>>),
+          py::arg("filename"), py::arg("obj"), py::arg("sertype"));
+    m.def("DeserializePrivateKey", static_cast<std::tuple<PrivateKey<DCRTPoly>,bool> (*)(const std::string&, const SerType::SERJSON&)>(&DeserializeFromFileWrapper<PrivateKey<DCRTPoly>, SerType::SERJSON>),
+            py::arg("filename"), py::arg("sertype"));
+    m.def("SerializeToFile", static_cast<bool (*)(const std::string&, const Ciphertext<DCRTPoly>&, const SerType::SERJSON&)>(&Serial::SerializeToFile<Ciphertext<DCRTPoly>>),
+          py::arg("filename"), py::arg("obj"), py::arg("sertype"));
+    m.def("DeserializeCiphertext", static_cast<std::tuple<Ciphertext<DCRTPoly>,bool> (*)(const std::string&, const SerType::SERJSON&)>(&DeserializeFromFileWrapper<Ciphertext<DCRTPoly>, SerType::SERJSON>),
+          py::arg("filename"), py::arg("sertype"));
     // Binary Serialization
-    m.def("SerializeToFile", static_cast<bool (*)(const std::string&, const CryptoContext<DCRTPoly>&, const SerType::SERBINARY&)>(&Serial::SerializeToFile<DCRTPoly>), py::arg("filename"), py::arg("obj"), py::arg("sertype"));
-    m.def("DeserializeFromFile", static_cast<bool (*)(const std::string&, CryptoContext<DCRTPoly>& ,const SerType::SERBINARY&)>(&Serial::DeserializeFromFile<DCRTPoly>), py::arg("filename"), py::arg("obj"), py::arg("sertype"));
-    m.def("SerializeToFile", static_cast<bool (*)(const std::string&, const PublicKey<DCRTPoly>&, const SerType::SERBINARY&)>(&Serial::SerializeToFile<PublicKey<DCRTPoly>>), py::arg("filename"), py::arg("obj"), py::arg("sertype"));
-    m.def("DeserializeFromFile", static_cast<bool (*)(const std::string&, PublicKey<DCRTPoly>& ,const SerType::SERBINARY&)>(&Serial::DeserializeFromFile<PublicKey<DCRTPoly>>), py::arg("filename"), py::arg("obj"), py::arg("sertype"));
-    m.def("SerializeToFile", static_cast<bool (*)(const std::string&, const PrivateKey<DCRTPoly>&, const SerType::SERBINARY&)>(&Serial::SerializeToFile<PrivateKey<DCRTPoly>>), py::arg("filename"), py::arg("obj"), py::arg("sertype"));
-    m.def("DeserializeFromFile", static_cast<bool (*)(const std::string&, PrivateKey<DCRTPoly>& ,const SerType::SERBINARY&)>(&Serial::DeserializeFromFile<PrivateKey<DCRTPoly>>), py::arg("filename"), py::arg("obj"), py::arg("sertype"));
-    m.def("SerializeToFile", static_cast<bool (*)(const std::string&, const Ciphertext<DCRTPoly>&, const SerType::SERBINARY&)>(&Serial::SerializeToFile<Ciphertext<DCRTPoly>>), py::arg("filename"), py::arg("obj"), py::arg("sertype"));
-    m.def("DeserializeFromFile", static_cast<bool (*)(const std::string&, Ciphertext<DCRTPoly>& ,const SerType::SERBINARY&)>(&Serial::DeserializeFromFile<Ciphertext<DCRTPoly>>), py::arg("filename"), py::arg("obj"), py::arg("sertype"));
-    
+    m.def("SerializeToFile", static_cast<bool (*)(const std::string&,const CryptoContext<DCRTPoly>&, const SerType::SERBINARY&)>(&Serial::SerializeToFile<DCRTPoly>),
+          py::arg("filename"), py::arg("obj"), py::arg("sertype"));
+    m.def("DeserializeCryptoContext", static_cast<std::tuple<CryptoContext<DCRTPoly>,bool> (*)(const std::string&, const SerType::SERBINARY&)>(&DeserializeCCWrapper<SerType::SERBINARY>),
+          py::arg("filename"), py::arg("sertype"));
+    m.def("SerializeToFile", static_cast<bool (*)(const std::string&, const PublicKey<DCRTPoly>&, const SerType::SERBINARY&)>(&Serial::SerializeToFile<PublicKey<DCRTPoly>>),
+          py::arg("filename"), py::arg("obj"), py::arg("sertype"));
+    m.def("DeserializePublicKey", static_cast<std::tuple<PublicKey<DCRTPoly>,bool> (*)(const std::string&, const SerType::SERBINARY&)>(&DeserializeFromFileWrapper<PublicKey<DCRTPoly>, SerType::SERBINARY>),
+          py::arg("filename"), py::arg("sertype"));
+    m.def("SerializeToFile", static_cast<bool (*)(const std::string&, const PrivateKey<DCRTPoly>&, const SerType::SERBINARY&)>(&Serial::SerializeToFile<PrivateKey<DCRTPoly>>),
+          py::arg("filename"), py::arg("obj"), py::arg("sertype"));
+    m.def("DeserializePrivateKey", static_cast<std::tuple<PrivateKey<DCRTPoly>,bool> (*)(const std::string&, const SerType::SERBINARY&)>(&DeserializeFromFileWrapper<PrivateKey<DCRTPoly>, SerType::SERBINARY>),
+          py::arg("filename"), py::arg("sertype"));
+    m.def("SerializeToFile", static_cast<bool (*)(const std::string&, const Ciphertext<DCRTPoly>&, const SerType::SERBINARY&)>(&Serial::SerializeToFile<Ciphertext<DCRTPoly>>),
+          py::arg("filename"), py::arg("obj"), py::arg("sertype"));
+    m.def("DeserializeCiphertext", static_cast<std::tuple<Ciphertext<DCRTPoly>,bool> (*)(const std::string&, const SerType::SERBINARY&)>(&DeserializeFromFileWrapper<Ciphertext<DCRTPoly>, SerType::SERBINARY>),
+            py::arg("filename"), py::arg("sertype"));   
     
 }
 
-

+ 59 - 0
src/pke/examples/test_serial_cc.py

@@ -0,0 +1,59 @@
+# Initial Settings
+from openfhe import *
+# import openfhe.PKESchemeFeature as Feature
+
+datafolder = 'demoData'
+
+print("This program requres the subdirectory `" + datafolder + "' to exist, otherwise you will get an error writing serializations.")
+
+# Sample Program: Step 1: Set CryptoContext
+parameters = CCParamsBFVRNS()
+parameters.SetPlaintextModulus(65537)
+parameters.SetMultiplicativeDepth(2)
+
+cryptoContext = GenCryptoContext(parameters)
+# Enable features that you wish to use
+cryptoContext.Enable(PKESchemeFeature.PKE)
+cryptoContext.Enable(PKESchemeFeature.KEYSWITCH)
+cryptoContext.Enable(PKESchemeFeature.LEVELEDSHE)
+
+keypair = cryptoContext.KeyGen()
+vectorOfInts1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
+plaintext1 = cryptoContext.MakePackedPlaintext(vectorOfInts1)
+ciphertext1 = cryptoContext.Encrypt(keypair.publicKey, plaintext1)
+
+# Serialize cryptocontext
+if not SerializeToFile(datafolder + "/cryptocontext.json", cryptoContext, JSON):
+   raise Exception("Error writing serialization of the crypto context to cryptocontext.json")
+print("The cryptocontext has been serialized.")
+# Serialize Ciphertext
+if not SerializeToFile(datafolder + "/ciphertext1.json", ciphertext1, JSON):
+   raise Exception("Error writing serialization of the ciphertext to ciphertext1.json")
+
+cryptoContext.ClearEvalMultKeys()
+cryptoContext.ClearEvalAutomorphismKeys()
+ReleaseAllContexts()
+# Deserialize the crypto context
+#cc = CryptoContext()
+
+res, cc = DeserializeFromFiletuple(datafolder + "/cryptocontext.json", JSON)
+if not res:
+   raise Exception("Error reading serialization of the crypto context from cryptocontext.txt")
+# cc = DeserializeFromFile2(datafolder + "/cryptocontext.json", JSON)
+# print("The cryptocontext has been deserialized.")
+# Serialize cryptocontext again
+if not SerializeToFile(datafolder + "/cryptocontext2.json", cc, JSON):
+   raise Exception("Error writing serialization of the crypto context to cryptocontext.json")
+print("The cryptocontext has been serialized.")
+
+ct1 = Ciphertext()
+# Deserialize the ciphertext
+if not DeserializeFromFile(datafolder + "/ciphertext1.json", ct1, JSON):
+   raise Exception("Error reading serialization of the ciphertext from ciphertext1.txt")
+
+# Serialize the ciphertext again
+if not SerializeToFile(datafolder + "/ciphertext12.json", ct1, JSON):
+   raise Exception("Error writing serialization of the ciphertext to ciphertext2.json")
+
+
+