public void FVEncryptSquareDecryptNET() { var parms = new EncryptionParameters(MemoryPoolHandle.AcquireNew()); parms.SetDecompositionBitCount(4); parms.SetNoiseStandardDeviation(3.19); parms.SetNoiseMaxDeviation(35.06); var coeffModulus = new BigUInt(48); coeffModulus.Set("FFFFFFFFC001"); parms.SetCoeffModulus(coeffModulus); var plainModulus = new BigUInt(7); plainModulus.Set(1 << 6); parms.SetPlainModulus(plainModulus); var polyModulus = new BigPoly(65, 1); polyModulus[0].Set(1); polyModulus[64].Set(1); parms.SetPolyModulus(polyModulus); parms.Validate(); var keygen = new KeyGenerator(parms, MemoryPoolHandle.AcquireNew()); keygen.Generate(); var encoder = new BalancedEncoder(parms.PlainModulus, MemoryPoolHandle.AcquireNew()); var encryptor = new Encryptor(parms, keygen.PublicKey, MemoryPoolHandle.AcquireNew()); var evaluator = new Evaluator(parms, MemoryPoolHandle.AcquireNew()); var decryptor = new Decryptor(parms, keygen.SecretKey, MemoryPoolHandle.AcquireNew()); var encrypted1 = encryptor.Encrypt(encoder.Encode(1)); var product = evaluator.Square(encrypted1); Assert.AreEqual(1UL, encoder.DecodeUInt64(decryptor.Decrypt(product))); encrypted1 = encryptor.Encrypt(encoder.Encode(0)); product = evaluator.Square(encrypted1); Assert.AreEqual(0UL, encoder.DecodeUInt64(decryptor.Decrypt(product))); encrypted1 = encryptor.Encrypt(encoder.Encode(-5)); product = evaluator.Square(encrypted1); Assert.AreEqual(25UL, encoder.DecodeUInt64(decryptor.Decrypt(product))); encrypted1 = encryptor.Encrypt(encoder.Encode(-1)); product = evaluator.Square(encrypted1); Assert.AreEqual(1UL, encoder.DecodeUInt64(decryptor.Decrypt(product))); encrypted1 = encryptor.Encrypt(encoder.Encode(123)); product = evaluator.Square(encrypted1); Assert.AreEqual(15129UL, encoder.DecodeUInt64(decryptor.Decrypt(product))); }
public void BalancedEncodeDecodeInt32NET() { var modulus = new BigUInt("10000"); var encoder = new BalancedEncoder(modulus, 3); var poly = encoder.Encode(0); Assert.AreEqual(0, poly.GetSignificantCoeffCount()); Assert.IsTrue(poly.IsZero); Assert.AreEqual(0, encoder.DecodeInt32(poly)); var poly1 = encoder.Encode(1); Assert.AreEqual(1, poly1.GetSignificantCoeffCount()); Assert.AreEqual(modulus.BitCount, poly1.CoeffBitCount); Assert.AreEqual("1", poly1.ToString()); Assert.AreEqual(1, encoder.DecodeInt32(poly1)); var poly2 = encoder.Encode(2); Assert.AreEqual(2, poly2.GetSignificantCoeffCount()); Assert.AreEqual(modulus.BitCount, poly2.CoeffBitCount); Assert.AreEqual("1x^1 + FFFF", poly2.ToString()); Assert.AreEqual(2, encoder.DecodeInt32(poly2)); var poly3 = encoder.Encode(3); Assert.AreEqual(2, poly3.GetSignificantCoeffCount()); Assert.AreEqual(modulus.BitCount, poly3.CoeffBitCount); Assert.AreEqual("1x^1", poly3.ToString()); Assert.AreEqual(3, encoder.DecodeInt32(poly3)); var poly4 = encoder.Encode(-1); Assert.AreEqual(1, poly4.GetSignificantCoeffCount()); Assert.AreEqual(modulus.BitCount, poly4.CoeffBitCount); Assert.AreEqual("FFFF", poly4.ToString()); Assert.AreEqual(-1, encoder.DecodeInt32(poly4)); var poly5 = encoder.Encode(-2); Assert.AreEqual(2, poly5.GetSignificantCoeffCount()); Assert.AreEqual(modulus.BitCount, poly5.CoeffBitCount); Assert.AreEqual("FFFFx^1 + 1", poly5.ToString()); Assert.AreEqual(-2, encoder.DecodeInt32(poly5)); var poly6 = encoder.Encode(-3); Assert.AreEqual(2, poly6.GetSignificantCoeffCount()); Assert.AreEqual(modulus.BitCount, poly6.CoeffBitCount); Assert.AreEqual("FFFFx^1", poly6.ToString()); Assert.AreEqual(-3, encoder.DecodeInt32(poly6)); var poly7 = encoder.Encode(-0x2671); Assert.AreEqual(9, poly7.GetSignificantCoeffCount()); Assert.AreEqual(modulus.BitCount, poly7.CoeffBitCount); for (int i = 0; i < 9; ++i) { Assert.AreEqual("FFFF", poly7[i].ToString()); } Assert.AreEqual(-0x2671, encoder.DecodeInt32(poly7)); var poly8 = encoder.Encode(-4374); Assert.AreEqual(9, poly8.GetSignificantCoeffCount()); Assert.AreEqual(modulus.BitCount, poly8.CoeffBitCount); Assert.AreEqual("FFFF", poly8[8].ToString()); Assert.AreEqual("1", poly8[7].ToString()); for (int i = 0; i < 7; ++i) { Assert.IsTrue(poly8[i].IsZero); } Assert.AreEqual(-4374, encoder.DecodeInt32(poly8)); var poly9 = encoder.Encode(-0xD4EB); Assert.AreEqual(11, poly9.GetSignificantCoeffCount()); Assert.AreEqual(modulus.BitCount, poly9.CoeffBitCount); for (int i = 0; i < 11; ++i) { if (i % 3 == 1) { Assert.AreEqual("FFFF", poly9[i].ToString()); } else if (i % 3 == 0) { Assert.IsTrue(poly9[i].IsZero); } else { Assert.AreEqual("1", poly9[i].ToString()); } } Assert.AreEqual(-0xD4EB, encoder.DecodeInt32(poly9)); var poly10 = encoder.Encode(-30724); Assert.AreEqual(11, poly10.GetSignificantCoeffCount()); Assert.AreEqual(modulus.BitCount, poly10.CoeffBitCount); Assert.AreEqual("FFFF", poly10[10].ToString()); Assert.AreEqual("1", poly10[9].ToString()); Assert.AreEqual("1", poly10[8].ToString()); Assert.AreEqual("1", poly10[7].ToString()); Assert.IsTrue(poly10[6].IsZero); Assert.IsTrue(poly10[5].IsZero); Assert.AreEqual("FFFF", poly10[4].ToString()); Assert.AreEqual("FFFF", poly10[3].ToString()); Assert.IsTrue(poly10[2].IsZero); Assert.AreEqual("1", poly10[1].ToString()); Assert.AreEqual("FFFF", poly10[0].ToString()); Assert.AreEqual(-30724, encoder.DecodeInt32(poly10)); modulus.Set("FFFF"); var encoder2 = new BalancedEncoder(modulus, 7); var poly12 = new BigPoly(6, 16); poly12[0].Set(1); poly12[1].Set("FFFE"); // -1 poly12[2].Set("FFFD"); // -2 poly12[3].Set("8000"); // -32767 poly12[4].Set("7FFF"); // 32767 poly12[5].Set("7FFE"); // 32766 Assert.AreEqual(1 + -1 * 7 + -2 * 49 + -32767 * 343 + 32767 * 2401 + 32766 * 16807, encoder2.DecodeInt32(poly12)); }
public void BalancedEncodeDecodeUInt32NET() { var modulus = new BigUInt("10000"); var encoder = new BalancedEncoder(modulus, 3); var poly = encoder.Encode(0U); Assert.AreEqual(0, poly.GetSignificantCoeffCount()); Assert.IsTrue(poly.IsZero); Assert.AreEqual(0U, encoder.DecodeUInt32(poly)); var poly1 = encoder.Encode(1U); Assert.AreEqual(1, poly1.GetSignificantCoeffCount()); Assert.AreEqual(modulus.BitCount, poly1.CoeffBitCount); Assert.AreEqual("1", poly1.ToString()); Assert.AreEqual(1U, encoder.DecodeUInt32(poly1)); var poly2 = encoder.Encode(2U); Assert.AreEqual(2, poly2.GetSignificantCoeffCount()); Assert.AreEqual(modulus.BitCount, poly2.CoeffBitCount); Assert.AreEqual("1x^1 + FFFF", poly2.ToString()); Assert.AreEqual(2U, encoder.DecodeUInt32(poly2)); var poly3 = encoder.Encode(3U); Assert.AreEqual(2, poly3.GetSignificantCoeffCount()); Assert.AreEqual(modulus.BitCount, poly3.CoeffBitCount); Assert.AreEqual("1x^1", poly3.ToString()); Assert.AreEqual(3U, encoder.DecodeUInt32(poly3)); var poly4 = encoder.Encode(0x2671U); Assert.AreEqual(9, poly4.GetSignificantCoeffCount()); Assert.AreEqual(modulus.BitCount, poly4.CoeffBitCount); for (int i = 0; i < 9; ++i) { Assert.IsTrue("1" == poly4[i].ToString()); } Assert.AreEqual(0x2671U, encoder.DecodeUInt32(poly4)); var poly5 = encoder.Encode(0xD4EBU); Assert.AreEqual(11, poly5.GetSignificantCoeffCount()); Assert.AreEqual(modulus.BitCount, poly5.CoeffBitCount); for (int i = 0; i < 11; ++i) { if (i % 3 == 1) { Assert.AreEqual("1", poly5[i].ToString()); } else if (i % 3 == 0) { Assert.IsTrue(poly5[i].IsZero); } else { Assert.AreEqual("FFFF", poly5[i].ToString()); } } Assert.AreEqual(0xD4EBU, encoder.DecodeUInt32(poly5)); var poly6 = new BigPoly(3, 10); poly6[0].Set(1); poly6[1].Set(500); poly6[2].Set(1023); Assert.AreEqual(1U + 500 * 3 + 1023 * 9, encoder.DecodeUInt32(poly6)); var encoder2 = new BalancedEncoder(modulus, 7); var poly7 = new BigPoly(4, 16); poly7[0].Set(123); // 123 (*1) poly7[1].Set("FFFF"); // -1 (*7) poly7[2].Set(511); // 511 (*49) poly7[3].Set(1); // 1 (*343) Assert.AreEqual((UInt32)(123 + -1 * 7 + 511 * 49 + 1 * 343), encoder2.DecodeUInt32(poly7)); }
public void BalancedEncodeDecodeInt32NET() { var modulus = new SmallModulus(0x10000); var encoder = new BalancedEncoder(modulus, 3, MemoryPoolHandle.New()); var poly = encoder.Encode(0); Assert.AreEqual(0, poly.SignificantCoeffCount()); Assert.IsTrue(poly.IsZero); Assert.AreEqual(0, encoder.DecodeInt32(poly)); var poly1 = encoder.Encode(1); Assert.AreEqual(1, poly1.SignificantCoeffCount()); Assert.AreEqual("1", poly1.ToString()); Assert.AreEqual(1, encoder.DecodeInt32(poly1)); var poly2 = encoder.Encode(2); Assert.AreEqual(2, poly2.SignificantCoeffCount()); Assert.AreEqual("1x^1 + FFFF", poly2.ToString()); Assert.AreEqual(2, encoder.DecodeInt32(poly2)); var poly3 = encoder.Encode(3); Assert.AreEqual(2, poly3.SignificantCoeffCount()); Assert.AreEqual("1x^1", poly3.ToString()); Assert.AreEqual(3, encoder.DecodeInt32(poly3)); var poly4 = encoder.Encode(-1); Assert.AreEqual(1, poly4.SignificantCoeffCount()); Assert.AreEqual("FFFF", poly4.ToString()); Assert.AreEqual(-1, encoder.DecodeInt32(poly4)); var poly5 = encoder.Encode(-2); Assert.AreEqual(2, poly5.SignificantCoeffCount()); Assert.AreEqual("FFFFx^1 + 1", poly5.ToString()); Assert.AreEqual(-2, encoder.DecodeInt32(poly5)); var poly6 = encoder.Encode(-3); Assert.AreEqual(2, poly6.SignificantCoeffCount()); Assert.AreEqual("FFFFx^1", poly6.ToString()); Assert.AreEqual(-3, encoder.DecodeInt32(poly6)); var poly7 = encoder.Encode(-0x2671); Assert.AreEqual(9, poly7.SignificantCoeffCount()); for (int i = 0; i < 9; ++i) { Assert.AreEqual(0xFFFFUL, poly7[i]); } Assert.AreEqual(-0x2671, encoder.DecodeInt32(poly7)); var poly8 = encoder.Encode(-4374); Assert.AreEqual(9, poly8.SignificantCoeffCount()); Assert.AreEqual(0xFFFFUL, poly8[8]); Assert.AreEqual(1UL, poly8[7]); for (int i = 0; i < 7; ++i) { Assert.IsTrue(poly8[i] == 0); } Assert.AreEqual(-4374, encoder.DecodeInt32(poly8)); var poly9 = encoder.Encode(-0xD4EB); Assert.AreEqual(11, poly9.SignificantCoeffCount()); for (int i = 0; i < 11; ++i) { if (i % 3 == 1) { Assert.AreEqual(0xFFFFUL, poly9[i]); } else if (i % 3 == 0) { Assert.IsTrue(poly9[i] == 0); } else { Assert.AreEqual(1UL, poly9[i]); } } Assert.AreEqual(-0xD4EB, encoder.DecodeInt32(poly9)); var poly10 = encoder.Encode(-30724); Assert.AreEqual(11, poly10.SignificantCoeffCount()); Assert.AreEqual(0xFFFFUL, poly10[10]); Assert.AreEqual(1UL, poly10[9]); Assert.AreEqual(1UL, poly10[8]); Assert.AreEqual(1UL, poly10[7]); Assert.IsTrue(poly10[6] == 0); Assert.IsTrue(poly10[5] == 0); Assert.AreEqual(0xFFFFUL, poly10[4]); Assert.AreEqual(0xFFFFUL, poly10[3]); Assert.IsTrue(poly10[2] == 0); Assert.AreEqual(1UL, poly10[1]); Assert.AreEqual(0xFFFFUL, poly10[0]); Assert.AreEqual(-30724, encoder.DecodeInt32(poly10)); modulus.Set(0xFFFF); var encoder2 = new BalancedEncoder(modulus, 7, MemoryPoolHandle.New()); var poly12 = new Plaintext(6); poly12[0] = 1; poly12[1] = 0xFFFE; // -1 poly12[2] = 0xFFFD; // -2 poly12[3] = 0x8000; // -32767 poly12[4] = 0x7FFF; // 32767 poly12[5] = 0x7FFE; // 32766 Assert.AreEqual(1 + -1 * 7 + -2 * 49 + -32767 * 343 + 32767 * 2401 + 32766 * 16807, encoder2.DecodeInt32(poly12)); var encoder4 = new BalancedEncoder(modulus, 6, MemoryPoolHandle.New()); poly8 = new Plaintext(4); poly8[0] = 5; poly8[1] = 4; poly8[2] = 3; poly8[3] = (modulus.Value - 2); Int32 value = 5 + 4 * 6 + 3 * 36 - 2 * 216; Assert.AreEqual(value, encoder4.DecodeInt32(poly8)); var encoder5 = new BalancedEncoder(modulus, 10, MemoryPoolHandle.New()); poly9 = new Plaintext(4); poly9[0] = 1; poly9[1] = 2; poly9[2] = 3; poly9[3] = 4; value = 4321; Assert.AreEqual(value, encoder5.DecodeInt32(poly9)); value = -1234; poly10.Set(encoder2.Encode(value)); Assert.AreEqual(5, poly10.SignificantCoeffCount()); Assert.IsTrue(value.Equals(encoder2.DecodeInt32(poly10))); value = -1234; var poly11 = encoder4.Encode(value); Assert.AreEqual(5, poly11.SignificantCoeffCount()); Assert.AreEqual(value, encoder4.DecodeInt32(poly11)); value = -1234; poly12.Set(encoder5.Encode(value)); Assert.AreEqual(4, poly12.SignificantCoeffCount()); Assert.IsTrue(value.Equals(encoder5.DecodeInt32(poly12))); }
public void BalancedEncodeDecodeUInt32NET() { var modulus = new SmallModulus(0x10000); var encoder = new BalancedEncoder(modulus, 3, MemoryPoolHandle.New()); var poly = encoder.Encode(0U); Assert.AreEqual(0, poly.SignificantCoeffCount()); Assert.IsTrue(poly.IsZero); Assert.AreEqual(0U, encoder.DecodeUInt32(poly)); var poly1 = encoder.Encode(1U); Assert.AreEqual(1, poly1.SignificantCoeffCount()); Assert.AreEqual("1", poly1.ToString()); Assert.AreEqual(1U, encoder.DecodeUInt32(poly1)); var poly2 = encoder.Encode(2U); Assert.AreEqual(2, poly2.SignificantCoeffCount()); Assert.AreEqual("1x^1 + FFFF", poly2.ToString()); Assert.AreEqual(2U, encoder.DecodeUInt32(poly2)); var poly3 = encoder.Encode(3U); Assert.AreEqual(2, poly3.SignificantCoeffCount()); Assert.AreEqual("1x^1", poly3.ToString()); Assert.AreEqual(3U, encoder.DecodeUInt32(poly3)); var poly4 = encoder.Encode(0x2671U); Assert.AreEqual(9, poly4.SignificantCoeffCount()); for (int i = 0; i < 9; ++i) { Assert.AreEqual(1UL, poly4[i]); } Assert.AreEqual(0x2671U, encoder.DecodeUInt32(poly4)); var poly5 = encoder.Encode(0xD4EBU); Assert.AreEqual(11, poly5.SignificantCoeffCount()); for (int i = 0; i < 11; ++i) { if (i % 3 == 1) { Assert.AreEqual(1UL, poly5[i]); } else if (i % 3 == 0) { Assert.IsTrue(poly5[i] == 0); } else { Assert.AreEqual(0xFFFFUL, poly5[i]); } } Assert.AreEqual(0xD4EBU, encoder.DecodeUInt32(poly5)); var poly6 = new Plaintext(3); poly6[0] = 1; poly6[1] = 500; poly6[2] = 1023; Assert.AreEqual(1U + 500 * 3 + 1023 * 9, encoder.DecodeUInt32(poly6)); var encoder2 = new BalancedEncoder(modulus, 7, MemoryPoolHandle.New()); var poly7 = new Plaintext(4); poly7[0] = 123; // 123 (*1) poly7[1] = 0xFFFF; // -1 (*7) poly7[2] = 511; // 511 (*49) poly7[3] = 1; // 1 (*343) Assert.AreEqual((UInt32)(123 + -1 * 7 + 511 * 49 + 1 * 343), encoder2.DecodeUInt32(poly7)); var encoder3 = new BalancedEncoder(modulus, 6, MemoryPoolHandle.New()); var poly8 = new Plaintext(4); poly8[0] = 5; poly8[1] = 4; poly8[2] = 3; poly8[3] = 2; UInt64 value = 5 + 4 * 6 + 3 * 36 + 2 * 216; Assert.AreEqual(value, encoder3.DecodeUInt32(poly8)); var encoder4 = new BalancedEncoder(modulus, 10, MemoryPoolHandle.New()); var poly9 = new Plaintext(4); poly9[0] = 1; poly9[1] = 2; poly9[2] = 3; poly9[3] = 4; value = 4321; Assert.AreEqual(value, encoder4.DecodeUInt32(poly9)); value = 1234; var poly10 = encoder2.Encode(value); Assert.AreEqual(5, poly10.SignificantCoeffCount()); Assert.IsTrue(value.Equals(encoder2.DecodeUInt32(poly10))); value = 1234; var poly11 = encoder3.Encode(value); Assert.AreEqual(5, poly11.SignificantCoeffCount()); Assert.IsTrue(value.Equals(encoder3.DecodeUInt32(poly11))); value = 1234; var poly12 = encoder4.Encode(value); Assert.AreEqual(4, poly12.SignificantCoeffCount()); Assert.IsTrue(value.Equals(encoder4.DecodeUInt32(poly12))); }
public void FVEncryptDecryptNET() { var parms = new EncryptionParameters(); var plain_modulus = new SmallModulus(1 << 6); parms.NoiseStandardDeviation = 3.19; parms.PlainModulus = plain_modulus; { parms.PolyModulus = "1x^64 + 1"; parms.CoeffModulus = new List <SmallModulus> { DefaultParams.SmallMods60Bit(0) }; var context = new SEALContext(parms); var keygen = new KeyGenerator(context); var encoder = new BalancedEncoder(plain_modulus); var encryptor = new Encryptor(context, keygen.PublicKey); var decryptor = new Decryptor(context, keygen.SecretKey); var encrypted = new Ciphertext(); var plain = new Plaintext(); encryptor.Encrypt(encoder.Encode(0x12345678), encrypted); decryptor.Decrypt(encrypted, plain); Assert.AreEqual(0x12345678UL, encoder.DecodeUInt64(plain)); Assert.AreEqual(encrypted.HashBlock, parms.HashBlock); encryptor.Encrypt(encoder.Encode(0), encrypted); decryptor.Decrypt(encrypted, plain); Assert.AreEqual(0UL, encoder.DecodeUInt64(plain)); Assert.AreEqual(encrypted.HashBlock, parms.HashBlock); encryptor.Encrypt(encoder.Encode(1), encrypted); decryptor.Decrypt(encrypted, plain); Assert.AreEqual(1UL, encoder.DecodeUInt64(plain)); Assert.AreEqual(encrypted.HashBlock, parms.HashBlock); encryptor.Encrypt(encoder.Encode(2), encrypted); decryptor.Decrypt(encrypted, plain); Assert.AreEqual(2UL, encoder.DecodeUInt64(plain)); Assert.AreEqual(encrypted.HashBlock, parms.HashBlock); encryptor.Encrypt(encoder.Encode(0x7FFFFFFFFFFFFFFD), encrypted); decryptor.Decrypt(encrypted, plain); Assert.AreEqual(0x7FFFFFFFFFFFFFFDUL, encoder.DecodeUInt64(plain)); Assert.AreEqual(encrypted.HashBlock, parms.HashBlock); encryptor.Encrypt(encoder.Encode(0x7FFFFFFFFFFFFFFE), encrypted); decryptor.Decrypt(encrypted, plain); Assert.AreEqual(0x7FFFFFFFFFFFFFFEUL, encoder.DecodeUInt64(plain)); Assert.AreEqual(encrypted.HashBlock, parms.HashBlock); encryptor.Encrypt(encoder.Encode(0x7FFFFFFFFFFFFFFF), encrypted); decryptor.Decrypt(encrypted, plain); Assert.AreEqual(0x7FFFFFFFFFFFFFFFUL, encoder.DecodeUInt64(plain)); Assert.AreEqual(encrypted.HashBlock, parms.HashBlock); encryptor.Encrypt(encoder.Encode(314159265), encrypted); decryptor.Decrypt(encrypted, plain); Assert.AreEqual(314159265UL, encoder.DecodeUInt64(plain)); Assert.AreEqual(encrypted.HashBlock, parms.HashBlock); } { parms.PolyModulus = "1x^128 + 1"; parms.CoeffModulus = new List <SmallModulus> { DefaultParams.SmallMods40Bit(0), DefaultParams.SmallMods40Bit(1) }; var context = new SEALContext(parms); var keygen = new KeyGenerator(context); var encoder = new BalancedEncoder(plain_modulus); var encryptor = new Encryptor(context, keygen.PublicKey); var decryptor = new Decryptor(context, keygen.SecretKey); var encrypted = new Ciphertext(); var plain = new Plaintext(); encryptor.Encrypt(encoder.Encode(0x12345678), encrypted); decryptor.Decrypt(encrypted, plain); Assert.AreEqual(0x12345678UL, encoder.DecodeUInt64(plain)); Assert.AreEqual(encrypted.HashBlock, parms.HashBlock); encryptor.Encrypt(encoder.Encode(0), encrypted); decryptor.Decrypt(encrypted, plain); Assert.AreEqual(0UL, encoder.DecodeUInt64(plain)); Assert.AreEqual(encrypted.HashBlock, parms.HashBlock); encryptor.Encrypt(encoder.Encode(1), encrypted); decryptor.Decrypt(encrypted, plain); Assert.AreEqual(1UL, encoder.DecodeUInt64(plain)); Assert.AreEqual(encrypted.HashBlock, parms.HashBlock); encryptor.Encrypt(encoder.Encode(2), encrypted); decryptor.Decrypt(encrypted, plain); Assert.AreEqual(2UL, encoder.DecodeUInt64(plain)); Assert.AreEqual(encrypted.HashBlock, parms.HashBlock); encryptor.Encrypt(encoder.Encode(0x7FFFFFFFFFFFFFFD), encrypted); decryptor.Decrypt(encrypted, plain); Assert.AreEqual(0x7FFFFFFFFFFFFFFDUL, encoder.DecodeUInt64(plain)); Assert.AreEqual(encrypted.HashBlock, parms.HashBlock); encryptor.Encrypt(encoder.Encode(0x7FFFFFFFFFFFFFFE), encrypted); decryptor.Decrypt(encrypted, plain); Assert.AreEqual(0x7FFFFFFFFFFFFFFEUL, encoder.DecodeUInt64(plain)); Assert.AreEqual(encrypted.HashBlock, parms.HashBlock); encryptor.Encrypt(encoder.Encode(0x7FFFFFFFFFFFFFFF), encrypted); decryptor.Decrypt(encrypted, plain); Assert.AreEqual(0x7FFFFFFFFFFFFFFFUL, encoder.DecodeUInt64(plain)); Assert.AreEqual(encrypted.HashBlock, parms.HashBlock); encryptor.Encrypt(encoder.Encode(314159265), encrypted); decryptor.Decrypt(encrypted, plain); Assert.AreEqual(314159265UL, encoder.DecodeUInt64(plain)); Assert.AreEqual(encrypted.HashBlock, parms.HashBlock); } { parms.PolyModulus = "1x^256 + 1"; parms.CoeffModulus = new List <SmallModulus> { DefaultParams.SmallMods40Bit(0), DefaultParams.SmallMods40Bit(1), DefaultParams.SmallMods40Bit(2) }; var context = new SEALContext(parms); var keygen = new KeyGenerator(context); var encoder = new BalancedEncoder(plain_modulus); var encryptor = new Encryptor(context, keygen.PublicKey); var decryptor = new Decryptor(context, keygen.SecretKey); var encrypted = new Ciphertext(); var plain = new Plaintext(); encryptor.Encrypt(encoder.Encode(0x12345678), encrypted); decryptor.Decrypt(encrypted, plain); Assert.AreEqual(0x12345678UL, encoder.DecodeUInt64(plain)); Assert.AreEqual(encrypted.HashBlock, parms.HashBlock); encryptor.Encrypt(encoder.Encode(0), encrypted); decryptor.Decrypt(encrypted, plain); Assert.AreEqual(0UL, encoder.DecodeUInt64(plain)); Assert.AreEqual(encrypted.HashBlock, parms.HashBlock); encryptor.Encrypt(encoder.Encode(1), encrypted); decryptor.Decrypt(encrypted, plain); Assert.AreEqual(1UL, encoder.DecodeUInt64(plain)); Assert.AreEqual(encrypted.HashBlock, parms.HashBlock); encryptor.Encrypt(encoder.Encode(2), encrypted); decryptor.Decrypt(encrypted, plain); Assert.AreEqual(2UL, encoder.DecodeUInt64(plain)); Assert.AreEqual(encrypted.HashBlock, parms.HashBlock); encryptor.Encrypt(encoder.Encode(0x7FFFFFFFFFFFFFFD), encrypted); decryptor.Decrypt(encrypted, plain); Assert.AreEqual(0x7FFFFFFFFFFFFFFDUL, encoder.DecodeUInt64(plain)); Assert.AreEqual(encrypted.HashBlock, parms.HashBlock); encryptor.Encrypt(encoder.Encode(0x7FFFFFFFFFFFFFFE), encrypted); decryptor.Decrypt(encrypted, plain); Assert.AreEqual(0x7FFFFFFFFFFFFFFEUL, encoder.DecodeUInt64(plain)); Assert.AreEqual(encrypted.HashBlock, parms.HashBlock); encryptor.Encrypt(encoder.Encode(0x7FFFFFFFFFFFFFFF), encrypted); decryptor.Decrypt(encrypted, plain); Assert.AreEqual(0x7FFFFFFFFFFFFFFFUL, encoder.DecodeUInt64(plain)); Assert.AreEqual(encrypted.HashBlock, parms.HashBlock); encryptor.Encrypt(encoder.Encode(314159265), encrypted); decryptor.Decrypt(encrypted, plain); Assert.AreEqual(314159265UL, encoder.DecodeUInt64(plain)); Assert.AreEqual(encrypted.HashBlock, parms.HashBlock); } }
static void ExampleBasics() { PrintExampleBanner("Example: Basics"); // In this example we demonstrate using some of the basic arithmetic operations on integers. // Create encryption parameters. var parms = new EncryptionParameters(); /* * First choose the polynomial modulus. This must be a power-of-2 cyclotomic polynomial, * i.e. a polynomial of the form "1x^(power-of-2) + 1". We recommend using polynomials of * degree at least 1024. */ parms.PolyModulus.Set("1x^4096 + 1"); /* * Next choose the coefficient modulus. The values we recommend to be used are: * * [ degree(poly_modulus), coeff_modulus ] * [ 1024, "FFFFFFFFC001" ], * [ 2048, "7FFFFFFFFFFFFFFFFFFF001"], * [ 4096, "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"], * [ 8192, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC000001"], * [ 16384, "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000001"]. * * These can be conveniently accessed using ChooserEvaluator.DefaultParameterOptions(), * which returns the above list of options as a Dictionary, keyed by the degree of the polynomial modulus. */ parms.CoeffModulus.Set(ChooserEvaluator.DefaultParameterOptions[4096]); /* * Now we set the plaintext modulus. This can be any integer, even though here we take it to be a power of two. * A larger plaintext modulus causes the noise to grow faster in homomorphic multiplication, and * also lowers the maximum amount of noise in ciphertexts that the system can tolerate. * On the other hand, a larger plaintext modulus typically allows for better homomorphic integer arithmetic, * although this depends strongly on which encoder is used to encode integers into plaintext polynomials. */ parms.PlainModulus.Set(1 << 10); /* * The decomposition bit count affects the behavior of the relinearization (key switch) operation, * which is typically performed after each homomorphic multiplication. A smaller decomposition * bit count makes relinearization slower, but improves the noise growth behavior on multiplication. * Conversely, a larger decomposition bit count makes homomorphic multiplication faster at the cost * of increased noise growth. */ parms.DecompositionBitCount = 32; /* * We use a constant standard deviation for the error distribution. Using a larger standard * deviation will result in larger noise growth, but in theory should make the system more secure. */ parms.NoiseStandardDeviation = ChooserEvaluator.DefaultNoiseStandardDeviation; // For the bound on the error distribution we can take for instance 5 * standard_deviation. parms.NoiseMaxDeviation = 5 * parms.NoiseStandardDeviation; Console.WriteLine("Encryption parameters specify {0} coefficients with {1} bits per coefficient", parms.PolyModulus.GetSignificantCoeffCount(), parms.CoeffModulus.GetSignificantBitCount()); // Encode two integers as polynomials. const int value1 = 5; const int value2 = -7; var encoder = new BalancedEncoder(parms.PlainModulus); var encoded1 = encoder.Encode(value1); var encoded2 = encoder.Encode(value2); Console.WriteLine("Encoded {0} as polynomial {1}", value1, encoded1); Console.WriteLine("Encoded {0} as polynomial {1}", value2, encoded2); // Generate keys. Console.WriteLine("Generating keys..."); var generator = new KeyGenerator(parms); generator.Generate(); Console.WriteLine("... key generation completed"); var publicKey = generator.PublicKey; var secretKey = generator.SecretKey; var evaluationKeys = generator.EvaluationKeys; //Console.WriteLine("Public Key = {0}", publicKey); //Console.WriteLine("Secret Key = {0}", secretKey); // Encrypt values. Console.WriteLine("Encrypting values..."); var encryptor = new Encryptor(parms, publicKey); var encrypted1 = encryptor.Encrypt(encoded1); var encrypted2 = encryptor.Encrypt(encoded2); // Perform arithmetic on encrypted values. Console.WriteLine("Performing encrypted arithmetic..."); var evaluator = new Evaluator(parms, evaluationKeys); Console.WriteLine("... Performing negation..."); var encryptedNegated1 = evaluator.Negate(encrypted1); Console.WriteLine("... Performing addition..."); var encryptedSum = evaluator.Add(encrypted1, encrypted2); Console.WriteLine("... Performing subtraction..."); var encryptedDiff = evaluator.Sub(encrypted1, encrypted2); Console.WriteLine("... Performing multiplication..."); var encryptedProduct = evaluator.Multiply(encrypted1, encrypted2); // Decrypt results. Console.WriteLine("Decrypting results..."); var decryptor = new Decryptor(parms, secretKey); var decrypted1 = decryptor.Decrypt(encrypted1); var decrypted2 = decryptor.Decrypt(encrypted2); var decryptedNegated1 = decryptor.Decrypt(encryptedNegated1); var decryptedSum = decryptor.Decrypt(encryptedSum); var decryptedDiff = decryptor.Decrypt(encryptedDiff); var decryptedProduct = decryptor.Decrypt(encryptedProduct); // Decode results. var decoded1 = encoder.DecodeInt32(decrypted1); var decoded2 = encoder.DecodeInt32(decrypted2); var decodedNegated1 = encoder.DecodeInt32(decryptedNegated1); var decodedSum = encoder.DecodeInt32(decryptedSum); var decodedDiff = encoder.DecodeInt32(decryptedDiff); var decodedProduct = encoder.DecodeInt32(decryptedProduct); // Display results. Console.WriteLine("{0} after encryption/decryption = {1}", value1, decoded1); Console.WriteLine("{0} after encryption/decryption = {1}", value2, decoded2); Console.WriteLine("encrypted negate of {0} = {1}", value1, decodedNegated1); Console.WriteLine("encrypted addition of {0} and {1} = {2}", value1, value2, decodedSum); Console.WriteLine("encrypted subtraction of {0} and {1} = {2}", value1, value2, decodedDiff); Console.WriteLine("encrypted multiplication of {0} and {1} = {2}", value1, value2, decodedProduct); // How did the noise grow in these operations? var maxNoiseBitCount = Utilities.InherentNoiseMax(parms).GetSignificantBitCount(); Console.WriteLine("Noise in encryption of {0}: {1}/{2} bits", value1, Utilities.InherentNoise(encrypted1, parms, secretKey).GetSignificantBitCount(), maxNoiseBitCount); Console.WriteLine("Noise in encryption of {0}: {1}/{2} bits", value2, Utilities.InherentNoise(encrypted1, parms, secretKey).GetSignificantBitCount(), maxNoiseBitCount); Console.WriteLine("Noise in the sum: {0}/{1} bits", Utilities.InherentNoise(encryptedSum, parms, secretKey).GetSignificantBitCount(), maxNoiseBitCount); Console.WriteLine("Noise in the product: {0}/{1} bits", Utilities.InherentNoise(encryptedProduct, parms, secretKey).GetSignificantBitCount(), maxNoiseBitCount); }
static void ExampleParameterSelection() { PrintExampleBanner("Example: Automatic Parameter Selection"); /* * Here we demonstrate the automatic parameter selection tool. Suppose we want to find parameters * that are optimized in a way that allows us to evaluate the polynomial 42x^3-27x+1. We need to know * the size of the input data, so let's assume that x is an integer with base-3 representation of length * at most 10. */ Console.Write("Finding optimized parameters for computing 42x^3-27x+1 ... "); var chooserEncoder = new ChooserEncoder(); var chooserEvaluator = new ChooserEvaluator(); // First create a ChooserPoly representing the input data. You can think of this modeling a freshly // encrypted cipheretext of a plaintext polynomial with length at most 10 coefficients, where the // coefficients have absolute value at most 1. var cinput = new ChooserPoly(10, 1); // Compute the first term var ccubedInput = chooserEvaluator.Exponentiate(cinput, 3); var cterm1 = chooserEvaluator.MultiplyPlain(ccubedInput, chooserEncoder.Encode(42)); // Compute the second term var cterm2 = chooserEvaluator.MultiplyPlain(cinput, chooserEncoder.Encode(27)); // Subtract the first two terms var csum12 = chooserEvaluator.Sub(cterm1, cterm2); // Add the constant term 1 var cresult = chooserEvaluator.AddPlain(csum12, chooserEncoder.Encode(1)); // To find an optimized set of parameters, we use ChooserEvaluator::select_parameters(...). var optimalParms = new EncryptionParameters(); chooserEvaluator.SelectParameters(cresult, optimalParms); Console.WriteLine("done."); // Let's print these to see what was recommended Console.WriteLine("Selected parameters:"); Console.WriteLine("{{ poly_modulus: {0}", optimalParms.PolyModulus.ToString()); Console.WriteLine("{{ coeff_modulus: {0}", optimalParms.CoeffModulus.ToString()); Console.WriteLine("{{ plain_modulus: {0}", optimalParms.PlainModulus.ToDecimalString()); Console.WriteLine("{{ decomposition_bit_count: {0}", optimalParms.DecompositionBitCount); Console.WriteLine("{{ noise_standard_deviation: {0}", optimalParms.NoiseStandardDeviation); Console.WriteLine("{{ noise_max_deviation: {0}", optimalParms.NoiseMaxDeviation); // Let's try to actually perform the homomorphic computation using the recommended parameters. // Generate keys. Console.WriteLine("Generating keys..."); var generator = new KeyGenerator(optimalParms); generator.Generate(); Console.WriteLine("... key generation completed"); var publicKey = generator.PublicKey; var secretKey = generator.SecretKey; var evaluationKeys = generator.EvaluationKeys; // Create the encoding/encryption tools var encoder = new BalancedEncoder(optimalParms.PlainModulus); var encryptor = new Encryptor(optimalParms, publicKey); var evaluator = new Evaluator(optimalParms, evaluationKeys); var decryptor = new Decryptor(optimalParms, secretKey); // Now perform the computations on real encrypted data. const int inputValue = 12345; var plainInput = encoder.Encode(inputValue); Console.WriteLine("Encoded {0} as polynomial {1}", inputValue, plainInput.ToString()); Console.Write("Encrypting ... "); var input = encryptor.Encrypt(plainInput); Console.WriteLine("done."); // Compute the first term Console.Write("Computing first term ... "); var cubedInput = evaluator.Exponentiate(input, 3); var term1 = evaluator.MultiplyPlain(cubedInput, encoder.Encode(42)); Console.WriteLine("done."); // Compute the second term Console.Write("Computing second term ... "); var term2 = evaluator.MultiplyPlain(input, encoder.Encode(27)); Console.WriteLine("done."); // Subtract the first two terms Console.Write("Subtracting first two terms ... "); var sum12 = evaluator.Sub(term1, term2); Console.WriteLine("done."); // Add the constant term 1 Console.Write("Adding one ... "); var result = evaluator.AddPlain(sum12, encoder.Encode(1)); Console.WriteLine("done."); // Decrypt and decode Console.Write("Decrypting ... "); var plainResult = decryptor.Decrypt(result); Console.WriteLine("done."); // Finally print the result Console.WriteLine("Polynomial 42x^3-27x+1 evaluated at x=12345: {0}", encoder.DecodeUInt64(plainResult)); // How much noise did we end up with? Console.WriteLine("Noise in the result: {0}/{1} bits", Utilities.InherentNoise(result, optimalParms, secretKey).GetSignificantBitCount(), Utilities.InherentNoiseMax(optimalParms).GetSignificantBitCount()); }
public static void ExampleBasics() { PrintExampleBanner("Example: Basics"); /* * In this example we demonstrate using some of the basic arithmetic operations on integers. * * SEAL uses the Fan-Vercauteren (FV) homomorphic encryption scheme. We refer to * https://eprint.iacr.org/2012/144 for full details on how the FV scheme works. */ // Create encryption parameters. var parms = new EncryptionParameters(); /* * First choose the polynomial modulus. This must be a power-of-2 cyclotomic polynomial, * i.e. a polynomial of the form "1x^(power-of-2) + 1". We recommend using polynomials of * degree at least 1024. */ parms.PolyModulus.Set("1x^2048 + 1"); /* * Next choose the coefficient modulus. The values we recommend to be used are: * * [ degree(PolyModulus), CoeffModulus ] * [ 1024, "FFFFFFF00001" ], * [ 2048, "3FFFFFFFFFFFFFFFFFF00001"], * [ 4096, "3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0000001"], * [ 8192, "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE00000001"], * [ 16384, "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000001"]. * * These can be conveniently accessed using ChooserEvaluator.DefaultParameterOptions, which returns * the above list of options as a Dictionary, keyed by the degree of the polynomial modulus. * * The user can also relatively easily choose their custom coefficient modulus. It should be a prime number * of the form 2^A - 2^B + 1, where A > B > degree(PolyModulus). Moreover, B should be as small as possible * for improved efficiency in modular reduction. For security, we recommend strictly adhering to the following * size bounds: (see Lepoint-Naehrig (2014) [https://eprint.iacr.org/2014/062]) * /-----------------------------------------------------------------\ | PolyModulus | CoeffModulus bound | default CoeffModulus | | -------------|--------------------|-----------------------------| | 1x^1024 + 1 | 48 bits | 2^48 - 2^20 + 1 (47 bits) | | 1x^2048 + 1 | 96 bits | 2^94 - 2^20 + 1 (93 bits) | | 1x^4096 + 1 | 192 bits | 2^190 - 2^30 + 1 (189 bits) | | 1x^8192 + 1 | 384 bits | 2^383 - 2^33 + 1 (382 bits) | | 1x^16384 + 1 | 768 bits | 2^767 - 2^56 + 1 (766 bits) | \-----------------------------------------------------------------/ | | The size of CoeffModulus affects the upper bound on the "inherent noise" that a ciphertext can contain | before becoming corrupted. More precisely, every ciphertext starts with a certain amount of noise in it, | which grows in all homomorphic operations - in particular in multiplication. Once a ciphertext contains | too much noise, it becomes impossible to decrypt. The upper bound on the noise is roughly given by | CoeffModulus/PlainModulus (see below), so increasing CoeffModulus will allow the user to perform more | homomorphic operations on the ciphertexts without corrupting them. We would like to stress, however, that | the bounds given above for CoeffModulus should absolutely not be exceeded. */ parms.CoeffModulus.Set(ChooserEvaluator.DefaultParameterOptions[2048]); /* * Now we set the plaintext modulus. This can be any positive integer, even though here we take it to be a * power of two. A larger plaintext modulus causes the noise to grow faster in homomorphic multiplication, * and also lowers the maximum amount of noise in ciphertexts that the system can tolerate (see above). * On the other hand, a larger plaintext modulus typically allows for better homomorphic integer arithmetic, * although this depends strongly on which encoder is used to encode integers into plaintext polynomials. */ parms.PlainModulus.Set(1 << 8); Console.WriteLine("Encryption parameters specify {0} coefficients with {1} bits per coefficient", parms.PolyModulus.GetSignificantCoeffCount(), parms.CoeffModulus.GetSignificantBitCount()); /* * Plaintext elements in the FV scheme are polynomials (represented by the BigPoly class) with coefficients * integers modulo plain_modulus. To encrypt integers instead, one must use an "encoding scheme", i.e. * a specific way of representing integers as such polynomials. SEAL comes with a few basic encoders: * * BinaryEncoder: * Encodes positive integers as plaintext polynomials where the coefficients are either 0 or 1 according * to the binary representation of the integer to be encoded. Decoding amounts to evaluating the polynomial * at x=2. For example, the integer 26 = 2^4 + 2^3 + 2^1 is encoded as the polynomial 1x^4 + 1x^3 + 1x^1. * Negative integers are encoded similarly but with each coefficient coefficient of the polynomial replaced * with its negative modulo PlainModulus. * * BalancedEncoder: * Given an odd integer base b, encodes integers as plaintext polynomials where the coefficients are according * to the "balanced" base b representation of the integer to be encoded, i.e. where each coefficient is in the * range -(b-1)/2,...,(b-1)/2. Decoding amounts to evaluating the polynomial at x=b. For example, when b=3 the * integer 25 = 3^3 - 3^1 + 3^0 is encoded as the polynomial 1x^3 - 1x^1 + 1. * * BinaryFractionalEncoder: * Encodes rational numbers as follows. First represent the number in binary, possibly truncating an infinite * fractional part to some fixed precision, e.g. 26.75 = 2^4 + 2^3 + 2^1 + 2^(-1) + 2^(-2). For the sake of * the example, suppose PolyModulus is 1x^1024 + 1. Next represent the integer part of the number in the same * was as in BinaryEncoder. Finally, represent the fractional part in the leading coefficients of the polynomial, * but when doing so invert the signs of the coefficients. So in this example we would represent 26.75 as the * polynomial -1x^1023 - 1x^1022 + 1x^4 + 1x^3 + 1x^1. The negative coefficients of the polynomial will again be * represented as their negatives modulo PlainModulus. * * BalancedFractionalEncoder: * Same as BinaryFractionalEncoder, except instead of using base 2 uses any odd base b and balanced * representatives for the coefficients, i.e. integers in the range -(b-1)/2,...,(b-1)/2. * * PolyCRTBuilder: * If PolyModulus is 1x^n + 1, PolyCRTBuilder allows "batching" of n plaintext integers modulo PlainModulus * into one plaintext polynomial, where homomorphic operations can be carried out very efficiently in a SIMD * manner by operating on such a "composed" plaintext or ciphertext polynomials. For full details on this very * powerful technique we recommend https://eprint.iacr.org/2012/565.pdf and https://eprint.iacr.org/2011/133. * * A crucial fact to understand is that when homomorphic operations are performed on ciphertexts, they will * carry over to the underlying plaintexts, and as a result of additions and multiplications the coefficients * in the plaintext polynomials will increase from what they originally were in freshly encoded polynomials. * This becomes a problem when the coefficients reach the size of PlainModulus, in which case they will get * automatically reduced modulo PlainModulus, and might render the underlying plaintext polynomial impossible * to be correctly decoded back into an integer or rational number. Therefore, it is typically crucial to * have a good sense of how large the coefficients will grow in the underlying plaintext polynomials when * homomorphic computations are carried out on the ciphertexts, and make sure that PlainModulus is chosen to * be at least as large as this number. */ // Encode two integers as polynomials. const int value1 = 5; const int value2 = -7; var encoder = new BalancedEncoder(parms.PlainModulus); var encoded1 = encoder.Encode(value1); var encoded2 = encoder.Encode(value2); Console.WriteLine("Encoded {0} as polynomial {1}", value1, encoded1); Console.WriteLine("Encoded {0} as polynomial {1}", value2, encoded2); // Generate keys. Console.WriteLine("Generating keys..."); var generator = new KeyGenerator(parms); generator.Generate(); Console.WriteLine("... key generation completed"); var publicKey = generator.PublicKey; var secretKey = generator.SecretKey; //Console.WriteLine("Public Key = {0}", publicKey); //Console.WriteLine("Secret Key = {0}", secretKey); // Encrypt values. Console.WriteLine("Encrypting values..."); var encryptor = new Encryptor(parms, publicKey); var encrypted1 = encryptor.Encrypt(encoded1); var encrypted2 = encryptor.Encrypt(encoded2); // Perform arithmetic on encrypted values. Console.WriteLine("Performing encrypted arithmetic..."); var evaluator = new Evaluator(parms); Console.WriteLine("... Performing negation..."); var encryptedNegated1 = evaluator.Negate(encrypted1); Console.WriteLine("... Performing addition..."); var encryptedSum = evaluator.Add(encrypted1, encrypted2); Console.WriteLine("... Performing subtraction..."); var encryptedDiff = evaluator.Sub(encrypted1, encrypted2); Console.WriteLine("... Performing multiplication..."); var encryptedProduct = evaluator.Multiply(encrypted1, encrypted2); // Decrypt results. Console.WriteLine("Decrypting results..."); var decryptor = new Decryptor(parms, secretKey); var decrypted1 = decryptor.Decrypt(encrypted1); var decrypted2 = decryptor.Decrypt(encrypted2); var decryptedNegated1 = decryptor.Decrypt(encryptedNegated1); var decryptedSum = decryptor.Decrypt(encryptedSum); var decryptedDiff = decryptor.Decrypt(encryptedDiff); var decryptedProduct = decryptor.Decrypt(encryptedProduct); // Decode results. var decoded1 = encoder.DecodeInt32(decrypted1); var decoded2 = encoder.DecodeInt32(decrypted2); var decodedNegated1 = encoder.DecodeInt32(decryptedNegated1); var decodedSum = encoder.DecodeInt32(decryptedSum); var decodedDiff = encoder.DecodeInt32(decryptedDiff); var decodedProduct = encoder.DecodeInt32(decryptedProduct); // Display results. Console.WriteLine("{0} after encryption/decryption = {1}", value1, decoded1); Console.WriteLine("{0} after encryption/decryption = {1}", value2, decoded2); Console.WriteLine("encrypted negate of {0} = {1}", value1, decodedNegated1); Console.WriteLine("encrypted addition of {0} and {1} = {2}", value1, value2, decodedSum); Console.WriteLine("encrypted subtraction of {0} and {1} = {2}", value1, value2, decodedDiff); Console.WriteLine("encrypted multiplication of {0} and {1} = {2}", value1, value2, decodedProduct); // How did the noise grow in these operations? var maxNoiseBitCount = Utilities.InherentNoiseMax(parms).GetSignificantBitCount(); Console.WriteLine("Noise in encryption of {0}: {1}/{2} bits", value1, Utilities.InherentNoise(encrypted1, parms, secretKey).GetSignificantBitCount(), maxNoiseBitCount); Console.WriteLine("Noise in encryption of {0}: {1}/{2} bits", value2, Utilities.InherentNoise(encrypted1, parms, secretKey).GetSignificantBitCount(), maxNoiseBitCount); Console.WriteLine("Noise in the sum: {0}/{1} bits", Utilities.InherentNoise(encryptedSum, parms, secretKey).GetSignificantBitCount(), maxNoiseBitCount); Console.WriteLine("Noise in the product: {0}/{1} bits", Utilities.InherentNoise(encryptedProduct, parms, secretKey).GetSignificantBitCount(), maxNoiseBitCount); }