1 // Copyright (c) Microsoft Corporation. All rights reserved. 2 // Licensed under the MIT license. 3 4 using Microsoft.Research.SEAL; 5 using Microsoft.VisualStudio.TestTools.UnitTesting; 6 using System; 7 using System.Collections.Generic; 8 using System.Linq; 9 using System.Numerics; 10 11 namespace SEALNetTest 12 { 13 [TestClass] 14 public class EvaluatorTests 15 { 16 [TestMethod] CreateTest()17 public void CreateTest() 18 { 19 Evaluator evaluator = new Evaluator(GlobalContext.BFVContext); 20 Assert.IsNotNull(evaluator); 21 } 22 23 [TestMethod] NegateTest()24 public void NegateTest() 25 { 26 EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) 27 { 28 PolyModulusDegree = 64, 29 PlainModulus = new Modulus(1 << 6), 30 CoeffModulus = CoeffModulus.Create(64, new int[] { 40 }) 31 }; 32 SEALContext context = new SEALContext(parms, 33 expandModChain: false, 34 secLevel: SecLevelType.None); 35 KeyGenerator keygen = new KeyGenerator(context); 36 Assert.IsTrue(context.ParametersSet); 37 keygen.CreatePublicKey(out PublicKey publicKey); 38 39 Encryptor encryptor = new Encryptor(context, publicKey); 40 Decryptor decryptor = new Decryptor(context, keygen.SecretKey); 41 Evaluator evaluator = new Evaluator(context); 42 43 Ciphertext encrypted = new Ciphertext(); 44 Ciphertext encdestination = new Ciphertext(); 45 Plaintext plain = new Plaintext("3x^2 + 2x^1 + 1"); 46 Plaintext plaindest = new Plaintext(); 47 encryptor.Encrypt(plain, encrypted); 48 evaluator.Negate(encrypted, encdestination); 49 decryptor.Decrypt(encdestination, plaindest); 50 51 // coefficients are negated (modulo 64) 52 Assert.AreEqual(0x3Ful, plaindest[0]); 53 Assert.AreEqual(0x3Eul, plaindest[1]); 54 Assert.AreEqual(0x3Dul, plaindest[2]); 55 56 plain = new Plaintext("6x^3 + 7x^2 + 8x^1 + 9"); 57 encryptor.Encrypt(plain, encrypted); 58 evaluator.NegateInplace(encrypted); 59 decryptor.Decrypt(encrypted, plain); 60 61 // coefficients are negated (modulo 64) 62 Assert.AreEqual(0x37ul, plain[0]); 63 Assert.AreEqual(0x38ul, plain[1]); 64 Assert.AreEqual(0x39ul, plain[2]); 65 Assert.AreEqual(0x3Aul, plain[3]); 66 } 67 68 [TestMethod] AddTest()69 public void AddTest() 70 { 71 EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) 72 { 73 PolyModulusDegree = 64, 74 PlainModulus = new Modulus(1 << 6), 75 CoeffModulus = CoeffModulus.Create(64, new int[] { 40 }) 76 }; 77 SEALContext context = new SEALContext(parms, 78 expandModChain: false, 79 secLevel: SecLevelType.None); 80 KeyGenerator keygen = new KeyGenerator(context); 81 keygen.CreatePublicKey(out PublicKey publicKey); 82 83 Encryptor encryptor = new Encryptor(context, publicKey); 84 Decryptor decryptor = new Decryptor(context, keygen.SecretKey); 85 Evaluator evaluator = new Evaluator(context); 86 87 Ciphertext encrypted1 = new Ciphertext(); 88 Ciphertext encrypted2 = new Ciphertext(); 89 Ciphertext encdestination = new Ciphertext(); 90 91 Plaintext plain1 = new Plaintext("5x^4 + 4x^3 + 3x^2 + 2x^1 + 1"); 92 Plaintext plain2 = new Plaintext("4x^7 + 5x^6 + 6x^5 + 7x^4 + 8x^3 + 9x^2 + Ax^1 + B"); 93 Plaintext plaindest = new Plaintext(); 94 95 encryptor.Encrypt(plain1, encrypted1); 96 encryptor.Encrypt(plain2, encrypted2); 97 evaluator.Add(encrypted1, encrypted2, encdestination); 98 decryptor.Decrypt(encdestination, plaindest); 99 100 Assert.AreEqual(12ul, plaindest[0]); 101 Assert.AreEqual(12ul, plaindest[1]); 102 Assert.AreEqual(12ul, plaindest[2]); 103 Assert.AreEqual(12ul, plaindest[3]); 104 Assert.AreEqual(12ul, plaindest[4]); 105 Assert.AreEqual(6ul, plaindest[5]); 106 Assert.AreEqual(5ul, plaindest[6]); 107 Assert.AreEqual(4ul, plaindest[7]); 108 109 plain1 = new Plaintext("1x^2 + 2x^1 + 3"); 110 plain2 = new Plaintext("2x^3 + 2x^2 + 2x^1 + 2"); 111 112 encryptor.Encrypt(plain1, encrypted1); 113 encryptor.Encrypt(plain2, encrypted2); 114 evaluator.AddInplace(encrypted1, encrypted2); 115 decryptor.Decrypt(encrypted1, plaindest); 116 117 Assert.AreEqual(5ul, plaindest[0]); 118 Assert.AreEqual(4ul, plaindest[1]); 119 Assert.AreEqual(3ul, plaindest[2]); 120 Assert.AreEqual(2ul, plaindest[3]); 121 } 122 123 [TestMethod] AddPlainTest()124 public void AddPlainTest() 125 { 126 EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) 127 { 128 PolyModulusDegree = 64, 129 PlainModulus = new Modulus(1 << 6), 130 CoeffModulus = CoeffModulus.Create(64, new int[] { 40 }) 131 }; 132 SEALContext context = new SEALContext(parms, 133 expandModChain: false, 134 secLevel: SecLevelType.None); 135 KeyGenerator keygen = new KeyGenerator(context); 136 keygen.CreatePublicKey(out PublicKey publicKey); 137 138 Encryptor encryptor = new Encryptor(context, publicKey); 139 Decryptor decryptor = new Decryptor(context, keygen.SecretKey); 140 Evaluator evaluator = new Evaluator(context); 141 142 Ciphertext encrypted = new Ciphertext(); 143 Ciphertext encdest = new Ciphertext(); 144 Plaintext plain = new Plaintext("3x^2 + 2x^1 + 1"); 145 Plaintext plaindest = new Plaintext(); 146 147 encryptor.Encrypt(new Plaintext("2x^2 + 2x^1 + 2"), encrypted); 148 evaluator.AddPlain(encrypted, plain, encdest); 149 decryptor.Decrypt(encdest, plaindest); 150 151 Assert.AreEqual(3ul, plaindest[0]); 152 Assert.AreEqual(4ul, plaindest[1]); 153 Assert.AreEqual(5ul, plaindest[2]); 154 155 plain.Set("1x^2 + 1x^1 + 1"); 156 encryptor.Encrypt(new Plaintext("2x^3 + 2x^2 + 2x^1 + 2"), encrypted); 157 evaluator.AddPlainInplace(encrypted, plain); 158 decryptor.Decrypt(encrypted, plaindest); 159 160 Assert.AreEqual(4ul, plaindest.CoeffCount); 161 Assert.AreEqual(3ul, plaindest[0]); 162 Assert.AreEqual(3ul, plaindest[1]); 163 Assert.AreEqual(3ul, plaindest[2]); 164 Assert.AreEqual(2ul, plaindest[3]); 165 } 166 167 [TestMethod] AddManyTest()168 public void AddManyTest() 169 { 170 EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) 171 { 172 PolyModulusDegree = 64, 173 PlainModulus = new Modulus(1 << 6), 174 CoeffModulus = CoeffModulus.Create(64, new int[] { 40 }) 175 }; 176 SEALContext context = new SEALContext(parms, 177 expandModChain: false, 178 secLevel: SecLevelType.None); 179 KeyGenerator keygen = new KeyGenerator(context); 180 keygen.CreatePublicKey(out PublicKey publicKey); 181 182 Encryptor encryptor = new Encryptor(context, publicKey); 183 Decryptor decryptor = new Decryptor(context, keygen.SecretKey); 184 Evaluator evaluator = new Evaluator(context); 185 186 Ciphertext[] encrypteds = new Ciphertext[6]; 187 188 for(int i = 0; i < encrypteds.Length; i++) 189 { 190 encrypteds[i] = new Ciphertext(); 191 encryptor.Encrypt(new Plaintext((i + 1).ToString()), encrypteds[i]); 192 } 193 194 Ciphertext encdest = new Ciphertext(); 195 Plaintext plaindest = new Plaintext(); 196 evaluator.AddMany(encrypteds, encdest); 197 decryptor.Decrypt(encdest, plaindest); 198 199 // 1+2+3+4+5+6 200 Assert.AreEqual(21ul, plaindest[0]); 201 } 202 203 [TestMethod] SubTest()204 public void SubTest() 205 { 206 EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) 207 { 208 PolyModulusDegree = 64, 209 PlainModulus = new Modulus(1 << 6), 210 CoeffModulus = CoeffModulus.Create(64, new int[] { 40 }) 211 }; 212 SEALContext context = new SEALContext(parms, 213 expandModChain: false, 214 secLevel: SecLevelType.None); 215 KeyGenerator keygen = new KeyGenerator(context); 216 keygen.CreatePublicKey(out PublicKey publicKey); 217 218 Encryptor encryptor = new Encryptor(context, publicKey); 219 Decryptor decryptor = new Decryptor(context, keygen.SecretKey); 220 Evaluator evaluator = new Evaluator(context); 221 222 Ciphertext encrypted1 = new Ciphertext(); 223 Ciphertext encrypted2 = new Ciphertext(); 224 Ciphertext encdest = new Ciphertext(); 225 Plaintext plain1 = new Plaintext("Ax^2 + Bx^1 + C"); 226 Plaintext plain2 = new Plaintext("5x^3 + 5x^2 + 5x^1 + 5"); 227 Plaintext plaindest = new Plaintext(); 228 229 encryptor.Encrypt(plain1, encrypted1); 230 encryptor.Encrypt(plain2, encrypted2); 231 evaluator.Sub(encrypted1, encrypted2, encdest); 232 decryptor.Decrypt(encdest, plaindest); 233 234 Assert.AreEqual(7ul, plaindest[0]); 235 Assert.AreEqual(6ul, plaindest[1]); 236 Assert.AreEqual(5ul, plaindest[2]); 237 Assert.AreEqual(0x3Bul, plaindest[3]); 238 239 plain1.Set("Ax^3 + Bx^2 + Cx^1 + D"); 240 plain2.Set("5x^2 + 5x^1 + 5"); 241 242 encryptor.Encrypt(plain1, encrypted1); 243 encryptor.Encrypt(plain2, encrypted2); 244 evaluator.SubInplace(encrypted1, encrypted2); 245 decryptor.Decrypt(encrypted1, plaindest); 246 247 Assert.AreEqual(8ul, plaindest[0]); 248 Assert.AreEqual(7ul, plaindest[1]); 249 Assert.AreEqual(6ul, plaindest[2]); 250 Assert.AreEqual(10ul, plaindest[3]); 251 } 252 253 [TestMethod] SubPlainTest()254 public void SubPlainTest() 255 { 256 EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) 257 { 258 PolyModulusDegree = 64, 259 PlainModulus = new Modulus(1 << 6), 260 CoeffModulus = CoeffModulus.Create(64, new int[] { 40 }) 261 }; 262 SEALContext context = new SEALContext(parms, 263 expandModChain: false, 264 secLevel: SecLevelType.None); 265 KeyGenerator keygen = new KeyGenerator(context); 266 keygen.CreatePublicKey(out PublicKey publicKey); 267 268 Encryptor encryptor = new Encryptor(context, publicKey); 269 Decryptor decryptor = new Decryptor(context, keygen.SecretKey); 270 Evaluator evaluator = new Evaluator(context); 271 272 Ciphertext encrypted = new Ciphertext(); 273 Ciphertext encdest = new Ciphertext(); 274 Plaintext plain = new Plaintext("5x^2 + 4x^1 + 3"); 275 Plaintext plaindest = new Plaintext(); 276 277 encryptor.Encrypt(new Plaintext("3x^1 + 4"), encrypted); 278 evaluator.SubPlain(encrypted, plain, encdest); 279 decryptor.Decrypt(encdest, plaindest); 280 281 Assert.AreEqual(3ul, plaindest.CoeffCount); 282 Assert.AreEqual(1ul, plaindest[0]); 283 Assert.AreEqual(0x3Ful, plaindest[1]); // -1 284 Assert.AreEqual(0x3Bul, plaindest[2]); // -5 285 286 plain.Set("6x^3 + 1x^2 + 7x^1 + 2"); 287 encryptor.Encrypt(new Plaintext("Ax^2 + Bx^1 + C"), encrypted); 288 evaluator.SubPlainInplace(encrypted, plain); 289 decryptor.Decrypt(encrypted, plaindest); 290 291 Assert.AreEqual(4ul, plaindest.CoeffCount); 292 Assert.AreEqual(10ul, plaindest[0]); 293 Assert.AreEqual(4ul, plaindest[1]); 294 Assert.AreEqual(9ul, plaindest[2]); 295 Assert.AreEqual(0x3Aul, plaindest[3]); // -6 296 } 297 298 [TestMethod] MultiplyTest()299 public void MultiplyTest() 300 { 301 EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) 302 { 303 PolyModulusDegree = 64, 304 PlainModulus = new Modulus(1 << 6), 305 CoeffModulus = CoeffModulus.Create(64, new int[] { 40 }) 306 }; 307 SEALContext context = new SEALContext(parms, 308 expandModChain: false, 309 secLevel: SecLevelType.None); 310 KeyGenerator keygen = new KeyGenerator(context); 311 keygen.CreatePublicKey(out PublicKey publicKey); 312 313 Encryptor encryptor = new Encryptor(context, publicKey); 314 Decryptor decryptor = new Decryptor(context, keygen.SecretKey); 315 Evaluator evaluator = new Evaluator(context); 316 317 Ciphertext encrypted1 = new Ciphertext(); 318 Ciphertext encrypted2 = new Ciphertext(); 319 Ciphertext encdest = new Ciphertext(); 320 Plaintext plaindest = new Plaintext(); 321 322 encryptor.Encrypt(new Plaintext("1x^4 + 2x^3 + 3x^2 + 4x^1 + 5"), encrypted1); 323 encryptor.Encrypt(new Plaintext("3x^2 + 2x^1 + 1"), encrypted2); 324 evaluator.Multiply(encrypted1, encrypted2, encdest); 325 decryptor.Decrypt(encdest, plaindest); 326 327 // {3x^6 + 8x^5 + Ex^4 + 14x^3 + 1Ax^2 + Ex^1 + 5} 328 Assert.AreEqual(7ul, plaindest.CoeffCount); 329 Assert.AreEqual(5ul, plaindest[0]); 330 Assert.AreEqual(14ul, plaindest[1]); 331 Assert.AreEqual(26ul, plaindest[2]); 332 Assert.AreEqual(20ul, plaindest[3]); 333 Assert.AreEqual(14ul, plaindest[4]); 334 Assert.AreEqual(8ul, plaindest[5]); 335 Assert.AreEqual(3ul, plaindest[6]); 336 337 encryptor.Encrypt(new Plaintext("2x^2 + 3x^1 + 4"), encrypted1); 338 encryptor.Encrypt(new Plaintext("4x^1 + 5"), encrypted2); 339 evaluator.MultiplyInplace(encrypted1, encrypted2); 340 decryptor.Decrypt(encrypted1, plaindest); 341 342 // {8x^3 + 16x^2 + 1Fx^1 + 14} 343 Assert.AreEqual(4ul, plaindest.CoeffCount); 344 Assert.AreEqual(20ul, plaindest[0]); 345 Assert.AreEqual(31ul, plaindest[1]); 346 Assert.AreEqual(22ul, plaindest[2]); 347 Assert.AreEqual(8ul, plaindest[3]); 348 } 349 350 [TestMethod] MultiplyManyTest()351 public void MultiplyManyTest() 352 { 353 EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) 354 { 355 PolyModulusDegree = 128, 356 PlainModulus = new Modulus(1 << 6), 357 CoeffModulus = CoeffModulus.Create(128, new int[] { 40, 40, 40 }) 358 }; 359 SEALContext context = new SEALContext(parms, 360 expandModChain: false, 361 secLevel: SecLevelType.None); 362 KeyGenerator keygen = new KeyGenerator(context); 363 keygen.CreatePublicKey(out PublicKey publicKey); 364 keygen.CreateRelinKeys(out RelinKeys relinKeys); 365 366 Encryptor encryptor = new Encryptor(context, publicKey); 367 Decryptor decryptor = new Decryptor(context, keygen.SecretKey); 368 Evaluator evaluator = new Evaluator(context); 369 370 Ciphertext[] encrypteds = new Ciphertext[4]; 371 Ciphertext encdest = new Ciphertext(); 372 Plaintext plaindest = new Plaintext(); 373 374 for (int i = 0; i < encrypteds.Length; i++) 375 { 376 encrypteds[i] = new Ciphertext(); 377 encryptor.Encrypt(new Plaintext((i + 1).ToString()), encrypteds[i]); 378 } 379 380 evaluator.MultiplyMany(encrypteds, relinKeys, encdest); 381 decryptor.Decrypt(encdest, plaindest); 382 383 Assert.AreEqual(1ul, plaindest.CoeffCount); 384 Assert.AreEqual(24ul, plaindest[0]); 385 386 Utilities.AssertThrows<ArgumentException>(() => 387 { 388 // Uninitialized memory pool handle 389 MemoryPoolHandle pool = new MemoryPoolHandle(); 390 evaluator.MultiplyMany(encrypteds, relinKeys, encdest, pool); 391 }); 392 } 393 394 [TestMethod] MultiplyPlainTest()395 public void MultiplyPlainTest() 396 { 397 EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) 398 { 399 PolyModulusDegree = 128, 400 PlainModulus = new Modulus(1 << 6), 401 CoeffModulus = CoeffModulus.Create(128, new int[] { 40, 40 }) 402 }; 403 SEALContext context = new SEALContext(parms, 404 expandModChain: false, 405 secLevel: SecLevelType.None); 406 KeyGenerator keygen = new KeyGenerator(context); 407 keygen.CreatePublicKey(out PublicKey publicKey); 408 keygen.CreateRelinKeys(out RelinKeys relinKeys); 409 410 Encryptor encryptor = new Encryptor(context, publicKey); 411 Decryptor decryptor = new Decryptor(context, keygen.SecretKey); 412 Evaluator evaluator = new Evaluator(context); 413 414 Ciphertext encrypted = new Ciphertext(); 415 Ciphertext encdest = new Ciphertext(); 416 Plaintext plain = new Plaintext("2x^2 + 1"); 417 Plaintext plaindest = new Plaintext(); 418 419 encryptor.Encrypt(new Plaintext("3x^2 + 2"), encrypted); 420 evaluator.MultiplyPlain(encrypted, plain, encdest); 421 decryptor.Decrypt(encdest, plaindest); 422 423 // {6x^4 + 7x^2 + 2} 424 Assert.AreEqual(5ul, plaindest.CoeffCount); 425 Assert.AreEqual(2ul, plaindest[0]); 426 Assert.AreEqual(0ul, plaindest[1]); 427 Assert.AreEqual(7ul, plaindest[2]); 428 Assert.AreEqual(0ul, plaindest[3]); 429 Assert.AreEqual(6ul, plaindest[4]); 430 431 encryptor.Encrypt(new Plaintext("4x^1 + 3"), encrypted); 432 plain.Set("2x^2 + 1"); 433 evaluator.MultiplyPlainInplace(encrypted, plain); 434 decryptor.Decrypt(encrypted, plaindest); 435 436 // {8x^3 + 6x^2 + 4x^1 + 3} 437 Assert.AreEqual(4ul, plaindest.CoeffCount); 438 Assert.AreEqual(3ul, plaindest[0]); 439 Assert.AreEqual(4ul, plaindest[1]); 440 Assert.AreEqual(6ul, plaindest[2]); 441 Assert.AreEqual(8ul, plaindest[3]); 442 443 encryptor.Encrypt(new Plaintext("4x^1 + 3"), encrypted); 444 plain.Set("3x^5"); 445 evaluator.MultiplyPlainInplace(encrypted, plain); 446 decryptor.Decrypt(encrypted, plaindest); 447 448 // {Cx^6 + 9x^5} 449 Assert.AreEqual(7ul, plaindest.CoeffCount); 450 Assert.AreEqual(2ul, plaindest.NonZeroCoeffCount); 451 Assert.AreEqual(0ul, plaindest[0]); 452 Assert.AreEqual(0ul, plaindest[1]); 453 Assert.AreEqual(0ul, plaindest[2]); 454 Assert.AreEqual(0ul, plaindest[3]); 455 Assert.AreEqual(0ul, plaindest[4]); 456 Assert.AreEqual(9ul, plaindest[5]); 457 Assert.AreEqual(12ul, plaindest[6]); 458 459 Utilities.AssertThrows<ArgumentException>(() => 460 { 461 // Uninitialized pool 462 MemoryPoolHandle pool = new MemoryPoolHandle(); 463 evaluator.MultiplyPlain(encrypted, plain, encdest, pool); 464 }); 465 } 466 467 [TestMethod] SquareTest()468 public void SquareTest() 469 { 470 EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) 471 { 472 PolyModulusDegree = 128, 473 PlainModulus = new Modulus(1 << 6), 474 CoeffModulus = CoeffModulus.Create(128, new int[] { 40, 40 }) 475 }; 476 SEALContext context = new SEALContext(parms, 477 expandModChain: false, 478 secLevel: SecLevelType.None); 479 KeyGenerator keygen = new KeyGenerator(context); 480 keygen.CreatePublicKey(out PublicKey publicKey); 481 482 Encryptor encryptor = new Encryptor(context, publicKey); 483 Decryptor decryptor = new Decryptor(context, keygen.SecretKey); 484 Evaluator evaluator = new Evaluator(context); 485 486 Ciphertext encrypted = new Ciphertext(); 487 Ciphertext encdest = new Ciphertext(); 488 Plaintext plain = new Plaintext("2x^2 + 3x^1 + 4"); 489 Plaintext plaindest = new Plaintext(); 490 491 encryptor.Encrypt(plain, encrypted); 492 evaluator.Square(encrypted, encdest); 493 decryptor.Decrypt(encdest, plaindest); 494 495 // {4x^4 + Cx^3 + 19x^2 + 18x^1 + 10} 496 Assert.AreEqual(5ul, plaindest.CoeffCount); 497 Assert.AreEqual(16ul, plaindest[0]); 498 Assert.AreEqual(24ul, plaindest[1]); 499 Assert.AreEqual(25ul, plaindest[2]); 500 Assert.AreEqual(12ul, plaindest[3]); 501 Assert.AreEqual(4ul, plaindest[4]); 502 503 encryptor.Encrypt(new Plaintext("3x^1 + 2"), encrypted); 504 evaluator.SquareInplace(encrypted); 505 decryptor.Decrypt(encrypted, plaindest); 506 507 // {9x^2 + Cx^1 + 4} 508 Assert.AreEqual(3ul, plaindest.CoeffCount); 509 Assert.AreEqual(4ul, plaindest[0]); 510 Assert.AreEqual(12ul, plaindest[1]); 511 Assert.AreEqual(9ul, plaindest[2]); 512 } 513 514 [TestMethod] ExponentiateTest()515 public void ExponentiateTest() 516 { 517 EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) 518 { 519 PolyModulusDegree = 128, 520 PlainModulus = new Modulus(1 << 6), 521 CoeffModulus = CoeffModulus.Create(128, new int[] { 40, 40, 40 }) 522 }; 523 SEALContext context = new SEALContext(parms, 524 expandModChain: false, 525 secLevel: SecLevelType.None); 526 KeyGenerator keygen = new KeyGenerator(context); 527 keygen.CreatePublicKey(out PublicKey publicKey); 528 keygen.CreateRelinKeys(out RelinKeys relinKeys); 529 530 Encryptor encryptor = new Encryptor(context, publicKey); 531 Decryptor decryptor = new Decryptor(context, keygen.SecretKey); 532 Evaluator evaluator = new Evaluator(context); 533 534 Ciphertext encrypted = new Ciphertext(); 535 Ciphertext encdest = new Ciphertext(); 536 Plaintext plain = new Plaintext(); 537 538 encryptor.Encrypt(new Plaintext("2x^2 + 1"), encrypted); 539 evaluator.Exponentiate(encrypted, 3, relinKeys, encdest); 540 decryptor.Decrypt(encdest, plain); 541 542 // {8x^6 + Cx^4 + 6x^2 + 1} 543 Assert.AreEqual(7ul, plain.CoeffCount); 544 Assert.AreEqual(1ul, plain[0]); 545 Assert.AreEqual(0ul, plain[1]); 546 Assert.AreEqual(6ul, plain[2]); 547 Assert.AreEqual(0ul, plain[3]); 548 Assert.AreEqual(12ul, plain[4]); 549 Assert.AreEqual(0ul, plain[5]); 550 Assert.AreEqual(8ul, plain[6]); 551 552 encryptor.Encrypt(new Plaintext("3x^3 + 2"), encrypted); 553 evaluator.ExponentiateInplace(encrypted, 4, relinKeys); 554 decryptor.Decrypt(encrypted, plain); 555 556 // {11x^12 + 18x^9 + 18x^6 + 20x^3 + 10} 557 Assert.AreEqual(13ul, plain.CoeffCount); 558 Assert.AreEqual(16ul, plain[0]); 559 Assert.AreEqual(0ul, plain[1]); 560 Assert.AreEqual(0ul, plain[2]); 561 Assert.AreEqual(32ul, plain[3]); 562 Assert.AreEqual(0ul, plain[4]); 563 Assert.AreEqual(0ul, plain[5]); 564 Assert.AreEqual(24ul, plain[6]); 565 Assert.AreEqual(0ul, plain[7]); 566 Assert.AreEqual(0ul, plain[8]); 567 Assert.AreEqual(24ul, plain[9]); 568 Assert.AreEqual(0ul, plain[10]); 569 Assert.AreEqual(0ul, plain[11]); 570 Assert.AreEqual(17ul, plain[12]); 571 } 572 573 [TestMethod] ApplyGaloisTest()574 public void ApplyGaloisTest() 575 { 576 EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) 577 { 578 PolyModulusDegree = 8, 579 PlainModulus = new Modulus(257), 580 CoeffModulus = CoeffModulus.Create(8, new int[] { 40, 40 }) 581 }; 582 SEALContext context = new SEALContext(parms, 583 expandModChain: false, 584 secLevel: SecLevelType.None); 585 KeyGenerator keygen = new KeyGenerator(context); 586 keygen.CreatePublicKey(out PublicKey publicKey); 587 keygen.CreateGaloisKeys(galoisElts: new uint[] { 1u, 3u, 5u, 15u }, out GaloisKeys galoisKeys); 588 589 Encryptor encryptor = new Encryptor(context, publicKey); 590 Decryptor decryptor = new Decryptor(context, keygen.SecretKey); 591 Evaluator evaluator = new Evaluator(context); 592 593 Plaintext plain = new Plaintext("1"); 594 Plaintext plaindest = new Plaintext(); 595 Ciphertext encrypted = new Ciphertext(); 596 Ciphertext encdest = new Ciphertext(); 597 598 encryptor.Encrypt(plain, encrypted); 599 evaluator.ApplyGalois(encrypted, galoisElt: 1, galoisKeys: galoisKeys, destination: encdest); 600 decryptor.Decrypt(encdest, plaindest); 601 602 Assert.AreEqual(1ul, plaindest.CoeffCount); 603 Assert.AreEqual(1ul, plaindest[0]); 604 605 plain.Set("1x^1"); 606 encryptor.Encrypt(plain, encrypted); 607 evaluator.ApplyGalois(encrypted, galoisElt: 1, galoisKeys: galoisKeys, destination: encdest); 608 decryptor.Decrypt(encdest, plaindest); 609 610 // {1x^1} 611 Assert.AreEqual(2ul, plaindest.CoeffCount); 612 Assert.AreEqual(0ul, plaindest[0]); 613 Assert.AreEqual(1ul, plaindest[1]); 614 615 evaluator.ApplyGalois(encdest, galoisElt: 3, galoisKeys: galoisKeys, destination: encrypted); 616 decryptor.Decrypt(encrypted, plaindest); 617 618 // {1x^3} 619 Assert.AreEqual(4ul, plaindest.CoeffCount); 620 Assert.AreEqual(0ul, plaindest[0]); 621 Assert.AreEqual(0ul, plaindest[1]); 622 Assert.AreEqual(0ul, plaindest[2]); 623 Assert.AreEqual(1ul, plaindest[3]); 624 625 evaluator.ApplyGalois(encrypted, galoisElt: 5, galoisKeys: galoisKeys, destination: encdest); 626 decryptor.Decrypt(encdest, plaindest); 627 628 // {100x^7} 629 Assert.AreEqual(8ul, plaindest.CoeffCount); 630 Assert.AreEqual(0ul, plaindest[0]); 631 Assert.AreEqual(0ul, plaindest[1]); 632 Assert.AreEqual(0ul, plaindest[2]); 633 Assert.AreEqual(0ul, plaindest[3]); 634 Assert.AreEqual(0ul, plaindest[4]); 635 Assert.AreEqual(0ul, plaindest[5]); 636 Assert.AreEqual(0ul, plaindest[6]); 637 Assert.AreEqual(256ul, plaindest[7]); 638 639 plain.Set("1x^2"); 640 encryptor.Encrypt(plain, encrypted); 641 evaluator.ApplyGaloisInplace(encrypted, 1, galoisKeys); 642 decryptor.Decrypt(encrypted, plaindest); 643 644 // {1x^2} 645 Assert.AreEqual(3ul, plaindest.CoeffCount); 646 Assert.AreEqual(0ul, plaindest[0]); 647 Assert.AreEqual(0ul, plaindest[1]); 648 Assert.AreEqual(1ul, plaindest[2]); 649 650 evaluator.ApplyGaloisInplace(encrypted, 3, galoisKeys); 651 decryptor.Decrypt(encrypted, plaindest); 652 653 // {1x^6} 654 Assert.AreEqual(7ul, plaindest.CoeffCount); 655 Assert.AreEqual(0ul, plaindest[0]); 656 Assert.AreEqual(0ul, plaindest[1]); 657 Assert.AreEqual(0ul, plaindest[2]); 658 Assert.AreEqual(0ul, plaindest[3]); 659 Assert.AreEqual(0ul, plaindest[4]); 660 Assert.AreEqual(0ul, plaindest[5]); 661 Assert.AreEqual(1ul, plaindest[6]); 662 663 evaluator.ApplyGaloisInplace(encrypted, 5, galoisKeys); 664 decryptor.Decrypt(encrypted, plaindest); 665 666 // {100x^6} 667 Assert.AreEqual(7ul, plaindest.CoeffCount); 668 Assert.AreEqual(0ul, plaindest[0]); 669 Assert.AreEqual(0ul, plaindest[1]); 670 Assert.AreEqual(0ul, plaindest[2]); 671 Assert.AreEqual(0ul, plaindest[3]); 672 Assert.AreEqual(0ul, plaindest[4]); 673 Assert.AreEqual(0ul, plaindest[5]); 674 Assert.AreEqual(256ul, plaindest[6]); 675 } 676 677 [TestMethod] TransformPlainToNTTTest()678 public void TransformPlainToNTTTest() 679 { 680 EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) 681 { 682 PolyModulusDegree = 128, 683 PlainModulus = new Modulus(1 << 6), 684 CoeffModulus = CoeffModulus.Create(128, new int[] { 40, 40, 40 }) 685 }; 686 SEALContext context = new SEALContext(parms, 687 expandModChain: false, 688 secLevel: SecLevelType.None); 689 Evaluator evaluator = new Evaluator(context); 690 691 Plaintext plain = new Plaintext("0"); 692 Plaintext plaindest = new Plaintext(); 693 Assert.IsFalse(plain.IsNTTForm); 694 695 evaluator.TransformToNTT(plain, context.FirstParmsId, plaindest); 696 Assert.IsTrue(plaindest.IsZero); 697 Assert.IsTrue(plaindest.IsNTTForm); 698 Assert.IsTrue(plaindest.ParmsId == context.FirstParmsId); 699 700 plain = new Plaintext("1"); 701 Assert.IsFalse(plain.IsNTTForm); 702 703 evaluator.TransformToNTTInplace(plain, context.FirstParmsId); 704 Assert.IsTrue(plain.IsNTTForm); 705 706 for (ulong i = 0; i < 256; i++) 707 { 708 Assert.AreEqual(1ul, plain[i]); 709 } 710 } 711 712 [TestMethod] TransformEncryptedToNTTTest()713 public void TransformEncryptedToNTTTest() 714 { 715 EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) 716 { 717 PolyModulusDegree = 128, 718 PlainModulus = new Modulus(1 << 6), 719 CoeffModulus = CoeffModulus.Create(128, new int[] { 40, 40 }) 720 }; 721 SEALContext context = new SEALContext(parms, 722 expandModChain: false, 723 secLevel: SecLevelType.None); 724 KeyGenerator keygen = new KeyGenerator(context); 725 keygen.CreatePublicKey(out PublicKey publicKey); 726 727 Encryptor encryptor = new Encryptor(context, publicKey); 728 Decryptor decryptor = new Decryptor(context, keygen.SecretKey); 729 Evaluator evaluator = new Evaluator(context); 730 731 Ciphertext encrypted = new Ciphertext(); 732 Ciphertext encdest = new Ciphertext(); 733 Ciphertext encdest2 = new Ciphertext(); 734 Plaintext plaindest = new Plaintext(); 735 736 encryptor.Encrypt(new Plaintext("0"), encrypted); 737 Assert.IsFalse(encrypted.IsNTTForm); 738 739 evaluator.TransformToNTT(encrypted, encdest); 740 Assert.IsTrue(encdest.IsNTTForm); 741 742 evaluator.TransformFromNTT(encdest, encdest2); 743 Assert.IsFalse(encdest2.IsNTTForm); 744 745 decryptor.Decrypt(encdest2, plaindest); 746 Assert.AreEqual(1ul, plaindest.CoeffCount); 747 Assert.AreEqual(0ul, plaindest[0]); 748 Assert.AreEqual(context.FirstParmsId, encdest2.ParmsId); 749 750 encryptor.Encrypt(new Plaintext("1"), encrypted); 751 Assert.IsFalse(encrypted.IsNTTForm); 752 753 evaluator.TransformToNTTInplace(encrypted); 754 Assert.IsTrue(encrypted.IsNTTForm); 755 756 evaluator.TransformFromNTTInplace(encrypted); 757 Assert.IsFalse(encrypted.IsNTTForm); 758 759 decryptor.Decrypt(encrypted, plaindest); 760 761 Assert.AreEqual(1ul, plaindest.CoeffCount); 762 Assert.AreEqual(1ul, plaindest[0]); 763 Assert.AreEqual(context.FirstParmsId, encrypted.ParmsId); 764 } 765 766 [TestMethod] ModSwitchToNextTest()767 public void ModSwitchToNextTest() 768 { 769 EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) 770 { 771 PolyModulusDegree = 128, 772 PlainModulus = new Modulus(1 << 6), 773 CoeffModulus = CoeffModulus.Create(128, new int[] { 30, 30, 30 }) 774 }; 775 SEALContext context = new SEALContext(parms, 776 expandModChain: true, 777 secLevel: SecLevelType.None); 778 KeyGenerator keygen = new KeyGenerator(context); 779 keygen.CreatePublicKey(out PublicKey publicKey); 780 781 Encryptor encryptor = new Encryptor(context, publicKey); 782 Decryptor decryptor = new Decryptor(context, keygen.SecretKey); 783 Evaluator evaluator = new Evaluator(context); 784 785 Ciphertext encrypted = new Ciphertext(context); 786 Ciphertext encdest = new Ciphertext(); 787 Plaintext plain = new Plaintext(); 788 789 plain.Set("0"); 790 encryptor.Encrypt(plain, encrypted); 791 evaluator.ModSwitchToNext(encrypted, encdest); 792 decryptor.Decrypt(encdest, plain); 793 794 Assert.AreEqual(1ul, plain.CoeffCount); 795 Assert.AreEqual(0ul, plain[0]); 796 797 plain.Set("1"); 798 encryptor.Encrypt(plain, encrypted); 799 evaluator.ModSwitchToNextInplace(encrypted); 800 decryptor.Decrypt(encrypted, plain); 801 802 Assert.AreEqual(1ul, plain.CoeffCount); 803 Assert.AreEqual(1ul, plain[0]); 804 } 805 806 [TestMethod] ModSwitchToTest()807 public void ModSwitchToTest() 808 { 809 EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) 810 { 811 PolyModulusDegree = 128, 812 PlainModulus = new Modulus(1 << 6), 813 CoeffModulus = CoeffModulus.Create(128, new int[] { 30, 30, 30, 30 }) 814 }; 815 SEALContext context = new SEALContext(parms, 816 expandModChain: true, 817 secLevel: SecLevelType.None); 818 KeyGenerator keygen = new KeyGenerator(context); 819 keygen.CreatePublicKey(out PublicKey publicKey); 820 821 Encryptor encryptor = new Encryptor(context, publicKey); 822 Decryptor decryptor = new Decryptor(context, keygen.SecretKey); 823 Evaluator evaluator = new Evaluator(context); 824 825 Ciphertext encrypted = new Ciphertext(context); 826 Ciphertext encdest = new Ciphertext(context); 827 Plaintext plaindest = new Plaintext(); 828 829 encryptor.Encrypt(new Plaintext("1"), encrypted); 830 ParmsId destParmsId = context.FirstContextData.NextContextData 831 .NextContextData.ParmsId; 832 833 evaluator.ModSwitchTo(encrypted, context.FirstParmsId, encdest); 834 decryptor.Decrypt(encdest, plaindest); 835 836 Assert.IsTrue(encrypted.ParmsId == context.FirstParmsId); 837 Assert.IsTrue(encdest.ParmsId == context.FirstParmsId); 838 Assert.AreEqual(1ul, plaindest.CoeffCount); 839 Assert.AreEqual(1ul, plaindest[0]); 840 841 evaluator.ModSwitchTo(encrypted, destParmsId, encdest); 842 decryptor.Decrypt(encdest, plaindest); 843 844 Assert.IsTrue(encrypted.ParmsId == context.FirstParmsId); 845 Assert.IsTrue(encdest.ParmsId == destParmsId); 846 Assert.AreEqual(1ul, plaindest.CoeffCount); 847 Assert.AreEqual(1ul, plaindest[0]); 848 849 encryptor.Encrypt(new Plaintext("3x^2 + 2x^1 + 1"), encrypted); 850 evaluator.ModSwitchToInplace(encrypted, context.FirstParmsId); 851 decryptor.Decrypt(encrypted, plaindest); 852 853 Assert.IsTrue(encrypted.ParmsId == context.FirstParmsId); 854 Assert.AreEqual(3ul, plaindest.CoeffCount); 855 Assert.AreEqual(1ul, plaindest[0]); 856 Assert.AreEqual(2ul, plaindest[1]); 857 Assert.AreEqual(3ul, plaindest[2]); 858 859 evaluator.ModSwitchToInplace(encrypted, destParmsId); 860 decryptor.Decrypt(encrypted, plaindest); 861 862 Assert.IsTrue(encrypted.ParmsId == destParmsId); 863 Assert.AreEqual(3ul, plaindest.CoeffCount); 864 Assert.AreEqual(1ul, plaindest[0]); 865 Assert.AreEqual(2ul, plaindest[1]); 866 Assert.AreEqual(3ul, plaindest[2]); 867 } 868 869 [TestMethod] ModSwitchToPlainTest()870 public void ModSwitchToPlainTest() 871 { 872 EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS) 873 { 874 PolyModulusDegree = 1024, 875 CoeffModulus = CoeffModulus.Create(1024, new int[] { 40, 40, 40, 40, 40 }) 876 }; 877 878 SEALContext context = new SEALContext(parms, 879 expandModChain: true, 880 secLevel: SecLevelType.None); 881 CKKSEncoder encoder = new CKKSEncoder(context); 882 KeyGenerator keygen = new KeyGenerator(context); 883 SecretKey secretKey = keygen.SecretKey; 884 keygen.CreatePublicKey(out PublicKey publicKey); 885 keygen.CreateRelinKeys(out RelinKeys relinKeys); 886 887 Encryptor encryptor = new Encryptor(context, publicKey); 888 Evaluator evaluator = new Evaluator(context); 889 Decryptor decryptor = new Decryptor(context, secretKey); 890 891 double scale = parms.CoeffModulus.Last().Value; 892 Plaintext coeff1 = new Plaintext(); 893 Plaintext coeff2 = new Plaintext(); 894 Plaintext coeff3 = new Plaintext(); 895 encoder.Encode(2.0, scale, coeff1); 896 encoder.Encode(3.0, scale, coeff2); 897 encoder.Encode(1.0, scale, coeff3); 898 899 Ciphertext encX1 = new Ciphertext(); 900 Ciphertext encX2 = new Ciphertext(); 901 Ciphertext encX3 = new Ciphertext(); 902 encryptor.Encrypt(coeff1, encX1); 903 evaluator.Square(encX1, encX3); 904 evaluator.MultiplyPlain(encX1, coeff2, encX2); 905 evaluator.RelinearizeInplace(encX3, relinKeys); 906 evaluator.RescaleToNextInplace(encX3); 907 evaluator.RelinearizeInplace(encX2, relinKeys); 908 evaluator.RescaleToInplace(encX2, encX3.ParmsId); 909 910 evaluator.ModSwitchToInplace(coeff3, encX3.ParmsId); 911 evaluator.ModSwitchToNextInplace(coeff2); 912 913 evaluator.MultiplyPlainInplace(encX3, coeff3); 914 915 Plaintext result = new Plaintext(); 916 decryptor.Decrypt(encX3, result); 917 Assert.IsNotNull(result); 918 919 List<double> destination = new List<double>(); 920 encoder.Decode(result, destination); 921 922 Assert.IsNotNull(destination); 923 foreach(double val in destination) 924 { 925 Assert.AreEqual(4.0, val, delta: 0.001); 926 } 927 928 encoder.Decode(coeff2, destination); 929 930 foreach(double val in destination) 931 { 932 Assert.AreEqual(3.0, val, delta: 0.001); 933 } 934 935 decryptor.Decrypt(encX2, result); 936 encoder.Decode(result, destination); 937 938 foreach (double val in destination) 939 { 940 Assert.AreEqual(6.0, val, delta: 0.001); 941 } 942 } 943 944 [TestMethod] RotateMatrixTest()945 public void RotateMatrixTest() 946 { 947 EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) 948 { 949 PolyModulusDegree = 8, 950 PlainModulus = new Modulus(257), 951 CoeffModulus = CoeffModulus.Create(8, new int[] { 40, 40 }) 952 }; 953 SEALContext context = new SEALContext(parms, 954 expandModChain: false, 955 secLevel: SecLevelType.None); 956 KeyGenerator keygen = new KeyGenerator(context); 957 keygen.CreateGaloisKeys(out GaloisKeys galoisKeys); 958 keygen.CreatePublicKey(out PublicKey publicKey); 959 960 Encryptor encryptor = new Encryptor(context, publicKey); 961 Decryptor decryptor = new Decryptor(context, keygen.SecretKey); 962 Evaluator evaluator = new Evaluator(context); 963 BatchEncoder encoder = new BatchEncoder(context); 964 965 Plaintext plain = new Plaintext(); 966 List<ulong> vec = new List<ulong> 967 { 968 1, 2, 3, 4, 969 5, 6, 7, 8 970 }; 971 972 encoder.Encode(vec, plain); 973 974 Ciphertext encrypted = new Ciphertext(); 975 Ciphertext encdest = new Ciphertext(); 976 Plaintext plaindest = new Plaintext(); 977 978 encryptor.Encrypt(plain, encrypted); 979 evaluator.RotateColumns(encrypted, galoisKeys, encdest); 980 decryptor.Decrypt(encdest, plaindest); 981 encoder.Decode(plaindest, vec); 982 983 Assert.IsTrue(AreCollectionsEqual(vec, new List<ulong> 984 { 985 5, 6, 7, 8, 986 1, 2, 3, 4 987 })); 988 989 evaluator.RotateRows(encdest, -1, galoisKeys, encrypted); 990 decryptor.Decrypt(encrypted, plaindest); 991 encoder.Decode(plaindest, vec); 992 993 Assert.IsTrue(AreCollectionsEqual(vec, new List<ulong> 994 { 995 8, 5, 6, 7, 996 4, 1, 2, 3 997 })); 998 999 evaluator.RotateRowsInplace(encrypted, 2, galoisKeys); 1000 decryptor.Decrypt(encrypted, plaindest); 1001 encoder.Decode(plaindest, vec); 1002 1003 Assert.IsTrue(AreCollectionsEqual(vec, new List<ulong> 1004 { 1005 6, 7, 8, 5, 1006 2, 3, 4, 1 1007 })); 1008 1009 evaluator.RotateColumnsInplace(encrypted, galoisKeys); 1010 decryptor.Decrypt(encrypted, plaindest); 1011 encoder.Decode(plaindest, vec); 1012 1013 Assert.IsTrue(AreCollectionsEqual(vec, new List<ulong> 1014 { 1015 2, 3, 4, 1, 1016 6, 7, 8, 5 1017 })); 1018 } 1019 1020 [TestMethod] RelinearizeTest()1021 public void RelinearizeTest() 1022 { 1023 EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) 1024 { 1025 PolyModulusDegree = 128, 1026 PlainModulus = new Modulus(1 << 6), 1027 CoeffModulus = CoeffModulus.Create(128, new int[] { 40, 40, 40 }) 1028 }; 1029 SEALContext context = new SEALContext(parms, 1030 expandModChain: false, 1031 secLevel: SecLevelType.None); 1032 KeyGenerator keygen = new KeyGenerator(context); 1033 keygen.CreateRelinKeys(out RelinKeys relinKeys); 1034 keygen.CreatePublicKey(out PublicKey publicKey); 1035 1036 Encryptor encryptor = new Encryptor(context, publicKey); 1037 Decryptor decryptor = new Decryptor(context, keygen.SecretKey); 1038 Evaluator evaluator = new Evaluator(context); 1039 1040 Ciphertext encrypted1 = new Ciphertext(context); 1041 Ciphertext encrypted2 = new Ciphertext(context); 1042 Plaintext plain1 = new Plaintext(); 1043 Plaintext plain2 = new Plaintext(); 1044 1045 plain1.Set(0); 1046 encryptor.Encrypt(plain1, encrypted1); 1047 evaluator.SquareInplace(encrypted1); 1048 evaluator.RelinearizeInplace(encrypted1, relinKeys); 1049 decryptor.Decrypt(encrypted1, plain2); 1050 1051 Assert.AreEqual(1ul, plain2.CoeffCount); 1052 Assert.AreEqual(0ul, plain2[0]); 1053 1054 plain1.Set("1x^10 + 2"); 1055 encryptor.Encrypt(plain1, encrypted1); 1056 evaluator.SquareInplace(encrypted1); 1057 evaluator.RelinearizeInplace(encrypted1, relinKeys); 1058 evaluator.SquareInplace(encrypted1); 1059 evaluator.Relinearize(encrypted1, relinKeys, encrypted2); 1060 decryptor.Decrypt(encrypted2, plain2); 1061 1062 // {1x^40 + 8x^30 + 18x^20 + 20x^10 + 10} 1063 Assert.AreEqual(41ul, plain2.CoeffCount); 1064 Assert.AreEqual(16ul, plain2[0]); 1065 Assert.AreEqual(32ul, plain2[10]); 1066 Assert.AreEqual(24ul, plain2[20]); 1067 Assert.AreEqual(8ul, plain2[30]); 1068 Assert.AreEqual(1ul, plain2[40]); 1069 } 1070 1071 [TestMethod] RotateVectorTest()1072 public void RotateVectorTest() 1073 { 1074 int slotSize = 4; 1075 EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS) 1076 { 1077 PolyModulusDegree = 2 * (ulong)slotSize, 1078 CoeffModulus = CoeffModulus.Create(2 * (ulong)slotSize, new int[] { 40, 40, 40, 40 }) 1079 }; 1080 SEALContext context = new SEALContext(parms, 1081 expandModChain: false, 1082 secLevel: SecLevelType.None); 1083 KeyGenerator keygen = new KeyGenerator(context); 1084 keygen.CreateGaloisKeys(out GaloisKeys galoisKeys); 1085 keygen.CreatePublicKey(out PublicKey publicKey); 1086 1087 Encryptor encryptor = new Encryptor(context, publicKey); 1088 Decryptor decryptor = new Decryptor(context, keygen.SecretKey); 1089 Evaluator evaluator = new Evaluator(context); 1090 CKKSEncoder encoder = new CKKSEncoder(context); 1091 1092 const double delta = 1ul << 30; 1093 1094 Ciphertext encrypted = new Ciphertext(); 1095 Plaintext plain = new Plaintext(); 1096 1097 List<Complex> input = new List<Complex> 1098 { 1099 new Complex(1, 1), 1100 new Complex(2, 2), 1101 new Complex(3, 3), 1102 new Complex(4, 4) 1103 }; 1104 1105 List<Complex> output = new List<Complex>(); 1106 1107 encoder.Encode(input, context.FirstParmsId, delta, plain); 1108 1109 int shift = 1; 1110 encryptor.Encrypt(plain, encrypted); 1111 evaluator.RotateVectorInplace(encrypted, shift, galoisKeys); 1112 decryptor.Decrypt(encrypted, plain); 1113 encoder.Decode(plain, output); 1114 1115 for (int i = 0; i < slotSize; i++) 1116 { 1117 Assert.AreEqual(input[(i + shift) % slotSize].Real, Math.Round(output[i].Real), delta: 0.1); 1118 Assert.AreEqual(input[(i + shift) % slotSize].Imaginary, Math.Round(output[i].Imaginary), delta: 0.1); 1119 } 1120 1121 encoder.Encode(input, context.FirstParmsId, delta, plain); 1122 shift = 3; 1123 encryptor.Encrypt(plain, encrypted); 1124 evaluator.RotateVectorInplace(encrypted, shift, galoisKeys); 1125 decryptor.Decrypt(encrypted, plain); 1126 encoder.Decode(plain, output); 1127 1128 for (int i = 0; i < slotSize; i++) 1129 { 1130 Assert.AreEqual(input[(i + shift) % slotSize].Real, Math.Round(output[i].Real), delta: 0.1); 1131 Assert.AreEqual(input[(i + shift) % slotSize].Imaginary, Math.Round(output[i].Imaginary), delta: 0.1); 1132 } 1133 } 1134 1135 [TestMethod] ComplexConjugateTest()1136 public void ComplexConjugateTest() 1137 { 1138 int slotSize = 4; 1139 EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS) 1140 { 1141 PolyModulusDegree = 2 * (ulong)slotSize, 1142 CoeffModulus = CoeffModulus.Create(2 * (ulong)slotSize, new int[] { 40, 40, 40, 40 }) 1143 }; 1144 SEALContext context = new SEALContext(parms, 1145 expandModChain: false, 1146 secLevel: SecLevelType.None); 1147 KeyGenerator keygen = new KeyGenerator(context); 1148 keygen.CreateGaloisKeys(out GaloisKeys galoisKeys); 1149 keygen.CreatePublicKey(out PublicKey publicKey); 1150 1151 Encryptor encryptor = new Encryptor(context, publicKey); 1152 Decryptor decryptor = new Decryptor(context, keygen.SecretKey); 1153 Evaluator evaluator = new Evaluator(context); 1154 CKKSEncoder encoder = new CKKSEncoder(context); 1155 1156 const double delta = 1ul << 30; 1157 1158 Ciphertext encrypted = new Ciphertext(); 1159 Plaintext plain = new Plaintext(); 1160 1161 List<Complex> input = new List<Complex> 1162 { 1163 new Complex(1, 1), 1164 new Complex(2, 2), 1165 new Complex(3, 3), 1166 new Complex(4, 4) 1167 }; 1168 1169 List<Complex> output = new List<Complex>(); 1170 1171 encoder.Encode(input, context.FirstParmsId, delta, plain); 1172 encryptor.Encrypt(plain, encrypted); 1173 evaluator.ComplexConjugateInplace(encrypted, galoisKeys); 1174 decryptor.Decrypt(encrypted, plain); 1175 encoder.Decode(plain, output); 1176 1177 for (int i = 0; i < slotSize; i++) 1178 { 1179 Assert.AreEqual(input[i].Real, output[i].Real, delta: 0.1); 1180 Assert.AreEqual(-input[i].Imaginary, output[i].Imaginary, delta: 0.1); 1181 } 1182 } 1183 1184 [TestMethod] ExceptionsTest()1185 public void ExceptionsTest() 1186 { 1187 EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV) 1188 { 1189 PolyModulusDegree = 64, 1190 PlainModulus = new Modulus(65537ul), 1191 CoeffModulus = CoeffModulus.Create(64, new int[] { 40, 40 }) 1192 }; 1193 SEALContext context = new SEALContext(parms, 1194 expandModChain: false, 1195 secLevel: SecLevelType.None); 1196 1197 Evaluator evaluator = null; 1198 Utilities.AssertThrows<ArgumentNullException>(() => evaluator = new Evaluator(null)); 1199 evaluator = new Evaluator(context); 1200 1201 KeyGenerator keygen = new KeyGenerator(context); 1202 keygen.CreateGaloisKeys(out GaloisKeys galoisKeys); 1203 keygen.CreateRelinKeys(out RelinKeys relinKeys); 1204 1205 Ciphertext encrypted1 = new Ciphertext(); 1206 Ciphertext encrypted2 = new Ciphertext(); 1207 Ciphertext encrypted3 = new Ciphertext(); 1208 Plaintext plain1 = new Plaintext(); 1209 Plaintext plain2 = new Plaintext(); 1210 List<Ciphertext> encrypteds = new List<Ciphertext>(); 1211 1212 MemoryPoolHandle pool = MemoryManager.GetPool(MMProfOpt.ForceGlobal); 1213 1214 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Add(null, encrypted2, encrypted3)); 1215 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Add(encrypted1, null, encrypted3)); 1216 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Add(encrypted1, encrypted2, null)); 1217 Utilities.AssertThrows<ArgumentException>(() => evaluator.Add(encrypted1, encrypted2, encrypted3)); 1218 1219 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.AddInplace(encrypted1, null)); 1220 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.AddInplace(null, encrypted2)); 1221 1222 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.AddMany(encrypteds, null)); 1223 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.AddMany(null, encrypted2)); 1224 1225 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.AddPlain(encrypted1, plain1, null)); 1226 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.AddPlain(encrypted1, null, encrypted2)); 1227 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.AddPlain(null, plain1, encrypted2)); 1228 Utilities.AssertThrows<ArgumentException>(() => evaluator.AddPlain(encrypted1, plain1, encrypted2)); 1229 1230 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.AddPlainInplace(encrypted1, null)); 1231 1232 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ApplyGalois(encrypted1, 1, galoisKeys, null)); 1233 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ApplyGalois(encrypted1, 1, null, encrypted2)); 1234 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ApplyGalois(null, 1, galoisKeys, encrypted2)); 1235 Utilities.AssertThrows<ArgumentException>(() => evaluator.ApplyGalois(encrypted1, 1, galoisKeys, encrypted2, pool)); 1236 1237 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ApplyGaloisInplace(encrypted1, 1, null)); 1238 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ApplyGaloisInplace(null, 1, galoisKeys)); 1239 1240 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ComplexConjugate(encrypted1, galoisKeys, null)); 1241 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ComplexConjugate(encrypted1, null, encrypted2)); 1242 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ComplexConjugate(null, galoisKeys, encrypted2)); 1243 1244 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ComplexConjugateInplace(encrypted1, null)); 1245 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ComplexConjugateInplace(null, galoisKeys)); 1246 1247 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Exponentiate(encrypted1, 2, relinKeys, null)); 1248 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Exponentiate(encrypted1, 2, null, encrypted2)); 1249 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Exponentiate(null, 2, relinKeys, encrypted2)); 1250 1251 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ExponentiateInplace(encrypted1, 2, null)); 1252 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ExponentiateInplace(null, 2, relinKeys)); 1253 1254 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchTo(plain1, ParmsId.Zero, null)); 1255 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchTo(plain1, null, plain2)); 1256 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchTo(null, ParmsId.Zero, plain2)); 1257 1258 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchTo(encrypted1, ParmsId.Zero, null)); 1259 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchTo(encrypted1, null, encrypted2)); 1260 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchTo(null, ParmsId.Zero, encrypted2)); 1261 Utilities.AssertThrows<ArgumentException>(() => evaluator.ModSwitchTo(encrypted1, ParmsId.Zero, encrypted2, pool)); 1262 1263 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToInplace(encrypted1, null)); 1264 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToInplace(encrypted: null, parmsId: ParmsId.Zero)); 1265 Utilities.AssertThrows<ArgumentException>(() => evaluator.ModSwitchToInplace(encrypted1, ParmsId.Zero, pool)); 1266 1267 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToInplace(plain1, null)); 1268 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToInplace(plain: null, parmsId: ParmsId.Zero)); 1269 1270 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToNext(plain1, null)); 1271 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToNext(null, plain2)); 1272 1273 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToNextInplace(null)); 1274 1275 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToNext(encrypted1, null)); 1276 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToNext(null, encrypted2)); 1277 Utilities.AssertThrows<ArgumentException>(() => evaluator.ModSwitchToNext(encrypted1, encrypted2, pool)); 1278 1279 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToNextInplace(encrypted: null)); 1280 Utilities.AssertThrows<ArgumentException>(() => evaluator.ModSwitchToNextInplace(encrypted1, pool)); 1281 1282 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Multiply(encrypted1, encrypted2, null)); 1283 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Multiply(encrypted1, null, encrypted3)); 1284 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Multiply(null, encrypted2, encrypted3)); 1285 Utilities.AssertThrows<ArgumentException>(() => evaluator.Multiply(encrypted1, encrypted2, encrypted3, pool)); 1286 1287 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyInplace(encrypted1, null)); 1288 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyInplace(null, encrypted2)); 1289 Utilities.AssertThrows<ArgumentException>(() => evaluator.MultiplyInplace(encrypted1, encrypted2, pool)); 1290 1291 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyMany(encrypteds, relinKeys, null)); 1292 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyMany(encrypteds, null, encrypted2)); 1293 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyMany(null, relinKeys, encrypted2)); 1294 Utilities.AssertThrows<ArgumentException>(() => evaluator.MultiplyMany(encrypteds, relinKeys, encrypted2, pool)); 1295 1296 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyPlain(encrypted1, plain1, null)); 1297 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyPlain(encrypted1, null, encrypted2)); 1298 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyPlain(null, plain1, encrypted2)); 1299 Utilities.AssertThrows<ArgumentException>(() => evaluator.MultiplyPlain(encrypted1, plain1, encrypted2, pool)); 1300 1301 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyPlainInplace(encrypted1, null)); 1302 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyPlainInplace(null, plain1)); 1303 1304 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Negate(encrypted1, null)); 1305 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Negate(null, encrypted2)); 1306 Utilities.AssertThrows<ArgumentException>(() => evaluator.Negate(encrypted1, encrypted2)); 1307 1308 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.NegateInplace(null)); 1309 1310 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Relinearize(encrypted1, relinKeys, null)); 1311 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Relinearize(encrypted1, null, encrypted2)); 1312 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Relinearize(null, relinKeys, encrypted2)); 1313 Utilities.AssertThrows<ArgumentException>(() => evaluator.Relinearize(encrypted1, relinKeys, encrypted2, pool)); 1314 1315 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RelinearizeInplace(encrypted1, null)); 1316 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RelinearizeInplace(null, relinKeys)); 1317 Utilities.AssertThrows<ArgumentException>(() => evaluator.RelinearizeInplace(encrypted1, relinKeys, pool)); 1318 1319 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RescaleTo(encrypted1, ParmsId.Zero, null)); 1320 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RescaleTo(encrypted1, null, encrypted2)); 1321 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RescaleTo(null, ParmsId.Zero, encrypted2)); 1322 Utilities.AssertThrows<ArgumentException>(() => evaluator.RescaleTo(encrypted1, ParmsId.Zero, encrypted2, pool)); 1323 1324 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RescaleToInplace(encrypted1, null)); 1325 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RescaleToInplace(null, ParmsId.Zero)); 1326 Utilities.AssertThrows<ArgumentException>(() => evaluator.RescaleToInplace(encrypted1, ParmsId.Zero, pool)); 1327 1328 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RescaleToNext(encrypted1, null)); 1329 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RescaleToNext(null, encrypted2)); 1330 Utilities.AssertThrows<ArgumentException>(() => evaluator.RescaleToNext(encrypted1, encrypted2, pool)); 1331 1332 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RescaleToNextInplace(null)); 1333 Utilities.AssertThrows<ArgumentException>(() => evaluator.RescaleToNextInplace(encrypted1, pool)); 1334 1335 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateColumns(encrypted1, galoisKeys, null)); 1336 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateColumns(encrypted1, null, encrypted2)); 1337 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateColumns(null, galoisKeys, encrypted2)); 1338 Utilities.AssertThrows<ArgumentException>(() => evaluator.RotateColumns(encrypted1, galoisKeys, encrypted2, pool)); 1339 1340 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateColumnsInplace(encrypted1, null)); 1341 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateColumnsInplace(null, galoisKeys)); 1342 Utilities.AssertThrows<ArgumentException>(() => evaluator.RotateColumnsInplace(encrypted1, galoisKeys, pool)); 1343 1344 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateRows(encrypted1, 1, galoisKeys, null)); 1345 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateRows(encrypted1, 1, null, encrypted2)); 1346 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateRows(null, 1, galoisKeys, encrypted2)); 1347 Utilities.AssertThrows<ArgumentException>(() => evaluator.RotateRows(encrypted1, 1, galoisKeys, encrypted2, pool)); 1348 1349 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateRowsInplace(encrypted1, 1, null)); 1350 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateRowsInplace(null, 1, galoisKeys)); 1351 Utilities.AssertThrows<ArgumentException>(() => evaluator.RotateRowsInplace(encrypted1, 1, galoisKeys, pool)); 1352 1353 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateVector(encrypted1, 1, galoisKeys, null)); 1354 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateVector(encrypted1, 1, null, encrypted2)); 1355 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateVector(null, 1, galoisKeys, encrypted2)); 1356 1357 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateVectorInplace(encrypted1, 1, null)); 1358 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateVectorInplace(null, 1, galoisKeys)); 1359 1360 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Square(encrypted1, null)); 1361 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Square(null, encrypted2)); 1362 Utilities.AssertThrows<ArgumentException>(() => evaluator.Square(encrypted1, encrypted2, pool)); 1363 1364 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.SquareInplace(null)); 1365 Utilities.AssertThrows<ArgumentException>(() => evaluator.SquareInplace(encrypted1, pool)); 1366 1367 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Sub(encrypted1, encrypted2, null)); 1368 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Sub(encrypted1, null, encrypted3)); 1369 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Sub(null, encrypted2, encrypted3)); 1370 Utilities.AssertThrows<ArgumentException>(() => evaluator.Sub(encrypted1, encrypted2, encrypted3)); 1371 1372 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.SubInplace(encrypted1, null)); 1373 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.SubInplace(null, encrypted2)); 1374 1375 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.SubPlain(encrypted1, plain1, null)); 1376 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.SubPlain(encrypted1, null, encrypted2)); 1377 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.SubPlain(null, plain1, encrypted2)); 1378 Utilities.AssertThrows<ArgumentException>(() => evaluator.SubPlain(encrypted1, plain1, encrypted2)); 1379 1380 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.SubPlainInplace(encrypted1, null)); 1381 1382 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformFromNTT(encrypted1, null)); 1383 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformFromNTT(null, encrypted2)); 1384 Utilities.AssertThrows<ArgumentException>(() => evaluator.TransformFromNTT(encrypted1, encrypted2)); 1385 1386 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformFromNTTInplace(null)); 1387 1388 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformToNTT(encrypted1, null)); 1389 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformToNTT(null, encrypted2)); 1390 1391 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformToNTTInplace(null)); 1392 1393 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformToNTT(plain1, ParmsId.Zero, null)); 1394 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformToNTT(plain1, null, plain2)); 1395 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformToNTT(null, ParmsId.Zero, plain2)); 1396 Utilities.AssertThrows<ArgumentException>(() => evaluator.TransformToNTT(plain1, ParmsId.Zero, plain2, pool)); 1397 1398 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformToNTTInplace(plain1, null)); 1399 Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformToNTTInplace(null, ParmsId.Zero)); 1400 Utilities.AssertThrows<ArgumentException>(() => evaluator.TransformToNTTInplace(plain1, ParmsId.Zero, pool)); 1401 } 1402 1403 /// <summary> 1404 /// Returns true if the two given collections have equivalent elements, false otherwise 1405 /// </summary> AreCollectionsEqual(IEnumerable<T> coll1, IEnumerable<T> coll2)1406 private static bool AreCollectionsEqual<T>(IEnumerable<T> coll1, IEnumerable<T> coll2) 1407 { 1408 int size1 = coll1.Count(); 1409 int size2 = coll2.Count(); 1410 1411 if (size1 != size2) 1412 return false; 1413 1414 IEnumerator<T> en1 = coll1.GetEnumerator(); 1415 IEnumerator<T> en2 = coll2.GetEnumerator(); 1416 1417 while (en1.MoveNext() && en2.MoveNext()) 1418 { 1419 if (!en1.Current.Equals(en2.Current)) 1420 return false; 1421 } 1422 1423 return true; 1424 } 1425 } 1426 } 1427