Created
May 21, 2020 18:14
-
-
Save giancarloGiuffra/f7da5e7f856be6eb64a1069cc1afbf22 to your computer and use it in GitHub Desktop.
reprex for stackoverflow question https://stackoverflow.com/q/61895626/4970597
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# the compiler: gcc for C program, define as g++ for C++ | |
CC = g++ | |
INCLUDEDIR = /usr/local/include | |
LIBDIR = /usr/local/helib_pack/lib | |
LIBS = -lntl -lhelib -lgmp -lboost_serialization | |
# compiler flags: | |
CFLAGS = -g -Wall -std=c++14 -I $(INCLUDEDIR) | |
TARGETS = test-serialization | |
DEPS = serialization.hpp | |
all: $(TARGETS) | |
test-serialization: test-serialization.o | |
$(TARGETS): | |
$(CC) -o $@ $^ $(CFLAGS) -Wl,-rpath,$(LIBDIR) -L $(LIBDIR) $(LIBS) | |
%.o: %.cpp $(DEPS) | |
$(CC) -c -o $@ $< $(CFLAGS) | |
clean: | |
$(RM) $(TARGETS) *.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef EVOTING_SERIALIZATION_H | |
#define EVOTING_SERIALIZATION_H | |
#define BOOST_TEST_MODULE main | |
#include <helib/helib.h> | |
#include <boost/archive/text_oarchive.hpp> | |
#include <boost/archive/text_iarchive.hpp> | |
#include <boost/serialization/split_free.hpp> | |
#include <boost/serialization/vector.hpp> | |
#include <boost/test/included/unit_test.hpp> | |
#include <boost/serialization/map.hpp> | |
#include <boost/serialization/export.hpp> | |
#include <NTL/ZZ_limbs.h> | |
namespace boost{ | |
namespace serialization{ | |
/* helib::IndexSet */ | |
template<class Archive> | |
void save(Archive & archive, const helib::IndexSet & index_set, const unsigned int version){ | |
std::vector<long> elements; | |
for(long element = index_set.first(); element <= index_set.last(); element = index_set.next(element)) | |
elements.push_back(element); | |
archive << elements; | |
} | |
template<class Archive> | |
void load(Archive & archive, helib::IndexSet & index_set, const unsigned int version){ | |
std::vector<long> elements; | |
archive >> elements; | |
index_set = helib::IndexSet(); | |
for(auto element : elements) | |
index_set.insert(element); | |
} | |
/* helib::SKHandle */ | |
template<class Archive> | |
void save(Archive & archive, const helib::SKHandle & skhandle, const unsigned int version){ | |
archive << skhandle.getPowerOfS(); | |
archive << skhandle.getPowerOfX(); | |
archive << skhandle.getSecretKeyID(); | |
} | |
template<class Archive> | |
void load(Archive & archive, helib::SKHandle & skhandle, const unsigned int version){ | |
long powerOfS, powerOfX, secretKeyID; | |
archive >> powerOfS; | |
archive >> powerOfX; | |
archive >> secretKeyID; | |
skhandle = helib::SKHandle(powerOfS, powerOfX, secretKeyID); | |
} | |
/* NTL::Vec<T> */ | |
template<class Archive, typename T> | |
void save(Archive & archive, const NTL::Vec<T> & ntl_vector, const unsigned int version){ | |
std::vector<T> elements; | |
for(auto it = ntl_vector.begin(); it != ntl_vector.end(); ++it) | |
elements.push_back(*it); | |
archive << elements; | |
} | |
template<class Archive, typename T> | |
void load(Archive & archive, NTL::Vec<T> & ntl_vector, const unsigned int version){ | |
std::vector<T> elements; | |
archive >> elements; | |
for(auto element : elements) | |
ntl_vector.append(element); | |
} | |
template<class Archive, typename T> | |
void serialize(Archive & archive, NTL::Vec<T> & ntl_vector, const unsigned int version){ | |
split_free(archive, ntl_vector, version); | |
} | |
/* helib::IndexMap<T> */ | |
template<class Archive, typename T> | |
void save(Archive & archive, const helib::IndexMap<NTL::Vec<T>> & index_map, const unsigned int version){ | |
auto index_set = index_map.getIndexSet(); | |
std::map<long,NTL::Vec<T>> map; | |
for(auto index = index_set.first(); index <= index_set.last(); index = index_set.next(index)) | |
map[index] = index_map[index]; | |
archive << index_set; | |
archive << map; | |
} | |
template<class Archive, typename T> | |
void load(Archive & archive, helib::IndexMap<NTL::Vec<T>> & index_map, const unsigned int version){ | |
helib::IndexSet index_set; | |
std::map<long,NTL::Vec<T>> map; | |
archive >> index_set; | |
archive >> map; | |
index_map.clear(); | |
index_map.insert(index_set); | |
for(auto index = index_set.first(); index <= index_set.last(); index = index_set.next(index)){ | |
index_map[index].QuickSetLength(map[index].length()); | |
index_map[index] = map[index]; | |
} | |
} | |
template<class Archive, typename T> | |
void serialize(Archive & archive, helib::IndexMap<NTL::Vec<T>> & index_map, const unsigned int version){ | |
split_free(archive, index_map, version); | |
} | |
/* helib::DoubleCRT */ | |
template<class Archive> | |
void save_construct_data(Archive & archive, const helib::DoubleCRT * polynomial, const unsigned int version){ | |
NTL::ZZX polynomialZZX; | |
polynomial->toPoly(polynomialZZX); | |
auto context = polynomial->getContext(); | |
archive << &context; | |
archive << polynomial->getIndexSet(); | |
archive << polynomialZZX; | |
} | |
template<class Archive> | |
void load_construct_data(Archive & archive, helib::DoubleCRT * polynomial, const unsigned int version){ | |
helib::Context * context = new helib::Context(2,3,1); //random numbers since there is no default constructor | |
helib::IndexSet index_set; | |
NTL::ZZX polynomialZZX; | |
archive >> context; | |
archive >> index_set; | |
archive >> polynomialZZX; | |
::new(polynomial)helib::DoubleCRT(polynomialZZX, *context, index_set); | |
} | |
template<class Archive> | |
void serialize(Archive & archive, helib::DoubleCRT & polynomial, const unsigned int version){} | |
/* helib::Context */ | |
template<class Archive> | |
inline void save_construct_data(Archive & archive, const helib::Context * context, const unsigned int version){ | |
archive << context->zMStar.getM(); | |
archive << context->zMStar.getP(); | |
archive << context->alMod.getR(); | |
archive << context->smallPrimes; | |
archive << context->ctxtPrimes; | |
archive << context->specialPrimes; | |
archive << context->digits; | |
auto lastIndexPrime = context->allPrimes().last(); | |
std::vector<long> primes(lastIndexPrime + 1); | |
for(auto index = context->smallPrimes.first(); index <= context->smallPrimes.last(); index = context->smallPrimes.next(index)) | |
primes[index] = context->ithPrime(index); | |
for(auto index = context->ctxtPrimes.first(); index <= context->ctxtPrimes.last(); index = context->ctxtPrimes.next(index)) | |
primes[index] = context->ithPrime(index); | |
for(auto index = context->specialPrimes.first(); index <= context->specialPrimes.last(); index = context->specialPrimes.next(index)) | |
primes[index] = context->ithPrime(index); | |
archive << primes; | |
} | |
template<class Archive> | |
inline void load_construct_data(Archive & archive, helib::Context * context, const unsigned int version){ | |
unsigned long m; | |
unsigned long p; | |
unsigned long r; | |
helib::IndexSet smallPrimes; | |
helib::IndexSet ctxtPrimes; | |
helib::IndexSet specialPrimes; | |
std::vector<helib::IndexSet> digits; | |
std::vector<long> primes; | |
archive >> m; | |
archive >> p; | |
archive >> r; | |
archive >> smallPrimes; | |
archive >> ctxtPrimes; | |
archive >> specialPrimes; | |
archive >> digits; | |
archive >> primes; | |
::new(context)helib::Context(m, p, r); | |
//restore smallPrimes | |
for(long index = smallPrimes.first(); index <= smallPrimes.last(); index = smallPrimes.next(index)) | |
context->AddSmallPrime(primes[index]); | |
//restore ctxtPrimes | |
for(long index = ctxtPrimes.first(); index <= ctxtPrimes.last(); index = ctxtPrimes.next(index)) | |
context->AddCtxtPrime(primes[index]); | |
//restore specialPrimes | |
for(long index = specialPrimes.first(); index <= specialPrimes.last(); index = specialPrimes.next(index)) | |
context->AddSpecialPrime(primes[index]); | |
//restore digits | |
context->digits = digits; | |
//last operation made in buildModchain | |
endBuildModChain(*context); | |
} | |
template<class Archive> | |
void serialize(Archive & archive, helib::Context & context, const unsigned int version){} | |
/* NTL::ZZ */ | |
template<class Archive> | |
void save(Archive & archive, const NTL::ZZ & big_integer, const unsigned int version){ | |
archive << big_integer.size(); | |
archive << boost::serialization::make_array(ZZ_limbs_get(big_integer), big_integer.size()); | |
} | |
template<class Archive> | |
void load(Archive & archive, NTL::ZZ & big_integer, const unsigned int version){ | |
long size; | |
NTL::ZZ_limb_t * pointer; | |
archive >> size; | |
archive >> boost::serialization::make_array(pointer, size); | |
ZZ_limbs_set(big_integer, pointer, size); | |
} | |
/* NTL::ZZX */ | |
template<class Archive> | |
void save(Archive & archive, const NTL::ZZX & polynomial, const unsigned int version){ | |
auto degree = NTL::deg(polynomial); | |
std::vector<NTL::ZZ> coefficients; | |
for(int term = 0; term <= degree; ++term) | |
coefficients.push_back(NTL::coeff(polynomial, term)); | |
archive << coefficients; | |
} | |
template<class Archive> | |
void load(Archive & archive, NTL::ZZX & polynomial, const unsigned int version){ | |
std::vector<NTL::ZZ> coefficients; | |
archive >> coefficients; | |
NTL::clear(polynomial); | |
for(int term = 0; term < coefficients.size(); ++term) | |
NTL::SetCoeff(polynomial, term, coefficients[term]); | |
} | |
/* NTL::xdouble */ | |
template<class Archive> | |
void serialize(Archive & archive, NTL::xdouble & xdouble, const unsigned int version){ | |
archive & xdouble.x; | |
archive & xdouble.e; | |
} | |
/* helib::KeySwitch */ | |
template<class Archive> | |
void serialize(Archive & archive, helib::KeySwitch & keyswitch, const unsigned int version){ | |
archive & keyswitch.fromKey; | |
archive & keyswitch.toKeyID; | |
archive & keyswitch.ptxtSpace; | |
archive & keyswitch.prgSeed; | |
archive & keyswitch.b; | |
} | |
template<class Archive> | |
void save(Archive & archive, const helib::PubKey & pubkey, const unsigned int version){ | |
BOOST_TEST_MESSAGE("inside save_construct_data"); | |
archive << &(pubkey.context); | |
archive << pubkey.skBounds; | |
archive << pubkey.keySwitching; | |
archive << pubkey.keySwitchMap; | |
archive << pubkey.KS_strategy; | |
archive << pubkey.recryptKeyID; | |
} | |
template<class Archive> | |
void load_construct_data(Archive & archive, helib::PubKey * pubkey, const unsigned int version){ | |
helib::Context * context = new helib::Context(2,3,1); //random numbers since there is no default constructor | |
BOOST_TEST_MESSAGE("deserializing context"); | |
archive >> context; | |
std::vector<double> skBounds; | |
std::vector<helib::KeySwitch> keySwitching; | |
std::vector<std::vector<long>> keySwitchMap; | |
NTL::Vec<long> KS_strategy; | |
long recryptKeyID; | |
BOOST_TEST_MESSAGE("deserializing skbounds"); | |
archive >> skBounds; | |
BOOST_TEST_MESSAGE("deserializing keyswitching"); | |
archive >> keySwitching; | |
BOOST_TEST_MESSAGE("deserializing keyswitchmap"); | |
archive >> keySwitchMap; | |
BOOST_TEST_MESSAGE("deserializing KS_strategy"); | |
archive >> KS_strategy; | |
BOOST_TEST_MESSAGE("deserializing recryptKeyID"); | |
archive >> recryptKeyID; | |
BOOST_TEST_MESSAGE("new pubkey"); | |
::new(pubkey)helib::PubKey(*context); | |
} | |
template<class Archive> | |
void serialize(Archive & archive, helib::PubKey & pubkey, const unsigned int version){ | |
split_free(archive, pubkey, version); | |
} | |
template<class Archive> | |
void load(Archive & archive, helib::PubKey & pubkey, const unsigned int version){ | |
} | |
}//namespace boost | |
}//namespace serialization | |
BOOST_SERIALIZATION_SPLIT_FREE(helib::IndexSet) | |
BOOST_SERIALIZATION_SPLIT_FREE(helib::SKHandle) | |
BOOST_SERIALIZATION_SPLIT_FREE(NTL::ZZ) | |
BOOST_SERIALIZATION_SPLIT_FREE(NTL::ZZX) | |
#endif //EVOTING_SERIALIZATION_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define BOOST_TEST_MODULE main | |
#include <boost/test/included/unit_test.hpp> | |
#include <helib/helib.h> | |
#include <fstream> | |
#include "serialization.hpp" | |
#include <boost/archive/text_oarchive.hpp> | |
#include <boost/archive/text_iarchive.hpp> | |
#include <boost/archive/binary_oarchive.hpp> | |
#include <boost/archive/binary_iarchive.hpp> | |
helib::Context helibTestContext(){ | |
// Plaintext prime modulus | |
unsigned long p = 4999; | |
// Cyclotomic polynomial - defines phi(m) | |
unsigned long m = 32109; | |
// Hensel lifting (default = 1) | |
unsigned long r = 1; | |
// Number of bits of the modulus chain | |
unsigned long bits = 300; | |
// Number of columns of Key-Switching matix (default = 2 or 3) | |
unsigned long c = 2; | |
helib::Context context(m, p, r); | |
// Modify the context, adding primes to the modulus chain | |
buildModChain(context, bits, c); | |
return context; | |
} | |
BOOST_AUTO_TEST_CASE(serialization_pubkey) | |
{ | |
auto context = helibTestContext(); | |
helib::SecKey secret_key(context); | |
secret_key.GenSecKey(); | |
// Compute key-switching matrices that we need | |
helib::addSome1DMatrices(secret_key); | |
// Set the secret key (upcast: SecKey is a subclass of PubKey) | |
const helib::PubKey& original_pubkey = secret_key; | |
std::string filename = "pubkey.serialized"; | |
std::ofstream os(filename, std::ios::binary); | |
{ | |
boost::archive::binary_oarchive oarchive(os); | |
oarchive << original_pubkey; | |
} | |
helib::PubKey * restored_pubkey = new helib::PubKey(helib::Context(2,3,1)); | |
{ | |
std::ifstream ifs(filename, std::ios::binary); | |
boost::archive::binary_iarchive iarchive(ifs); | |
BOOST_TEST_CHECKPOINT("calling deserialization"); | |
iarchive >> restored_pubkey; | |
BOOST_TEST_CHECKPOINT("done with deserialization"); | |
} | |
BOOST_TEST((restored_pubkey->context == original_pubkey.context)); | |
BOOST_TEST((restored_pubkey->skBounds == original_pubkey.skBounds)); | |
BOOST_TEST((restored_pubkey->keySwitching == original_pubkey.keySwitching)); | |
BOOST_TEST((restored_pubkey->keySwitchMap == original_pubkey.keySwitchMap)); | |
BOOST_TEST((restored_pubkey->KS_strategy == original_pubkey.KS_strategy)); | |
BOOST_TEST((restored_pubkey->recryptKeyID == original_pubkey.recryptKeyID)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment