private void OutputSizeTests() { byte[] K = new byte[32]; byte[] A = null; byte[] N = new byte[12]; AeadParameters parameters = new AeadParameters(new KeyParameter(K), 16 * 8, N, A); ChaCha20Poly1305 cipher = InitCipher(true, parameters); if (cipher.GetUpdateOutputSize(0) != 0) { Fail("incorrect getUpdateOutputSize for initial 0 bytes encryption"); } if (cipher.GetOutputSize(0) != 16) { Fail("incorrect getOutputSize for initial 0 bytes encryption"); } cipher.Init(false, parameters); if (cipher.GetUpdateOutputSize(0) != 0) { Fail("incorrect getUpdateOutputSize for initial 0 bytes decryption"); } // NOTE: 0 bytes would be truncated data, but we want it to fail in the doFinal, not here if (cipher.GetOutputSize(0) != 0) { Fail("fragile getOutputSize for initial 0 bytes decryption"); } if (cipher.GetOutputSize(16) != 0) { Fail("incorrect getOutputSize for initial MAC-size bytes decryption"); } }
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"); } }