// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using Microsoft.Research.SEAL; using Microsoft.VisualStudio.TestTools.UnitTesting; using System; using System.Collections.Generic; using System.IO; using System.Numerics; namespace SEALNetTest { [TestClass] public class EncryptorTests { [TestMethod] public void EncryptTest() { { SEALContext context = GlobalContext.BFVContext; KeyGenerator keygen = new KeyGenerator(context); keygen.CreatePublicKey(out PublicKey publicKey); SecretKey secretKey = keygen.SecretKey; Encryptor encryptor = new Encryptor(context, publicKey, secretKey); Assert.IsNotNull(encryptor); Plaintext plain = new Plaintext("1x^1 + 1"); Ciphertext cipher = new Ciphertext(); Assert.AreEqual(0ul, cipher.Size); encryptor.Encrypt(plain, cipher); Assert.IsNotNull(cipher); Assert.AreEqual(2ul, cipher.Size); } using (MemoryStream stream = new MemoryStream()) { SEALContext context = GlobalContext.BFVContext; KeyGenerator keygen = new KeyGenerator(context); keygen.CreatePublicKey(out PublicKey publicKey); Encryptor encryptor = new Encryptor(context, publicKey); Assert.IsNotNull(encryptor); Plaintext plain = new Plaintext("1x^1 + 1"); encryptor.Encrypt(plain).Save(stream); stream.Seek(0, SeekOrigin.Begin); Ciphertext cipher = new Ciphertext(); cipher.Load(context, stream); Assert.IsNotNull(cipher); Assert.AreEqual(2ul, cipher.Size); } { SEALContext context = GlobalContext.BFVContext; KeyGenerator keygen = new KeyGenerator(context); SecretKey secretKey = keygen.SecretKey; Encryptor encryptor = new Encryptor(context, secretKey); Assert.IsNotNull(encryptor); Plaintext plain = new Plaintext("1x^1 + 1"); Ciphertext cipher = new Ciphertext(); Assert.AreEqual(0ul, cipher.Size); encryptor.EncryptSymmetric(plain, cipher); Assert.IsNotNull(cipher); Assert.AreEqual(2ul, cipher.Size); } using (MemoryStream stream = new MemoryStream()) { SEALContext context = GlobalContext.BFVContext; KeyGenerator keygen = new KeyGenerator(context); SecretKey secretKey = keygen.SecretKey; Encryptor encryptor = new Encryptor(context, secretKey); Assert.IsNotNull(encryptor); Plaintext plain = new Plaintext("1x^1 + 1"); encryptor.EncryptSymmetric(plain).Save(stream); stream.Seek(0, SeekOrigin.Begin); Ciphertext cipher = new Ciphertext(); cipher.Load(context, stream); Assert.IsNotNull(cipher); Assert.AreEqual(2ul, cipher.Size); } { SEALContext context = GlobalContext.BGVContext; KeyGenerator keygen = new KeyGenerator(context); keygen.CreatePublicKey(out PublicKey publicKey); SecretKey secretKey = keygen.SecretKey; Encryptor encryptor = new Encryptor(context, publicKey, secretKey); Assert.IsNotNull(encryptor); Plaintext plain = new Plaintext("1x^1 + 1"); Ciphertext cipher = new Ciphertext(); Assert.AreEqual(0ul, cipher.Size); encryptor.Encrypt(plain, cipher); Assert.IsNotNull(cipher); Assert.AreEqual(2ul, cipher.Size); } using (MemoryStream stream = new MemoryStream()) { SEALContext context = GlobalContext.BGVContext; KeyGenerator keygen = new KeyGenerator(context); keygen.CreatePublicKey(out PublicKey publicKey); Encryptor encryptor = new Encryptor(context, publicKey); Assert.IsNotNull(encryptor); Plaintext plain = new Plaintext("1x^1 + 1"); encryptor.Encrypt(plain).Save(stream); stream.Seek(0, SeekOrigin.Begin); Ciphertext cipher = new Ciphertext(); cipher.Load(context, stream); Assert.IsNotNull(cipher); Assert.AreEqual(2ul, cipher.Size); } { SEALContext context = GlobalContext.BGVContext; KeyGenerator keygen = new KeyGenerator(context); SecretKey secretKey = keygen.SecretKey; Encryptor encryptor = new Encryptor(context, secretKey); Assert.IsNotNull(encryptor); Plaintext plain = new Plaintext("1x^1 + 1"); Ciphertext cipher = new Ciphertext(); Assert.AreEqual(0ul, cipher.Size); encryptor.EncryptSymmetric(plain, cipher); Assert.IsNotNull(cipher); Assert.AreEqual(2ul, cipher.Size); } using (MemoryStream stream = new MemoryStream()) { SEALContext context = GlobalContext.BGVContext; KeyGenerator keygen = new KeyGenerator(context); SecretKey secretKey = keygen.SecretKey; Encryptor encryptor = new Encryptor(context, secretKey); Assert.IsNotNull(encryptor); Plaintext plain = new Plaintext("1x^1 + 1"); encryptor.EncryptSymmetric(plain).Save(stream); stream.Seek(0, SeekOrigin.Begin); Ciphertext cipher = new Ciphertext(); cipher.Load(context, stream); Assert.IsNotNull(cipher); Assert.AreEqual(2ul, cipher.Size); } } [TestMethod] public void EncryptZeroTest() { { SEALContext context = GlobalContext.BFVContext; KeyGenerator keygen = new KeyGenerator(context); keygen.CreatePublicKey(out PublicKey publicKey); SecretKey secretKey = keygen.SecretKey; Decryptor decryptor = new Decryptor(context, secretKey); Assert.IsNotNull(decryptor); Ciphertext cipher = new Ciphertext(); Plaintext plain = new Plaintext(); ParmsId nextParms = context.FirstContextData.NextContextData.ParmsId; { Encryptor encryptor = new Encryptor(context, publicKey); Assert.IsNotNull(encryptor); encryptor.EncryptZero(cipher); Assert.IsFalse(cipher.IsNTTForm); Assert.IsFalse(cipher.IsTransparent); Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); decryptor.Decrypt(cipher, plain); Assert.IsTrue(plain.IsZero); encryptor.EncryptZero(nextParms, cipher); Assert.IsFalse(cipher.IsNTTForm); Assert.IsFalse(cipher.IsTransparent); Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); Assert.AreEqual(cipher.ParmsId, nextParms); decryptor.Decrypt(cipher, plain); Assert.IsTrue(plain.IsZero); } { Encryptor encryptor = new Encryptor(context, secretKey); encryptor.EncryptZeroSymmetric(cipher); Assert.IsFalse(cipher.IsNTTForm); Assert.IsFalse(cipher.IsTransparent); Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); decryptor.Decrypt(cipher, plain); Assert.IsTrue(plain.IsZero); encryptor.EncryptZeroSymmetric(nextParms, cipher); Assert.IsFalse(cipher.IsNTTForm); Assert.IsFalse(cipher.IsTransparent); Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); Assert.AreEqual(cipher.ParmsId, nextParms); decryptor.Decrypt(cipher, plain); Assert.IsTrue(plain.IsZero); } using (MemoryStream stream = new MemoryStream()) { Encryptor encryptor = new Encryptor(context, publicKey); encryptor.EncryptZero().Save(stream); stream.Seek(0, SeekOrigin.Begin); cipher.Load(context, stream); Assert.IsFalse(cipher.IsNTTForm); Assert.IsFalse(cipher.IsTransparent); Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); decryptor.Decrypt(cipher, plain); Assert.IsTrue(plain.IsZero); } using (MemoryStream stream = new MemoryStream()) { Encryptor encryptor = new Encryptor(context, publicKey); encryptor.EncryptZero(nextParms).Save(stream); stream.Seek(0, SeekOrigin.Begin); cipher.Load(context, stream); Assert.IsFalse(cipher.IsNTTForm); Assert.IsFalse(cipher.IsTransparent); Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); Assert.AreEqual(cipher.ParmsId, nextParms); decryptor.Decrypt(cipher, plain); Assert.IsTrue(plain.IsZero); } using (MemoryStream stream = new MemoryStream()) { Encryptor encryptor = new Encryptor(context, secretKey); encryptor.EncryptZeroSymmetric().Save(stream); stream.Seek(0, SeekOrigin.Begin); cipher.Load(context, stream); Assert.IsFalse(cipher.IsNTTForm); Assert.IsFalse(cipher.IsTransparent); Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); decryptor.Decrypt(cipher, plain); Assert.IsTrue(plain.IsZero); } using (MemoryStream stream = new MemoryStream()) { Encryptor encryptor = new Encryptor(context, secretKey); encryptor.EncryptZeroSymmetric(nextParms).Save(stream); stream.Seek(0, SeekOrigin.Begin); cipher.Load(context, stream); Assert.IsFalse(cipher.IsNTTForm); Assert.IsFalse(cipher.IsTransparent); Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); Assert.AreEqual(cipher.ParmsId, nextParms); decryptor.Decrypt(cipher, plain); Assert.IsTrue(plain.IsZero); } } { SEALContext context = GlobalContext.BGVContext; KeyGenerator keygen = new KeyGenerator(context); keygen.CreatePublicKey(out PublicKey publicKey); SecretKey secretKey = keygen.SecretKey; Decryptor decryptor = new Decryptor(context, secretKey); Assert.IsNotNull(decryptor); Ciphertext cipher = new Ciphertext(); Plaintext plain = new Plaintext(); ParmsId nextParms = context.FirstContextData.NextContextData.ParmsId; { Encryptor encryptor = new Encryptor(context, publicKey); Assert.IsNotNull(encryptor); encryptor.EncryptZero(cipher); Assert.IsFalse(cipher.IsNTTForm); Assert.IsFalse(cipher.IsTransparent); Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); decryptor.Decrypt(cipher, plain); Assert.IsTrue(plain.IsZero); encryptor.EncryptZero(nextParms, cipher); Assert.IsFalse(cipher.IsNTTForm); Assert.IsFalse(cipher.IsTransparent); Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); Assert.AreEqual(cipher.ParmsId, nextParms); decryptor.Decrypt(cipher, plain); Assert.IsTrue(plain.IsZero); } { Encryptor encryptor = new Encryptor(context, secretKey); encryptor.EncryptZeroSymmetric(cipher); Assert.IsFalse(cipher.IsNTTForm); Assert.IsFalse(cipher.IsTransparent); Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); decryptor.Decrypt(cipher, plain); Assert.IsTrue(plain.IsZero); encryptor.EncryptZeroSymmetric(nextParms, cipher); Assert.IsFalse(cipher.IsNTTForm); Assert.IsFalse(cipher.IsTransparent); Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); Assert.AreEqual(cipher.ParmsId, nextParms); decryptor.Decrypt(cipher, plain); Assert.IsTrue(plain.IsZero); } using (MemoryStream stream = new MemoryStream()) { Encryptor encryptor = new Encryptor(context, publicKey); encryptor.EncryptZero().Save(stream); stream.Seek(0, SeekOrigin.Begin); cipher.Load(context, stream); Assert.IsFalse(cipher.IsNTTForm); Assert.IsFalse(cipher.IsTransparent); Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); decryptor.Decrypt(cipher, plain); Assert.IsTrue(plain.IsZero); } using (MemoryStream stream = new MemoryStream()) { Encryptor encryptor = new Encryptor(context, publicKey); encryptor.EncryptZero(nextParms).Save(stream); stream.Seek(0, SeekOrigin.Begin); cipher.Load(context, stream); Assert.IsFalse(cipher.IsNTTForm); Assert.IsFalse(cipher.IsTransparent); Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); Assert.AreEqual(cipher.ParmsId, nextParms); decryptor.Decrypt(cipher, plain); Assert.IsTrue(plain.IsZero); } using (MemoryStream stream = new MemoryStream()) { Encryptor encryptor = new Encryptor(context, secretKey); encryptor.EncryptZeroSymmetric().Save(stream); stream.Seek(0, SeekOrigin.Begin); cipher.Load(context, stream); Assert.IsFalse(cipher.IsNTTForm); Assert.IsFalse(cipher.IsTransparent); Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); decryptor.Decrypt(cipher, plain); Assert.IsTrue(plain.IsZero); } using (MemoryStream stream = new MemoryStream()) { Encryptor encryptor = new Encryptor(context, secretKey); encryptor.EncryptZeroSymmetric(nextParms).Save(stream); stream.Seek(0, SeekOrigin.Begin); cipher.Load(context, stream); Assert.IsFalse(cipher.IsNTTForm); Assert.IsFalse(cipher.IsTransparent); Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); Assert.AreEqual(cipher.ParmsId, nextParms); decryptor.Decrypt(cipher, plain); Assert.IsTrue(plain.IsZero); } } { SEALContext context = GlobalContext.CKKSContext; KeyGenerator keygen = new KeyGenerator(context); keygen.CreatePublicKey(out PublicKey publicKey); SecretKey secretKey = keygen.SecretKey; Decryptor decryptor = new Decryptor(context, secretKey); CKKSEncoder encoder = new CKKSEncoder(context); Assert.IsNotNull(decryptor); Ciphertext cipher = new Ciphertext(); Plaintext plain = new Plaintext(); ParmsId nextParms = context.FirstContextData.NextContextData.ParmsId; List res = new List(); { Encryptor encryptor = new Encryptor(context, publicKey); Assert.IsNotNull(encryptor); encryptor.EncryptZero(cipher); Assert.IsTrue(cipher.IsNTTForm); Assert.IsFalse(cipher.IsTransparent); Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); cipher.Scale = Math.Pow(2.0, 30); decryptor.Decrypt(cipher, plain); encoder.Decode(plain, res); foreach (Complex val in res) { Assert.AreEqual(val.Real, 0.0, 0.01); Assert.AreEqual(val.Imaginary, 0.0, 0.01); } encryptor.EncryptZero(nextParms, cipher); Assert.IsTrue(cipher.IsNTTForm); Assert.IsFalse(cipher.IsTransparent); Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); cipher.Scale = Math.Pow(2.0, 30); Assert.AreEqual(cipher.ParmsId, nextParms); decryptor.Decrypt(cipher, plain); Assert.AreEqual(plain.ParmsId, nextParms); encoder.Decode(plain, res); foreach (Complex val in res) { Assert.AreEqual(val.Real, 0.0, 0.01); Assert.AreEqual(val.Imaginary, 0.0, 0.01); } } { Encryptor encryptor = new Encryptor(context, secretKey); encryptor.EncryptZeroSymmetric(cipher); Assert.IsTrue(cipher.IsNTTForm); Assert.IsFalse(cipher.IsTransparent); Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); cipher.Scale = Math.Pow(2.0, 30); decryptor.Decrypt(cipher, plain); encoder.Decode(plain, res); foreach (Complex val in res) { Assert.AreEqual(val.Real, 0.0, 0.01); Assert.AreEqual(val.Imaginary, 0.0, 0.01); } encryptor.EncryptZeroSymmetric(nextParms, cipher); Assert.IsTrue(cipher.IsNTTForm); Assert.IsFalse(cipher.IsTransparent); Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); cipher.Scale = Math.Pow(2.0, 30); Assert.AreEqual(cipher.ParmsId, nextParms); decryptor.Decrypt(cipher, plain); Assert.AreEqual(plain.ParmsId, nextParms); encoder.Decode(plain, res); foreach (Complex val in res) { Assert.AreEqual(val.Real, 0.0, 0.01); Assert.AreEqual(val.Imaginary, 0.0, 0.01); } } using (MemoryStream stream = new MemoryStream()) { Encryptor encryptor = new Encryptor(context, publicKey); encryptor.EncryptZero().Save(stream); stream.Seek(0, SeekOrigin.Begin); cipher.Load(context, stream); Assert.IsTrue(cipher.IsNTTForm); Assert.IsFalse(cipher.IsTransparent); Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); cipher.Scale = Math.Pow(2.0, 30); decryptor.Decrypt(cipher, plain); encoder.Decode(plain, res); foreach (Complex val in res) { Assert.AreEqual(val.Real, 0.0, 0.01); Assert.AreEqual(val.Imaginary, 0.0, 0.01); } } using (MemoryStream stream = new MemoryStream()) { Encryptor encryptor = new Encryptor(context, publicKey); encryptor.EncryptZero(nextParms).Save(stream); stream.Seek(0, SeekOrigin.Begin); cipher.Load(context, stream); Assert.IsTrue(cipher.IsNTTForm); Assert.IsFalse(cipher.IsTransparent); Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); cipher.Scale = Math.Pow(2.0, 30); Assert.AreEqual(cipher.ParmsId, nextParms); decryptor.Decrypt(cipher, plain); Assert.AreEqual(plain.ParmsId, nextParms); encoder.Decode(plain, res); foreach (Complex val in res) { Assert.AreEqual(val.Real, 0.0, 0.01); Assert.AreEqual(val.Imaginary, 0.0, 0.01); } } using (MemoryStream stream = new MemoryStream()) { Encryptor encryptor = new Encryptor(context, secretKey); encryptor.EncryptZeroSymmetric().Save(stream); stream.Seek(0, SeekOrigin.Begin); cipher.Load(context, stream); Assert.IsTrue(cipher.IsNTTForm); Assert.IsFalse(cipher.IsTransparent); Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); cipher.Scale = Math.Pow(2.0, 30); decryptor.Decrypt(cipher, plain); encoder.Decode(plain, res); foreach (Complex val in res) { Assert.AreEqual(val.Real, 0.0, 0.01); Assert.AreEqual(val.Imaginary, 0.0, 0.01); } } using (MemoryStream stream = new MemoryStream()) { Encryptor encryptor = new Encryptor(context, secretKey); encryptor.EncryptZeroSymmetric(nextParms).Save(stream); stream.Seek(0, SeekOrigin.Begin); cipher.Load(context, stream); Assert.IsTrue(cipher.IsNTTForm); Assert.IsFalse(cipher.IsTransparent); Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon); cipher.Scale = Math.Pow(2.0, 30); Assert.AreEqual(cipher.ParmsId, nextParms); decryptor.Decrypt(cipher, plain); Assert.AreEqual(plain.ParmsId, nextParms); encoder.Decode(plain, res); foreach (Complex val in res) { Assert.AreEqual(val.Real, 0.0, 0.01); Assert.AreEqual(val.Imaginary, 0.0, 0.01); } } } } [TestMethod] public void ExceptionsTest() { { SEALContext context = GlobalContext.BFVContext; KeyGenerator keygen = new KeyGenerator(context); keygen.CreatePublicKey(out PublicKey pubKey); PublicKey pubKey_invalid = new PublicKey(); SecretKey secKey = keygen.SecretKey; SecretKey secKey_invalid = new SecretKey(); Encryptor encryptor = new Encryptor(context, pubKey); Plaintext plain = new Plaintext(); Ciphertext cipher = new Ciphertext(); MemoryPoolHandle pool_invalid = new MemoryPoolHandle(); ParmsId parmsId_invalid = new ParmsId(); Utilities.AssertThrows(() => encryptor = new Encryptor(context, null)); Utilities.AssertThrows(() => encryptor = new Encryptor(null, pubKey)); Utilities.AssertThrows(() => encryptor = new Encryptor(context, pubKey_invalid)); Utilities.AssertThrows(() => encryptor = new Encryptor(context, pubKey_invalid, secKey)); encryptor = new Encryptor(context, pubKey, secKey); Utilities.AssertThrows(() => encryptor.SetPublicKey(pubKey_invalid)); Utilities.AssertThrows(() => encryptor.SetSecretKey(secKey_invalid)); Utilities.AssertThrows(() => encryptor.Encrypt(null, cipher)); Utilities.AssertThrows(() => encryptor.Encrypt(plain, cipher, pool_invalid)); Utilities.AssertThrows(() => encryptor.EncryptZero(cipher, pool_invalid)); Utilities.AssertThrows(() => encryptor.EncryptZero(parmsId_invalid, cipher)); Utilities.AssertThrows(() => encryptor.EncryptSymmetric(plain, destination: null)); Utilities.AssertThrows(() => encryptor.EncryptSymmetric(null, cipher)); Utilities.AssertThrows(() => encryptor.EncryptSymmetric(plain, cipher, pool_invalid)); Utilities.AssertThrows(() => encryptor.EncryptZeroSymmetric(cipher, pool_invalid)); Utilities.AssertThrows(() => encryptor.EncryptZeroSymmetric(parmsId_invalid, cipher)); Utilities.AssertThrows(() => encryptor.EncryptSymmetric(plain).Save(null)); Utilities.AssertThrows(() => encryptor.EncryptZeroSymmetric().Save(null)); } { SEALContext context = GlobalContext.BGVContext; KeyGenerator keygen = new KeyGenerator(context); keygen.CreatePublicKey(out PublicKey pubKey); PublicKey pubKey_invalid = new PublicKey(); SecretKey secKey = keygen.SecretKey; SecretKey secKey_invalid = new SecretKey(); Encryptor encryptor = new Encryptor(context, pubKey); Plaintext plain = new Plaintext(); Ciphertext cipher = new Ciphertext(); MemoryPoolHandle pool_invalid = new MemoryPoolHandle(); ParmsId parmsId_invalid = new ParmsId(); Utilities.AssertThrows(() => encryptor = new Encryptor(context, null)); Utilities.AssertThrows(() => encryptor = new Encryptor(null, pubKey)); Utilities.AssertThrows(() => encryptor = new Encryptor(context, pubKey_invalid)); Utilities.AssertThrows(() => encryptor = new Encryptor(context, pubKey_invalid, secKey)); encryptor = new Encryptor(context, pubKey, secKey); Utilities.AssertThrows(() => encryptor.SetPublicKey(pubKey_invalid)); Utilities.AssertThrows(() => encryptor.SetSecretKey(secKey_invalid)); Utilities.AssertThrows(() => encryptor.Encrypt(null, cipher)); Utilities.AssertThrows(() => encryptor.Encrypt(plain, cipher, pool_invalid)); Utilities.AssertThrows(() => encryptor.EncryptZero(cipher, pool_invalid)); Utilities.AssertThrows(() => encryptor.EncryptZero(parmsId_invalid, cipher)); Utilities.AssertThrows(() => encryptor.EncryptSymmetric(plain, destination: null)); Utilities.AssertThrows(() => encryptor.EncryptSymmetric(null, cipher)); Utilities.AssertThrows(() => encryptor.EncryptSymmetric(plain, cipher, pool_invalid)); Utilities.AssertThrows(() => encryptor.EncryptZeroSymmetric(cipher, pool_invalid)); Utilities.AssertThrows(() => encryptor.EncryptZeroSymmetric(parmsId_invalid, cipher)); Utilities.AssertThrows(() => encryptor.EncryptSymmetric(plain).Save(null)); Utilities.AssertThrows(() => encryptor.EncryptZeroSymmetric().Save(null)); } } } }