static GlobalContext() { EncryptionParameters encParams = new EncryptionParameters(SchemeType.BFV) { PolyModulusDegree = 8192, CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree: 8192) }; encParams.SetPlainModulus(65537ul); BFVContext = new SEALContext(encParams); encParams = new EncryptionParameters(SchemeType.CKKS) { PolyModulusDegree = 8192, CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree: 8192) }; CKKSContext = new SEALContext(encParams); encParams = new EncryptionParameters(SchemeType.BGV) { PolyModulusDegree = 8192, CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree: 8192) }; encParams.SetPlainModulus(65537ul); BGVContext = new SEALContext(encParams); }
public void ExpandModChainTest() { EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) { PolyModulusDegree = 4096, CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree: 4096), PlainModulus = new Modulus(1 << 20) }; SEALContext context1 = new SEALContext(parms, expandModChain: true, secLevel: SecLevelType.None); // By default there is a chain SEALContext.ContextData contextData = context1.KeyContextData; Assert.IsNotNull(contextData); Assert.IsNull(contextData.PrevContextData); Assert.IsNotNull(contextData.NextContextData); contextData = context1.FirstContextData; Assert.IsNotNull(contextData); Assert.IsNotNull(contextData.PrevContextData); Assert.IsNotNull(contextData.NextContextData); // This should not create a chain SEALContext context2 = new SEALContext(parms, expandModChain: false); contextData = context2.KeyContextData; Assert.IsNotNull(contextData); Assert.IsNull(contextData.PrevContextData); Assert.IsNotNull(contextData.NextContextData); contextData = context2.FirstContextData; Assert.IsNotNull(contextData); Assert.IsNotNull(contextData.PrevContextData); Assert.IsNull(contextData.NextContextData); }
private static void ExampleCKKSPerformanceDefault() { Utilities.PrintExampleBanner("CKKS Performance Test with Degrees: 4096, 8192, and 16384"); // It is not recommended to use BFVDefault primes in CKKS. However, for performance // test, BFVDefault primes are good enough. EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS); ulong polyModulusDegree = 4096; parms.PolyModulusDegree = polyModulusDegree; parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree); CKKSPerformanceTest(new SEALContext(parms)); Console.WriteLine(); polyModulusDegree = 8192; parms.PolyModulusDegree = polyModulusDegree; parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree); CKKSPerformanceTest(new SEALContext(parms)); Console.WriteLine(); polyModulusDegree = 16384; parms.PolyModulusDegree = polyModulusDegree; parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree); CKKSPerformanceTest(new SEALContext(parms)); /* * Comment out the following to run the biggest example. */ //Console.WriteLine(); //polyModulusDegree = 32768; //parms.PolyModulusDegree = polyModulusDegree; //parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree); //CKKSPerformanceTest(new SEALContext(parms)); }
private static void ExampleCKKSPerformanceCustom() { Console.Write("> Set PolyModulusDegree (1024, 2048, 4096, 8192, 16384, or 32768): "); string input = Console.ReadLine(); if (!ulong.TryParse(input, out ulong polyModulusDegree)) { Console.WriteLine("Invalid option."); return; } if (polyModulusDegree < 1024 || polyModulusDegree > 32768 || (polyModulusDegree & (polyModulusDegree - 1)) != 0) { Console.WriteLine("Invalid option."); return; } string banner = $"CKKS Performance Test with Degree: {polyModulusDegree}"; Utilities.PrintExampleBanner(banner); using EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS) { PolyModulusDegree = polyModulusDegree, CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree) }; using (SEALContext context = new SEALContext(parms)) { CKKSPerformanceTest(context); } }
public ContextManager() { EncryptionParams = new EncryptionParameters(SchemeType.BFV); const ulong polyModulusDegree = 2048; EncryptionParams.PolyModulusDegree = polyModulusDegree; EncryptionParams.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree); EncryptionParams.PlainModulus = new Modulus(1024); Context = new SEALContext(EncryptionParams); }
public void generateKeys(int x, int y, string publicFile, string secretFile, string encryptedXFile, string encryptedYFile) { //Console.WriteLine("Rider at ({0},{1})",x,y); using EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV); ulong polyModulusDegree = 4096; parms.PolyModulusDegree = polyModulusDegree; parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree); parms.PlainModulus = new Modulus(1024); using SEALContext context = new SEALContext(parms); //Console.WriteLine("Set encryption parameters and print"); //Console.WriteLine(context); //Console.WriteLine("Parameter validation (success): {0}", context.ParameterErrorMessage()); using KeyGenerator keygen = new KeyGenerator(context); using PublicKey riderPub = keygen.PublicKey; using SecretKey riderSec = keygen.SecretKey; using Evaluator evaluator = new Evaluator(context); using IntegerEncoder encoder = new IntegerEncoder(context); using Encryptor riderEncryptor = new Encryptor(context, riderPub); using Decryptor riderDecryptor = new Decryptor(context, riderSec); using Plaintext riderxPlain = encoder.Encode(x); using Plaintext rideryPlain = encoder.Encode(y); using Ciphertext riderxEncrypted = new Ciphertext(); using Ciphertext rideryEncrypted = new Ciphertext(); riderEncryptor.Encrypt(riderxPlain, riderxEncrypted); riderEncryptor.Encrypt(rideryPlain, rideryEncrypted); var fileStream = File.Create(publicFile); riderPub.Save(fileStream); fileStream.Close(); fileStream = File.Create(secretFile); riderSec.Save(fileStream); fileStream.Close(); fileStream = File.Create(encryptedXFile); riderxEncrypted.Save(fileStream); fileStream.Close(); fileStream = File.Create(encryptedYFile); rideryEncrypted.Save(fileStream); fileStream.Close(); }
public void PropertiesTest() { SEALContext context = GlobalContext.BFVContext; Assert.IsTrue(context.FirstContextData.Qualifiers.ParametersSet); Assert.IsTrue(context.FirstContextData.Qualifiers.UsingBatching); Assert.IsTrue(context.FirstContextData.Qualifiers.UsingFastPlainLift); Assert.IsTrue(context.FirstContextData.Qualifiers.UsingFFT); Assert.AreEqual(SecLevelType.TC128, context.FirstContextData.Qualifiers.SecLevel); Assert.IsFalse(context.FirstContextData.Qualifiers.UsingDescendingModulusChain); Assert.IsTrue(context.FirstContextData.Qualifiers.UsingNTT); Assert.IsTrue(context.UsingKeyswitching); EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS) { PolyModulusDegree = 4096, CoeffModulus = CoeffModulus.BFVDefault(4096) }; SEALContext context2 = new SEALContext(parms); Assert.IsTrue(context2.FirstContextData.Qualifiers.ParametersSet); Assert.IsTrue(context2.FirstContextData.Qualifiers.UsingBatching); Assert.IsFalse(context2.FirstContextData.Qualifiers.UsingFastPlainLift); Assert.IsTrue(context2.FirstContextData.Qualifiers.UsingFFT); Assert.AreEqual(SecLevelType.TC128, context2.FirstContextData.Qualifiers.SecLevel); Assert.IsFalse(context.FirstContextData.Qualifiers.UsingDescendingModulusChain); Assert.IsTrue(context2.FirstContextData.Qualifiers.UsingNTT); Assert.IsTrue(context.UsingKeyswitching); EncryptionParameterQualifiers qualifiers = new EncryptionParameterQualifiers(context2.FirstContextData.Qualifiers); Assert.IsNotNull(qualifiers); Assert.IsTrue(qualifiers.ParametersSet); Assert.IsTrue(qualifiers.UsingBatching); Assert.IsFalse(qualifiers.UsingFastPlainLift); Assert.IsTrue(qualifiers.UsingFFT); Assert.AreEqual(SecLevelType.TC128, qualifiers.SecLevel); Assert.IsTrue(qualifiers.UsingDescendingModulusChain); Assert.IsTrue(qualifiers.UsingNTT); SEALContext context3 = GlobalContext.BGVContext; Assert.IsTrue(context.FirstContextData.Qualifiers.ParametersSet); Assert.IsTrue(context.FirstContextData.Qualifiers.UsingBatching); Assert.IsTrue(context.FirstContextData.Qualifiers.UsingFastPlainLift); Assert.IsTrue(context.FirstContextData.Qualifiers.UsingFFT); Assert.AreEqual(SecLevelType.TC128, context.FirstContextData.Qualifiers.SecLevel); Assert.IsFalse(context.FirstContextData.Qualifiers.UsingDescendingModulusChain); Assert.IsTrue(context.FirstContextData.Qualifiers.UsingNTT); Assert.IsTrue(context.UsingKeyswitching); }
public EncounterContext() { @params = new EncryptionParameters(SchemeType.BFV) { PolyModulusDegree = polyModDeg, // Must be a positive power of 2 CoeffModulus = CoeffModulus.BFVDefault(polyModDeg), PlainModulus = new SmallModulus(256) // Try to keep this as small as possible }; SealContext = new SEALContext(@params); KeyGen = new KeyGenerator(SealContext); Decryptor = new Decryptor(SealContext, KeyGen.SecretKey); Encryptor = new Encryptor(SealContext, KeyGen.PublicKey); }
private static void ExampleBFVPerformanceDefault() { Utilities.PrintExampleBanner("BFV Performance Test with Degrees: 4096, 8192, and 16384"); using EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV); ulong polyModulusDegree = 4096; parms.PolyModulusDegree = polyModulusDegree; parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree); parms.PlainModulus = new Modulus(786433); using (SEALContext context = new SEALContext(parms)) { BFVPerformanceTest(context); } Console.WriteLine(); polyModulusDegree = 8192; parms.PolyModulusDegree = polyModulusDegree; parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree); parms.PlainModulus = new Modulus(786433); using (SEALContext context = new SEALContext(parms)) { BFVPerformanceTest(context); } Console.WriteLine(); polyModulusDegree = 16384; parms.PolyModulusDegree = polyModulusDegree; parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree); parms.PlainModulus = new Modulus(786433); using (SEALContext context = new SEALContext(parms)) { BFVPerformanceTest(context); } /* * Comment out the following to run the biggest example. */ //Console.WriteLine(); //polyModulusDegree = 32768; //parms.PolyModulusDegree = polyModulusDegree; //parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree); //parms.PlainModulus = new Modulus(786433); //using (SEALContext context = new SEALContext(parms)) //{ // BFVPerformanceTest(context); //} }
public void encryptDriverLocation(int x, int y, string publicFile, string encryptedXFile, string encryptedYFile) { //Console.WriteLine("Driver at ({0},{1})",x,y); using EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV); ulong polyModulusDegree = 4096; parms.PolyModulusDegree = polyModulusDegree; parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree); parms.PlainModulus = new Modulus(1024); using SEALContext context = new SEALContext(parms); using KeyGenerator keygen = new KeyGenerator(context); using PublicKey riderPub = new PublicKey(); using Ciphertext xEncrypted = new Ciphertext(); using (var sr = new StreamReader(publicFile)) { riderPub.Load(context, sr.BaseStream); } using Evaluator evaluator = new Evaluator(context); using IntegerEncoder encoder = new IntegerEncoder(context); using Encryptor riderEncryptor = new Encryptor(context, riderPub); using Plaintext driverxPlain = encoder.Encode(x); using Plaintext driveryPlain = encoder.Encode(y); using Ciphertext driverxEncrypted = new Ciphertext(); using Ciphertext driveryEncrypted = new Ciphertext(); riderEncryptor.Encrypt(driverxPlain, driverxEncrypted); riderEncryptor.Encrypt(driveryPlain, driveryEncrypted); var fileStream = File.Create(encryptedXFile); driverxEncrypted.Save(fileStream); fileStream.Close(); fileStream = File.Create(encryptedYFile); driveryEncrypted.Save(fileStream); fileStream.Close(); }
public ulong decryptDistance(string publicFile, string secretFile, string distanceFile) { using EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV); ulong polyModulusDegree = 4096; parms.PolyModulusDegree = polyModulusDegree; parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree); parms.PlainModulus = new Modulus(1024); using SEALContext context = new SEALContext(parms); using KeyGenerator keygen = new KeyGenerator(context); using PublicKey riderPub = new PublicKey(); using (var sr = new StreamReader(publicFile)) { riderPub.Load(context, sr.BaseStream); } using SecretKey riderSec = new SecretKey(); using (var sr = new StreamReader(secretFile)) { riderSec.Load(context, sr.BaseStream); } using Ciphertext X2MinusX1SquaredPlusY2MinusY1Squared = new Ciphertext(); using (var sr = new StreamReader(distanceFile)) { X2MinusX1SquaredPlusY2MinusY1Squared.Load(context, sr.BaseStream); } using Encryptor riderEncryptor = new Encryptor(context, riderPub); using Decryptor riderDecryptor = new Decryptor(context, riderSec); using Plaintext distance = new Plaintext(); riderDecryptor.Decrypt(X2MinusX1SquaredPlusY2MinusY1Squared, distance); using IntegerEncoder encoder = new IntegerEncoder(context); //Console.WriteLine("Decrypted polynomial f(x) = {0}.", distance ); //Console.WriteLine(" distance from rider {0}", encoder.DecodeUInt64(distance)); return(encoder.DecodeUInt64(distance)); }
public void CoeffModulusTest() { EncryptionParameters encParams = new EncryptionParameters(SchemeType.BFV); Assert.IsNotNull(encParams); List <SmallModulus> coeffs = new List <SmallModulus>(encParams.CoeffModulus); Assert.IsNotNull(coeffs); Assert.AreEqual(0, coeffs.Count); encParams.CoeffModulus = CoeffModulus.BFVDefault(4096); List <SmallModulus> newCoeffs = new List <SmallModulus>(encParams.CoeffModulus); Assert.IsNotNull(newCoeffs); Assert.AreEqual(3, newCoeffs.Count); Assert.AreEqual(0xffffee001ul, newCoeffs[0].Value); Assert.AreEqual(0xffffc4001ul, newCoeffs[1].Value); Assert.AreEqual(0x1ffffe0001ul, newCoeffs[2].Value); }
public static SEALContext GetContext() { var encryptionParameters = new EncryptionParameters(SchemeType.BFV) { PolyModulusDegree = 32768, CoeffModulus = CoeffModulus.BFVDefault(32768) }; //encryptionParameters.PlainModulus = new Modulus(1024); /* * To enable batching, we need to set the plain_modulus to be a prime number * congruent to 1 modulo 2*PolyModulusDegree. Microsoft SEAL provides a helper * method for finding such a prime. In this example we create a 20-bit prime * that supports batching. */ encryptionParameters.PlainModulus = PlainModulus.Batching(32768, 20); SEALContext new_context = new SEALContext(encryptionParameters); return(new_context); }
private static void ExampleBFVPerformanceCustom() { Console.Write("> Set PolyModulusDegree (1024, 2048, 4096, 8192, 16384, or 32768): "); string input = Console.ReadLine(); if (!ulong.TryParse(input, out ulong polyModulusDegree)) { Console.WriteLine("Invalid option."); return; } if (polyModulusDegree < 1024 || polyModulusDegree > 32768 || (polyModulusDegree & (polyModulusDegree - 1)) != 0) { Console.WriteLine("Invalid option."); return; } string banner = $"BFV Performance Test with Degree: {polyModulusDegree}"; Utilities.PrintExampleBanner(banner); EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) { PolyModulusDegree = polyModulusDegree, CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree) }; if (polyModulusDegree == 1024) { parms.PlainModulus = new SmallModulus(12289); } else { parms.PlainModulus = new SmallModulus(786433); } BFVPerformanceTest(new SEALContext(parms)); }
/* * In `1_BFV_Basics.cs' we showed how to perform a very simple computation using the * BFV scheme. The computation was performed modulo the PlainModulus parameter, and * utilized only one coefficient from a BFV plaintext polynomial. This approach has * two notable problems: * * (1) Practical applications typically use integer or real number arithmetic, * not modular arithmetic; * (2) We used only one coefficient of the plaintext polynomial. This is really * wasteful, as the plaintext polynomial is large and will in any case be * encrypted in its entirety. * * For (1), one may ask why not just increase the PlainModulus parameter until no * overflow occurs, and the computations behave as in integer arithmetic. The problem * is that increasing PlainModulus increases noise budget consumption, and decreases * the initial noise budget too. * * In these examples we will discuss other ways of laying out data into plaintext * elements (encoding) that allow more computations without data type overflow, and * can allow the full plaintext polynomial to be utilized. */ private static void ExampleBatchEncoder() { Utilities.PrintExampleBanner("Example: Encoders / Batch Encoder"); /* * [BatchEncoder] (For BFV scheme only) * * Let N denote the PolyModulusDegree and T denote the PlainModulus. Batching * allows the BFV plaintext polynomials to be viewed as 2-by-(N/2) matrices, with * each element an integer modulo T. In the matrix view, encrypted operations act * element-wise on encrypted matrices, allowing the user to obtain speeds-ups of * several orders of magnitude in fully vectorizable computations. Thus, in all * but the simplest computations, batching should be the preferred method to use * with BFV, and when used properly will result in implementations outperforming * anything done without batching. */ using EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV); ulong polyModulusDegree = 8192; parms.PolyModulusDegree = polyModulusDegree; parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree); /* * To enable batching, we need to set the plain_modulus to be a prime number * congruent to 1 modulo 2*PolyModulusDegree. Microsoft SEAL provides a helper * method for finding such a prime. In this example we create a 20-bit prime * that supports batching. */ parms.PlainModulus = PlainModulus.Batching(polyModulusDegree, 20); using SEALContext context = new SEALContext(parms); Utilities.PrintParameters(context); Console.WriteLine(); /* * We can verify that batching is indeed enabled by looking at the encryption * parameter qualifiers created by SEALContext. */ using var qualifiers = context.FirstContextData.Qualifiers; Console.WriteLine($"Batching enabled: {qualifiers.UsingBatching}"); using KeyGenerator keygen = new KeyGenerator(context); using SecretKey secretKey = keygen.SecretKey; keygen.CreatePublicKey(out PublicKey publicKey); keygen.CreateRelinKeys(out RelinKeys relinKeys); using Encryptor encryptor = new Encryptor(context, publicKey); using Evaluator evaluator = new Evaluator(context); using Decryptor decryptor = new Decryptor(context, secretKey); /* * Batching is done through an instance of the BatchEncoder class. */ using BatchEncoder batchEncoder = new BatchEncoder(context); /* * The total number of batching `slots' equals the PolyModulusDegree, N, and * these slots are organized into 2-by-(N/2) matrices that can be encrypted and * computed on. Each slot contains an integer modulo PlainModulus. */ ulong slotCount = batchEncoder.SlotCount; ulong rowSize = slotCount / 2; Console.WriteLine($"Plaintext matrix row size: {rowSize}"); /* * The matrix plaintext is simply given to BatchEncoder as a flattened vector * of numbers. The first `rowSize' many numbers form the first row, and the * rest form the second row. Here we create the following matrix: * * [ 0, 1, 2, 3, 0, 0, ..., 0 ] * [ 4, 5, 6, 7, 0, 0, ..., 0 ] */ ulong[] podMatrix = new ulong[slotCount]; podMatrix[0] = 0; podMatrix[1] = 1; podMatrix[2] = 2; podMatrix[3] = 3; podMatrix[rowSize] = 4; podMatrix[rowSize + 1] = 5; podMatrix[rowSize + 2] = 6; podMatrix[rowSize + 3] = 7; Console.WriteLine("Input plaintext matrix:"); Utilities.PrintMatrix(podMatrix, (int)rowSize); /* * First we use BatchEncoder to encode the matrix into a plaintext polynomial. */ using Plaintext plainMatrix = new Plaintext(); Utilities.PrintLine(); Console.WriteLine("Encode plaintext matrix:"); batchEncoder.Encode(podMatrix, plainMatrix); /* * We can instantly decode to verify correctness of the encoding. Note that no * encryption or decryption has yet taken place. */ List <ulong> podResult = new List <ulong>(); Console.WriteLine(" + Decode plaintext matrix ...... Correct."); batchEncoder.Decode(plainMatrix, podResult); Utilities.PrintMatrix(podResult, (int)rowSize); /* * Next we encrypt the encoded plaintext. */ using Ciphertext encryptedMatrix = new Ciphertext(); Utilities.PrintLine(); Console.WriteLine("Encrypt plainMatrix to encryptedMatrix."); encryptor.Encrypt(plainMatrix, encryptedMatrix); Console.WriteLine(" + Noise budget in encryptedMatrix: {0} bits", decryptor.InvariantNoiseBudget(encryptedMatrix)); /* * Operating on the ciphertext results in homomorphic operations being performed * simultaneously in all 8192 slots (matrix elements). To illustrate this, we * form another plaintext matrix * * [ 1, 2, 1, 2, 1, 2, ..., 2 ] * [ 1, 2, 1, 2, 1, 2, ..., 2 ] * * and encode it into a plaintext. */ ulong[] podMatrix2 = new ulong[slotCount]; for (ulong i = 0; i < slotCount; i++) { podMatrix2[i] = (i & 1) + 1; } using Plaintext plainMatrix2 = new Plaintext(); batchEncoder.Encode(podMatrix2, plainMatrix2); Console.WriteLine(); Console.WriteLine("Second input plaintext matrix:"); Utilities.PrintMatrix(podMatrix2, (int)rowSize); /* * We now add the second (plaintext) matrix to the encrypted matrix, and square * the sum. */ Utilities.PrintLine(); Console.WriteLine("Sum, square, and relinearize."); evaluator.AddPlainInplace(encryptedMatrix, plainMatrix2); evaluator.SquareInplace(encryptedMatrix); evaluator.RelinearizeInplace(encryptedMatrix, relinKeys); /* * How much noise budget do we have left? */ Console.WriteLine(" + Noise budget in result: {0} bits", decryptor.InvariantNoiseBudget(encryptedMatrix)); /* * We decrypt and decompose the plaintext to recover the result as a matrix. */ using Plaintext plainResult = new Plaintext(); Utilities.PrintLine(); Console.WriteLine("Decrypt and decode result."); decryptor.Decrypt(encryptedMatrix, plainResult); batchEncoder.Decode(plainResult, podResult); Console.WriteLine(" + Result plaintext matrix ...... Correct."); Utilities.PrintMatrix(podResult, (int)rowSize); /* * Batching allows us to efficiently use the full plaintext polynomial when the * desired encrypted computation is highly parallelizable. However, it has not * solved the other problem mentioned in the beginning of this file: each slot * holds only an integer modulo plain_modulus, and unless plain_modulus is very * large, we can quickly encounter data type overflow and get unexpected results * when integer computations are desired. Note that overflow cannot be detected * in encrypted form. The CKKS scheme (and the CKKSEncoder) addresses the data * type overflow issue, but at the cost of yielding only approximate results. */ }
/* * In `1_BFV_Basics.cs' we showed how to perform a very simple computation using the * BFV scheme. The computation was performed modulo the PlainModulus parameter, and * utilized only one coefficient from a BFV plaintext polynomial. This approach has * two notable problems: * * (1) Practical applications typically use integer or real number arithmetic, * not modular arithmetic; * (2) We used only one coefficient of the plaintext polynomial. This is really * wasteful, as the plaintext polynomial is large and will in any case be * encrypted in its entirety. * * For (1), one may ask why not just increase the PlainModulus parameter until no * overflow occurs, and the computations behave as in integer arithmetic. The problem * is that increasing PlainModulus increases noise budget consumption, and decreases * the initial noise budget too. * * In these examples we will discuss other ways of laying out data into plaintext * elements (encoding) that allow more computations without data type overflow, and * can allow the full plaintext polynomial to be utilized. */ private static void ExampleIntegerEncoder() { Utilities.PrintExampleBanner("Example: Encoders / Integer Encoder"); /* * [IntegerEncoder] (For BFV scheme only) * * The IntegerEncoder encodes integers to BFV plaintext polynomials as follows. * First, a binary expansion of the integer is computed. Next, a polynomial is * created with the bits as coefficients. For example, the integer * * 26 = 2^4 + 2^3 + 2^1 * * is encoded as the polynomial 1x^4 + 1x^3 + 1x^1. Conversely, plaintext * polynomials are decoded by evaluating them at x=2. For negative numbers the * IntegerEncoder simply stores all coefficients as either 0 or -1, where -1 is * represented by the unsigned integer PlainModulus - 1 in memory. * * Since encrypted computations operate on the polynomials rather than on the * encoded integers themselves, the polynomial coefficients will grow in the * course of such computations. For example, computing the sum of the encrypted * encoded integer 26 with itself will result in an encrypted polynomial with * larger coefficients: 2x^4 + 2x^3 + 2x^1. Squaring the encrypted encoded * integer 26 results also in increased coefficients due to cross-terms, namely, * * (1x^4 + 1x^3 + 1x^1)^2 = 1x^8 + 2x^7 + 1x^6 + 2x^5 + 2x^4 + 1x^2; * * further computations will quickly increase the coefficients much more. * Decoding will still work correctly in this case (evaluating the polynomial * at x=2), but since the coefficients of plaintext polynomials are really * integers modulo plain_modulus, implicit reduction modulo plain_modulus may * yield unexpected results. For example, adding 1x^4 + 1x^3 + 1x^1 to itself * plain_modulus many times will result in the constant polynomial 0, which is * clearly not equal to 26 * plain_modulus. It can be difficult to predict when * such overflow will take place especially when computing several sequential * multiplications. * * The IntegerEncoder is easy to understand and use for simple computations, * and can be a good tool to experiment with for users new to Microsoft SEAL. * However, advanced users will probably prefer more efficient approaches, * such as the BatchEncoder or the CKKSEncoder. */ EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV); ulong polyModulusDegree = 4096; parms.PolyModulusDegree = polyModulusDegree; parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree); /* * There is no hidden logic behind our choice of the plain_modulus. The only * thing that matters is that the plaintext polynomial coefficients will not * exceed this value at any point during our computation; otherwise the result * will be incorrect. */ parms.PlainModulus = new SmallModulus(512); SEALContext context = new SEALContext(parms); Utilities.PrintParameters(context); Console.WriteLine(); KeyGenerator keygen = new KeyGenerator(context); PublicKey publicKey = keygen.PublicKey; SecretKey secretKey = keygen.SecretKey; Encryptor encryptor = new Encryptor(context, publicKey); Evaluator evaluator = new Evaluator(context); Decryptor decryptor = new Decryptor(context, secretKey); /* * We create an IntegerEncoder. */ IntegerEncoder encoder = new IntegerEncoder(context); /* * First, we encode two integers as plaintext polynomials. Note that encoding * is not encryption: at this point nothing is encrypted. */ int value1 = 5; Plaintext plain1 = encoder.Encode(value1); Utilities.PrintLine(); Console.WriteLine($"Encode {value1} as polynomial {plain1} (plain1),"); int value2 = -7; Plaintext plain2 = encoder.Encode(value2); Console.WriteLine(new string(' ', 13) + $"Encode {value2} as polynomial {plain2} (plain2),"); /* * Now we can encrypt the plaintext polynomials. */ Ciphertext encrypted1 = new Ciphertext(); Ciphertext encrypted2 = new Ciphertext(); Utilities.PrintLine(); Console.WriteLine("Encrypt plain1 to encrypted1 and plain2 to encrypted2."); encryptor.Encrypt(plain1, encrypted1); encryptor.Encrypt(plain2, encrypted2); Console.WriteLine(" + Noise budget in encrypted1: {0} bits", decryptor.InvariantNoiseBudget(encrypted1)); Console.WriteLine(" + Noise budget in encrypted2: {0} bits", decryptor.InvariantNoiseBudget(encrypted2)); /* * As a simple example, we compute (-encrypted1 + encrypted2) * encrypted2. */ encryptor.Encrypt(plain2, encrypted2); Ciphertext encryptedResult = new Ciphertext(); Utilities.PrintLine(); Console.WriteLine("Compute encrypted_result = (-encrypted1 + encrypted2) * encrypted2."); evaluator.Negate(encrypted1, encryptedResult); evaluator.AddInplace(encryptedResult, encrypted2); evaluator.MultiplyInplace(encryptedResult, encrypted2); Console.WriteLine(" + Noise budget in encryptedResult: {0} bits", decryptor.InvariantNoiseBudget(encryptedResult)); Plaintext plainResult = new Plaintext(); Utilities.PrintLine(); Console.WriteLine("Decrypt encrypted_result to plain_result."); decryptor.Decrypt(encryptedResult, plainResult); /* * Print the result plaintext polynomial. The coefficients are not even close * to exceeding our plainModulus, 512. */ Console.WriteLine($" + Plaintext polynomial: {plainResult}"); /* * Decode to obtain an integer result. */ Utilities.PrintLine(); Console.WriteLine("Decode plain_result."); Console.WriteLine(" + Decoded integer: {0} ...... Correct.", encoder.DecodeInt32(plainResult)); }
private static void ExampleBGVBasics() { Utilities.PrintExampleBanner("Example: BGV Basics"); /* * As an example, we evaluate the degree 8 polynomial * * x^8 * * over an encrypted x over integers 1, 2, 3, 4. The coefficients of the * polynomial can be considered as plaintext inputs, as we will see below. The * computation is done modulo the plain_modulus 1032193. * * Computing over encrypted data in the BGV scheme is similar to that in BFV. * The purpose of this example is mainly to explain the differences between BFV * and BGV in terms of ciphertext coefficient modulus selection and noise control. * * Most of the following code are repeated from "BFV basics" and "encoders" examples. */ /* * Note that scheme_type is now "bgv". */ using EncryptionParameters parms = new EncryptionParameters(SchemeType.BGV); ulong polyModulusDegree = 8192; parms.PolyModulusDegree = polyModulusDegree; /* * We can certainly use BFVDefault coeff_modulus. In later parts of this example, * we will demonstrate how to choose coeff_modulus that is more useful in BGV. */ parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree); parms.PlainModulus = PlainModulus.Batching(polyModulusDegree, 20); using SEALContext context = new SEALContext(parms); /* * Print the parameters that we have chosen. */ Utilities.PrintLine(); Console.WriteLine("Set encryption parameters and print"); Utilities.PrintParameters(context); using KeyGenerator keygen = new KeyGenerator(context); using SecretKey secretKey = keygen.SecretKey; keygen.CreatePublicKey(out PublicKey publicKey); keygen.CreateRelinKeys(out RelinKeys relinKeys); using Encryptor encryptor = new Encryptor(context, publicKey); using Evaluator evaluator = new Evaluator(context); using Decryptor decryptor = new Decryptor(context, secretKey); /* * Batching and slot operations are the same in BFV and BGV. */ using BatchEncoder batchEncoder = new BatchEncoder(context); ulong slotCount = batchEncoder.SlotCount; ulong rowSize = slotCount / 2; Console.WriteLine($"Plaintext matrix row size: {rowSize}"); /* * Here we create the following matrix: * [ 1, 2, 3, 4, 0, 0, ..., 0 ] * [ 0, 0, 0, 0, 0, 0, ..., 0 ] */ ulong[] podMatrix = new ulong[slotCount]; podMatrix[0] = 1; podMatrix[1] = 2; podMatrix[2] = 3; podMatrix[3] = 4; Console.WriteLine("Input plaintext matrix:"); Utilities.PrintMatrix(podMatrix, (int)rowSize); using Plaintext xPlain = new Plaintext(); Console.WriteLine("Encode plaintext matrix to xPlain:"); batchEncoder.Encode(podMatrix, xPlain); /* * Next we encrypt the encoded plaintext. */ using Ciphertext xEncrypted = new Ciphertext(); Utilities.PrintLine(); Console.WriteLine("Encrypt xPlain to xEncrypted."); encryptor.Encrypt(xPlain, xEncrypted); Console.WriteLine(" + noise budget in freshly encrypted x: {0} bits", decryptor.InvariantNoiseBudget(xEncrypted)); Console.WriteLine(); /* * Then we compute x^2. */ Utilities.PrintLine(); Console.WriteLine("Compute and relinearize xSquared (x^2),"); using Ciphertext xSquared = new Ciphertext(); evaluator.Square(xEncrypted, xSquared); Console.WriteLine($" + size of xSquared: {xSquared.Size}"); evaluator.RelinearizeInplace(xSquared, relinKeys); Console.WriteLine(" + size of xSquared (after relinearization): {0}", xSquared.Size); Console.WriteLine(" + noise budget in xSquared: {0} bits", decryptor.InvariantNoiseBudget(xSquared)); using Plaintext decryptedResult = new Plaintext(); decryptor.Decrypt(xSquared, decryptedResult); List <ulong> podResult = new List <ulong>(); batchEncoder.Decode(decryptedResult, podResult); Console.WriteLine(" + result plaintext matrix ...... Correct."); Utilities.PrintMatrix(podResult, (int)rowSize); /* * Next we compute x^4. */ Utilities.PrintLine(); Console.WriteLine("Compute and relinearize x4th (x^4),"); using Ciphertext x4th = new Ciphertext(); evaluator.Square(xSquared, x4th); Console.WriteLine($" + size of x4th: {x4th.Size}"); evaluator.RelinearizeInplace(x4th, relinKeys); Console.WriteLine(" + size of x4th (after relinearization): {0}", x4th.Size); Console.WriteLine(" + noise budget in x4th: {0} bits", decryptor.InvariantNoiseBudget(x4th)); decryptor.Decrypt(x4th, decryptedResult); batchEncoder.Decode(decryptedResult, podResult); Console.WriteLine(" + result plaintext matrix ...... Correct."); Utilities.PrintMatrix(podResult, (int)rowSize); /* * Last we compute x^8. We run out of noise budget. */ Utilities.PrintLine(); Console.WriteLine("Compute and relinearize x8th (x^8),"); using Ciphertext x8th = new Ciphertext(); evaluator.Square(x4th, x8th); Console.WriteLine($" + size of x8th: {x8th.Size}"); evaluator.RelinearizeInplace(x8th, relinKeys); Console.WriteLine(" + size of x8th (after relinearization): {0}", x8th.Size); Console.WriteLine(" + noise budget in x8th: {0} bits", decryptor.InvariantNoiseBudget(x8th)); Console.WriteLine("NOTE: Notice the increase in remaining noise budget."); Console.WriteLine(); Console.WriteLine("~~~~~~ Use modulus switching to calculate x^8. ~~~~~~"); /* * Noise budget has reached 0, which means that decryption cannot be expected * to give the correct result. BGV requires modulus switching to reduce noise * growth. In the following demonstration, we will insert a modulus switching * after each relinearization. */ Utilities.PrintLine(); Console.WriteLine("Encrypt xPlain to xEncrypted."); encryptor.Encrypt(xPlain, xEncrypted); Console.WriteLine(" + noise budget in freshly encrypted x: {0} bits", decryptor.InvariantNoiseBudget(xEncrypted)); Console.WriteLine(); /* * Then we compute x^2. */ Utilities.PrintLine(); Console.WriteLine("Compute and relinearize xSquared (x^2),"); Console.WriteLine(" + noise budget in xSquared (previously): {0} bits", decryptor.InvariantNoiseBudget(xSquared)); evaluator.Square(xEncrypted, xSquared); evaluator.RelinearizeInplace(xSquared, relinKeys); evaluator.ModSwitchToNextInplace(xSquared); Console.WriteLine(" + noise budget in xSquared (with modulus switching): {0} bits", decryptor.InvariantNoiseBudget(xSquared)); decryptor.Decrypt(xSquared, decryptedResult); batchEncoder.Decode(decryptedResult, podResult); Console.WriteLine(" + result plaintext matrix ...... Correct."); Utilities.PrintMatrix(podResult, (int)rowSize); /* * Next we compute x^4. */ Utilities.PrintLine(); Console.WriteLine("Compute and relinearize x4th (x^4),"); Console.WriteLine(" + noise budget in x4th (previously): {0} bits", decryptor.InvariantNoiseBudget(x4th)); evaluator.Square(xSquared, x4th); evaluator.RelinearizeInplace(x4th, relinKeys); evaluator.ModSwitchToNextInplace(x4th); Console.WriteLine(" + noise budget in x4th (with modulus switching): {0} bits", decryptor.InvariantNoiseBudget(x4th)); decryptor.Decrypt(x4th, decryptedResult); batchEncoder.Decode(decryptedResult, podResult); Console.WriteLine(" + result plaintext matrix ...... Correct."); Utilities.PrintMatrix(podResult, (int)rowSize); /* * Last we compute x^8. We still have budget left. */ Utilities.PrintLine(); Console.WriteLine("Compute and relinearize x8th (x^8),"); Console.WriteLine(" + noise budget in x8th (previously): {0} bits", decryptor.InvariantNoiseBudget(x8th)); evaluator.Square(x4th, x8th); evaluator.RelinearizeInplace(x8th, relinKeys); evaluator.ModSwitchToNextInplace(x8th); Console.WriteLine(" + noise budget in x8th (with modulus switching): {0} bits", decryptor.InvariantNoiseBudget(x8th)); decryptor.Decrypt(x8th, decryptedResult); batchEncoder.Decode(decryptedResult, podResult); Console.WriteLine(" + result plaintext matrix ...... Correct."); Utilities.PrintMatrix(podResult, (int)rowSize); /* * Although with modulus switching x_squared has less noise budget than before, * noise budget is consumed at a slower rate. To achieve the optimal consumption * rate of noise budget in an application, one needs to carefully choose the * location to insert modulus switching and manually choose coeff_modulus. */ }
static async Task RunAsync() { // Update port # in the following line. client.BaseAddress = new Uri("http://localhost/"); //client.BaseAddress = new Uri("https://sealserver20200623225403.azurewebsites.net/"); client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/octet-stream")); UriBuilder builder = new UriBuilder(); builder.Port = 50755; builder.Path = "sealoperation"; using EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV); ulong polyModulusDegree = 4096; parms.PolyModulusDegree = polyModulusDegree; parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree); parms.PlainModulus = new Modulus(4096); using SEALContext context = new SEALContext(parms); using Evaluator evaluator = new Evaluator(context); using KeyGenerator keygen = new KeyGenerator(context); using PublicKey publicKey = keygen.PublicKey; using SecretKey secretKey = keygen.SecretKey; using Encryptor encryptor = new Encryptor(context, publicKey); using Decryptor decryptor = new Decryptor(context, secretKey); //BigInteger bint = BigInteger.Parse("97391909619002370737223511047161666878854921822310726371156754097341907215981"); BigInteger bint = BigInteger.Parse("998745113"); //int xVal = 625; //int degree = 10; //int coeff = 25; // These are good starting points for small numbers < 100mil /* * int tConst = 121; * int xVal = 10; * int degree = 2; * int coeff = 3; */ int tConst = 1210; int xVal = 25; int degree = 4; int coeff = 3; // Candidate first result from initial polynomial List <int> terms; BigInteger res = createBigIntFromPoly(degree, coeff, xVal, tConst, out terms); // compare res to target BigInteger, if way smaller, then create a new // result after increasing any of the polynomial values while (BigInteger.Compare(res, bint) < 0) // res is less than bint { BigInteger halfVal = BigInteger.Divide(bint, new BigInteger(2)); BigInteger onePercent = BigInteger.Divide(bint, new BigInteger(100)); BigInteger tenPercent = BigInteger.Multiply(onePercent, new BigInteger(10)); //BigInteger quarterVal = BigInteger.Divide(bint, new BigInteger(4)); if (BigInteger.Compare(halfVal, res) > 0) { //coeff += 1; int len = halfVal.ToString().Length; int len2 = res.ToString().Length; if (len == len2) { coeff *= 2; } else { degree += 2; } res = createBigIntFromPoly(degree, coeff, xVal, tConst, out terms); } else { BigInteger difference = BigInteger.Subtract(bint, res); if (BigInteger.Compare(tenPercent, difference) > 0) { tConst += 1111; } else { coeff += 1; } res = createBigIntFromPoly(degree, coeff, xVal, tConst, out terms); } //Console.WriteLine(res.ToString()); Console.WriteLine("..."); } // Res is now equal or greater to bint tConst = tConst - (int)BigInteger.Subtract(res, bint); // Now check the polynomial BigInteger testPoly = createBigIntFromPoly(degree, coeff, xVal, tConst, out terms); Console.WriteLine("For Big Integer {0}", bint.ToString()); foreach (int term in terms) { Console.WriteLine("Polynomial term is {0}x^{1}", coeff, term); } Console.WriteLine("Final term is constant {0} with x={1}", tConst, xVal); byte[] bytespan = bint.ToByteArray(); byte[] newspan = new byte[bytespan.Length]; newspan[0] = bytespan[0]; BigInteger binttemp = new BigInteger(bytespan); // Pick an 'x' value for the polynomial that is big enough to represent the upper 10 digits of the value BigInteger bint2 = BigInteger.Parse("7983012132846067729184195556448685457666384473549591845215215701504271855338012801306119587019479688581971723759499902125851173348207536911525267617909811"); BigInteger bintres = bint * bint2; using Plaintext bPlainB = new Plaintext(bint.ToString()); int x = 9; Console.WriteLine("Plain x value to set"); Console.WriteLine(x.ToString()); using Plaintext xPlainX = new Plaintext(Convert.ToString(x, 16)); Console.WriteLine("Hex value being set"); Console.WriteLine(xPlainX.ToString()); using Ciphertext xEncrypted = new Ciphertext(); Console.WriteLine("Encrypt xPlain to xEncrypted."); encryptor.Encrypt(xPlainX, xEncrypted); int y = 5; Console.WriteLine("Plain y value to set"); Console.WriteLine(y.ToString()); using Plaintext xPlainY = new Plaintext(Convert.ToString(y, 16)); Console.WriteLine("Hex y value being set"); Console.WriteLine(xPlainY.ToString()); using Ciphertext yEncrypted = new Ciphertext(); encryptor.Encrypt(xPlainY, yEncrypted); FHEParams fHEParams = new FHEParams(); fHEParams.param1 = xEncrypted; fHEParams.param2 = yEncrypted; fHEParams.result = new Ciphertext(); // DEBUG ONLY Ciphertext mAnswer = new Ciphertext(); evaluator.Multiply(fHEParams.param1, fHEParams.param2, mAnswer); evaluator.Add(fHEParams.param1, fHEParams.param2, fHEParams.result); string expAnswer = SerializeSEAL(fHEParams.result); using Plaintext xDecrypted2 = new Plaintext(); decryptor.Decrypt(mAnswer, xDecrypted2); Console.WriteLine(xDecrypted2.ToString()); decryptor.Decrypt(fHEParams.result, xDecrypted2); string answer = xDecrypted2.ToString(); int num = 0; Int32.TryParse(answer, System.Globalization.NumberStyles.HexNumber, CultureInfo.InvariantCulture, out num); Console.WriteLine("Local answer"); Console.WriteLine(answer); Console.WriteLine(num.ToString()); // END DEBUG //fHEParams.param1. fHEParams.operation = "add"; SEALTransport transport = new SEALTransport(); transport.ContextParams = SerializeSEAL(parms); transport.FHEParam1 = SerializeSEAL(fHEParams.param1); // Console.WriteLine(transport.FHEParam1); transport.FHEParam2 = SerializeSEAL(fHEParams.param2); transport.FHEResult = SerializeSEAL(fHEParams.result); transport.Operation = fHEParams.operation; try { // Get the parameters, SEALTransport response = await PostFHEResultAsync(builder.Uri.AbsoluteUri, transport); Ciphertext result = new Ciphertext(); byte[] fp1 = System.Convert.FromBase64String(response.FHEResult); string recAnswer = response.FHEResult; if (expAnswer == recAnswer) { Console.WriteLine("Expected answer matches received answer"); } MemoryStream mst = new MemoryStream(fp1); result.Load(context, mst); Plaintext xDecrypted3 = new Plaintext(); decryptor.Decrypt(result, xDecrypted3); answer = xDecrypted3.ToString(); Console.WriteLine(answer); Console.WriteLine("Remote Decimal answer"); Int32.TryParse(answer, System.Globalization.NumberStyles.HexNumber, CultureInfo.InvariantCulture, out num); Console.WriteLine(num.ToString()); } catch (Exception e) { Console.WriteLine(e.Message); } Console.ReadLine(); }
private static void ExampleBFVBasics() { Utilities.PrintExampleBanner("Example: BFV Basics"); /* * In this example, we demonstrate performing simple computations (a polynomial * evaluation) on encrypted integers using the BFV encryption scheme. * * The first task is to set up an instance of the EncryptionParameters class. * It is critical to understand how the different parameters behave, how they * affect the encryption scheme, performance, and the security level. There are * three encryption parameters that are necessary to set: * * - PolyModulusDegree (degree of polynomial modulus); * - CoeffModulus ([ciphertext] coefficient modulus); * - PlainModulus (plaintext modulus; only for the BFV scheme). * * The BFV scheme cannot perform arbitrary computations on encrypted data. * Instead, each ciphertext has a specific quantity called the `invariant noise * budget' -- or `noise budget' for short -- measured in bits. The noise budget * in a freshly encrypted ciphertext (initial noise budget) is determined by * the encryption parameters. Homomorphic operations consume the noise budget * at a rate also determined by the encryption parameters. In BFV the two basic * operations allowed on encrypted data are additions and multiplications, of * which additions can generally be thought of as being nearly free in terms of * noise budget consumption compared to multiplications. Since noise budget * consumption compounds in sequential multiplications, the most significant * factor in choosing appropriate encryption parameters is the multiplicative * depth of the arithmetic circuit that the user wants to evaluate on encrypted * data. Once the noise budget of a ciphertext reaches zero it becomes too * corrupted to be decrypted. Thus, it is essential to choose the parameters to * be large enough to support the desired computation; otherwise the result is * impossible to make sense of even with the secret key. */ EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV); /* * The first parameter we set is the degree of the `polynomial modulus'. This * must be a positive power of 2, representing the degree of a power-of-two * cyclotomic polynomial; it is not necessary to understand what this means. * * Larger PolyModulusDegree makes ciphertext sizes larger and all operations * slower, but enables more complicated encrypted computations. Recommended * values are 1024, 2048, 4096, 8192, 16384, 32768, but it is also possible * to go beyond this range. * * In this example we use a relatively small polynomial modulus. Anything * smaller than this will enable only very restricted encrypted computations. */ ulong polyModulusDegree = 4096; parms.PolyModulusDegree = polyModulusDegree; /* * Next we set the [ciphertext] `coefficient modulus' (CoeffModulus). This * parameter is a large integer, which is a product of distinct prime numbers, * numbers, each represented by an instance of the SmallModulus class. The * bit-length of CoeffModulus means the sum of the bit-lengths of its prime * factors. * * A larger CoeffModulus implies a larger noise budget, hence more encrypted * computation capabilities. However, an upper bound for the total bit-length * of the CoeffModulus is determined by the PolyModulusDegree, as follows: * +----------------------------------------------------+ | PolyModulusDegree | max CoeffModulus bit-length | +---------------------+------------------------------+ | 1024 | 27 | | 2048 | 54 | | 4096 | 109 | | 8192 | 218 | | 16384 | 438 | | 32768 | 881 | +---------------------+------------------------------+ | | These numbers can also be found in native/src/seal/util/hestdparms.h encoded | in the function SEAL_HE_STD_PARMS_128_TC, and can also be obtained from the | function | | CoeffModulus.MaxBitCount(polyModulusDegree). | | For example, if PolyModulusDegree is 4096, the coeff_modulus could consist | of three 36-bit primes (108 bits). | | Microsoft SEAL comes with helper functions for selecting the CoeffModulus. | For new users the easiest way is to simply use | | CoeffModulus.BFVDefault(polyModulusDegree), | | which returns IEnumerable<SmallModulus> consisting of a generally good choice | for the given PolyModulusDegree. */ parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree); /* * The plaintext modulus can be any positive integer, even though here we take * it to be a power of two. In fact, in many cases one might instead want it * to be a prime number; we will see this in later examples. The plaintext * modulus determines the size of the plaintext data type and the consumption * of noise budget in multiplications. Thus, it is essential to try to keep the * plaintext data type as small as possible for best performance. The noise * budget in a freshly encrypted ciphertext is * * ~ log2(CoeffModulus/PlainModulus) (bits) * * and the noise budget consumption in a homomorphic multiplication is of the * form log2(PlainModulus) + (other terms). * * The plaintext modulus is specific to the BFV scheme, and cannot be set when * using the CKKS scheme. */ parms.PlainModulus = new SmallModulus(1024); /* * Now that all parameters are set, we are ready to construct a SEALContext * object. This is a heavy class that checks the validity and properties of the * parameters we just set. */ SEALContext context = new SEALContext(parms); /* * Print the parameters that we have chosen. */ Utilities.PrintLine(); Console.WriteLine("Set encryption parameters and print"); Utilities.PrintParameters(context); Console.WriteLine(); Console.WriteLine("~~~~~~ A naive way to calculate 4(x^2+1)(x+1)^2. ~~~~~~"); /* * The encryption schemes in Microsoft SEAL are public key encryption schemes. * For users unfamiliar with this terminology, a public key encryption scheme * has a separate public key for encrypting data, and a separate secret key for * decrypting data. This way multiple parties can encrypt data using the same * shared public key, but only the proper recipient of the data can decrypt it * with the secret key. * * We are now ready to generate the secret and public keys. For this purpose * we need an instance of the KeyGenerator class. Constructing a KeyGenerator * automatically generates the public and secret key, which can immediately be * read to local variables. */ KeyGenerator keygen = new KeyGenerator(context); PublicKey publicKey = keygen.PublicKey; SecretKey secretKey = keygen.SecretKey; /* * To be able to encrypt we need to construct an instance of Encryptor. Note * that the Encryptor only requires the public key, as expected. */ Encryptor encryptor = new Encryptor(context, publicKey); /* * Computations on the ciphertexts are performed with the Evaluator class. In * a real use-case the Evaluator would not be constructed by the same party * that holds the secret key. */ Evaluator evaluator = new Evaluator(context); /* * We will of course want to decrypt our results to verify that everything worked, * so we need to also construct an instance of Decryptor. Note that the Decryptor * requires the secret key. */ Decryptor decryptor = new Decryptor(context, secretKey); /* * As an example, we evaluate the degree 4 polynomial * * 4x^4 + 8x^3 + 8x^2 + 8x + 4 * * over an encrypted x = 6. The coefficients of the polynomial can be considered * as plaintext inputs, as we will see below. The computation is done modulo the * plain_modulus 1024. * * While this examples is simple and easy to understand, it does not have much * practical value. In later examples we will demonstrate how to compute more * efficiently on encrypted integers and real or complex numbers. * * Plaintexts in the BFV scheme are polynomials of degree less than the degree * of the polynomial modulus, and coefficients integers modulo the plaintext * modulus. For readers with background in ring theory, the plaintext space is * the polynomial quotient ring Z_T[X]/(X^N + 1), where N is PolyModulusDegree * and T is PlainModulus. * * To get started, we create a plaintext containing the constant 6. For the * plaintext element we use a constructor that takes the desired polynomial as * a string with coefficients represented as hexadecimal numbers. */ Utilities.PrintLine(); int x = 6; Plaintext xPlain = new Plaintext(x.ToString()); Console.WriteLine($"Express x = {x} as a plaintext polynomial 0x{xPlain}."); /* * We then encrypt the plaintext, producing a ciphertext. */ Utilities.PrintLine(); Ciphertext xEncrypted = new Ciphertext(); Console.WriteLine("Encrypt xPlain to xEncrypted."); encryptor.Encrypt(xPlain, xEncrypted); /* * In Microsoft SEAL, a valid ciphertext consists of two or more polynomials * whose coefficients are integers modulo the product of the primes in the * coeff_modulus. The number of polynomials in a ciphertext is called its `size' * and is given by Ciphertext.Size. A freshly encrypted ciphertext always has * size 2. */ Console.WriteLine($" + size of freshly encrypted x: {xEncrypted.Size}"); /* * There is plenty of noise budget left in this freshly encrypted ciphertext. */ Console.WriteLine(" + noise budget in freshly encrypted x: {0} bits", decryptor.InvariantNoiseBudget(xEncrypted)); /* * We decrypt the ciphertext and print the resulting plaintext in order to * demonstrate correctness of the encryption. */ Plaintext xDecrypted = new Plaintext(); Console.Write(" + decryption of encrypted_x: "); decryptor.Decrypt(xEncrypted, xDecrypted); Console.WriteLine($"0x{xDecrypted} ...... Correct."); /* * When using Microsoft SEAL, it is typically advantageous to compute in a way * that minimizes the longest chain of sequential multiplications. In other * words, encrypted computations are best evaluated in a way that minimizes * the multiplicative depth of the computation, because the total noise budget * consumption is proportional to the multiplicative depth. For example, for * our example computation it is advantageous to factorize the polynomial as * * 4x^4 + 8x^3 + 8x^2 + 8x + 4 = 4(x + 1)^2 * (x^2 + 1) * * to obtain a simple depth 2 representation. Thus, we compute (x + 1)^2 and * (x^2 + 1) separately, before multiplying them, and multiplying by 4. * * First, we compute x^2 and add a plaintext "1". We can clearly see from the * print-out that multiplication has consumed a lot of noise budget. The user * can vary the plain_modulus parameter to see its effect on the rate of noise * budget consumption. */ Utilities.PrintLine(); Console.WriteLine("Compute xSqPlusOne (x^2+1)."); Ciphertext xSqPlusOne = new Ciphertext(); evaluator.Square(xEncrypted, xSqPlusOne); Plaintext plainOne = new Plaintext("1"); evaluator.AddPlainInplace(xSqPlusOne, plainOne); /* * Encrypted multiplication results in the output ciphertext growing in size. * More precisely, if the input ciphertexts have size M and N, then the output * ciphertext after homomorphic multiplication will have size M+N-1. In this * case we perform a squaring, and observe both size growth and noise budget * consumption. */ Console.WriteLine($" + size of xSqPlusOne: {xSqPlusOne.Size}"); Console.WriteLine(" + noise budget in xSqPlusOne: {0} bits", decryptor.InvariantNoiseBudget(xSqPlusOne)); /* * Even though the size has grown, decryption works as usual as long as noise * budget has not reached 0. */ Plaintext decryptedResult = new Plaintext(); Console.Write(" + decryption of xSqPlusOne: "); decryptor.Decrypt(xSqPlusOne, decryptedResult); Console.WriteLine($"0x{decryptedResult} ...... Correct."); /* * Next, we compute (x + 1)^2. */ Utilities.PrintLine(); Console.WriteLine("Compute xPlusOneSq ((x+1)^2)."); Ciphertext xPlusOneSq = new Ciphertext(); evaluator.AddPlain(xEncrypted, plainOne, xPlusOneSq); evaluator.SquareInplace(xPlusOneSq); Console.WriteLine($" + size of xPlusOneSq: {xPlusOneSq.Size}"); Console.WriteLine(" + noise budget in xPlusOneSq: {0} bits", decryptor.InvariantNoiseBudget(xPlusOneSq)); Console.Write(" + decryption of xPlusOneSq: "); decryptor.Decrypt(xPlusOneSq, decryptedResult); Console.WriteLine($"0x{decryptedResult} ...... Correct."); /* * Finally, we multiply (x^2 + 1) * (x + 1)^2 * 4. */ Utilities.PrintLine(); Console.WriteLine("Compute encryptedResult (4(x^2+1)(x+1)^2)."); Ciphertext encryptedResult = new Ciphertext(); Plaintext plainFour = new Plaintext("4"); evaluator.MultiplyPlainInplace(xSqPlusOne, plainFour); evaluator.Multiply(xSqPlusOne, xPlusOneSq, encryptedResult); Console.WriteLine($" + size of encrypted_result: {encryptedResult.Size}"); Console.WriteLine(" + noise budget in encrypted_result: {0} bits", decryptor.InvariantNoiseBudget(encryptedResult)); Console.WriteLine("NOTE: Decryption can be incorrect if noise budget is zero."); Console.WriteLine(); Console.WriteLine("~~~~~~ A better way to calculate 4(x^2+1)(x+1)^2. ~~~~~~"); /* * Noise budget has reached 0, which means that decryption cannot be expected * to give the correct result. This is because both ciphertexts xSqPlusOne and * xPlusOneSq consist of 3 polynomials due to the previous squaring operations, * and homomorphic operations on large ciphertexts consume much more noise budget * than computations on small ciphertexts. Computing on smaller ciphertexts is * also computationally significantly cheaper. * * `Relinearization' is an operation that reduces the size of a ciphertext after * multiplication back to the initial size, 2. Thus, relinearizing one or both * input ciphertexts before the next multiplication can have a huge positive * impact on both noise growth and performance, even though relinearization has * a significant computational cost itself. It is only possible to relinearize * size 3 ciphertexts down to size 2, so often the user would want to relinearize * after each multiplication to keep the ciphertext sizes at 2. * * Relinearization requires special `relinearization keys', which can be thought * of as a kind of public key. Relinearization keys can easily be created with * the KeyGenerator. * * Relinearization is used similarly in both the BFV and the CKKS schemes, but * in this example we continue using BFV. We repeat our computation from before, * but this time relinearize after every multiplication. * * We use KeyGenerator.RelinKeys() to create relinearization keys. */ Utilities.PrintLine(); Console.WriteLine("Generate relinearization keys."); RelinKeys relinKeys = keygen.RelinKeys(); /* * We now repeat the computation relinearizing after each multiplication. */ Utilities.PrintLine(); Console.WriteLine("Compute and relinearize xSquared (x^2),"); Console.WriteLine(new string(' ', 13) + "then compute xSqPlusOne (x^2+1)"); Ciphertext xSquared = new Ciphertext(); evaluator.Square(xEncrypted, xSquared); Console.WriteLine($" + size of xSquared: {xSquared.Size}"); evaluator.RelinearizeInplace(xSquared, relinKeys); Console.WriteLine(" + size of xSquared (after relinearization): {0}", xSquared.Size); evaluator.AddPlain(xSquared, plainOne, xSqPlusOne); Console.WriteLine(" + noise budget in xSqPlusOne: {0} bits", decryptor.InvariantNoiseBudget(xSqPlusOne)); Console.Write(" + decryption of xSqPlusOne: "); decryptor.Decrypt(xSqPlusOne, decryptedResult); Console.WriteLine($"0x{decryptedResult} ...... Correct."); Utilities.PrintLine(); Ciphertext xPlusOne = new Ciphertext(); Console.WriteLine("Compute xPlusOne (x+1),"); Console.WriteLine(new string(' ', 13) + "then compute and relinearize xPlusOneSq ((x+1)^2)."); evaluator.AddPlain(xEncrypted, plainOne, xPlusOne); evaluator.Square(xPlusOne, xPlusOneSq); Console.WriteLine($" + size of xPlusOneSq: {xPlusOneSq.Size}"); evaluator.RelinearizeInplace(xPlusOneSq, relinKeys); Console.WriteLine(" + noise budget in xPlusOneSq: {0} bits", decryptor.InvariantNoiseBudget(xPlusOneSq)); Console.Write(" + decryption of xPlusOneSq: "); decryptor.Decrypt(xPlusOneSq, decryptedResult); Console.WriteLine($"0x{decryptedResult} ...... Correct."); Utilities.PrintLine(); Console.WriteLine("Compute and relinearize encryptedResult (4(x^2+1)(x+1)^2)."); evaluator.MultiplyPlainInplace(xSqPlusOne, plainFour); evaluator.Multiply(xSqPlusOne, xPlusOneSq, encryptedResult); Console.WriteLine($" + size of encryptedResult: {encryptedResult.Size}"); evaluator.RelinearizeInplace(encryptedResult, relinKeys); Console.WriteLine(" + size of encryptedResult (after relinearization): {0}", encryptedResult.Size); Console.WriteLine(" + noise budget in encryptedResult: {0} bits", decryptor.InvariantNoiseBudget(encryptedResult)); Console.WriteLine(); Console.WriteLine("NOTE: Notice the increase in remaining noise budget."); /* * Relinearization clearly improved our noise consumption. We have still plenty * of noise budget left, so we can expect the correct answer when decrypting. */ Utilities.PrintLine(); Console.WriteLine("Decrypt encrypted_result (4(x^2+1)(x+1)^2)."); decryptor.Decrypt(encryptedResult, decryptedResult); Console.WriteLine(" + decryption of 4(x^2+1)(x+1)^2 = 0x{0} ...... Correct.", decryptedResult); /* * For x=6, 4(x^2+1)(x+1)^2 = 7252. Since the plaintext modulus is set to 1024, * this result is computed in integers modulo 1024. Therefore the expected output * should be 7252 % 1024 == 84, or 0x54 in hexadecimal. */ }
public void Calculation(double step, int m, string func, TcpClient client) { Dispatcher.BeginInvoke(new ThreadStart(delegate { Canvas.Children.Clear(); AxisInit(m); })); points = new List <List <Point> >(); EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV); parms.PolyModulusDegree = 4096; parms.CoeffModulus = CoeffModulus.BFVDefault(4096); parms.PlainModulus = new Modulus(4096); SEALContext context = new SEALContext(new EncryptionParameters(parms)); KeyGenerator keygen = new KeyGenerator(context); PublicKey publicKey = keygen.PublicKey; SecretKey secretKey = keygen.SecretKey; Encryptor encryptor = new Encryptor(context, publicKey); Decryptor decryptor = new Decryptor(context, secretKey); MemoryStream streamParms = new MemoryStream(); MemoryStream streamSk = new MemoryStream(); secretKey.Save(streamSk); parms.Save(streamParms); byte[] spbuff = streamParms.GetBuffer(); client.Client.Send(spbuff); byte[] count = Encoding.ASCII.GetBytes(Convert.ToInt32(Canvas.ActualWidth + step).ToString()); client.Client.Send(count); byte[] func_buffer = Encoding.ASCII.GetBytes(func); client.Client.Send(func_buffer); byte[] offset_buffer = Encoding.ASCII.GetBytes((0).ToString()); client.Client.Send(offset_buffer); int x = -(int)Canvas.ActualWidth / 2; for (int i = 0; i <= (int)(Canvas.ActualWidth / step); i += 1) { Plaintext data = new Plaintext(); string temp = (i).ToString(); bool sign; if (x >= 0) { data = new Plaintext(x.ToString()); sign = false; } else { data = new Plaintext(Math.Abs(x).ToString()); sign = true; } Ciphertext dataEncrypted = new Ciphertext(); encryptor.Encrypt(data, dataEncrypted); byte[] sbuff; MemoryStream streamEncrypted = new MemoryStream(); dataEncrypted.Save(streamEncrypted); sbuff = streamEncrypted.GetBuffer(); client.Client.Send(sbuff); streamEncrypted.Close(); byte[] bufferRecieved = new byte[9377792 * 2]; dataEncrypted = new Ciphertext(); client.Client.Receive(bufferRecieved); MemoryStream streamRecieved = new MemoryStream(bufferRecieved); Ciphertext c = new Ciphertext(); c.Load(context, streamRecieved); dataEncrypted = c; data = new Plaintext(); decryptor.Decrypt(dataEncrypted, data); streamParms.Close(); streamSk.Close(); double f; string t = data.ToString(); f = Convert.ToInt32(data.ToString(), 16); List <Point> p = new List <Point>(); int ep = 0; Dispatcher.BeginInvoke(new ThreadStart(delegate { ep = (int)scale_bar.Maximum + 1; })); Thread.Sleep(10); if (sign) { x = -Math.Abs(x); //f = -Math.Abs(f); } for (int k = 1; k < ep; k++) { //p.Add(new Point((i - (int)Canvas.ActualWidth / 2) * k, (f + Canvas.ActualHeight / 2) * k)); p.Add(new Point((x) * k + Canvas.ActualWidth / 2, f * k + Canvas.ActualHeight / 2)); } points.Add(p); Dispatcher.BeginInvoke(new ThreadStart(delegate { if (i > 1 && points.Count > 1 && i < points.Count) { Lines(points[i - 1][(int)(scale_bar.Value - 1)], points[i][(int)(scale_bar.Value - 1)]); } })); if (x < Canvas.ActualWidth / 2) { x += (int)step; } } client.Client.Disconnect(true); ///// ///// ///// //for (int i = 0; i < points.Count - 1; i++) //{ // Lines(points[i][(int)(scale_bar.Value - 1)], points[i + 1][(int)(scale_bar.Value - 1)]); //} ///// ///// ///// }
static void Main(string[] args) { EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV); parms.PolyModulusDegree = 4096; parms.CoeffModulus = CoeffModulus.BFVDefault(4096); parms.PlainModulus = new Modulus(4096 * 2); SEALContext context = new SEALContext(new EncryptionParameters(parms)); Console.WriteLine(context.ParameterErrorMessage()); KeyGenerator keygen = new KeyGenerator(context); PublicKey publicKey = new PublicKey(keygen.PublicKey); SecretKey secretKey = new SecretKey(keygen.SecretKey); Encryptor encryptor = new Encryptor(context, publicKey); Evaluator evaluator = new Evaluator(context); Decryptor decryptor = new Decryptor(context, secretKey); Console.WriteLine("Generate locally usable relinearization keys."); using RelinKeys relinKeys = keygen.RelinKeysLocal(); int x = 6; using Plaintext xPlain = new Plaintext(x.ToString()); using Ciphertext xEncrypted = new Ciphertext(); encryptor.Encrypt(xPlain, xEncrypted); using Ciphertext xSqPlusOne = new Ciphertext(); using Plaintext decryptedResult = new Plaintext(); using Ciphertext xPlusOneSq = new Ciphertext(); using Ciphertext encryptedResult = new Ciphertext(); using Plaintext plainOne = new Plaintext("1"); using Plaintext plainFour = new Plaintext("4"); /* * We now repeat the computation relinearizing after each multiplication. */ Console.WriteLine("Compute and relinearize xSquared (x^2),"); Console.WriteLine(new string(' ', 13) + "then compute xSqPlusOne (x^2+1)"); using Ciphertext xSquared = new Ciphertext(); evaluator.Square(xEncrypted, xSquared); Console.WriteLine($" + size of xSquared: {xSquared.Size}"); evaluator.RelinearizeInplace(xSquared, relinKeys); Console.WriteLine(" + size of xSquared (after relinearization): {0}", xSquared.Size); evaluator.AddPlain(xSquared, plainOne, xSqPlusOne); Console.WriteLine(" + noise budget in xSqPlusOne: {0} bits", decryptor.InvariantNoiseBudget(xSqPlusOne)); Console.Write(" + decryption of xSqPlusOne: "); decryptor.Decrypt(xSqPlusOne, decryptedResult); int q = Convert.ToInt32(decryptedResult.ToString(), 16); Console.WriteLine($"{q} ...... Correct."); //Console.WriteLine($"0x{decryptedResult} ...... Correct."); using Ciphertext xPlusOne = new Ciphertext(); Console.WriteLine("Compute xPlusOne (x+1),"); Console.WriteLine(new string(' ', 13) + "then compute and relinearize xPlusOneSq ((x+1)^2)."); evaluator.AddPlain(xEncrypted, plainOne, xPlusOne); evaluator.Square(xPlusOne, xPlusOneSq); Console.WriteLine($" + size of xPlusOneSq: {xPlusOneSq.Size}"); evaluator.RelinearizeInplace(xPlusOneSq, relinKeys); Console.WriteLine(" + noise budget in xPlusOneSq: {0} bits", decryptor.InvariantNoiseBudget(xPlusOneSq)); Console.Write(" + decryption of xPlusOneSq: "); decryptor.Decrypt(xPlusOneSq, decryptedResult); int r = Convert.ToInt32(decryptedResult.ToString(), 16); Console.WriteLine($"{r} ...... Correct."); Console.WriteLine("Compute and relinearize encryptedResult (4(x^2+1)(x+1)^2)."); evaluator.MultiplyPlainInplace(xSqPlusOne, plainFour); evaluator.Multiply(xSqPlusOne, xPlusOneSq, encryptedResult); Console.WriteLine($" + size of encryptedResult: {encryptedResult.Size}"); evaluator.RelinearizeInplace(encryptedResult, relinKeys); Console.WriteLine(" + size of encryptedResult (after relinearization): {0}", encryptedResult.Size); Console.WriteLine(" + noise budget in encryptedResult: {0} bits", decryptor.InvariantNoiseBudget(encryptedResult)); Console.WriteLine(); Console.WriteLine("NOTE: Notice the increase in remaining noise budget."); /* * Relinearization clearly improved our noise consumption. We have still plenty * of noise budget left, so we can expect the correct answer when decrypting. */ Console.WriteLine("Decrypt encrypted_result (4(x^2+1)(x+1)^2)."); decryptor.Decrypt(encryptedResult, decryptedResult); int t = Convert.ToInt32(decryptedResult.ToString(), 16); Console.WriteLine(" + decryption of 4(x^2+1)(x+1)^2 = 0x{0} ...... Correct.", t); Plaintext four = new Plaintext("4"); Plaintext four1 = new Plaintext("5"); Ciphertext fourEncrypted = new Ciphertext(); Ciphertext four1Encrypted = new Ciphertext(); encryptor.Encrypt(four, fourEncrypted); encryptor.Encrypt(four1, four1Encrypted); Ciphertext d = new Ciphertext(); evaluator.Sub(fourEncrypted, four1Encrypted, d); Plaintext temp = new Plaintext(); decryptor.Decrypt(d, temp); Console.WriteLine($"{Convert.ToInt32(temp.ToString(), 16)}"); }
public void calculateDistance(string encryptedRiderXFile, string encryptedRiderYFile, string encryptedDriverXFile, string encryptedDriverYFile, string distanceFile) { using EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV); ulong polyModulusDegree = 4096; parms.PolyModulusDegree = polyModulusDegree; parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree); parms.PlainModulus = new Modulus(1024); using SEALContext context = new SEALContext(parms); using KeyGenerator keygen = new KeyGenerator(context); using PublicKey riderPub = new PublicKey(); using Ciphertext xRiderEncrypted = new Ciphertext(); using (var sr = new StreamReader(encryptedRiderXFile)) { xRiderEncrypted.Load(context, sr.BaseStream); } using Ciphertext yRiderEncrypted = new Ciphertext(); using (var sr = new StreamReader(encryptedRiderYFile)) { yRiderEncrypted.Load(context, sr.BaseStream); } using Ciphertext xDriverEncrypted = new Ciphertext(); using (var sr = new StreamReader(encryptedDriverXFile)) { xDriverEncrypted.Load(context, sr.BaseStream); } using Ciphertext yDriverEncrypted = new Ciphertext(); using (var sr = new StreamReader(encryptedDriverYFile)) { yDriverEncrypted.Load(context, sr.BaseStream); } //Console.WriteLine("Calculate ( (x2-x1)^2 + (y2-y1)^2 )"); using Evaluator evaluator = new Evaluator(context); using IntegerEncoder encoder = new IntegerEncoder(context); using RelinKeys relinKeys = keygen.RelinKeysLocal(); using Ciphertext X2MinusX1 = new Ciphertext(); evaluator.Sub(xDriverEncrypted, xRiderEncrypted, X2MinusX1); // (x2-x1) using Ciphertext Y2MinusY1 = new Ciphertext(); evaluator.Sub(yDriverEncrypted, yRiderEncrypted, Y2MinusY1); // (y2-y1) using Ciphertext X2MinusX1Squared = new Ciphertext(); evaluator.Square(X2MinusX1, X2MinusX1Squared); // (x2-x1)^2 //evaluator.RelinearizeInplace(X2MinusX1Squared, relinKeys); using Ciphertext Y2MinusY1Squared = new Ciphertext(); evaluator.Square(Y2MinusY1, Y2MinusY1Squared); // (x2-x1)^2 //evaluator.RelinearizeInplace(Y2MinusY1Squared, relinKeys); using Ciphertext X2MinusX1SquaredPlusY2MinusY1Squared = new Ciphertext(); evaluator.Add(X2MinusX1Squared, Y2MinusY1Squared, X2MinusX1SquaredPlusY2MinusY1Squared); // (x2-x1)^2 + (y2-y1)^2 // using Ciphertext SquareRootOfX2MinusX1SquaredPlusY2MinusY1Squared = new Ciphertext(); // decimal vIn = 0.5M; // ulong vOut = Convert.ToUInt64(vIn); // evaluator.Exponentiate(X2MinusX1SquaredPlusY2MinusY1Squared, vOut,relinKeys,SquareRootOfX2MinusX1SquaredPlusY2MinusY1Squared); var fileStream = File.Create(distanceFile); X2MinusX1SquaredPlusY2MinusY1Squared.Save(fileStream); fileStream.Close(); }
public static List <int> Run(ulong polyModulusDegree, ulong plainModulus, int[] xs, int[] ys) { // for communication between client and server var parmsStream = new MemoryStream(); var relinKeysStream = new MemoryStream(); var dataStream = new MemoryStream(); var resultsStream = new MemoryStream(); // for client's internal use var secretKeyStream = new MemoryStream(); { /* * Client */ Console.WriteLine($"<Client> Client has {xs.Length} elements: [{string.Join(", ", xs)}]."); using var parms = new EncryptionParameters(SchemeType.BFV) { PolyModulusDegree = polyModulusDegree, CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree), PlainModulus = new Modulus(plainModulus) }; using var context = new SEALContext(parms); using var keygen = new KeyGenerator(context); using var secretKey = keygen.SecretKey; keygen.CreatePublicKey(out var publicKey); keygen.CreateRelinKeys(out var relinKeys); var writer = new BinaryWriter(dataStream); writer.Write((int)xs.Length); using var encryptor = new Encryptor(context, publicKey); for (int i = 0; i < xs.Length; i++) { using var xPlain = new Plaintext(xs[i].ToString("X")); encryptor.Encrypt(xPlain).Save(dataStream); } dataStream.Seek(0, SeekOrigin.Begin); parms.Save(parmsStream); parmsStream.Seek(0, SeekOrigin.Begin); relinKeys.Save(relinKeysStream); relinKeysStream.Seek(0, SeekOrigin.Begin); secretKey.Save(secretKeyStream); secretKeyStream.Seek(0, SeekOrigin.Begin); Console.WriteLine("----------------------"); } { /* * Server */ Console.WriteLine($"<Server> Server has {ys.Length} elements: [{string.Join(", ", ys)}]."); using var parms = new EncryptionParameters(); parms.Load(parmsStream); parmsStream.Seek(0, SeekOrigin.Begin); var plainModulusValue = (int)parms.PlainModulus.Value; using var context = new SEALContext(parms); using var evaluator = new Evaluator(context); using var relinKeys = new RelinKeys(); relinKeys.Load(context, relinKeysStream); var ysPlain = new Plaintext[ys.Length]; for (int j = 0; j < ys.Length; j++) { ysPlain[j] = new Plaintext(ys[j].ToString("X")); } var reader = new BinaryReader(dataStream); int dataSize = reader.ReadInt32(); var writer = new BinaryWriter(resultsStream); writer.Write((int)dataSize); var rnd = new Random(); for (int i = 0; i < dataSize; i++) { using var xEncrypted = new Ciphertext(); xEncrypted.Load(context, dataStream); var tmpEncrypted = new Ciphertext[ys.Length]; for (int j = 0; j < ys.Length; j++) { tmpEncrypted[j] = new Ciphertext(); evaluator.SubPlain(xEncrypted, ysPlain[j], tmpEncrypted[j]); } using var plainRandomText = new Plaintext(rnd.Next(1, plainModulusValue).ToString("X")); using var resultEncrypted = new Ciphertext(); evaluator.MultiplyMany(tmpEncrypted, relinKeys, resultEncrypted); evaluator.MultiplyPlainInplace(resultEncrypted, plainRandomText); resultEncrypted.Save(resultsStream); } resultsStream.Seek(0, SeekOrigin.Begin); Console.WriteLine("----------------------"); } { /* * Client */ using var parms = new EncryptionParameters(); parms.Load(parmsStream); using var context = new SEALContext(parms); using var secretKey = new SecretKey(); secretKey.Load(context, secretKeyStream); using var decryptor = new Decryptor(context, secretKey); var reader = new BinaryReader(resultsStream); int resultsSize = reader.ReadInt32(); List <int> intersection = new List <int>(); for (int i = 0; i < resultsSize; i++) { using var resultEncrypted = new Ciphertext(); resultEncrypted.Load(context, resultsStream); var noiseBudget = decryptor.InvariantNoiseBudget(resultEncrypted); if (noiseBudget > 0) { Console.WriteLine($"Noise: {noiseBudget} bits"); using var result = new Plaintext(); decryptor.Decrypt(resultEncrypted, result); if (result.IsZero == true) { intersection.Add(xs[i]); } } else { Console.WriteLine("Ciphertext has too much noise."); } } Console.WriteLine($"<Client> Intersection contains {intersection.Count} elements: [{string.Join(", ", intersection)}]"); Console.WriteLine("----------------------"); return(intersection); } }
/* * Both the BFV scheme (with BatchEncoder) as well as the CKKS scheme support native * vectorized computations on encrypted numbers. In addition to computing slot-wise, * it is possible to rotate the encrypted vectors cyclically. */ private static void ExampleRotationBFV() { Utilities.PrintExampleBanner("Example: Rotation / Rotation in BFV"); using EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV); ulong polyModulusDegree = 8192; parms.PolyModulusDegree = polyModulusDegree; parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree); parms.PlainModulus = PlainModulus.Batching(polyModulusDegree, 20); using SEALContext context = new SEALContext(parms); Utilities.PrintParameters(context); Console.WriteLine(); using KeyGenerator keygen = new KeyGenerator(context); using SecretKey secretKey = keygen.SecretKey; keygen.CreatePublicKey(out PublicKey publicKey); keygen.CreateRelinKeys(out RelinKeys relinKeys); using Encryptor encryptor = new Encryptor(context, publicKey); using Evaluator evaluator = new Evaluator(context); using Decryptor decryptor = new Decryptor(context, secretKey); using BatchEncoder batchEncoder = new BatchEncoder(context); ulong slotCount = batchEncoder.SlotCount; ulong rowSize = slotCount / 2; Console.WriteLine($"Plaintext matrix row size: {rowSize}"); ulong[] podMatrix = new ulong[slotCount]; podMatrix[0] = 0; podMatrix[1] = 1; podMatrix[2] = 2; podMatrix[3] = 3; podMatrix[rowSize] = 4; podMatrix[rowSize + 1] = 5; podMatrix[rowSize + 2] = 6; podMatrix[rowSize + 3] = 7; Console.WriteLine("Input plaintext matrix:"); Utilities.PrintMatrix(podMatrix, (int)rowSize); Console.WriteLine(); /* * First we use BatchEncoder to encode the matrix into a plaintext. We encrypt * the plaintext as usual. */ Utilities.PrintLine(); using Plaintext plainMatrix = new Plaintext(); Console.WriteLine("Encode and encrypt."); batchEncoder.Encode(podMatrix, plainMatrix); using Ciphertext encryptedMatrix = new Ciphertext(); encryptor.Encrypt(plainMatrix, encryptedMatrix); Console.WriteLine(" + Noise budget in fresh encryption: {0} bits", decryptor.InvariantNoiseBudget(encryptedMatrix)); Console.WriteLine(); /* * Rotations require yet another type of special key called `Galois keys'. These * are easily obtained from the KeyGenerator. */ keygen.CreateGaloisKeys(out GaloisKeys galoisKeys); /* * Now rotate both matrix rows 3 steps to the left, decrypt, decode, and print. */ Utilities.PrintLine(); Console.WriteLine("Rotate rows 3 steps left."); evaluator.RotateRowsInplace(encryptedMatrix, 3, galoisKeys); using Plaintext plainResult = new Plaintext(); Console.WriteLine(" + Noise budget after rotation: {0} bits", decryptor.InvariantNoiseBudget(encryptedMatrix)); Console.WriteLine(" + Decrypt and decode ...... Correct."); decryptor.Decrypt(encryptedMatrix, plainResult); List <ulong> podResult = new List <ulong>(); batchEncoder.Decode(plainResult, podResult); Utilities.PrintMatrix(podResult, (int)rowSize); /* * We can also rotate the columns, i.e., swap the rows. */ Utilities.PrintLine(); Console.WriteLine("Rotate columns."); evaluator.RotateColumnsInplace(encryptedMatrix, galoisKeys); Console.WriteLine(" + Noise budget after rotation: {0} bits", decryptor.InvariantNoiseBudget(encryptedMatrix)); Console.WriteLine(" + Decrypt and decode ...... Correct."); decryptor.Decrypt(encryptedMatrix, plainResult); batchEncoder.Decode(plainResult, podResult); Utilities.PrintMatrix(podResult, (int)rowSize); /* * Finally, we rotate the rows 4 steps to the right, decrypt, decode, and print. */ Utilities.PrintLine(); Console.WriteLine("Rotate rows 4 steps right."); evaluator.RotateRowsInplace(encryptedMatrix, -4, galoisKeys); Console.WriteLine(" + Noise budget after rotation: {0} bits", decryptor.InvariantNoiseBudget(encryptedMatrix)); Console.WriteLine(" + Decrypt and decode ...... Correct."); decryptor.Decrypt(encryptedMatrix, plainResult); batchEncoder.Decode(plainResult, podResult); Utilities.PrintMatrix(podResult, (int)rowSize); /* * Note that rotations do not consume any noise budget. However, this is only * the case when the special prime is at least as large as the other primes. The * same holds for relinearization. Microsoft SEAL does not require that the * special prime is of any particular size, so ensuring this is the case is left * for the user to do. */ }