diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj
index 73afed47e..392ff5813 100644
--- a/crypto/crypto.csproj
+++ b/crypto/crypto.csproj
@@ -11760,6 +11760,11 @@
BuildAction = "Compile"
/>
<File
+ RelPath = "test\src\crypto\test\StreamCipherResetTest.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
RelPath = "test\src\crypto\test\StreamCipherVectorTest.cs"
SubType = "Code"
BuildAction = "Compile"
diff --git a/crypto/src/crypto/engines/HC128Engine.cs b/crypto/src/crypto/engines/HC128Engine.cs
index 7bd1a48ed..b83eb7083 100644
--- a/crypto/src/crypto/engines/HC128Engine.cs
+++ b/crypto/src/crypto/engines/HC128Engine.cs
@@ -107,7 +107,8 @@ namespace Org.BouncyCastle.Crypto.Engines
if (key.Length != 16)
throw new ArgumentException("The key must be 128 bits long");
- cnt = 0;
+ idx = 0;
+ cnt = 0;
uint[] w = new uint[1280];
@@ -223,7 +224,6 @@ namespace Org.BouncyCastle.Crypto.Engines
public virtual void Reset()
{
- idx = 0;
Init();
}
diff --git a/crypto/src/crypto/engines/HC256Engine.cs b/crypto/src/crypto/engines/HC256Engine.cs
index b72258a19..d8d83a634 100644
--- a/crypto/src/crypto/engines/HC256Engine.cs
+++ b/crypto/src/crypto/engines/HC256Engine.cs
@@ -92,6 +92,7 @@ namespace Org.BouncyCastle.Crypto.Engines
iv = newIV;
}
+ idx = 0;
cnt = 0;
uint[] w = new uint[2560];
@@ -207,7 +208,6 @@ namespace Org.BouncyCastle.Crypto.Engines
public virtual void Reset()
{
- idx = 0;
Init();
}
diff --git a/crypto/test/UnitTests.csproj b/crypto/test/UnitTests.csproj
index 24a60346e..94fd1cf7a 100644
--- a/crypto/test/UnitTests.csproj
+++ b/crypto/test/UnitTests.csproj
@@ -252,6 +252,7 @@
<Compile Include="src\crypto\test\SM3DigestTest.cs" />
<Compile Include="src\crypto\test\SkeinDigestTest.cs" />
<Compile Include="src\crypto\test\SkeinMacTest.cs" />
+ <Compile Include="src\crypto\test\StreamCipherResetTest.cs" />
<Compile Include="src\crypto\test\Threefish1024Test.cs" />
<Compile Include="src\crypto\test\Threefish256Test.cs" />
<Compile Include="src\crypto\test\Threefish512Test.cs" />
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);
+ }
+ }
+}
|