public void SetConstants() { FiveMinuteBreak = new Plaintext(); encoder.Encode(5.0, scale, FiveMinuteBreak); DivideByFive = new Plaintext(); encoder.Encode(0.20, scale, DivideByFive); }
public ImageProcessorServer( Evaluator evaluator, CKKSEncoder encoder, double scale) { _evaluator = evaluator ?? throw new ArgumentNullException(nameof(evaluator)); encoder.Encode(0.3, scale, RMultiplePtx); encoder.Encode(0.59, scale, GMultiplePtx); encoder.Encode(0.11, scale, BMultiplePtx); }
public void EncodeDecodeComplexTest() { EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS) { PolyModulusDegree = 64, CoeffModulus = CoeffModulus.Create(64, new int[] { 40, 40, 40, 40 }) }; SEALContext context = new SEALContext(parms, expandModChain: false, secLevel: SecLevelType.None); CKKSEncoder encoder = new CKKSEncoder(context); Plaintext plain = new Plaintext(); Complex value = new Complex(3.1415, 2.71828); encoder.Encode(value, scale: Math.Pow(2, 20), destination: plain); List <Complex> result = new List <Complex>(); encoder.Decode(plain, result); Assert.IsTrue(result.Count > 0); Assert.AreEqual(3.1415, result[0].Real, delta: 0.0001); Assert.AreEqual(2.71828, result[0].Imaginary, delta: 0.0001); }
public void EncodeDecodeUlongTest() { int slots = 32; EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS); parms.PolyModulusDegree = (ulong)slots * 2; parms.CoeffModulus = CoeffModulus.Create(64, new int[] { 40, 40, 40, 40 }); SEALContext context = new SEALContext(parms, expandModChain: false, secLevel: SecLevelType.None); CKKSEncoder encoder = new CKKSEncoder(context); Plaintext plain = new Plaintext(); List <Complex> result = new List <Complex>(); long value = 15; encoder.Encode(value, plain); encoder.Decode(plain, result); for (int i = 0; i < slots; i++) { double tmp = Math.Abs(value - result[i].Real); Assert.IsTrue(tmp < 0.5); } }
public void EncodeDecodeDoubleTest() { EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS); parms.PolyModulusDegree = 64; parms.CoeffModulus = CoeffModulus.Create(64, new int[] { 40, 40, 40, 40 }); SEALContext context = new SEALContext(parms, expandModChain: false, secLevel: SecLevelType.None); int slots = 16; Plaintext plain = new Plaintext(); double delta = 1 << 16; List <Complex> result = new List <Complex>(); CKKSEncoder encoder = new CKKSEncoder(context); Assert.AreEqual(32ul, encoder.SlotCount); double value = 10d; encoder.Encode(value, delta, plain); encoder.Decode(plain, result); for (int i = 0; i < slots; i++) { double tmp = Math.Abs(value - result[i].Real); Assert.IsTrue(tmp < 0.5); } }
public void EncodeDecodeVectorDoubleTest() { EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS) { PolyModulusDegree = 64, CoeffModulus = CoeffModulus.Create(64, new int[] { 30, 30 }) }; SEALContext context = new SEALContext(parms, expandModChain: false, secLevel: SecLevelType.None); CKKSEncoder encoder = new CKKSEncoder(context); Plaintext plain = new Plaintext(); double[] values = new double[] { 0.1, 2.3, 34.4 }; encoder.Encode(values, scale: Math.Pow(2, 20), destination: plain); List <double> result = new List <double>(); encoder.Decode(plain, result); Assert.IsNotNull(result); Assert.AreEqual(0.1, result[0], delta: 0.001); Assert.AreEqual(2.3, result[1], delta: 0.001); Assert.AreEqual(34.4, result[2], delta: 0.001); }
// private static void SinglePredict(Svc secureSvc, double[] feature, int i, CKKSEncoder encoder, Encryptor encryptor, Decryptor decryptor, Stopwatch innerProductStopwatch, Stopwatch degreeStopwatch, Stopwatch negateStopwatch, Stopwatch serverDecisionStopWatch, double scale, Result[] results) { double finalResult = 0; Console.WriteLine($"start {i} \n"); var plaintexts = new Plaintext(); var featuresCiphertexts = new Ciphertext(); encoder.Encode(feature, scale, plaintexts); encryptor.Encrypt(plaintexts, featuresCiphertexts); // Server side start var cyphetResult = secureSvc.Predict(featuresCiphertexts, true, true, innerProductStopwatch, degreeStopwatch, negateStopwatch, serverDecisionStopWatch); // Server side end //timePredictSum.Stop(); Plaintext plainResult = new Plaintext(); decryptor.Decrypt(cyphetResult, plainResult); List <double> result = new List <double>(); encoder.Decode(plainResult, result); finalResult = result[0]; int estimation = finalResult > 0 ? 0 : 1; Console.WriteLine($"\n ************************************************"); Console.WriteLine($"SVC estimation{i} is : {estimation} , result : {finalResult}"); //file.WriteLine($"{i} , {estimation} , {finalResult} "); Console.WriteLine($"************************************************ \n"); results[i] = new Result(finalResult, estimation); //Console.WriteLine($"SecureSVC estimation{i} is : {estimation} , finalResult = {finalResult} , Time = {timePredictSum.ElapsedMilliseconds}"); }
private void SetConstants() { //Encodes negative six and stores in variable negativeSix. negativeSix = new Plaintext(); encoder.Encode(-6, scale, negativeSix); }
public void SetConstants() { // Encode the constant 1/52 and store in DivideByFiftyTwo. DivideByFiftyTwo = new Plaintext(); encoder.Encode(0.01923076, scale, DivideByFiftyTwo); }
public void EncodeDecodeComplexTest() { EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS) { PolyModulusDegree = 64, CoeffModulus = new List <SmallModulus>() { DefaultParams.SmallMods40Bit(0), DefaultParams.SmallMods40Bit(1), DefaultParams.SmallMods40Bit(2), DefaultParams.SmallMods40Bit(3) } }; SEALContext context = SEALContext.Create(parms); CKKSEncoder encoder = new CKKSEncoder(context); Plaintext plain = new Plaintext(); Complex value = new Complex(3.1415, 2.71828); encoder.Encode(value, scale: Math.Pow(2, 20), destination: plain); List <Complex> result = new List <Complex>(); encoder.Decode(plain, result); Assert.IsTrue(result.Count > 0); Assert.AreEqual(3.1415, result[0].Real, delta: 0.0001); Assert.AreEqual(2.71828, result[0].Imaginary, delta: 0.0001); }
public void EncodeDecodeUlongTest() { int slots = 32; EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS); parms.PolyModulusDegree = (ulong)slots * 2; List <SmallModulus> coeffModulus = new List <SmallModulus>(4); coeffModulus.Add(DefaultParams.SmallMods40Bit(0)); coeffModulus.Add(DefaultParams.SmallMods40Bit(1)); coeffModulus.Add(DefaultParams.SmallMods40Bit(2)); coeffModulus.Add(DefaultParams.SmallMods40Bit(3)); parms.CoeffModulus = coeffModulus; SEALContext context = SEALContext.Create(parms); CKKSEncoder encoder = new CKKSEncoder(context); Plaintext plain = new Plaintext(); List <Complex> result = new List <Complex>(); long value = 15; encoder.Encode(value, plain); encoder.Decode(plain, result); for (int i = 0; i < slots; i++) { double tmp = Math.Abs(value - result[i].Real); Assert.IsTrue(tmp < 0.5); } }
public void EncodeDecodeVectorDoubleTest() { EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS) { PolyModulusDegree = 64, CoeffModulus = new List <SmallModulus>() { DefaultParams.SmallMods30Bit(0), DefaultParams.SmallMods30Bit(1) } }; SEALContext context = SEALContext.Create(parms); CKKSEncoder encoder = new CKKSEncoder(context); Plaintext plain = new Plaintext(); double[] values = new double[] { 0.1, 2.3, 34.4 }; encoder.Encode(values, scale: Math.Pow(2, 20), destination: plain); List <double> result = new List <double>(); encoder.Decode(plain, result); Assert.IsNotNull(result); Assert.AreEqual(0.1, result[0], delta: 0.001); Assert.AreEqual(2.3, result[1], delta: 0.001); Assert.AreEqual(34.4, result[2], delta: 0.001); }
public void EncodeDecodeDoubleTest() { EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS); parms.PolyModulusDegree = 64; List <SmallModulus> coeffModulus = new List <SmallModulus>(4); coeffModulus.Add(DefaultParams.SmallMods40Bit(0)); coeffModulus.Add(DefaultParams.SmallMods40Bit(1)); coeffModulus.Add(DefaultParams.SmallMods40Bit(2)); coeffModulus.Add(DefaultParams.SmallMods40Bit(3)); parms.CoeffModulus = coeffModulus; SEALContext context = SEALContext.Create(parms); int slots = 16; Plaintext plain = new Plaintext(); double delta = 1 << 16; List <Complex> result = new List <Complex>(); CKKSEncoder encoder = new CKKSEncoder(context); Assert.AreEqual(32ul, encoder.SlotCount); double value = 10d; encoder.Encode(value, delta, plain); encoder.Decode(plain, result); for (int i = 0; i < slots; i++) { double tmp = Math.Abs(value - result[i].Real); Assert.IsTrue(tmp < 0.5); } }
public static List <Ciphertext> Encrypt( this byte[] data, CKKSEncoder encoder, Encryptor encryptor, double scale, int slots) { return(ComputeInBatches( data, slots, bytes => { using var pt = new Plaintext(); encoder.Encode( bytes.Select(d => Convert.ToDouble(d)), scale, pt); var ct = new Ciphertext(); encryptor.Encrypt(pt, ct); return ct; })); }
public void ScaleTest() { EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS) { PolyModulusDegree = 8, CoeffModulus = CoeffModulus.Create(8, new int[] { 40, 40, 40, 40 }) }; SEALContext context = new SEALContext(parms, expandModChain: true, secLevel: SecLevelType.None); KeyGenerator keygen = new KeyGenerator(context); keygen.CreatePublicKey(out PublicKey publicKey); keygen.CreateGaloisKeys(out GaloisKeys galoisKeys); Encryptor encryptor = new Encryptor(context, publicKey); Evaluator evaluator = new Evaluator(context); CKKSEncoder encoder = new CKKSEncoder(context); MemoryPoolHandle pool = MemoryManager.GetPool(MMProfOpt.ForceNew); Assert.AreEqual(0ul, pool.AllocByteCount); Ciphertext encrypted = new Ciphertext(pool); Plaintext plain = new Plaintext(); MemoryPoolHandle cipherPool = encrypted.Pool; Assert.IsNotNull(cipherPool); Assert.AreEqual(0ul, cipherPool.AllocByteCount); List <Complex> input = new List <Complex>() { new Complex(1, 1), new Complex(2, 2), new Complex(3, 3), new Complex(4, 4) }; double delta = Math.Pow(2, 70); encoder.Encode(input, context.FirstParmsId, delta, plain); encryptor.Encrypt(plain, encrypted); Assert.AreEqual(delta, encrypted.Scale, delta: Math.Pow(2, 60)); Ciphertext encrypted2 = new Ciphertext(); encrypted2.Set(encrypted); Assert.AreEqual(delta, encrypted2.Scale, delta: Math.Pow(2, 60)); evaluator.RescaleToNextInplace(encrypted); Assert.AreEqual(Math.Pow(2, 30), encrypted.Scale, delta: 10000); Assert.AreNotEqual(0ul, cipherPool.AllocByteCount); double newScale = Math.Pow(2, 10); encrypted.Scale = newScale; Assert.AreEqual(newScale, encrypted.Scale, delta: 100); }
public void SetConstants() { //Find out if the correct number of hours have been slept negativeEight = new Plaintext(); //Encode negative 8 using the CKKS scheme. encoder.Encode(-8, scale, negativeEight); }
public Ciphertext EncryptLong(long input) { //Takes in a input of type long and returns a Ciphertext. Plaintext encoded = new Plaintext(); Ciphertext encrypted = new Ciphertext(); encoder.Encode(input, scale, encoded); encryptor.Encrypt(encoded, encrypted); return(encrypted); }
public static Ciphertext Encrypt( this byte data, CKKSEncoder encoder, Encryptor encryptor, double scale) { using var pt = new Plaintext(); encoder.Encode(Convert.ToDouble(data), scale, pt); var ct = new Ciphertext(); encryptor.Encrypt(pt, ct); return(ct); }
public static Plaintext[][][] GetWeightsPlaintext(CKKSEncoder encoder, double scale, double[][][] weights) { Plaintext[][][] toReturn = new Plaintext[weights.Length][][]; for (int i = 0; i < weights.Length; i++) { Plaintext[][] layerWeightsPlaintext = new Plaintext[weights[i].Length][]; for (int j = 0; j < weights[i].Length; j++) { Plaintext[] layerNodeWeightsPlaintext = new Plaintext[weights[i][j].Length]; for (int k = 0; k < weights[i][j].Length; k++) { Plaintext weightPT = new Plaintext(); encoder.Encode(weights[i][j][k], scale, weightPT); layerNodeWeightsPlaintext[k] = weightPT; } layerWeightsPlaintext[j] = layerNodeWeightsPlaintext; } toReturn[i] = layerWeightsPlaintext; } return(toReturn); }
public void EncodeDecodeVectorTest() { int slots = 32; EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS); parms.PolyModulusDegree = (ulong)slots * 2; List <SmallModulus> coeffModulus = new List <SmallModulus>(4); coeffModulus.Add(DefaultParams.SmallMods60Bit(0)); coeffModulus.Add(DefaultParams.SmallMods60Bit(1)); coeffModulus.Add(DefaultParams.SmallMods60Bit(2)); coeffModulus.Add(DefaultParams.SmallMods60Bit(3)); parms.CoeffModulus = coeffModulus; SEALContext context = SEALContext.Create(parms); CKKSEncoder encoder = new CKKSEncoder(context); List <Complex> values = new List <Complex>(slots); Random rnd = new Random(); int dataBound = 1 << 30; double delta = 1ul << 40; for (int i = 0; i < slots; i++) { values.Add(new Complex(rnd.Next() % dataBound, 0)); } Plaintext plain = new Plaintext(); encoder.Encode(values, delta, plain); List <Complex> result = new List <Complex>(); encoder.Decode(plain, result); for (int i = 0; i < slots; i++) { double tmp = Math.Abs(values[i].Real - result[i].Real); Assert.IsTrue(tmp < 0.5); } }
public void EncodeDecodeVectorTest() { int slots = 32; EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS); parms.PolyModulusDegree = (ulong)slots * 2; parms.CoeffModulus = CoeffModulus.Create((ulong)slots * 2, new int[] { 60, 60, 60, 60 }); SEALContext context = new SEALContext(parms, expandModChain: false, secLevel: SecLevelType.None); CKKSEncoder encoder = new CKKSEncoder(context); List <Complex> values = new List <Complex>(slots); Random rnd = new Random(); int dataBound = 1 << 30; double delta = 1ul << 40; for (int i = 0; i < slots; i++) { values.Add(new Complex(rnd.Next() % dataBound, 0)); } Plaintext plain = new Plaintext(); encoder.Encode(values, delta, plain); List <Complex> result = new List <Complex>(); encoder.Decode(plain, result); for (int i = 0; i < slots; i++) { double tmp = Math.Abs(values[i].Real - result[i].Real); Assert.IsTrue(tmp < 0.5); } }
static private void ExampleCKKSEncoder() { Utilities.PrintExampleBanner("Example: Encoders / CKKS Encoder"); /* * [CKKSEncoder] (For CKKS scheme only) * * In this example we demonstrate the Cheon-Kim-Kim-Song (CKKS) scheme for * computing on encrypted real or complex numbers. We start by creating * encryption parameters for the CKKS scheme. There are two important * differences compared to the BFV scheme: * * (1) CKKS does not use the PlainModulus encryption parameter; * (2) Selecting the CoeffModulus in a specific way can be very important * when using the CKKS scheme. We will explain this further in the file * `CKKS_Basics.cs'. In this example we use CoeffModulus.Create to * generate 5 40-bit prime numbers. */ using EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS); ulong polyModulusDegree = 8192; parms.PolyModulusDegree = polyModulusDegree; parms.CoeffModulus = CoeffModulus.Create( polyModulusDegree, new int[] { 40, 40, 40, 40, 40 }); /* * We create the SEALContext as usual and print the parameters. */ using SEALContext context = new SEALContext(parms); Utilities.PrintParameters(context); Console.WriteLine(); /* * Keys are created the same way as for the BFV scheme. */ using KeyGenerator keygen = new KeyGenerator(context); using SecretKey secretKey = keygen.SecretKey; keygen.CreatePublicKey(out PublicKey publicKey); keygen.CreateRelinKeys(out RelinKeys relinKeys); /* * We also set up an Encryptor, Evaluator, and Decryptor as usual. */ using Encryptor encryptor = new Encryptor(context, publicKey); using Evaluator evaluator = new Evaluator(context); using Decryptor decryptor = new Decryptor(context, secretKey); /* * To create CKKS plaintexts we need a special encoder: there is no other way * to create them. The BatchEncoder cannot be used with the * CKKS scheme. The CKKSEncoder encodes vectors of real or complex numbers into * Plaintext objects, which can subsequently be encrypted. At a high level this * looks a lot like what BatchEncoder does for the BFV scheme, but the theory * behind it is completely different. */ using CKKSEncoder encoder = new CKKSEncoder(context); /* * In CKKS the number of slots is PolyModulusDegree / 2 and each slot encodes * one real or complex number. This should be contrasted with BatchEncoder in * the BFV scheme, where the number of slots is equal to PolyModulusDegree * and they are arranged into a matrix with two rows. */ ulong slotCount = encoder.SlotCount; Console.WriteLine($"Number of slots: {slotCount}"); /* * We create a small vector to encode; the CKKSEncoder will implicitly pad it * with zeros to full size (PolyModulusDegree / 2) when encoding. */ double[] input = new double[] { 0.0, 1.1, 2.2, 3.3 }; Console.WriteLine("Input vector: "); Utilities.PrintVector(input); /* * Now we encode it with CKKSEncoder. The floating-point coefficients of `input' * will be scaled up by the parameter `scale'. This is necessary since even in * the CKKS scheme the plaintext elements are fundamentally polynomials with * integer coefficients. It is instructive to think of the scale as determining * the bit-precision of the encoding; naturally it will affect the precision of * the result. * * In CKKS the message is stored modulo CoeffModulus (in BFV it is stored modulo * PlainModulus), so the scaled message must not get too close to the total size * of CoeffModulus. In this case our CoeffModulus is quite large (200 bits) so * we have little to worry about in this regard. For this simple example a 30-bit * scale is more than enough. */ using Plaintext plain = new Plaintext(); double scale = Math.Pow(2.0, 30); Utilities.PrintLine(); Console.WriteLine("Encode input vector."); encoder.Encode(input, scale, plain); /* * We can instantly decode to check the correctness of encoding. */ List <double> output = new List <double>(); Console.WriteLine(" + Decode input vector ...... Correct."); encoder.Decode(plain, output); Utilities.PrintVector(output); /* * The vector is encrypted the same was as in BFV. */ using Ciphertext encrypted = new Ciphertext(); Utilities.PrintLine(); Console.WriteLine("Encrypt input vector, square, and relinearize."); encryptor.Encrypt(plain, encrypted); /* * Basic operations on the ciphertexts are still easy to do. Here we square * the ciphertext, decrypt, decode, and print the result. We note also that * decoding returns a vector of full size (PolyModulusDegree / 2); this is * because of the implicit zero-padding mentioned above. */ evaluator.SquareInplace(encrypted); evaluator.RelinearizeInplace(encrypted, relinKeys); /* * We notice that the scale in the result has increased. In fact, it is now * the square of the original scale: 2^60. */ Console.WriteLine(" + Scale in squared input: {0} ({1} bits)", encrypted.Scale, (int)Math.Ceiling(Math.Log(encrypted.Scale, newBase: 2))); Utilities.PrintLine(); Console.WriteLine("Decrypt and decode."); decryptor.Decrypt(encrypted, plain); encoder.Decode(plain, output); Console.WriteLine(" + Result vector ...... Correct."); Utilities.PrintVector(output); /* * The CKKS scheme allows the scale to be reduced between encrypted computations. * This is a fundamental and critical feature that makes CKKS very powerful and * flexible. We will discuss it in great detail in `3_Levels.cs' and later in * `4_CKKS_Basics.cs'. */ }
private static void CKKSPerformanceTest(SEALContext context) { Stopwatch timer; Utilities.PrintParameters(context); Console.WriteLine(); bool hasZLIB = Serialization.IsSupportedComprMode(ComprModeType.ZLIB); bool hasZSTD = Serialization.IsSupportedComprMode(ComprModeType.ZSTD); using EncryptionParameters parms = context.FirstContextData.Parms; ulong polyModulusDegree = parms.PolyModulusDegree; Console.Write("Generating secret/public keys: "); using KeyGenerator keygen = new KeyGenerator(context); Console.WriteLine("Done"); using SecretKey secretKey = keygen.SecretKey; keygen.CreatePublicKey(out PublicKey publicKey); Func <RelinKeys> GetRelinKeys = () => { if (context.UsingKeyswitching) { /* * Generate relinearization keys. */ Console.Write("Generating relinearization keys: "); timer = Stopwatch.StartNew(); keygen.CreateRelinKeys(out RelinKeys relinKeys); int micros = (int)(timer.Elapsed.TotalMilliseconds * 1000); Console.WriteLine($"Done [{micros} microseconds]"); return(relinKeys); } else { return(null); } }; Func <GaloisKeys> GetGaloisKeys = () => { if (context.UsingKeyswitching) { if (!context.KeyContextData.Qualifiers.UsingBatching) { Console.WriteLine("Given encryption parameters do not support batching."); return(null); } /* * Generate Galois keys. In larger examples the Galois keys can use a lot of * memory, which can be a problem in constrained systems. The user should * try some of the larger runs of the test and observe their effect on the * memory pool allocation size. The key generation can also take a long time, * as can be observed from the print-out. */ Console.Write($"Generating Galois keys: "); timer = Stopwatch.StartNew(); keygen.CreateGaloisKeys(out GaloisKeys galoisKeys); int micros = (int)(timer.Elapsed.TotalMilliseconds * 1000); Console.WriteLine($"Done [{micros} microseconds]"); return(galoisKeys); } else { return(null); } }; using RelinKeys relinKeys = GetRelinKeys(); using GaloisKeys galKeys = GetGaloisKeys(); using Encryptor encryptor = new Encryptor(context, publicKey); using Decryptor decryptor = new Decryptor(context, secretKey); using Evaluator evaluator = new Evaluator(context); using CKKSEncoder ckksEncoder = new CKKSEncoder(context); Stopwatch timeEncodeSum = new Stopwatch(); Stopwatch timeDecodeSum = new Stopwatch(); Stopwatch timeEncryptSum = new Stopwatch(); Stopwatch timeDecryptSum = new Stopwatch(); Stopwatch timeAddSum = new Stopwatch(); Stopwatch timeMultiplySum = new Stopwatch(); Stopwatch timeMultiplyPlainSum = new Stopwatch(); Stopwatch timeSquareSum = new Stopwatch(); Stopwatch timeRelinearizeSum = new Stopwatch(); Stopwatch timeRescaleSum = new Stopwatch(); Stopwatch timeRotateOneStepSum = new Stopwatch(); Stopwatch timeRotateRandomSum = new Stopwatch(); Stopwatch timeConjugateSum = new Stopwatch(); Stopwatch timeSerializeSum = new Stopwatch(); Stopwatch timeSerializeZLIBSum = new Stopwatch(); Stopwatch timeSerializeZSTDSum = new Stopwatch(); Random rnd = new Random(); /* * How many times to run the test? */ int count = 10; /* * Populate a vector of floating-point values to batch. */ ulong slotCount = ckksEncoder.SlotCount; double[] podValues = new double[slotCount]; for (ulong i = 0; i < slotCount; i++) { podValues[i] = 1.001 * i; } Console.Write("Running tests "); for (int i = 0; i < count; i++) { /* * [Encoding] * For scale we use the square root of the last CoeffModulus prime * from parms. */ double scale = Math.Sqrt(parms.CoeffModulus.Last().Value); using Plaintext plain = new Plaintext(parms.PolyModulusDegree * (ulong)parms.CoeffModulus.Count(), 0); timeEncodeSum.Start(); ckksEncoder.Encode(podValues, scale, plain); timeEncodeSum.Stop(); /* * [Decoding] */ List <double> podList = new List <double>((int)slotCount); timeDecodeSum.Start(); ckksEncoder.Decode(plain, podList); timeDecodeSum.Stop(); /* * [Encryption] */ using Ciphertext encrypted = new Ciphertext(context); timeEncryptSum.Start(); encryptor.Encrypt(plain, encrypted); timeEncryptSum.Stop(); /* * [Decryption] */ using Plaintext plain2 = new Plaintext(polyModulusDegree, 0); timeDecryptSum.Start(); decryptor.Decrypt(encrypted, plain2); timeDecryptSum.Stop(); /* * [Add] */ using Ciphertext encrypted1 = new Ciphertext(context); ckksEncoder.Encode(i + 1, plain); encryptor.Encrypt(plain, encrypted1); using Ciphertext encrypted2 = new Ciphertext(context); ckksEncoder.Encode(i + 1, plain2); encryptor.Encrypt(plain2, encrypted2); timeAddSum.Start(); evaluator.AddInplace(encrypted1, encrypted2); evaluator.AddInplace(encrypted2, encrypted2); evaluator.AddInplace(encrypted1, encrypted2); timeAddSum.Stop(); /* * [Multiply] */ encrypted1.Reserve(3); timeMultiplySum.Start(); evaluator.MultiplyInplace(encrypted1, encrypted2); timeMultiplySum.Stop(); /* * [Multiply Plain] */ timeMultiplyPlainSum.Start(); evaluator.MultiplyPlainInplace(encrypted2, plain); timeMultiplyPlainSum.Stop(); /* * [Square] */ timeSquareSum.Start(); evaluator.SquareInplace(encrypted2); timeSquareSum.Stop(); if (context.UsingKeyswitching) { /* * [Relinearize] */ timeRelinearizeSum.Start(); evaluator.RelinearizeInplace(encrypted1, relinKeys); timeRelinearizeSum.Stop(); /* * [Rescale] */ timeRescaleSum.Start(); evaluator.RescaleToNextInplace(encrypted1); timeRescaleSum.Stop(); /* * [Rotate Vector] */ timeRotateOneStepSum.Start(); evaluator.RotateVectorInplace(encrypted, 1, galKeys); evaluator.RotateVectorInplace(encrypted, -1, galKeys); timeRotateOneStepSum.Stop(); /* * [Rotate Vector Random] */ // ckksEncoder.SlotCount is always a power of 2. int randomRotation = rnd.Next() & ((int)ckksEncoder.SlotCount - 1); timeRotateRandomSum.Start(); evaluator.RotateVectorInplace(encrypted, randomRotation, galKeys); timeRotateRandomSum.Stop(); /* * [Complex Conjugate] */ timeConjugateSum.Start(); evaluator.ComplexConjugateInplace(encrypted, galKeys); timeConjugateSum.Stop(); } /* * [Serialize Ciphertext] */ using MemoryStream stream = new MemoryStream(); timeSerializeSum.Start(); encrypted.Save(stream, ComprModeType.None); timeSerializeSum.Stop(); if (hasZLIB) { /* * [Serialize Ciphertext (ZLIB)] */ timeSerializeZLIBSum.Start(); encrypted.Save(stream, ComprModeType.ZLIB); timeSerializeZLIBSum.Stop(); } if (hasZSTD) { /* * [Serialize Ciphertext (Zstandard)] */ timeSerializeZSTDSum.Start(); encrypted.Save(stream, ComprModeType.ZSTD); timeSerializeZSTDSum.Stop(); } /* * Print a dot to indicate progress. */ Console.Write("."); Console.Out.Flush(); } Console.WriteLine(" Done"); Console.WriteLine(); Console.Out.Flush(); int avgEncode = (int)(timeEncodeSum.Elapsed.TotalMilliseconds * 1000 / count); int avgDecode = (int)(timeDecodeSum.Elapsed.TotalMilliseconds * 1000 / count); int avgEncrypt = (int)(timeEncryptSum.Elapsed.TotalMilliseconds * 1000 / count); int avgDecrypt = (int)(timeDecryptSum.Elapsed.TotalMilliseconds * 1000 / count); int avgAdd = (int)(timeAddSum.Elapsed.TotalMilliseconds * 1000 / (3 * count)); int avgMultiply = (int)(timeMultiplySum.Elapsed.TotalMilliseconds * 1000 / count); int avgMultiplyPlain = (int)(timeMultiplyPlainSum.Elapsed.TotalMilliseconds * 1000 / count); int avgSquare = (int)(timeSquareSum.Elapsed.TotalMilliseconds * 1000 / count); int avgRelinearize = (int)(timeRelinearizeSum.Elapsed.TotalMilliseconds * 1000 / count); int avgRescale = (int)(timeRescaleSum.Elapsed.TotalMilliseconds * 1000 / count); int avgRotateOneStep = (int)(timeRotateOneStepSum.Elapsed.TotalMilliseconds * 1000 / (2 * count)); int avgRotateRandom = (int)(timeRotateRandomSum.Elapsed.TotalMilliseconds * 1000 / count); int avgConjugate = (int)(timeConjugateSum.Elapsed.TotalMilliseconds * 1000 / count); int avgSerializeSum = (int)(timeSerializeSum.Elapsed.TotalMilliseconds * 1000 / count); int avgSerializeZLIBSum = (int)(timeSerializeZLIBSum.Elapsed.TotalMilliseconds * 1000 / count); int avgSerializeZSTDSum = (int)(timeSerializeZSTDSum.Elapsed.TotalMilliseconds * 1000 / count); Console.WriteLine($"Average encode: {avgEncode} microseconds"); Console.WriteLine($"Average decode: {avgDecode} microseconds"); Console.WriteLine($"Average encrypt: {avgEncrypt} microseconds"); Console.WriteLine($"Average decrypt: {avgDecrypt} microseconds"); Console.WriteLine($"Average add: {avgAdd} microseconds"); Console.WriteLine($"Average multiply: {avgMultiply} microseconds"); Console.WriteLine($"Average multiply plain: {avgMultiplyPlain} microseconds"); Console.WriteLine($"Average square: {avgSquare} microseconds"); if (context.UsingKeyswitching) { Console.WriteLine($"Average relinearize: {avgRelinearize} microseconds"); Console.WriteLine($"Average rescale: {avgRescale} microseconds"); Console.WriteLine($"Average rotate vector one step: {avgRotateOneStep} microseconds"); Console.WriteLine($"Average rotate vector random: {avgRotateRandom} microseconds"); Console.WriteLine($"Average complex conjugate: {avgConjugate} microseconds"); } Console.WriteLine($"Average serialize ciphertext: {avgSerializeSum} microseconds"); if (hasZLIB) { Console.WriteLine( $"Average compressed (ZLIB) serialize ciphertext: {avgSerializeZLIBSum} microseconds"); } if (hasZSTD) { Console.WriteLine( $"Average compressed (Zstandard) serialize ciphertext: {avgSerializeZSTDSum} microseconds"); } Console.Out.Flush(); }
private static void ExampleCKKSBasics() { Utilities.PrintExampleBanner("Example: CKKS Basics"); /* * In this example we demonstrate evaluating a polynomial function * * PI*x^3 + 0.4*x + 1 * * on encrypted floating-point input data x for a set of 4096 equidistant points * in the interval [0, 1]. This example demonstrates many of the main features * of the CKKS scheme, but also the challenges in using it. * * We start by setting up the CKKS scheme. */ using EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS); /* * We saw in `2_Encoders.cs' that multiplication in CKKS causes scales in * ciphertexts to grow. The scale of any ciphertext must not get too close to * the total size of CoeffModulus, or else the ciphertext simply runs out of * room to store the scaled-up plaintext. The CKKS scheme provides a `rescale' * functionality that can reduce the scale, and stabilize the scale expansion. * * Rescaling is a kind of modulus switch operation (recall `3_Levels.cs'). * As modulus switching, it removes the last of the primes from CoeffModulus, * but as a side-effect it scales down the ciphertext by the removed prime. * Usually we want to have perfect control over how the scales are changed, * which is why for the CKKS scheme it is more common to use carefully selected * primes for the CoeffModulus. * * More precisely, suppose that the scale in a CKKS ciphertext is S, and the * last prime in the current CoeffModulus (for the ciphertext) is P. Rescaling * to the next level changes the scale to S/P, and removes the prime P from the * CoeffModulus, as usual in modulus switching. The number of primes limits * how many rescalings can be done, and thus limits the multiplicative depth of * the computation. * * It is possible to choose the initial scale freely. One good strategy can be * to is to set the initial scale S and primes P_i in the CoeffModulus to be * very close to each other. If ciphertexts have scale S before multiplication, * they have scale S^2 after multiplication, and S^2/P_i after rescaling. If all * P_i are close to S, then S^2/P_i is close to S again. This way we stabilize the * scales to be close to S throughout the computation. Generally, for a circuit * of depth D, we need to rescale D times, i.e., we need to be able to remove D * primes from the coefficient modulus. Once we have only one prime left in the * coeff_modulus, the remaining prime must be larger than S by a few bits to * preserve the pre-decimal-point value of the plaintext. * * Therefore, a generally good strategy is to choose parameters for the CKKS * scheme as follows: * * (1) Choose a 60-bit prime as the first prime in CoeffModulus. This will * give the highest precision when decrypting; * (2) Choose another 60-bit prime as the last element of CoeffModulus, as * this will be used as the special prime and should be as large as the * largest of the other primes; * (3) Choose the intermediate primes to be close to each other. * * We use CoeffModulus.Create to generate primes of the appropriate size. Note * that our CoeffModulus is 200 bits total, which is below the bound for our * PolyModulusDegree: CoeffModulus.MaxBitCount(8192) returns 218. */ ulong polyModulusDegree = 8192; parms.PolyModulusDegree = polyModulusDegree; parms.CoeffModulus = CoeffModulus.Create( polyModulusDegree, new int[] { 60, 40, 40, 60 }); /* * We choose the initial scale to be 2^40. At the last level, this leaves us * 60-40=20 bits of precision before the decimal point, and enough (roughly * 10-20 bits) of precision after the decimal point. Since our intermediate * primes are 40 bits (in fact, they are very close to 2^40), we can achieve * scale stabilization as described above. */ double scale = Math.Pow(2.0, 40); using SEALContext context = new SEALContext(parms); Utilities.PrintParameters(context); Console.WriteLine(); using KeyGenerator keygen = new KeyGenerator(context); using PublicKey publicKey = keygen.PublicKey; using SecretKey secretKey = keygen.SecretKey; using RelinKeys relinKeys = keygen.RelinKeysLocal(); using Encryptor encryptor = new Encryptor(context, publicKey); using Evaluator evaluator = new Evaluator(context); using Decryptor decryptor = new Decryptor(context, secretKey); using CKKSEncoder encoder = new CKKSEncoder(context); ulong slotCount = encoder.SlotCount; Console.WriteLine($"Number of slots: {slotCount}"); List <double> input = new List <double>((int)slotCount); double currPoint = 0, stepSize = 1.0 / (slotCount - 1); for (ulong i = 0; i < slotCount; i++, currPoint += stepSize) { input.Add(currPoint); } Console.WriteLine("Input vector:"); Utilities.PrintVector(input, 3, 7); Console.WriteLine("Evaluating polynomial PI*x^3 + 0.4x + 1 ..."); /* * We create plaintexts for PI, 0.4, and 1 using an overload of CKKSEncoder.Encode * that encodes the given floating-point value to every slot in the vector. */ using Plaintext plainCoeff3 = new Plaintext(), plainCoeff1 = new Plaintext(), plainCoeff0 = new Plaintext(); encoder.Encode(3.14159265, scale, plainCoeff3); encoder.Encode(0.4, scale, plainCoeff1); encoder.Encode(1.0, scale, plainCoeff0); using Plaintext xPlain = new Plaintext(); Utilities.PrintLine(); Console.WriteLine("Encode input vectors."); encoder.Encode(input, scale, xPlain); using Ciphertext x1Encrypted = new Ciphertext(); encryptor.Encrypt(xPlain, x1Encrypted); /* * To compute x^3 we first compute x^2 and relinearize. However, the scale has * now grown to 2^80. */ using Ciphertext x3Encrypted = new Ciphertext(); Utilities.PrintLine(); Console.WriteLine("Compute x^2 and relinearize:"); evaluator.Square(x1Encrypted, x3Encrypted); evaluator.RelinearizeInplace(x3Encrypted, relinKeys); Console.WriteLine(" + Scale of x^2 before rescale: {0} bits", Math.Log(x3Encrypted.Scale, newBase: 2)); /* * Now rescale; in addition to a modulus switch, the scale is reduced down by * a factor equal to the prime that was switched away (40-bit prime). Hence, the * new scale should be close to 2^40. Note, however, that the scale is not equal * to 2^40: this is because the 40-bit prime is only close to 2^40. */ Utilities.PrintLine(); Console.WriteLine("Rescale x^2."); evaluator.RescaleToNextInplace(x3Encrypted); Console.WriteLine(" + Scale of x^2 after rescale: {0} bits", Math.Log(x3Encrypted.Scale, newBase: 2)); /* * Now x3Encrypted is at a different level than x1Encrypted, which prevents us * from multiplying them to compute x^3. We could simply switch x1Encrypted to * the next parameters in the modulus switching chain. However, since we still * need to multiply the x^3 term with PI (plainCoeff3), we instead compute PI*x * first and multiply that with x^2 to obtain PI*x^3. To this end, we compute * PI*x and rescale it back from scale 2^80 to something close to 2^40. */ Utilities.PrintLine(); Console.WriteLine("Compute and rescale PI*x."); using Ciphertext x1EncryptedCoeff3 = new Ciphertext(); evaluator.MultiplyPlain(x1Encrypted, plainCoeff3, x1EncryptedCoeff3); Console.WriteLine(" + Scale of PI*x before rescale: {0} bits", Math.Log(x1EncryptedCoeff3.Scale, newBase: 2)); evaluator.RescaleToNextInplace(x1EncryptedCoeff3); Console.WriteLine(" + Scale of PI*x after rescale: {0} bits", Math.Log(x1EncryptedCoeff3.Scale, newBase: 2)); /* * Since x3Encrypted and x1EncryptedCoeff3 have the same exact scale and use * the same encryption parameters, we can multiply them together. We write the * result to x3Encrypted, relinearize, and rescale. Note that again the scale * is something close to 2^40, but not exactly 2^40 due to yet another scaling * by a prime. We are down to the last level in the modulus switching chain. */ Utilities.PrintLine(); Console.WriteLine("Compute, relinearize, and rescale (PI*x)*x^2."); evaluator.MultiplyInplace(x3Encrypted, x1EncryptedCoeff3); evaluator.RelinearizeInplace(x3Encrypted, relinKeys); Console.WriteLine(" + Scale of PI*x^3 before rescale: {0} bits", Math.Log(x3Encrypted.Scale, newBase: 2)); evaluator.RescaleToNextInplace(x3Encrypted); Console.WriteLine(" + Scale of PI*x^3 after rescale: {0} bits", Math.Log(x3Encrypted.Scale, newBase: 2)); /* * Next we compute the degree one term. All this requires is one MultiplyPlain * with plainCoeff1. We overwrite x1Encrypted with the result. */ Utilities.PrintLine(); Console.WriteLine("Compute and rescale 0.4*x."); evaluator.MultiplyPlainInplace(x1Encrypted, plainCoeff1); Console.WriteLine(" + Scale of 0.4*x before rescale: {0} bits", Math.Log(x1Encrypted.Scale, newBase: 2)); evaluator.RescaleToNextInplace(x1Encrypted); Console.WriteLine(" + Scale of 0.4*x after rescale: {0} bits", Math.Log(x1Encrypted.Scale, newBase: 2)); /* * Now we would hope to compute the sum of all three terms. However, there is * a serious problem: the encryption parameters used by all three terms are * different due to modulus switching from rescaling. * * Encrypted addition and subtraction require that the scales of the inputs are * the same, and also that the encryption parameters (ParmsId) match. If there * is a mismatch, Evaluator will throw an exception. */ Console.WriteLine(); Utilities.PrintLine(); Console.WriteLine("Parameters used by all three terms are different:"); Console.WriteLine(" + Modulus chain index for x3Encrypted: {0}", context.GetContextData(x3Encrypted.ParmsId).ChainIndex); Console.WriteLine(" + Modulus chain index for x1Encrypted: {0}", context.GetContextData(x1Encrypted.ParmsId).ChainIndex); Console.WriteLine(" + Modulus chain index for plainCoeff0: {0}", context.GetContextData(plainCoeff0.ParmsId).ChainIndex); Console.WriteLine(); /* * Let us carefully consider what the scales are at this point. We denote the * primes in coeff_modulus as P_0, P_1, P_2, P_3, in this order. P_3 is used as * the special modulus and is not involved in rescalings. After the computations * above the scales in ciphertexts are: * * - Product x^2 has scale 2^80 and is at level 2; * - Product PI*x has scale 2^80 and is at level 2; * - We rescaled both down to scale 2^80/P2 and level 1; * - Product PI*x^3 has scale (2^80/P_2)^2; * - We rescaled it down to scale (2^80/P_2)^2/P_1 and level 0; * - Product 0.4*x has scale 2^80; * - We rescaled it down to scale 2^80/P_2 and level 1; * - The contant term 1 has scale 2^40 and is at level 2. * * Although the scales of all three terms are approximately 2^40, their exact * values are different, hence they cannot be added together. */ Utilities.PrintLine(); Console.WriteLine("The exact scales of all three terms are different:"); Console.WriteLine(" + Exact scale in PI*x^3: {0:0.0000000000}", x3Encrypted.Scale); Console.WriteLine(" + Exact scale in 0.4*x: {0:0.0000000000}", x1Encrypted.Scale); Console.WriteLine(" + Exact scale in 1: {0:0.0000000000}", plainCoeff0.Scale); Console.WriteLine(); /* * There are many ways to fix this problem. Since P_2 and P_1 are really close * to 2^40, we can simply "lie" to Microsoft SEAL and set the scales to be the * same. For example, changing the scale of PI*x^3 to 2^40 simply means that we * scale the value of PI*x^3 by 2^120/(P_2^2*P_1), which is very close to 1. * This should not result in any noticeable error. * * Another option would be to encode 1 with scale 2^80/P_2, do a MultiplyPlain * with 0.4*x, and finally rescale. In this case we would need to additionally * make sure to encode 1 with appropriate encryption parameters (ParmsId). * * In this example we will use the first (simplest) approach and simply change * the scale of PI*x^3 and 0.4*x to 2^40. */ Utilities.PrintLine(); Console.WriteLine("Normalize scales to 2^40."); x3Encrypted.Scale = Math.Pow(2.0, 40); x1Encrypted.Scale = Math.Pow(2.0, 40); /* * We still have a problem with mismatching encryption parameters. This is easy * to fix by using traditional modulus switching (no rescaling). CKKS supports * modulus switching just like the BFV scheme, allowing us to switch away parts * of the coefficient modulus when it is simply not needed. */ Utilities.PrintLine(); Console.WriteLine("Normalize encryption parameters to the lowest level."); ParmsId lastParmsId = x3Encrypted.ParmsId; evaluator.ModSwitchToInplace(x1Encrypted, lastParmsId); evaluator.ModSwitchToInplace(plainCoeff0, lastParmsId); /* * All three ciphertexts are now compatible and can be added. */ Utilities.PrintLine(); Console.WriteLine("Compute PI*x^3 + 0.4*x + 1."); using Ciphertext encryptedResult = new Ciphertext(); evaluator.Add(x3Encrypted, x1Encrypted, encryptedResult); evaluator.AddPlainInplace(encryptedResult, plainCoeff0); /* * First print the true result. */ using Plaintext plainResult = new Plaintext(); Utilities.PrintLine(); Console.WriteLine("Decrypt and decode PI * x ^ 3 + 0.4x + 1."); Console.WriteLine(" + Expected result:"); List <double> trueResult = new List <double>(input.Count); foreach (double x in input) { trueResult.Add((3.14159265 * x * x + 0.4) * x + 1); } Utilities.PrintVector(trueResult, 3, 7); /* * We decrypt, decode, and print the result. */ decryptor.Decrypt(encryptedResult, plainResult); List <double> result = new List <double>(); encoder.Decode(plainResult, result); Console.WriteLine(" + Computed result ...... Correct."); Utilities.PrintVector(result, 3, 7); /* * While we did not show any computations on complex numbers in these examples, * the CKKSEncoder would allow us to have done that just as easily. Additions * and multiplications of complex numbers behave just as one would expect. */ }
//constructor for debugging , because it enables to pass secretkey which will not happen in real life // special parameters : // batchsize - number of batches sample in one ciphertext ,if the client batches mulitple samples in the ciphertet . // featureSize - number of features in sample private Svc(double[][] vectors, double[][] coefficients, double[] intercepts, String kernel, double gamma, double coef0, ulong degree, int power, PublicKey publicKey, SecretKey secretKey, RelinKeys relinKeys, GaloisKeys galoisKeys, int batchSize, int featureSize) { this._vectors = vectors; this._coefficients = coefficients; this._intercepts = intercepts; this._kernel = (Kernel)System.Enum.Parse(typeof(Kernel), kernel); this._gamma = gamma; this._coef0 = coef0; this._degree = degree; this._power = power; //Use the ckks SCheme EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS); // polyModulusDegree and CoeffModulus used for general SVM algorithm and depends on the polynomial kernel degree // ( and the percision constraint ) . // My implementation can be used up to dgree = 4 , but it can be easly refactored with some oprimizations to higher // polynomial degree ulong polyModulusDegree = 16384; if (power >= 20 && power < 40) { parms.CoeffModulus = CoeffModulus.Create(polyModulusDegree, new int[] { 60, 20, 21, 22, 23, 24, 25, 26, 27, 60 }); } else if (power >= 40 && power < 60) { parms.CoeffModulus = CoeffModulus.Create(polyModulusDegree, new int[] { 60, 40, 40, 40, 40, 40, 40, 40, 60 }); } else if (power == 60) { polyModulusDegree = 32768; parms.CoeffModulus = CoeffModulus.Create(polyModulusDegree, new int[] { 60, 60, 60, 60, 60, 60, 60, 60, 60 }); } parms.PolyModulusDegree = polyModulusDegree; _context = new SEALContext(parms); _publicKey = publicKey; _secretKey = secretKey; _relinKeys = relinKeys; _galoisKeys = galoisKeys; _evaluator = new Evaluator(_context); if (_secretKey != null) { _decryptor = new Decryptor(_context, _secretKey); //FOR DEBUG ONLY ( not used in real server) } _encoder = new CKKSEncoder(_context); Stopwatch serverInitStopwatch = new Stopwatch(); serverInitStopwatch.Start(); _numOfrowsCount = _vectors.Length; //Number of Support Vectors _numOfcolumnsCount = _vectors[0].Length; //Number of features in every Support vector _scale = Math.Pow(2.0, _power); // vars for batch rotations _svPlaintexts = new Plaintext[_numOfrowsCount]; //Encode support vectors _sums = new Ciphertext[_numOfrowsCount]; if (UseBatchInnerProduct) { double[] batchVectors = new double[batchSize * featureSize]; for (int i = 0; i < _numOfrowsCount; i++) { for (int k = 0; k < batchSize * featureSize; k++) { var index0 = k % featureSize; batchVectors[k] = index0 < _numOfcolumnsCount ? _vectors[i][index0] : 0; } _svPlaintexts[i] = new Plaintext(); _encoder.Encode(batchVectors, _scale, _svPlaintexts[i]); SVCUtilities.SvcUtilities.PrintScale(_svPlaintexts[i], "batch supportVectorsPlaintext" + i); _sums[i] = new Ciphertext(); } } else { ///////////////////////////////////////////////////////////////////////// // // vars for simple inner product // // Handle SV _svPlaintextsArr = new Plaintext[_numOfrowsCount, _numOfcolumnsCount]; //Encode SV for (int i = 0; i < _numOfrowsCount; i++) { for (int j = 0; j < _numOfcolumnsCount; j++) { _svPlaintextsArr[i, j] = new Plaintext(); _encoder.Encode(_vectors[i][j] != 0 ? _vectors[i][j] : Zero, _scale, _svPlaintextsArr[i, j]); SvcUtilities.PrintScale(_svPlaintextsArr[i, j], $"supportVectorsPlaintext[{i}][{j}]"); } } // Prepare sum of inner product _innerProdSums = new Ciphertext[_numOfcolumnsCount]; for (int i = 0; i < _numOfcolumnsCount; i++) { _innerProdSums[i] = new Ciphertext(); } ////////////////////////////////////////////////////////////// } // Allocate memory for svm secure calculation _kernels = new Ciphertext[_numOfrowsCount]; _decisionsArr = new Ciphertext[_numOfrowsCount]; _coefArr = new Plaintext[_numOfrowsCount]; for (int i = 0; i < _numOfrowsCount; i++) { _kernels[i] = new Ciphertext(); _decisionsArr[i] = new Ciphertext(); _coefArr[i] = new Plaintext(); } _gamaPlaintext = new Plaintext(); _encoder.Encode(_gamma != 0 ? _gamma : Zero, _scale, _gamaPlaintext); serverInitStopwatch.Stop(); Console.WriteLine($"server Init elapsed {serverInitStopwatch.ElapsedMilliseconds} ms"); }
// Function for classification of samples // I follow the SEAL eamples recomandations to rescale and relinearize after each calculation. // useRelinearizeInplace and useReScale should be always true. // This parametrs are enabled only for debugging and learning purpose. public Ciphertext Predict(Ciphertext featuresCiphertexts, bool useRelinearizeInplace, bool useReScale, Stopwatch innerProductStopwatch, Stopwatch degreeStopwatch, Stopwatch negateStopwatch, Stopwatch serverDecisionStopWatch) { Ciphertext tempCt = new Ciphertext(); // Level 1 for (int i = 0; i < _numOfrowsCount; i++) { //inner product //calculate IP = < x, x'> innerProductStopwatch.Start(); if (UseBatchInnerProduct) { _kernels[i] = InnerProduct(featuresCiphertexts, _svPlaintexts, i, _sums, _numOfcolumnsCount, tempCt); } innerProductStopwatch.Stop(); SvcUtilities.PrintCyprherText(_decryptor, _kernels[i], _encoder, $"inner product TotalValue {i}"); SvcUtilities.PrintScale(_kernels[i], "0. kernels" + i); if (useRelinearizeInplace) { _evaluator.RelinearizeInplace(_kernels[i], _relinKeys); } if (useReScale) { _evaluator.RescaleToNextInplace(_kernels[i]); } SvcUtilities.PrintScale(_kernels[i], "1. kernels" + i); _kernels[i].Scale = _scale; //For polynimial kernel calculate if (_kernel == Kernel.Poly) { // calculate (y *IP+r)^d // IP is calculated previously // y = gamma // r = _coef0 if (useReScale) { ParmsId lastParmsId = _kernels[i].ParmsId; _evaluator.ModSwitchToInplace(_gamaPlaintext, lastParmsId); } //calculate y * IP _evaluator.MultiplyPlainInplace(_kernels[i], _gamaPlaintext); SvcUtilities.PrintScale(_kernels[i], "2. kernels" + i); if (useRelinearizeInplace) { _evaluator.RelinearizeInplace(_kernels[i], _relinKeys); } if (useReScale) { _evaluator.RescaleToNextInplace(_kernels[i]); } SvcUtilities.PrintScale(_kernels[i], "3. kernels" + i); // add r if (Math.Abs(_coef0) > 0) { Plaintext coef0Plaintext = new Plaintext(); _encoder.Encode(_coef0, _kernels[i].Scale, coef0Plaintext); if (useReScale) { ParmsId lastParmsId = _kernels[i].ParmsId; _evaluator.ModSwitchToInplace(coef0Plaintext, lastParmsId); } //kernels[i].Scale = coef0Plaintext.Scale; _evaluator.AddPlainInplace(_kernels[i], coef0Plaintext); } SvcUtilities.PrintScale(_kernels[i], "4. kernels" + i); degreeStopwatch.Start(); // calculate the polynom degree var kernel = new Ciphertext(_kernels[i]); for (int d = 0; d < (int)_degree - 1; d++) { kernel.Scale = _kernels[i].Scale; if (useReScale) { ParmsId lastParmsId = _kernels[i].ParmsId; _evaluator.ModSwitchToInplace(kernel, lastParmsId); } _evaluator.MultiplyInplace(_kernels[i], kernel); SvcUtilities.PrintScale(_kernels[i], d + " 5. kernels" + i); if (useRelinearizeInplace) { _evaluator.RelinearizeInplace(_kernels[i], _relinKeys); } if (useReScale) { _evaluator.RescaleToNextInplace(_kernels[i]); } SvcUtilities.PrintScale(_kernels[i], d + " rescale 6. kernels" + i); } SvcUtilities.PrintScale(_kernels[i], "7. kernels" + i); degreeStopwatch.Stop(); } negateStopwatch.Start(); _evaluator.NegateInplace(_kernels[i]); negateStopwatch.Stop(); SvcUtilities.PrintScale(_kernels[i], "8. kernel" + i); SvcUtilities.PrintCyprherText(_decryptor, _kernels[i], _encoder, "kernel" + i); } serverDecisionStopWatch.Start(); // Encode coefficients : ParmsId! , scale! double scale2 = Math.Pow(2.0, _power); if (useReScale) { scale2 = _kernels[0].Scale; } for (int i = 0; i < _numOfrowsCount; i++) { _encoder.Encode(_coefficients[0][i], scale2, _coefArr[i]); SvcUtilities.PrintScale(_coefArr[i], "coefPlainText" + i); } if (useReScale) { for (int i = 0; i < _numOfrowsCount; i++) { ParmsId lastParmsId = _kernels[i].ParmsId; _evaluator.ModSwitchToInplace(_coefArr[i], lastParmsId); } } // Level 2 // Calculate decisionArr for (int i = 0; i < _numOfrowsCount; i++) { _evaluator.MultiplyPlain(_kernels[i], _coefArr[i], _decisionsArr[i]); if (useRelinearizeInplace) { _evaluator.RelinearizeInplace(_decisionsArr[i], _relinKeys); } if (useReScale) { _evaluator.RescaleToNextInplace(_decisionsArr[i]); } SvcUtilities.PrintScale(_decisionsArr[i], "decision" + i); SvcUtilities.PrintCyprherText(_decryptor, _decisionsArr[i], _encoder, "decision" + i); } // Calculate decisionTotal Ciphertext decisionTotal = new Ciphertext(); //================================================================= _evaluator.AddMany(_decisionsArr, decisionTotal); //================================================================= SvcUtilities.PrintScale(decisionTotal, "decisionTotal"); SvcUtilities.PrintCyprherText(_decryptor, decisionTotal, _encoder, "decision total"); // Encode intercepts : ParmsId! , scale! Plaintext interceptsPlainText = new Plaintext(); double scale3 = Math.Pow(2.0, _power * 3); if (useReScale) { scale3 = decisionTotal.Scale; } _encoder.Encode(_intercepts[0], scale3, interceptsPlainText); if (useReScale) { ParmsId lastParmsId = decisionTotal.ParmsId; _evaluator.ModSwitchToInplace(interceptsPlainText, lastParmsId); } SvcUtilities.PrintScale(interceptsPlainText, "interceptsPlainText"); SvcUtilities.PrintScale(decisionTotal, "decisionTotal"); //// Calculate finalTotal Ciphertext finalTotal = new Ciphertext(); //================================================================= _evaluator.AddPlainInplace(decisionTotal, interceptsPlainText); //================================================================= SvcUtilities.PrintScale(decisionTotal, "decisionTotal"); //Level 3 List <double> result = SvcUtilities.PrintCyprherText(_decryptor, decisionTotal, _encoder, "finalTotal", true); serverDecisionStopWatch.Stop(); long innerProductMilliseconds = innerProductStopwatch.ElapsedMilliseconds; //Console.WriteLine($"server innerProductStopwatch elapsed {innerProductMilliseconds} ms"); long negateMilliseconds = negateStopwatch.ElapsedMilliseconds; //Console.WriteLine($"server negateStopwatch elapsed {negateMilliseconds} ms"); long degreeMilliseconds = degreeStopwatch.ElapsedMilliseconds; //Console.WriteLine($"server degreeStopwatch elapsed {degreeMilliseconds} ms"); long serverDecisionMilliseconds = serverDecisionStopWatch.ElapsedMilliseconds; //Console.WriteLine($"server Decision elapsed {serverDecisionMilliseconds} ms"); return(decisionTotal); }
public int Predict(double[] features, int power, bool useRelinearizeInplace, bool useReScale, Stopwatch timePredictSum) { EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS); if (power < 60) { ulong polyModulusDegree = 8192; parms.PolyModulusDegree = polyModulusDegree; parms.CoeffModulus = CoeffModulus.Create(polyModulusDegree, new int[] { 60, 40, 40, 60 }); } else { ulong polyModulusDegree = 16384; parms.PolyModulusDegree = polyModulusDegree; parms.CoeffModulus = CoeffModulus.Create(polyModulusDegree, new int[] { 60, 60, 60, 60, 60, 60 }); } // double scale = Math.Pow(2.0, power); SEALContext context = new SEALContext(parms); Console.WriteLine(); KeyGenerator keygen = new KeyGenerator(context); PublicKey publicKey = keygen.PublicKey; SecretKey secretKey = keygen.SecretKey; RelinKeys relinKeys = keygen.RelinKeys(); Encryptor encryptor = new Encryptor(context, publicKey); Evaluator evaluator = new Evaluator(context); Decryptor decryptor = new Decryptor(context, secretKey); CKKSEncoder encoder = new CKKSEncoder(context); ulong slotCount = encoder.SlotCount; Console.WriteLine($"Number of slots: {slotCount}"); timePredictSum.Start(); var featuresLength = features.Length; var plaintexts = new Plaintext[featuresLength]; var featuresCiphertexts = new Ciphertext[featuresLength]; //Encode and encrypt features for (int i = 0; i < featuresLength; i++) { plaintexts[i] = new Plaintext(); encoder.Encode(features[i], scale, plaintexts[i]); SvcUtilities.PrintScale(plaintexts[i], "featurePlaintext" + i); featuresCiphertexts[i] = new Ciphertext(); encryptor.Encrypt(plaintexts[i], featuresCiphertexts[i]); SvcUtilities.PrintScale(featuresCiphertexts[i], "featurefEncrypted" + i); } // Handle SV var numOfrows = _vectors.Length; var numOfcolumns = _vectors[0].Length; var svPlaintexts = new Plaintext[numOfrows, numOfcolumns]; //Encode SV for (int i = 0; i < numOfrows; i++) { for (int j = 0; j < numOfcolumns; j++) { svPlaintexts[i, j] = new Plaintext(); encoder.Encode(_vectors[i][j], scale, svPlaintexts[i, j]); SvcUtilities.PrintScale(svPlaintexts[i, j], "supportVectorsPlaintext" + i + j); } } // Prepare sum of inner product var sums = new Ciphertext[numOfcolumns]; for (int i = 0; i < numOfcolumns; i++) { sums[i] = new Ciphertext(); } var kernels = new Ciphertext[numOfrows]; var decisionsArr = new Ciphertext[numOfrows]; var coefArr = new Plaintext [numOfrows]; for (int i = 0; i < numOfrows; i++) { kernels[i] = new Ciphertext(); decisionsArr[i] = new Ciphertext(); coefArr[i] = new Plaintext(); } // Level 1 for (int i = 0; i < numOfrows; i++) { var ciphertexts = new List <Ciphertext>(); //inner product for (int j = 0; j < numOfcolumns; j++) { evaluator.MultiplyPlain(featuresCiphertexts[j], svPlaintexts[i, j], sums[j]); if (useRelinearizeInplace) { evaluator.RelinearizeInplace(sums[j], relinKeys); } if (useReScale) { evaluator.RescaleToNextInplace(sums[j]); } SvcUtilities.PrintScale(sums[j], "tSum" + j); } evaluator.AddMany(sums, kernels[i]); evaluator.NegateInplace(kernels[i]); SvcUtilities.PrintScale(kernels[i], "kernel" + i); SvcUtilities.PrintCyprherText(decryptor, kernels[i], encoder, "kernel" + i); } // Encode coefficients : ParmsId! , scale! double scale2 = Math.Pow(2.0, power); if (useReScale) { scale2 = kernels[0].Scale; } for (int i = 0; i < numOfrows; i++) { encoder.Encode(_coefficients[0][i], scale2, coefArr[i]); SvcUtilities.PrintScale(coefArr[i], "coefPlainText+i"); } if (useReScale) { for (int i = 0; i < numOfrows; i++) { ParmsId lastParmsId = kernels[i].ParmsId; evaluator.ModSwitchToInplace(coefArr[i], lastParmsId); } } // Level 2 // Calculate decisionArr for (int i = 0; i < numOfrows; i++) { evaluator.MultiplyPlain(kernels[i], coefArr[i], decisionsArr[i]); if (useRelinearizeInplace) { evaluator.RelinearizeInplace(decisionsArr[i], relinKeys); } if (useReScale) { evaluator.RescaleToNextInplace(decisionsArr[i]); } SvcUtilities.PrintScale(decisionsArr[i], "decision" + i); SvcUtilities.PrintCyprherText(decryptor, decisionsArr[i], encoder, "decision" + i); } // Calculate decisionTotal Ciphertext decisionTotal = new Ciphertext(); //================================================================= evaluator.AddMany(decisionsArr, decisionTotal); //================================================================= SvcUtilities.PrintScale(decisionTotal, "decisionTotal"); SvcUtilities.PrintCyprherText(decryptor, decisionTotal, encoder, "decision total"); // Encode intercepts : ParmsId! , scale! Plaintext interceptsPlainText = new Plaintext(); double scale3 = Math.Pow(2.0, power * 3); if (useReScale) { scale3 = decisionTotal.Scale; } encoder.Encode(_intercepts[0], scale3, interceptsPlainText); if (useReScale) { ParmsId lastParmsId = decisionTotal.ParmsId; evaluator.ModSwitchToInplace(interceptsPlainText, lastParmsId); } SvcUtilities.PrintScale(interceptsPlainText, "interceptsPlainText"); SvcUtilities.PrintScale(decisionTotal, "decisionTotal"); //// Calculate finalTotal Ciphertext finalTotal = new Ciphertext(); //================================================================= evaluator.AddPlainInplace(decisionTotal, interceptsPlainText); //================================================================= timePredictSum.Stop(); SvcUtilities.PrintScale(decisionTotal, "decisionTotal"); //Level 3 List <double> result = SvcUtilities.PrintCyprherText(decryptor, decisionTotal, encoder, "finalTotal"); using (System.IO.StreamWriter file = new System.IO.StreamWriter( $@"{OutputDir}IrisLinear_IrisSecureSVC_total_{power}_{useRelinearizeInplace}_{useReScale}.txt", !_firstTime) ) { _firstTime = false; file.WriteLine($"{result[0]}"); } if (result[0] > 0) { return(0); } return(1); }
private static void ExampleRotationCKKS() { Utilities.PrintExampleBanner("Example: Rotation / Rotation in CKKS"); using EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS); ulong polyModulusDegree = 8192; parms.PolyModulusDegree = polyModulusDegree; parms.CoeffModulus = CoeffModulus.Create( polyModulusDegree, new int[] { 40, 40, 40, 40, 40 }); 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); keygen.CreateGaloisKeys(out GaloisKeys galoisKeys); using Encryptor encryptor = new Encryptor(context, publicKey); using Evaluator evaluator = new Evaluator(context); using Decryptor decryptor = new Decryptor(context, secretKey); using CKKSEncoder ckksEncoder = new CKKSEncoder(context); ulong slotCount = ckksEncoder.SlotCount; Console.WriteLine($"Number of slots: {slotCount}"); List <double> input = new List <double>((int)slotCount); double currPoint = 0, stepSize = 1.0 / (slotCount - 1); for (ulong i = 0; i < slotCount; i++, currPoint += stepSize) { input.Add(currPoint); } Console.WriteLine("Input vector:"); Utilities.PrintVector(input, 3, 7); double scale = Math.Pow(2.0, 50); Utilities.PrintLine(); Console.WriteLine("Encode and encrypt."); using Plaintext plain = new Plaintext(); ckksEncoder.Encode(input, scale, plain); using Ciphertext encrypted = new Ciphertext(); encryptor.Encrypt(plain, encrypted); using Ciphertext rotated = new Ciphertext(); Utilities.PrintLine(); Console.WriteLine("Rotate 2 steps left."); evaluator.RotateVector(encrypted, 2, galoisKeys, rotated); Console.WriteLine(" + Decrypt and decode ...... Correct."); decryptor.Decrypt(encrypted, plain); List <double> result = new List <double>(); ckksEncoder.Decode(plain, result); Utilities.PrintVector(result, 3, 7); /* * With the CKKS scheme it is also possible to evaluate a complex conjugation on * a vector of encrypted complex numbers, using Evaluator.ComplexConjugate. This * is in fact a kind of rotation, and requires also Galois keys. */ }
static async Task Main(string[] args) { Console.WriteLine("Secure Iris"); // Get Input from resource file or as args double[][] features; int numberOfFeatures = 4; int numOfRows = 0; // Option to load from args and not the whole dataset that is stored in resources if (args.Length >= numberOfFeatures) { numOfRows = args.Length / numberOfFeatures; // Features: features = new double[numOfRows][]; for (int i = 0; i < numOfRows; i++) { features[i] = new double[numberOfFeatures]; } for (int i = 0, l = args.Length; i < l; i++) { features[i / numberOfFeatures][i % numberOfFeatures] = Double.Parse(args[i]); } } else // load the whole dataset from resources { List <double[]> rows = new List <double[]>(); var bytes = Properties.Resources.iris; numOfRows = 0; features = SVCUtilities.SvcUtilities.LoadFeatures(bytes, numberOfFeatures, ref numOfRows); } Stopwatch clientStopwatch = new Stopwatch(); clientStopwatch.Start(); //svm algorithm parametrs calculated in python : training result double[][] vectors = new double[3][]; vectors[0] = new[] { 4.5, 2.3, 1.3, 0.3 }; vectors[1] = new[] { 5.1, 3.3, 1.7, 0.5 }; vectors[2] = new[] { 5.1, 2.5, 3.0, 1.1 }; double[][] coefficients = new double[1][]; coefficients[0] = new double[] { -0.07724840262003278, -0.6705185831514366, 0.7477669857714694 }; double[] intercepts = { 1.453766563649063 }; // SEAL parameters client side Console.WriteLine("SecureSVC : "); EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS); ulong polyModulusDegree = 16384; int power = 40; double scale = Math.Pow(2.0, power); if (power >= 20 && power < 40) { parms.CoeffModulus = CoeffModulus.Create(polyModulusDegree, new int[] { 60, 20, 21, 22, 23, 24, 25, 26, 27, 60 }); } else if (power >= 40 && power < 60) { parms.CoeffModulus = CoeffModulus.Create(polyModulusDegree, new int[] { 60, 40, 40, 40, 40, 40, 40, 40, 60 }); } else if (power == 60) { polyModulusDegree = 32768; parms.CoeffModulus = CoeffModulus.Create(polyModulusDegree, new int[] { 60, 60, 60, 60, 60, 60, 60, 60, 60 }); } parms.PolyModulusDegree = polyModulusDegree; var context = new SEALContext(parms); // Key generation KeyGenerator keygen = new KeyGenerator(context); var publicKey = keygen.PublicKey; var secretKey = keygen.SecretKey; var relinKeys = keygen.RelinKeys(); var galoisKeys = keygen.GaloisKeys(); var encryptor = new Encryptor(context, publicKey); var decryptor = new Decryptor(context, secretKey); var encoder = new CKKSEncoder(context); clientStopwatch.Stop(); using (System.IO.StreamWriter file = new System.IO.StreamWriter( $@"{OutputDir}IrisLinearSecured_{IsParallel}_{DateTime.Now.Day}_{DateTime.Now.ToShortTimeString().ToString().Replace(":", "_")}.txt") ) { // Only CONCEPT demonstation how to parrallel all the computation on all machine cpu's // Though the parallel here is done on the client side , in "real life" this parallel mechanism // Should on the server side if (IsParallel) { int processorCount = Environment.ProcessorCount; Console.WriteLine("Number Of Logical Processors: {0}", processorCount); Svc[] machines = new Svc[processorCount]; Stopwatch[] innerProductStopwatchArr = new Stopwatch[processorCount]; Stopwatch[] negateStopwatchArr = new Stopwatch[processorCount]; Stopwatch[] degreeStopwatchArr = new Stopwatch[processorCount]; Stopwatch[] serverDecisionStopWatchArr = new Stopwatch[processorCount]; Result[] results = new Result[numOfRows]; Task[] tasks = new Task[processorCount]; for (int i = 0; i < processorCount; i++) { machines[i] = new Svc(vectors, coefficients, intercepts, "Linear", 0.25, 0.0, 3, 40, publicKey /*, secretKey*/, relinKeys, galoisKeys, 1, 4); innerProductStopwatchArr[i] = new Stopwatch(); negateStopwatchArr[i] = new Stopwatch(); degreeStopwatchArr[i] = new Stopwatch(); serverDecisionStopWatchArr[i] = new Stopwatch(); } Stopwatch totalTime = new Stopwatch(); totalTime.Start(); for (int i = 0; i < numOfRows;) { for (int j = 0; j < processorCount && i < numOfRows; j++) { var secureSvc = machines[i % processorCount]; var feature = features[i]; //Console.WriteLine($"\n\n $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$"); List <object> l = new List <object>(); l.Add(secureSvc); //0 l.Add(feature); //1 l.Add(i); //2 l.Add(encoder); //3 l.Add(encryptor); //4 l.Add(decryptor); //5 l.Add(innerProductStopwatchArr[i % processorCount]); l.Add(degreeStopwatchArr[i % processorCount]); l.Add(negateStopwatchArr[i % processorCount]); l.Add(serverDecisionStopWatchArr[i % processorCount]); l.Add(results); tasks[j] = new TaskFactory().StartNew(new Action <object>((test) => { List <object> l2 = (List <object>)test; SinglePredict((Svc)l2[0], (double[])l2[1], (int)l2[2], (CKKSEncoder)l2[3], (Encryptor)l2[4], (Decryptor)l2[5], (Stopwatch)l2[6], (Stopwatch)l2[7], (Stopwatch)l2[8], (Stopwatch)l2[9], scale, (Result[])l2[10]); }), l); i++; } await Task.WhenAll(tasks); } totalTime.Stop(); for (int i = 0; i < numOfRows; i++) { var result = results[i]; file.WriteLine($"{i} , {result.Estimation} , {result.TotalValue} "); } double innerProductTime = 0; double degreeTime = 0; double negateTime = 0; double serverTime = 0; for (int i = 0; i < processorCount; i++) { innerProductTime = innerProductStopwatchArr[i].ElapsedMilliseconds; degreeTime = degreeStopwatchArr[i].ElapsedMilliseconds; negateTime = negateStopwatchArr[i].ElapsedMilliseconds; serverTime = serverDecisionStopWatchArr[i].ElapsedMilliseconds; } file.WriteLine($" Client time : {clientStopwatch.ElapsedMilliseconds} ms "); file.WriteLine($" Total time for {numOfRows} samples : {totalTime.ElapsedMilliseconds} ms "); file.WriteLine($" Avg time : {totalTime.ElapsedMilliseconds * 1000 / numOfRows} microSec "); file.WriteLine($" Inner Product time for {numOfRows} samples : {innerProductTime} ms "); file.WriteLine($" Inner Product Avg time : {innerProductTime * 1000 / numOfRows} microSec "); file.WriteLine($" Degree time for {numOfRows} samples : {degreeTime} ms "); file.WriteLine($" Degree Avg time : {degreeTime * 1000 / numOfRows} microSec "); file.WriteLine($" Negate time for {numOfRows} samples : {negateTime} ms "); file.WriteLine($" Negate Avg time : {negateTime * 1000 / numOfRows} microSec "); file.WriteLine($" Decision time for {numOfRows} samples : {serverTime} ms "); file.WriteLine($" Decision Avg time : {serverTime * 1000 / numOfRows} microSec "); } else { //Initiate Stopwatch for performance measure Stopwatch innerProductStopwatch = new Stopwatch(); Stopwatch negateStopwatch = new Stopwatch(); Stopwatch degreeStopwatch = new Stopwatch(); Stopwatch serverDecisionStopWatch = new Stopwatch(); int featureSizeWithSpace = numberOfFeatures; int batchSize = 200; if (batchSize > 1) { featureSizeWithSpace = numberOfFeatures * 2; } Svc clf = new Svc(vectors, coefficients, intercepts, "Linear", 0.25, 0.0, 3, 40, publicKey /*, secretKey*/, relinKeys, galoisKeys, batchSize, featureSizeWithSpace); Stopwatch totalTime = new Stopwatch(); totalTime.Start(); int start = 0; //double[] batchFeatures = new double[batchSize * featureSizeWithSpace]; for (int i = 0; i < numOfRows;) { start = i; double finalResult = -10000; double[][] batchRows = new double[batchSize][]; for (int j = 0; j < batchSize && i < numOfRows; j++) { batchRows[j] = features[i]; i++; } double[] batchFeatures = GetBatchFeatures(batchRows, batchSize, numberOfFeatures, featureSizeWithSpace); var plaintexts = new Plaintext(); var featuresCiphertexts = new Ciphertext(); encoder.Encode(batchFeatures, scale, plaintexts); encryptor.Encrypt(plaintexts, featuresCiphertexts); //Server side start var cypherResult = clf.Predict(featuresCiphertexts, true, true, innerProductStopwatch, degreeStopwatch, negateStopwatch, serverDecisionStopWatch); // Server side end Plaintext plainResult = new Plaintext(); decryptor.Decrypt(cypherResult, plainResult); List <double> result = new List <double>(); encoder.Decode(plainResult, result); for (int j = 0; j < batchSize && start < numOfRows; j++) { finalResult = result[j * featureSizeWithSpace]; int estimation = finalResult > 0 ? 0 : 1; Console.WriteLine($"\n ************************************************"); Console.WriteLine($"SVC estimation{i} is : {estimation} , result : {finalResult}"); file.WriteLine($"{start} , {estimation} , {finalResult} "); Console.WriteLine($"************************************************ \n"); start++; } } totalTime.Stop(); file.WriteLine($" Client time : {clientStopwatch.ElapsedMilliseconds} ms "); file.WriteLine($" Total time for {numOfRows} samples : {totalTime.ElapsedMilliseconds} ms "); file.WriteLine($" Avg time : {totalTime.ElapsedMilliseconds * 1000 / numOfRows} microSec "); file.WriteLine($" Inner Product time for {numOfRows} samples : {innerProductStopwatch.ElapsedMilliseconds} ms "); file.WriteLine($" Inner Product Avg time : {innerProductStopwatch.ElapsedMilliseconds * 1000 / numOfRows} microSec "); file.WriteLine($" Degree time for {numOfRows} samples : {degreeStopwatch.ElapsedMilliseconds} ms "); file.WriteLine($" Degree Avg time : {degreeStopwatch.ElapsedMilliseconds * 1000 / numOfRows} microSec "); file.WriteLine($" Negate time for {numOfRows} samples : {negateStopwatch.ElapsedMilliseconds} ms "); file.WriteLine($" Negate Avg time : {negateStopwatch.ElapsedMilliseconds * 1000 / numOfRows} microSec "); file.WriteLine($" Decision time for {numOfRows} samples : {serverDecisionStopWatch.ElapsedMilliseconds} ms "); file.WriteLine($" Decision Avg time : {serverDecisionStopWatch.ElapsedMilliseconds * 1000 / numOfRows} microSec "); } } }
public void ScaleTest() { List <SmallModulus> coeffModulus = new List <SmallModulus>() { DefaultParams.SmallMods40Bit(0), DefaultParams.SmallMods40Bit(1), DefaultParams.SmallMods40Bit(2), DefaultParams.SmallMods40Bit(3) }; EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS) { CoeffModulus = coeffModulus, PolyModulusDegree = 8 }; SEALContext context = SEALContext.Create(parms); KeyGenerator keygen = new KeyGenerator(context); GaloisKeys galoisKeys = keygen.GaloisKeys(decompositionBitCount: 4); Encryptor encryptor = new Encryptor(context, keygen.PublicKey); Evaluator evaluator = new Evaluator(context); CKKSEncoder encoder = new CKKSEncoder(context); MemoryPoolHandle pool = MemoryManager.GetPool(MMProfOpt.ForceNew); Assert.AreEqual(0ul, pool.AllocByteCount); Ciphertext encrypted = new Ciphertext(pool); Plaintext plain = new Plaintext(); MemoryPoolHandle cipherPool = encrypted.Pool; Assert.IsNotNull(cipherPool); Assert.AreEqual(0ul, cipherPool.AllocByteCount); List <Complex> input = new List <Complex>() { new Complex(1, 1), new Complex(2, 2), new Complex(3, 3), new Complex(4, 4) }; double delta = Math.Pow(2, 70); encoder.Encode(input, parms.ParmsId, delta, plain); encryptor.Encrypt(plain, encrypted); Assert.AreEqual(delta, encrypted.Scale, delta: Math.Pow(2, 60)); Ciphertext encrypted2 = new Ciphertext(); encrypted2.Set(encrypted); Assert.AreEqual(delta, encrypted2.Scale, delta: Math.Pow(2, 60)); evaluator.RescaleToNextInplace(encrypted); Assert.AreEqual(Math.Pow(2, 30), encrypted.Scale, delta: 10000); Assert.AreNotEqual(0ul, cipherPool.AllocByteCount); double newScale = Math.Pow(2, 10); encrypted.Scale = newScale; Assert.AreEqual(newScale, encrypted.Scale, delta: 100); }