private void RunTestCase(string testName, string[] testVector, int macLengthBits, byte[] K) { int pos = 0; byte[] N = Hex.Decode(testVector[pos++]); byte[] A = Hex.Decode(testVector[pos++]); byte[] P = Hex.Decode(testVector[pos++]); byte[] C = Hex.Decode(testVector[pos++]); int macLengthBytes = macLengthBits / 8; KeyParameter keyParameter = new KeyParameter(K); AeadParameters parameters = new AeadParameters(keyParameter, macLengthBits, N, A); IAeadBlockCipher encCipher = InitOcbCipher(true, parameters); IAeadBlockCipher decCipher = InitOcbCipher(false, parameters); CheckTestCase(encCipher, decCipher, testName, macLengthBytes, P, C); CheckTestCase(encCipher, decCipher, testName + " (reused)", macLengthBytes, P, C); // Key reuse AeadParameters keyReuseParams = AeadTestUtilities.ReuseKey(parameters); encCipher.Init(true, keyReuseParams); decCipher.Init(false, keyReuseParams); CheckTestCase(encCipher, decCipher, testName + " (key reuse)", macLengthBytes, P, C); }
private void RunTestCase( IGcmMultiplier encM, IGcmMultiplier decM, string testName, byte[] K, byte[] IV, byte[] A, byte[] SA, byte[] P, byte[] C, byte[] T) { AeadParameters parameters = new AeadParameters(new KeyParameter(K), T.Length * 8, IV, A); GcmBlockCipher encCipher = InitCipher(encM, true, parameters); GcmBlockCipher decCipher = InitCipher(decM, false, parameters); CheckTestCase(encCipher, decCipher, testName, SA, P, C, T); encCipher = InitCipher(encM, true, parameters); CheckTestCase(encCipher, decCipher, testName + " (reused)", SA, P, C, T); // Key reuse AeadParameters keyReuseParams = AeadTestUtilities.ReuseKey(parameters); try { encCipher.Init(true, keyReuseParams); Fail("no exception"); } catch (ArgumentException e) { IsTrue("wrong message", "cannot reuse nonce for GCM encryption".Equals(e.Message)); } }
private void TestExceptions() { ChaCha20Poly1305 c = new ChaCha20Poly1305(); try { c = new ChaCha20Poly1305(new SipHash()); Fail("incorrect mac size not picked up"); } catch (ArgumentException e) { // expected } try { c.Init(false, new KeyParameter(new byte[32])); Fail("illegal argument not picked up"); } catch (ArgumentException e) { // expected } AeadTestUtilities.TestTampering(this, c, new AeadParameters(new KeyParameter(new byte[32]), 128, new byte[12])); byte[] P = Strings.ToByteArray("Hello world!"); byte[] buf = new byte[100]; c = new ChaCha20Poly1305(); AeadParameters aeadParameters = new AeadParameters(new KeyParameter(new byte[32]), 128, new byte[12]); c.Init(true, aeadParameters); c.ProcessBytes(P, 0, P.Length, buf, 0); c.DoFinal(buf, 0); try { c.DoFinal(buf, 0); Fail("no exception on reuse"); } catch (InvalidOperationException e) { IsTrue("wrong message", e.Message.Equals("ChaCha20Poly1305 cannot be reused for encryption")); } try { c.Init(true, aeadParameters); Fail("no exception on reuse"); } catch (ArgumentException e) { IsTrue("wrong message", e.Message.Equals("cannot reuse nonce for ChaCha20Poly1305 encryption")); } }
private void RunTestCase( string testName, byte[] K, byte[] N, byte[] A, byte[] SA, byte[] P, byte[] C, byte[] T) { AeadParameters parameters = new AeadParameters(new KeyParameter(K), T.Length * 8, N, A); ChaCha20Poly1305 encCipher = InitCipher(true, parameters); ChaCha20Poly1305 decCipher = InitCipher(false, parameters); CheckTestCase(encCipher, decCipher, testName, SA, P, C, T); encCipher = InitCipher(true, parameters); CheckTestCase(encCipher, decCipher, testName + " (reused)", SA, P, C, T); // Key reuse AeadParameters keyReuseParams = AeadTestUtilities.ReuseKey(parameters); try { encCipher.Init(true, keyReuseParams); Fail("no exception"); } catch (ArgumentException e) { IsTrue("wrong message", "cannot reuse nonce for ChaCha20Poly1305 encryption".Equals(e.Message)); } }
private void DoTestExceptions() { GcmBlockCipher gcm = new GcmBlockCipher(CreateAesEngine()); try { gcm = new GcmBlockCipher(new DesEngine()); Fail("incorrect block size not picked up"); } catch (ArgumentException) { // expected } try { gcm.Init(false, new KeyParameter(new byte[16])); Fail("illegal argument not picked up"); } catch (ArgumentException) { // expected } AeadTestUtilities.TestTampering(this, gcm, new AeadParameters(new KeyParameter(new byte[16]), 128, new byte[16])); byte[] P = Strings.ToByteArray("Hello world!"); byte[] buf = new byte[100]; GcmBlockCipher c = new GcmBlockCipher(CreateAesEngine()); AeadParameters aeadParameters = new AeadParameters(new KeyParameter(new byte[16]), 128, new byte[16]); c.Init(true, aeadParameters); c.ProcessBytes(P, 0, P.Length, buf, 0); c.DoFinal(buf, 0); try { c.DoFinal(buf, 0); Fail("no exception on reuse"); } catch (InvalidOperationException e) { IsTrue("wrong message", e.Message.Equals("GCM cipher cannot be reused for encryption")); } try { c.Init(true, aeadParameters); Fail("no exception on reuse"); } catch (ArgumentException e) { IsTrue("wrong message", e.Message.Equals("cannot reuse nonce for GCM encryption")); } }
private void RunTestCase( IGcmMultiplier encM, IGcmMultiplier decM, string testName, byte[] K, byte[] IV, byte[] A, byte[] SA, byte[] P, byte[] C, byte[] T) { AeadParameters parameters = new AeadParameters(new KeyParameter(K), T.Length * 8, IV, A); GcmBlockCipher encCipher = InitCipher(encM, true, parameters); GcmBlockCipher decCipher = InitCipher(decM, false, parameters); CheckTestCase(encCipher, decCipher, testName, SA, P, C, T); CheckTestCase(encCipher, decCipher, testName + " (reused)", SA, P, C, T); // Key reuse AeadParameters keyReuseParams = AeadTestUtilities.ReuseKey(parameters); encCipher.Init(true, keyReuseParams); decCipher.Init(false, keyReuseParams); CheckTestCase(encCipher, decCipher, testName + " (key reuse)", SA, P, C, T); }
private void RandomTest(SecureRandom srng, IGcmMultiplier m) { int kLength = 16 + 8 * srng.Next(3); byte[] K = new byte[kLength]; srng.NextBytes(K); int pLength = srng.Next(65536); byte[] P = new byte[pLength]; srng.NextBytes(P); int aLength = srng.Next(256); byte[] A = new byte[aLength]; srng.NextBytes(A); int saLength = srng.Next(256); byte[] SA = new byte[saLength]; srng.NextBytes(SA); int ivLength = 1 + srng.Next(256); byte[] IV = new byte[ivLength]; srng.NextBytes(IV); AeadParameters parameters = new AeadParameters(new KeyParameter(K), 16 * 8, IV, A); GcmBlockCipher cipher = InitCipher(m, true, parameters); byte[] C = new byte[cipher.GetOutputSize(P.Length)]; int predicted = cipher.GetUpdateOutputSize(P.Length); int split = srng.Next(SA.Length + 1); cipher.ProcessAadBytes(SA, 0, split); int len = cipher.ProcessBytes(P, 0, P.Length, C, 0); cipher.ProcessAadBytes(SA, split, SA.Length - split); if (predicted != len) { Fail("encryption reported incorrect update length in randomised test"); } len += cipher.DoFinal(C, len); if (C.Length != len) { Fail("encryption reported incorrect length in randomised test"); } byte[] encT = cipher.GetMac(); byte[] tail = new byte[C.Length - P.Length]; Array.Copy(C, P.Length, tail, 0, tail.Length); if (!AreEqual(encT, tail)) { Fail("stream contained wrong mac in randomised test"); } cipher.Init(false, parameters); byte[] decP = new byte[cipher.GetOutputSize(C.Length)]; predicted = cipher.GetUpdateOutputSize(C.Length); split = srng.Next(SA.Length + 1); cipher.ProcessAadBytes(SA, 0, split); len = cipher.ProcessBytes(C, 0, C.Length, decP, 0); cipher.ProcessAadBytes(SA, split, SA.Length - split); if (predicted != len) { Fail("decryption reported incorrect update length in randomised test"); } len += cipher.DoFinal(decP, len); if (!AreEqual(P, decP)) { Fail("incorrect decrypt in randomised test"); } byte[] decT = cipher.GetMac(); if (!AreEqual(encT, decT)) { Fail("decryption produced different mac from encryption"); } // // key reuse test // cipher.Init(false, AeadTestUtilities.ReuseKey(parameters)); decP = new byte[cipher.GetOutputSize(C.Length)]; split = NextInt(srng, SA.Length + 1); cipher.ProcessAadBytes(SA, 0, split); len = cipher.ProcessBytes(C, 0, C.Length, decP, 0); cipher.ProcessAadBytes(SA, split, SA.Length - split); len += cipher.DoFinal(decP, len); if (!AreEqual(P, decP)) { Fail("incorrect decrypt in randomised test"); } decT = cipher.GetMac(); if (!AreEqual(encT, decT)) { Fail("decryption produced different mac from encryption"); } }
private void RandomTest(SecureRandom random) { int kLength = 32; byte[] K = new byte[kLength]; random.NextBytes(K); int pHead = random.Next(256); int pLength = random.Next(65536); int pTail = random.Next(256); byte[] P = new byte[pHead + pLength + pTail]; random.NextBytes(P); int aLength = random.Next(256); byte[] A = new byte[aLength]; random.NextBytes(A); int saLength = random.Next(256); byte[] SA = new byte[saLength]; random.NextBytes(SA); int nonceLength = 12; byte[] nonce = new byte[nonceLength]; random.NextBytes(nonce); AeadParameters parameters = new AeadParameters(new KeyParameter(K), 16 * 8, nonce, A); ChaCha20Poly1305 cipher = InitCipher(true, parameters); int ctLength = cipher.GetOutputSize(pLength); byte[] C = new byte[saLength + ctLength]; Array.Copy(SA, 0, C, 0, saLength); int split = NextInt(random, saLength + 1); cipher.ProcessAadBytes(C, 0, split); cipher.ProcessAadBytes(C, split, saLength - split); int predicted = cipher.GetUpdateOutputSize(pLength); int len = cipher.ProcessBytes(P, pHead, pLength, C, saLength); if (predicted != len) { Fail("encryption reported incorrect update length in randomised test"); } len += cipher.DoFinal(C, saLength + len); if (ctLength != len) { Fail("encryption reported incorrect length in randomised test"); } byte[] encT = cipher.GetMac(); byte[] tail = new byte[ctLength - pLength]; Array.Copy(C, saLength + pLength, tail, 0, tail.Length); if (!AreEqual(encT, tail)) { Fail("stream contained wrong mac in randomised test"); } cipher.Init(false, parameters); int decPHead = random.Next(256); int decPLength = cipher.GetOutputSize(ctLength); int decPTail = random.Next(256); byte[] decP = new byte[decPHead + decPLength + decPTail]; split = NextInt(random, saLength + 1); cipher.ProcessAadBytes(C, 0, split); cipher.ProcessAadBytes(C, split, saLength - split); predicted = cipher.GetUpdateOutputSize(ctLength); len = cipher.ProcessBytes(C, saLength, ctLength, decP, decPHead); if (predicted != len) { Fail("decryption reported incorrect update length in randomised test"); } len += cipher.DoFinal(decP, decPHead + len); if (!AreEqual(P, pHead, pHead + pLength, decP, decPHead, decPHead + decPLength)) { Fail("incorrect decrypt in randomised test"); } byte[] decT = cipher.GetMac(); if (!AreEqual(encT, decT)) { Fail("decryption produced different mac from encryption"); } // // key reuse test // cipher.Init(false, AeadTestUtilities.ReuseKey(parameters)); decPHead = random.Next(256); decPLength = cipher.GetOutputSize(ctLength); decPTail = random.Next(256); decP = new byte[decPHead + decPLength + decPTail]; split = NextInt(random, saLength + 1); cipher.ProcessAadBytes(C, 0, split); cipher.ProcessAadBytes(C, split, saLength - split); len = cipher.ProcessBytes(C, saLength, ctLength, decP, decPHead); len += cipher.DoFinal(decP, decPHead + len); if (!AreEqual(P, pHead, pHead + pLength, decP, decPHead, decPHead + decPLength)) { Fail("incorrect decrypt in randomised test"); } decT = cipher.GetMac(); if (!AreEqual(encT, decT)) { Fail("decryption produced different mac from encryption"); } }