Skip to content

Commit b7ee5b0

Browse files
authored
Merge pull request #155 from openfheorg/td-issue-145
#145 Add Serialize/Deserialize functions
2 parents 031e128 + 71707d2 commit b7ee5b0

File tree

3 files changed

+147
-2
lines changed

3 files changed

+147
-2
lines changed

src/include/pke/serialization.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "bindings.h"
3434

3535
using namespace lbcrypto;
36+
namespace py = pybind11;
3637

3738
template <typename ST>
3839
bool SerializeEvalMultKeyWrapper(const std::string& filename, const ST& sertype, std::string id);
@@ -43,4 +44,16 @@ bool SerializeEvalAutomorphismKeyWrapper(const std::string& filename, const ST&
4344
template <typename ST>
4445
bool DeserializeEvalMultKeyWrapper(const std::string& filename, const ST& sertype);
4546

47+
template <typename T, typename ST>
48+
std::string SerializeToStringWrapper(const T& obj, const ST& sertype);
49+
50+
template <typename T, typename ST>
51+
py::bytes SerializeToBytesWrapper(const T& obj, const ST& sertype);
52+
53+
template <typename T, typename ST>
54+
T DeserializeFromStringWrapper(const std::string& str, const ST& sertype);
55+
56+
template <typename T, typename ST>
57+
T DeserializeFromBytesWrapper(const py::bytes& bytes, const ST& sertype);
58+
4659
#endif // OPENFHE_SERIALIZATION_BINDINGS_H

src/lib/pke/serialization.cpp

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,39 @@ std::tuple<CryptoContext<DCRTPoly>, bool> DeserializeCCWrapper(const std::string
8888
return std::make_tuple(newob, result);
8989
}
9090

91+
template <typename T, typename ST>
92+
std::string SerializeToStringWrapper(const T& obj, const ST& sertype) {
93+
std::ostringstream oss;
94+
Serial::Serialize<T>(obj, oss, sertype);
95+
return oss.str();
96+
}
97+
98+
template <typename T, typename ST>
99+
py::bytes SerializeToBytesWrapper(const T& obj, const ST& sertype) {
100+
std::ostringstream oss(std::ios::binary);
101+
Serial::Serialize<T>(obj, oss, sertype);
102+
std::string str = oss.str();
103+
return py::bytes(str);
104+
}
105+
106+
template <typename T, typename ST>
107+
T DeserializeFromStringWrapper(const std::string& str, const ST& sertype) {
108+
T obj;
109+
std::istringstream iss(str);
110+
Serial::Deserialize<T>(obj, iss, sertype);
111+
return obj;
112+
}
113+
114+
template <typename T, typename ST>
115+
T DeserializeFromBytesWrapper(const py::bytes& bytes, const ST& sertype) {
116+
T obj;
117+
std::string str(bytes);
118+
std::istringstream iss(str, std::ios::binary);
119+
Serial::Deserialize<T>(obj, iss, sertype);
120+
return obj;
121+
}
122+
123+
91124
void bind_serialization(pybind11::module &m) {
92125
// Json Serialization
93126
m.def("SerializeToFile", static_cast<bool (*)(const std::string &, const CryptoContext<DCRTPoly> &, const SerType::SERJSON &)>(&Serial::SerializeToFile<DCRTPoly>),
@@ -110,6 +143,29 @@ void bind_serialization(pybind11::module &m) {
110143
py::arg("filename"), py::arg("obj"), py::arg("sertype"));
111144
m.def("DeserializeEvalKey", static_cast<std::tuple<EvalKey<DCRTPoly>,bool> (*)(const std::string&, const SerType::SERJSON&)>(&DeserializeFromFileWrapper<EvalKey<DCRTPoly>, SerType::SERJSON>),
112145
py::arg("filename"), py::arg("sertype"));
146+
147+
// JSON Serialization to string
148+
m.def("Serialize", &SerializeToStringWrapper<CryptoContext<DCRTPoly>, SerType::SERJSON>,
149+
py::arg("obj"), py::arg("sertype"));
150+
m.def("DeserializeCryptoContextString", &DeserializeFromStringWrapper<CryptoContext<DCRTPoly>, SerType::SERJSON>,
151+
py::arg("str"), py::arg("sertype"));
152+
m.def("Serialize", &SerializeToStringWrapper<PublicKey<DCRTPoly>, SerType::SERJSON>,
153+
py::arg("obj"), py::arg("sertype"));
154+
m.def("DeserializePublicKeyString", &DeserializeFromStringWrapper<PublicKey<DCRTPoly>, SerType::SERJSON>,
155+
py::arg("str"), py::arg("sertype"));
156+
m.def("Serialize", &SerializeToStringWrapper<PrivateKey<DCRTPoly>, SerType::SERJSON>,
157+
py::arg("obj"), py::arg("sertype"));
158+
m.def("DeserializePrivateKeyString", &DeserializeFromStringWrapper<PrivateKey<DCRTPoly>, SerType::SERJSON>,
159+
py::arg("str"), py::arg("sertype"));
160+
m.def("Serialize", &SerializeToStringWrapper<Ciphertext<DCRTPoly>, SerType::SERJSON>,
161+
py::arg("obj"), py::arg("sertype"));
162+
m.def("DeserializeCiphertextString", &DeserializeFromStringWrapper<Ciphertext<DCRTPoly>, SerType::SERJSON>,
163+
py::arg("str"), py::arg("sertype"));
164+
m.def("Serialize", &SerializeToStringWrapper<EvalKey<DCRTPoly>, SerType::SERJSON>,
165+
py::arg("obj"), py::arg("sertype"));
166+
m.def("DeserializeEvalKeyString", &DeserializeFromStringWrapper<EvalKey<DCRTPoly>, SerType::SERJSON>,
167+
py::arg("str"), py::arg("sertype"));
168+
113169
// Binary Serialization
114170
m.def("SerializeToFile", static_cast<bool (*)(const std::string&,const CryptoContext<DCRTPoly>&, const SerType::SERBINARY&)>(&Serial::SerializeToFile<DCRTPoly>),
115171
py::arg("filename"), py::arg("obj"), py::arg("sertype"));
@@ -130,7 +186,28 @@ void bind_serialization(pybind11::module &m) {
130186
m.def("SerializeToFile", static_cast<bool (*)(const std::string&, const EvalKey<DCRTPoly>&, const SerType::SERBINARY&)>(&Serial::SerializeToFile<EvalKey<DCRTPoly>>),
131187
py::arg("filename"), py::arg("obj"), py::arg("sertype"));
132188
m.def("DeserializeEvalKey", static_cast<std::tuple<EvalKey<DCRTPoly>,bool> (*)(const std::string&, const SerType::SERBINARY&)>(&DeserializeFromFileWrapper<EvalKey<DCRTPoly>, SerType::SERBINARY>),
133-
py::arg("filename"), py::arg("sertype"));
134-
189+
py::arg("filename"), py::arg("sertype"));
190+
191+
// Binary Serialization to bytes
192+
m.def("Serialize", &SerializeToBytesWrapper<CryptoContext<DCRTPoly>, SerType::SERBINARY>,
193+
py::arg("obj"), py::arg("sertype"));
194+
m.def("DeserializeCryptoContextString", &DeserializeFromBytesWrapper<CryptoContext<DCRTPoly>, SerType::SERBINARY>,
195+
py::arg("str"), py::arg("sertype"));
196+
m.def("Serialize", &SerializeToBytesWrapper<PublicKey<DCRTPoly>, SerType::SERBINARY>,
197+
py::arg("obj"), py::arg("sertype"));
198+
m.def("DeserializePublicKeyString", &DeserializeFromBytesWrapper<PublicKey<DCRTPoly>, SerType::SERBINARY>,
199+
py::arg("str"), py::arg("sertype"));
200+
m.def("Serialize", &SerializeToBytesWrapper<PrivateKey<DCRTPoly>, SerType::SERBINARY>,
201+
py::arg("obj"), py::arg("sertype"));
202+
m.def("DeserializePrivateKeyString", &DeserializeFromBytesWrapper<PrivateKey<DCRTPoly>, SerType::SERBINARY>,
203+
py::arg("str"), py::arg("sertype"));
204+
m.def("Serialize", &SerializeToBytesWrapper<Ciphertext<DCRTPoly>, SerType::SERBINARY>,
205+
py::arg("obj"), py::arg("sertype"));
206+
m.def("DeserializeCiphertextString", &DeserializeFromBytesWrapper<Ciphertext<DCRTPoly>, SerType::SERBINARY>,
207+
py::arg("str"), py::arg("sertype"));
208+
m.def("Serialize", &SerializeToBytesWrapper<EvalKey<DCRTPoly>, SerType::SERBINARY>,
209+
py::arg("obj"), py::arg("sertype"));
210+
m.def("DeserializeEvalKeyString", &DeserializeFromBytesWrapper<EvalKey<DCRTPoly>, SerType::SERBINARY>,
211+
py::arg("str"), py::arg("sertype"));
135212
}
136213

tests/test_serial_cc.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import logging
2+
import pytest
23

34
import openfhe as fhe
45

@@ -37,3 +38,57 @@ def test_serial_cryptocontext(tmp_path):
3738
assert isinstance(ct1, fhe.Ciphertext)
3839
LOGGER.debug("Cryptocontext deserializes to %s %s", success, ct1)
3940
assert fhe.SerializeToFile(str(tmp_path / "ciphertext12.json"), ct1, fhe.JSON)
41+
42+
43+
@pytest.mark.parametrize("mode", [fhe.JSON, fhe.BINARY])
44+
def test_serial_cryptocontext_str(mode):
45+
parameters = fhe.CCParamsBFVRNS()
46+
parameters.SetPlaintextModulus(65537)
47+
parameters.SetMultiplicativeDepth(2)
48+
49+
cryptoContext = fhe.GenCryptoContext(parameters)
50+
cryptoContext.Enable(fhe.PKESchemeFeature.PKE)
51+
cryptoContext.Enable(fhe.PKESchemeFeature.PRE)
52+
53+
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)
58+
59+
60+
cryptoContext_ser = fhe.Serialize(cryptoContext, mode)
61+
LOGGER.debug("The cryptocontext has been serialized.")
62+
publickey_ser = fhe.Serialize(keypair.publicKey, mode)
63+
LOGGER.debug("The public key has been serialized.")
64+
secretkey_ser = fhe.Serialize(keypair.secretKey, mode)
65+
LOGGER.debug("The private key has been serialized.")
66+
ciphertext_ser = fhe.Serialize(ciphertext, mode)
67+
LOGGER.debug("The ciphertext has been serialized.")
68+
evalKey_ser = fhe.Serialize(evalKey, mode)
69+
LOGGER.debug("The evaluation key has been serialized.")
70+
71+
72+
cryptoContext.ClearEvalMultKeys()
73+
cryptoContext.ClearEvalAutomorphismKeys()
74+
fhe.ReleaseAllContexts()
75+
76+
cc = fhe.DeserializeCryptoContextString(cryptoContext_ser, mode)
77+
assert isinstance(cc, fhe.CryptoContext)
78+
LOGGER.debug("The cryptocontext has been deserialized.")
79+
80+
pk = fhe.DeserializePublicKeyString(publickey_ser, mode)
81+
assert isinstance(pk, fhe.PublicKey)
82+
LOGGER.debug("The public key has been deserialized.")
83+
84+
sk = fhe.DeserializePrivateKeyString(secretkey_ser, mode)
85+
assert isinstance(sk, fhe.PrivateKey)
86+
LOGGER.debug("The private key has been deserialized.")
87+
88+
ct = fhe.DeserializeCiphertextString(ciphertext_ser, mode)
89+
assert isinstance(ct, fhe.Ciphertext)
90+
LOGGER.debug("The ciphertext has been reserialized.")
91+
92+
ek = fhe.DeserializeEvalKeyString(evalKey_ser, mode)
93+
assert isinstance(ek, fhe.EvalKey)
94+
LOGGER.debug("The evaluation key has been deserialized.")

0 commit comments

Comments
 (0)