From 4819cab88fdd657bd64c672ff62e255a5cc1fe3e Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sun, 17 Jan 2016 12:32:24 +0700 Subject: Fix re-init bug in HC128/256 engines - add StreamCipherResetTest from Java API --- crypto/crypto.csproj | 5 + crypto/src/crypto/engines/HC128Engine.cs | 4 +- crypto/src/crypto/engines/HC256Engine.cs | 2 +- crypto/test/UnitTests.csproj | 1 + crypto/test/src/crypto/test/RegressionTest.cs | 1 + .../test/src/crypto/test/StreamCipherResetTest.cs | 134 +++++++++++++++++++++ 6 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 crypto/test/src/crypto/test/StreamCipherResetTest.cs (limited to 'crypto') diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index 73afed47e..392ff5813 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -11759,6 +11759,11 @@ SubType = "Code" BuildAction = "Compile" /> + + diff --git a/crypto/test/src/crypto/test/RegressionTest.cs b/crypto/test/src/crypto/test/RegressionTest.cs index bf38ae360..ea9fd84f2 100644 --- a/crypto/test/src/crypto/test/RegressionTest.cs +++ b/crypto/test/src/crypto/test/RegressionTest.cs @@ -120,6 +120,7 @@ namespace Org.BouncyCastle.Crypto.Tests new Poly1305Test(), new OcbTest(), new NonMemoableDigestTest(), + new StreamCipherResetTest(), new SM3DigestTest(), new X931SignerTest(), new KeccakDigestTest(), diff --git a/crypto/test/src/crypto/test/StreamCipherResetTest.cs b/crypto/test/src/crypto/test/StreamCipherResetTest.cs new file mode 100644 index 000000000..49760a24b --- /dev/null +++ b/crypto/test/src/crypto/test/StreamCipherResetTest.cs @@ -0,0 +1,134 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * Test whether block ciphers implement reset contract on init, encrypt/decrypt and reset. + */ + [TestFixture] + public class StreamCipherResetTest + : SimpleTest + { + public override string Name + { + get { return "Stream Cipher Reset"; } + } + + public override void PerformTest() + { + TestReset(typeof(Salsa20Engine), 32, 8); + TestReset(typeof(Salsa20Engine), 16, 8); + TestReset(typeof(XSalsa20Engine), 32, 24); + TestReset(typeof(ChaChaEngine), 32, 8); + TestReset(typeof(ChaChaEngine), 16, 8); + TestReset(typeof(RC4Engine), 16); + TestReset(typeof(IsaacEngine), 16); + TestReset(typeof(HC128Engine), 16, 16); + TestReset(typeof(HC256Engine), 16, 16); + //TestReset(typeof(Grainv1Engine), 16, 8); + //TestReset(typeof(Grain128Engine), 16, 12); + } + + private static readonly SecureRandom RAND = new SecureRandom(); + + private static byte[] Random(int size) + { + return SecureRandom.GetNextBytes(RAND, size); + } + + private IStreamCipher Make(Type sct) + { + return (IStreamCipher)Activator.CreateInstance(sct); + } + + private void TestReset(Type sct, int keyLen) + { + TestReset(Make(sct), Make(sct), new KeyParameter(Random(keyLen))); + } + + private void TestReset(Type sct, int keyLen, int ivLen) + { + TestReset(Make(sct), Make(sct), new ParametersWithIV(new KeyParameter(Random(keyLen)), Random(ivLen))); + } + + private void TestReset(IStreamCipher cipher1, IStreamCipher cipher2, ICipherParameters cipherParams) + { + cipher1.Init(true, cipherParams); + + byte[] plaintext = new byte[1023]; + byte[] ciphertext = new byte[plaintext.Length]; + + // Establish baseline answer + cipher1.ProcessBytes(plaintext, 0, plaintext.Length, ciphertext, 0); + + // Test encryption resets + CheckReset(cipher1, cipherParams, true, plaintext, ciphertext); + + // Test decryption resets with fresh instance + cipher2.Init(false, cipherParams); + CheckReset(cipher2, cipherParams, false, ciphertext, plaintext); + } + + private void CheckReset(IStreamCipher cipher, ICipherParameters cipherParams, + bool encrypt, byte[] pretext, byte[] posttext) + { + // Do initial run + byte[] output = new byte[posttext.Length]; + cipher.ProcessBytes(pretext, 0, pretext.Length, output, 0); + + // Check encrypt resets cipher + cipher.Init(encrypt, cipherParams); + + try + { + cipher.ProcessBytes(pretext, 0, pretext.Length, output, 0); + } + catch (Exception e) + { + Fail(cipher.AlgorithmName + " init did not reset: " + e.Message); + } + if (!Arrays.AreEqual(output, posttext)) + { + Fail(cipher.AlgorithmName + " init did not reset.", Hex.ToHexString(posttext), Hex.ToHexString(output)); + } + + // Check reset resets data + cipher.Reset(); + + try + { + cipher.ProcessBytes(pretext, 0, pretext.Length, output, 0); + } + catch (Exception e) + { + Fail(cipher.AlgorithmName + " reset did not reset: " + e.Message); + } + if (!Arrays.AreEqual(output, posttext)) + { + Fail(cipher.AlgorithmName + " reset did not reset."); + } + } + + public static void Main(string[] args) + { + RunTest(new StreamCipherResetTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} -- cgit 1.5.1