Commit a135aa36 authored by Gerard Ryan's avatar Gerard Ryan
Browse files

Merge branch 'polyakov-v1.1.1' into v1.1.1-work-branch

parents ee559783 bafd969f
......@@ -681,43 +681,71 @@ PolyImpl<ModType,IntType,VecType,ParmType> PolyImpl<ModType,IntType,VecType,Parm
usint m = this->m_params->GetCyclotomicOrder();
usint n = this->m_params->GetRingDimension();
if (m_params->OrderIsPowerOfTwo() == false) {
if (this->m_format == EVALUATION) {
//Add a test based on the inverse totient hash table
//if (i % 2 == 0)
// throw std::runtime_error("automorphism index should be odd\n");
if (m_params->OrderIsPowerOfTwo() == false) {
const auto &modulus = this->m_params->GetModulus();
//Add a test based on the inverse totient hash table
//if (i % 2 == 0)
// throw std::runtime_error("automorphism index should be odd\n");
// All automorphism operations are performed for k coprime to m, which are generated using GetTotientList(m)
std::vector<usint> totientList = GetTotientList(m);
const auto &modulus = this->m_params->GetModulus();
// Temporary vector of size m is introduced
// This step can be eliminated by using a hash table that looks up the ring index (between 0 and n - 1)
// based on the totient index (between 0 and m - 1)
VecType expanded(m, modulus);
for (usint i = 0; i < n; i++) {
expanded.operator[](totientList.operator[](i))= m_values->operator[](i);
}
// All automorphism operations are performed for k coprime to m, which are generated using GetTotientList(m)
std::vector<usint> totientList = GetTotientList(m);
// Temporary vector of size m is introduced
// This step can be eliminated by using a hash table that looks up the ring index (between 0 and n - 1)
// based on the totient index (between 0 and m - 1)
VecType expanded(m, modulus);
for (usint i = 0; i < n; i++) {
expanded.operator[](totientList.operator[](i))= m_values->operator[](i);
}
for (usint i = 0; i < n; i++) {
for (usint i = 0; i < n; i++) {
//determines which power of primitive root unity we should switch to
usint idx = totientList.operator[](i)*k % m;
//determines which power of primitive root unity we should switch to
usint idx = totientList.operator[](i)*k % m;
result.m_values->operator[](i)= expanded.operator[](idx);
result.m_values->operator[](i)= expanded.operator[](idx);
}
} else { // power of two cyclotomics
if (k % 2 == 0)
throw std::runtime_error("automorphism index should be odd\n");
for (usint j = 1; j < m; j = j + 2) {
//determines which power of primitive root unity we should switch to
usint idx = (j*k) % m;
result.m_values->operator[]((j + 1) / 2 - 1)= GetValues().operator[]((idx + 1) / 2 - 1);
}
}
} else {
if (k % 2 == 0)
throw std::runtime_error("automorphism index should be odd\n");
}
else // automorphism in coefficient representation
{
if (m_params->OrderIsPowerOfTwo() == false) {
PALISADE_THROW( lbcrypto::math_error, "Automorphism in coefficient representation is not currently supported for non-power-of-two polynomials");
}
else { // power of two cyclotomics
if (k % 2 == 0)
throw std::runtime_error("automorphism index should be odd\n");
for (usint j = 1; j < n; j++) {
for (usint j = 1; j < m; j = j + 2) {
usint temp = j*k;
usint newIndex = temp % n;
//determines which power of primitive root unity we should switch to
usint idx = (j*k) % m;
result.m_values->operator[]((j + 1) / 2 - 1)= GetValues().operator[]((idx + 1) / 2 - 1);
if ((temp/n) % 2 == 1)
result.m_values->operator[](newIndex) = m_params->GetModulus() - m_values->operator[](j);
else
result.m_values->operator[](newIndex) = m_values->operator[](j);
}
}
}
......
......@@ -808,7 +808,7 @@ void other_methods() {
usint index = 3;
Element ilvAuto(ilv.AutomorphismTransform(index));
VecType expected(4, primeModulus);
expected = {"1","56","2","37"};
expected = {"56","2","36","1"};
EXPECT_EQ(expected, ilvAuto.GetValues())
<<"Failure: AutomorphismTransform()";
}
......
......@@ -69,8 +69,13 @@ void BGVAutomorphismPackedArray(usint i);
void ArbBGVAutomorphismPackedArray(usint i);
void BFVAutomorphismPackedArray(usint i);
void ArbBFVAutomorphismPackedArray(usint i);
void ArbBFVAutomorphismCoeffArray(usint i);
void ArbBFVAutomorphismPackedArray2n(usint i);
void ArbBFVAutomorphismCoeffArray2n(usint i);
void ArbNullAutomorphismPackedArray(usint i);
void ArbNullAutomorphismCoeffArray2n(usint i);
void ArbNullAutomorphismCoeffArray(usint i);
void ArbNullAutomorphismPackedArray2n(usint i);
int main() {
......@@ -127,16 +132,48 @@ int main() {
ArbBFVAutomorphismPackedArray2n(totientList2n[index]);
}
std::cout << "\n===========NULL TESTS (EVALAUTOMORPHISM-ARBITRARY)===============: " << std::endl;
std::cout << "\n===========NULL TESTS (EVALAUTOMORPHISM-POWER-OF-TWO)===============: " << std::endl;
for (usint index = 1; index < 16; index++) {
ArbNullAutomorphismPackedArray2n(totientList2n[index]);
}
std::cout << "\n===========BFV TESTS (EVALAUTOMORPHISM-POWER-OF-TWO-COEFF-ENCODING)===============: " << std::endl;
PackedEncoding::Destroy();
for (usint index = 1; index < 10; index++) {
ArbNullAutomorphismPackedArray(totientList[index]);
ArbBFVAutomorphismCoeffArray2n(totientList[index]);
}
std::cout << "\n===========NULL TESTS (EVALAUTOMORPHISM-POWER-OF-TWO-COEFF-ENCODING)===============: " << std::endl;
PackedEncoding::Destroy();
for (usint index = 1; index < 10; index++) {
ArbNullAutomorphismCoeffArray2n(totientList[index]);
}
std::cout << "Please press any key to continue..." << std::endl;
std::cout << "\n===========BFV TESTS (EVALAUTOMORPHISM-ARB-COEFF-ENCODING)===============: " << std::endl;
cin.get();
PackedEncoding::Destroy();
for (usint index = 1; index < 10; index++) {
ArbBFVAutomorphismCoeffArray(totientList[index]);
}
/*std::cout << "\n===========NULL TESTS (EVALAUTOMORPHISM-ARB-COEFF-ENCODING)===============: " << std::endl;
PackedEncoding::Destroy();
for (usint index = 1; index < 10; index++) {
ArbNullAutomorphismCoeffArray(totientList[index]);
}
std::cout << "\n===========NULL TESTS (EVALAUTOMORPHISM-ARBITRARY)===============: " << std::endl;
PackedEncoding::Destroy();
for (usint index = 1; index < 10; index++) {
ArbNullAutomorphismPackedArray(totientList[index]);
}
*/
//cin.get();
return 0;
}
......@@ -426,6 +463,62 @@ void ArbBFVAutomorphismPackedArray(usint i) {
std::cout << "Automorphed array - at index " << i << " (using only odd coefficients)\n\t" << *intArrayNew << std::endl;
}
void ArbBFVAutomorphismCoeffArray(usint i) {
usint m = 22;
usint p = 2333;
BigInteger modulusP(p);
BigInteger modulusQ("955263939794561");
BigInteger squareRootOfRoot("941018665059848");
//usint n = GetTotient(m);
BigInteger bigmodulus("80899135611688102162227204937217");
BigInteger bigroot("77936753846653065954043047918387");
auto cycloPoly = GetCyclotomicPolynomial<BigVector, BigInteger>(m, modulusQ);
ChineseRemainderTransformArb<BigInteger, BigVector>::SetCylotomicPolynomial(cycloPoly, modulusQ);
float stdDev = 4;
shared_ptr<ILParams> params(new ILParams(m, modulusQ, squareRootOfRoot, bigmodulus, bigroot));
BigInteger delta(modulusQ.DividedBy(modulusP));
CryptoContext<Poly> cc = CryptoContextFactory<Poly>::genCryptoContextBFV(
params, p,
8, stdDev, delta.ToString());
cc->Enable(ENCRYPTION);
cc->Enable(SHE);
// Initialize the public key containers.
LPKeyPair<Poly> kp = cc->KeyGen();
std::vector<int64_t> vectorOfInts = { 1,2,3,4,5,6,7,8, 9, 10};
Plaintext intArray = cc->MakeCoefPackedPlaintext(vectorOfInts);
if (i == 3)
std::cout << "Input array\n\t" << *intArray << std::endl;
auto ciphertext = cc->Encrypt(kp.publicKey, intArray);
std::vector<usint> indexList = GetTotientList(m);
indexList.erase(indexList.begin());
auto evalKeys = cc->EvalAutomorphismKeyGen(kp.secretKey, indexList);
auto permutedCiphertext = cc->EvalAutomorphism(ciphertext, i, *evalKeys);
Plaintext intArrayNew;
cc->Decrypt(kp.secretKey, permutedCiphertext, &intArrayNew);
std::cout << "Automorphed array - at index " << i << " (using only odd coefficients)\n\t" << *intArrayNew << std::endl;
}
void ArbNullAutomorphismPackedArray(usint i) {
......@@ -483,6 +576,62 @@ void ArbNullAutomorphismPackedArray(usint i) {
std::cout << "Automorphed array - at index " << i << " (using only odd coefficients)\n\t" << *intArrayNew << std::endl;
}
void ArbNullAutomorphismCoeffArray(usint i) {
usint m = 22;
PlaintextModulus p = 89;
BigInteger modulusP(p);
/*BigInteger modulusQ("577325471560727734926295560417311036005875689");
BigInteger squareRootOfRoot("576597741275581172514290864170674379520285921");*/
BigInteger modulusQ("955263939794561");
BigInteger squareRootOfRoot("941018665059848");
//BigInteger squareRootOfRoot = RootOfUnity(2*m,modulusQ);
//std::cout << squareRootOfRoot << std::endl;
BigInteger bigmodulus("80899135611688102162227204937217");
BigInteger bigroot("77936753846653065954043047918387");
//std::cout << bigroot << std::endl;
auto cycloPoly = GetCyclotomicPolynomial<BigVector, BigInteger>(m, modulusQ);
ChineseRemainderTransformArb<BigInteger, BigVector>::SetCylotomicPolynomial(cycloPoly, modulusQ);
usint batchSize = 8;
PackedEncoding::SetParams(m, p);
shared_ptr<ILParams> params(new ILParams(m, modulusQ, squareRootOfRoot, bigmodulus, bigroot));
EncodingParams encodingParams(new EncodingParamsImpl(p, batchSize, PackedEncoding::GetAutomorphismGenerator(m)));
CryptoContext<Poly> cc = CryptoContextFactory<Poly>::genCryptoContextNull(m, encodingParams);
cc->Enable(ENCRYPTION);
cc->Enable(SHE);
// Initialize the public key containers.
LPKeyPair<Poly> kp = cc->KeyGen();
std::vector<int64_t> vectorOfInts = { 1,2,3,4,5,6,7,8, 9, 10 };
Plaintext intArray = cc->MakeCoefPackedPlaintext(vectorOfInts);
if (i == 3)
std::cout << "Input array\n\t" << *intArray << std::endl;
auto ciphertext = cc->Encrypt(kp.publicKey, intArray);
std::vector<usint> indexList = GetTotientList(m);
indexList.erase(indexList.begin());
auto evalKeys = cc->EvalAutomorphismKeyGen(kp.secretKey, indexList);
auto permutedCiphertext = cc->EvalAutomorphism(ciphertext, i, *evalKeys);
Plaintext intArrayNew;
cc->Decrypt(kp.secretKey, permutedCiphertext, &intArrayNew);
std::cout << "Automorphed array - at index " << i << " (using only odd coefficients)\n\t" << *intArrayNew << std::endl;
}
void ArbBFVAutomorphismPackedArray2n(usint i) {
......@@ -538,3 +687,161 @@ void ArbBFVAutomorphismPackedArray2n(usint i) {
std::cout << "Automorphed array - at index " << i << " (using only odd coefficients)\n\t" << *intArrayNew << std::endl;
}
void ArbNullAutomorphismPackedArray2n(usint i) {
usint m = 32;
//usint phim = 1024;
PlaintextModulus p = 193; // we choose s.t. 2m|p-1 to leverage CRTArb
BigInteger modulusP(p);
PackedEncoding::SetParams(m, p);
usint batchSize = 16;
EncodingParams encodingParams(new EncodingParamsImpl(p, batchSize, PackedEncoding::GetAutomorphismGenerator(m)));
BigInteger modulusQ("4809848800078200833");
BigInteger rootOfUnity("1512511313188104877");
BigInteger delta(modulusQ.DividedBy(modulusP));
shared_ptr<ILParams> params(new ILParams(m, modulusQ, rootOfUnity));
BigInteger EvalMultModulus("1182196001696382977");
BigInteger EvalMultRootOfUnity("105268544709215333");
CryptoContext<Poly> cc = CryptoContextFactory<Poly>::genCryptoContextNull(m, p);
cc->Enable(ENCRYPTION);
cc->Enable(SHE);
// Initialize the public key containers.
LPKeyPair<Poly> kp = cc->KeyGen();
std::vector<uint64_t> vectorOfInts = { 1,2,3,4,5,6,7,8, 9, 10, 11, 12, 13, 14, 15, 16};
Plaintext intArray = cc->MakePackedPlaintext(vectorOfInts);
if (i == 3)
std::cout << "Input array\n\t" << *intArray << std::endl;
auto ciphertext = cc->Encrypt(kp.publicKey, intArray);
std::vector<usint> indexList = GetTotientList(m);
indexList.erase(indexList.begin());
auto evalKeys = cc->EvalAutomorphismKeyGen(kp.secretKey, indexList);
auto permutedCiphertext = cc->EvalAutomorphism(ciphertext, i, *evalKeys);
Plaintext intArrayNew;
cc->Decrypt(kp.secretKey, permutedCiphertext, &intArrayNew);
std::cout << "Automorphed array - at index " << i << " (using only odd coefficients)\n\t" << *intArrayNew << std::endl;
}
void ArbBFVAutomorphismCoeffArray2n(usint i) {
usint m = 32;
//usint phim = 1024;
PlaintextModulus p = 193; // we choose s.t. 2m|p-1 to leverage CRTArb
BigInteger modulusP(p);
PackedEncoding::SetParams(m, p);
//usint batchSize = 16;
//EncodingParams encodingParams(new EncodingParamsImpl(p, batchSize, PackedEncoding::GetAutomorphismGenerator(m)));
BigInteger modulusQ("4809848800078200833");
BigInteger rootOfUnity("1512511313188104877");
BigInteger delta(modulusQ.DividedBy(modulusP));
shared_ptr<ILParams> params(new ILParams(m, modulusQ, rootOfUnity));
BigInteger EvalMultModulus("1182196001696382977");
BigInteger EvalMultRootOfUnity("105268544709215333");
usint relinWindow = 1;
float stdDev = 4;
CryptoContext<Poly> cc = CryptoContextFactory<Poly>::genCryptoContextBFV(
params, p, relinWindow, stdDev, delta.ToString(), OPTIMIZED,
EvalMultModulus.ToString(), EvalMultRootOfUnity.ToString(), 0, 9, 1.006
);
cc->Enable(ENCRYPTION);
cc->Enable(SHE);
// Initialize the public key containers.
LPKeyPair<Poly> kp = cc->KeyGen();
std::vector<int64_t> vectorOfInts = { 1,2,3,4,5,6,7,8, 9, 10, 11, 12, 13, 14, 15, 16};
Plaintext intArray = cc->MakeCoefPackedPlaintext(vectorOfInts);
if (i == 3)
std::cout << "Input array\n\t" << *intArray << std::endl;
auto ciphertext = cc->Encrypt(kp.publicKey, intArray);
std::vector<usint> indexList = GetTotientList(m);
indexList.erase(indexList.begin());
auto evalKeys = cc->EvalAutomorphismKeyGen(kp.secretKey, indexList);
auto permutedCiphertext = cc->EvalAutomorphism(ciphertext, i, *evalKeys);
Plaintext intArrayNew;
cc->Decrypt(kp.secretKey, permutedCiphertext, &intArrayNew);
std::cout << "Automorphed array - at index " << i << " (using only odd coefficients)\n\t" << *intArrayNew << std::endl;
}
void ArbNullAutomorphismCoeffArray2n(usint i) {
usint m = 32;
//usint phim = 1024;
PlaintextModulus p = 193; // we choose s.t. 2m|p-1 to leverage CRTArb
BigInteger modulusP(p);
PackedEncoding::SetParams(m, p);
//usint batchSize = 16;
//EncodingParams encodingParams(new EncodingParamsImpl(p, batchSize, PackedEncoding::GetAutomorphismGenerator(m)));
BigInteger modulusQ("4809848800078200833");
BigInteger rootOfUnity("1512511313188104877");
BigInteger delta(modulusQ.DividedBy(modulusP));
shared_ptr<ILParams> params(new ILParams(m, modulusQ, rootOfUnity));
BigInteger EvalMultModulus("1182196001696382977");
BigInteger EvalMultRootOfUnity("105268544709215333");
//usint relinWindow = 1;
//float stdDev = 4;
CryptoContext<Poly> cc = CryptoContextFactory<Poly>::genCryptoContextNull(m, p);
cc->Enable(ENCRYPTION);
cc->Enable(SHE);
// Initialize the public key containers.
LPKeyPair<Poly> kp = cc->KeyGen();
std::vector<int64_t> vectorOfInts = { 1,2,3,4,5,6,7,8, 9, 10, 11, 12, 13, 14, 15, 16};
Plaintext intArray = cc->MakeCoefPackedPlaintext(vectorOfInts);
if (i == 3)
std::cout << "Input array\n\t" << *intArray << std::endl;
auto ciphertext = cc->Encrypt(kp.publicKey, intArray);
std::vector<usint> indexList = GetTotientList(m);
indexList.erase(indexList.begin());
auto evalKeys = cc->EvalAutomorphismKeyGen(kp.secretKey, indexList);
auto permutedCiphertext = cc->EvalAutomorphism(ciphertext, i, *evalKeys);
Plaintext intArrayNew;
cc->Decrypt(kp.secretKey, permutedCiphertext, &intArrayNew);
std::cout << "Automorphed array - at index " << i << " (using only odd coefficients)\n\t" << *intArrayNew << std::endl;
}
......@@ -102,8 +102,8 @@ int main() {
std::cout << "\n===========BGV TESTS (EVALAUTOMORPHISM-ARBITRARY)===============: " << std::endl;
ArbBGVAutomorphismPackedArray(3);
std::cout << "\n===========NULL TESTS (EVALAUTOMORPHISM-ARBITRARY)===============: " << std::endl;
ArbNullAutomorphismPackedArray(3);
//std::cout << "\n===========NULL TESTS (EVALAUTOMORPHISM-ARBITRARY)===============: " << std::endl;
//ArbNullAutomorphismPackedArray(3);
std::cout << "\n===========BGV TESTS (EVALINNER-PRODUCT-ARBITRARY)===============: " << std::endl;
ArbBGVInnerProductPackedArray();
......
......@@ -326,6 +326,9 @@ bool LPAlgorithmParamsGenBFV<Element>::ParamsGen(shared_ptr<LPCryptoParameters<E
}
if (ceil(log2(q))+1 > 125)
PALISADE_THROW( lbcrypto::math_error, "BFV cannot autogenerate parameters for this case, please use BFVrns instead.");
typename Element::Integer qPrime = FirstPrime<typename Element::Integer>(ceil(log2(q))+1, 2*n);
typename Element::Integer rootOfUnity = RootOfUnity<typename Element::Integer>(2 * n, qPrime);
......
......@@ -794,13 +794,7 @@ class LPAlgorithmSHENull : public LPSHEAlgorithm<Element> {
Element temp = ciphertext->GetElement();
//Switch from coefficient representation to evaluation
temp.SwitchFormat();
temp = temp.AutomorphismTransform(i);
//Switch from evaluation representation to coefficient
temp.SwitchFormat();
permutedCiphertext->SetElement(temp);
......@@ -846,39 +840,45 @@ class LPAlgorithmSHENull : public LPSHEAlgorithm<Element> {
typename Element::PolyType cResult(c1.GetParams(), Format::COEFFICIENT, true);
typename Element::PolyType cLarger(c1.GetParams(), Format::COEFFICIENT, true);
typename Element::PolyType::Integer ptm( ptmod.ConvertToInt() );
int ringdim = c1.GetRingDimension();
for (int c1e = 0; c1e<ringdim; c1e++) {
typename Element::PolyType::Integer answer, c1val, c2val, prod;
c1val = c1.at(c1e);
if (c1val != typename Element::PolyType::Integer(0)) {
for (int c2e = 0; c2e<ringdim; c2e++) {
c2val = c2.at(c2e);
if (c2val != typename Element::PolyType::Integer(0)) {
prod = c1val * c2val;
int index = (c1e + c2e);
if (index >= ringdim) {
index %= ringdim;
cLarger.at(index)= (cLarger.at(index) + prod) % ptm;
if (c1.GetParams()->OrderIsPowerOfTwo())
{
typename Element::PolyType cLarger(c1.GetParams(), Format::COEFFICIENT, true);
typename Element::PolyType::Integer ptm( ptmod.ConvertToInt() );
int ringdim = c1.GetRingDimension();
for (int c1e = 0; c1e<ringdim; c1e++) {
typename Element::PolyType::Integer answer, c1val, c2val, prod;
c1val = c1.at(c1e);
if (c1val != 0) {
for (int c2e = 0; c2e<ringdim; c2e++) {
c2val = c2.at(c2e);
if (c2val != 0) {
prod = c1val * c2val;
int index = (c1e + c2e);
if (index >= ringdim) {
index %= ringdim;
cLarger.at(index)= (cLarger.at(index) + prod) % ptm;
}
else
cResult.at(index)= (cResult.at(index) + prod) % ptm;
}
else
cResult.at(index)= (cResult.at(index) + prod) % ptm;
}
}
}
}
// fold cLarger back into the answer
for (int i = 0; i<ringdim; i++) {
typename Element::PolyType::Integer adj;
adj = cResult.at(i) + (ptm - cLarger.at(i)) % ptm;
cResult.at(i)= adj % ptm;
// fold cLarger back into the answer
for (int i = 0; i<ringdim; i++) {
typename Element::PolyType::Integer adj;
adj = cResult.at(i) + (ptm - cLarger.at(i)) % ptm;
cResult.at(i)= adj % ptm;
}
}
else
PALISADE_THROW( lbcrypto::math_error, "Polynomial multiplication in coefficient representation is not currently supported for non-power-of-two polynomials");
return std::move( cResult );
}
......
......@@ -56,6 +56,8 @@ std::vector<uint64_t> ArbLTVAutomorphismPackedArray(usint i);
std::vector<uint64_t> ArbBGVAutomorphismPackedArray(usint i);
//declaration for Automorphism Test on LTV scheme with polynomial operation in power of 2 cyclotomics.
std::vector<uint64_t> LTVAutomorphismPackedArray(usint i);
//declaration for Automorphism Test on Null scheme with polynomial operation in power of 2 cyclotomics.
std::vector<uint64_t> NullAutomorphismPackedArray(usint i);
//declaration for Automorphism Test on BGV scheme with polynomial operation in powerof 2 cyclotomics.
std::vector<uint64_t> BGVAutomorphismPackedArray(usint i);
//declaration for Automorphism Test on BFV scheme with polynomial operation in power of 2 cyclotomics.
......@@ -80,6 +82,18 @@ TEST_F(UTAUTOMORPHISM, Test_LTV_Automorphism_PowerOf2) {
}
TEST_F(UTAUTOMORPHISM, Test_Null_Automorphism_PowerOf2) {