diff --git a/crypto/test/src/crypto/test/AeadTestUtilities.cs b/crypto/test/src/crypto/test/AeadTestUtilities.cs
index 40f334202..a5e21552f 100644
--- a/crypto/test/src/crypto/test/AeadTestUtilities.cs
+++ b/crypto/test/src/crypto/test/AeadTestUtilities.cs
@@ -1,11 +1,74 @@
using System;
+using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Test;
namespace Org.BouncyCastle.Crypto.Tests
{
public class AeadTestUtilities
{
+ internal static void TestTampering(ITest test, IAeadCipher cipher, ICipherParameters parameters)
+ {
+ byte[] plaintext = new byte[1000];
+ for (int i = 0; i < plaintext.Length; i++)
+ {
+ plaintext[i] = (byte)i;
+ }
+ cipher.Init(true, parameters);
+
+ byte[] ciphertext = new byte[cipher.GetOutputSize(plaintext.Length)];
+ int len = cipher.ProcessBytes(plaintext, 0, plaintext.Length, ciphertext, 0);
+ cipher.DoFinal(ciphertext, len);
+
+ int macLength = cipher.GetMac().Length;
+
+ // Test tampering with a single byte
+ cipher.Init(false, parameters);
+ byte[] tampered = new byte[ciphertext.Length];
+ byte[] output = new byte[plaintext.Length];
+ Array.Copy(ciphertext, 0, tampered, 0, tampered.Length);
+ tampered[0] += 1;
+
+ cipher.ProcessBytes(tampered, 0, tampered.Length, output, 0);
+ try
+ {
+ cipher.DoFinal(output, 0);
+ throw new TestFailedException(
+ new SimpleTestResult(false, test + " : tampering of ciphertext not detected."));
+ }
+ catch (InvalidCipherTextException e)
+ {
+ // Expected
+ }
+
+ // Test truncation of ciphertext to < tag length
+ cipher.Init(false, parameters);
+ byte[] truncated = new byte[macLength - 1];
+ Array.Copy(ciphertext, 0, truncated, 0, truncated.Length);
+
+ cipher.ProcessBytes(truncated, 0, truncated.Length, output, 0);
+ try
+ {
+ cipher.DoFinal(output, 0);
+ Fail(test, "tampering of ciphertext not detected.");
+ }
+ catch (InvalidCipherTextException e)
+ {
+ // Expected
+ }
+ }
+
+ private static void Fail(ITest test, string message)
+ {
+ throw new TestFailedException(SimpleTestResult.Failed(test, message));
+ }
+
+ private static void Fail(ITest test, string message, string expected, string result)
+ {
+ throw new TestFailedException(SimpleTestResult.Failed(test, message, expected, result));
+ }
+
internal static AeadParameters ReuseKey(AeadParameters p)
{
return new AeadParameters(null, p.MacSize, p.GetNonce(), p.GetAssociatedText());
diff --git a/crypto/test/src/crypto/test/GCMTest.cs b/crypto/test/src/crypto/test/GCMTest.cs
index e5e5fc43e..2ab5c6216 100644
--- a/crypto/test/src/crypto/test/GCMTest.cs
+++ b/crypto/test/src/crypto/test/GCMTest.cs
@@ -9,6 +9,7 @@ using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Modes.Gcm;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Date;
using Org.BouncyCastle.Utilities.Encoders;
using Org.BouncyCastle.Utilities.Test;
@@ -356,39 +357,38 @@ namespace Org.BouncyCastle.Crypto.Tests
// expected
}
- // TODO
- //AEADTestUtil.testTampering(this, gcm, new AEADParameters(new KeyParameter(new byte[16]), 128, new byte[16]));
+ 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];
+ 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);
+ 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.ProcessBytes(P, 0, P.Length, buf, 0);
- //c.doFinal(buf, 0);
+ c.DoFinal(buf, 0);
- //try
- //{
- // c.doFinal(buf, 0);
- // fail("no exception on reuse");
- //}
- //catch (IllegalStateException e)
- //{
- // isTrue("wrong message", e.getMessage().equals("GCM cipher cannot be reused for encryption"));
- //}
+ 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 (IllegalArgumentException e)
- //{
- // isTrue("wrong message", e.getMessage().equals("cannot reuse nonce for GCM 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(string[] testVector)
|