PageRenderTime 1090ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/core/src/test/java/org/bouncycastle/crypto/test/BlockCipherResetTest.java

https://gitlab.com/edgardo001/bc-java
Java | 206 lines | 160 code | 24 blank | 22 comment | 6 complexity | 52900717bc159bdaef55836c2d116b00 MD5 | raw file
  1. package org.bouncycastle.crypto.test;
  2. import org.bouncycastle.crypto.BlockCipher;
  3. import org.bouncycastle.crypto.CipherParameters;
  4. import org.bouncycastle.crypto.DataLengthException;
  5. import org.bouncycastle.crypto.InvalidCipherTextException;
  6. import org.bouncycastle.crypto.engines.AESEngine;
  7. import org.bouncycastle.crypto.engines.AESFastEngine;
  8. import org.bouncycastle.crypto.engines.AESLightEngine;
  9. import org.bouncycastle.crypto.engines.BlowfishEngine;
  10. import org.bouncycastle.crypto.engines.CAST5Engine;
  11. import org.bouncycastle.crypto.engines.CAST6Engine;
  12. import org.bouncycastle.crypto.engines.DESEngine;
  13. import org.bouncycastle.crypto.engines.DESedeEngine;
  14. import org.bouncycastle.crypto.engines.NoekeonEngine;
  15. import org.bouncycastle.crypto.engines.RC6Engine;
  16. import org.bouncycastle.crypto.engines.SEEDEngine;
  17. import org.bouncycastle.crypto.engines.SerpentEngine;
  18. import org.bouncycastle.crypto.engines.TEAEngine;
  19. import org.bouncycastle.crypto.engines.TwofishEngine;
  20. import org.bouncycastle.crypto.engines.XTEAEngine;
  21. import org.bouncycastle.crypto.modes.CBCBlockCipher;
  22. import org.bouncycastle.crypto.modes.CFBBlockCipher;
  23. import org.bouncycastle.crypto.modes.GOFBBlockCipher;
  24. import org.bouncycastle.crypto.modes.OFBBlockCipher;
  25. import org.bouncycastle.crypto.modes.OpenPGPCFBBlockCipher;
  26. import org.bouncycastle.crypto.modes.PGPCFBBlockCipher;
  27. import org.bouncycastle.crypto.modes.SICBlockCipher;
  28. import org.bouncycastle.crypto.params.KeyParameter;
  29. import org.bouncycastle.crypto.params.ParametersWithIV;
  30. import org.bouncycastle.util.Arrays;
  31. import org.bouncycastle.util.encoders.Hex;
  32. import org.bouncycastle.util.test.SimpleTest;
  33. /**
  34. * Test whether block ciphers implement reset contract on init, encrypt/decrypt and reset.
  35. */
  36. public class BlockCipherResetTest
  37. extends SimpleTest
  38. {
  39. public String getName()
  40. {
  41. return "Block Cipher Reset";
  42. }
  43. public void performTest()
  44. throws Exception
  45. {
  46. // 128 bit block ciphers
  47. testReset("AESFastEngine", new AESFastEngine(), new AESFastEngine(), new KeyParameter(new byte[16]));
  48. testReset("AESEngine", new AESEngine(), new AESEngine(), new KeyParameter(new byte[16]));
  49. testReset("AESLightEngine", new AESLightEngine(), new AESLightEngine(), new KeyParameter(new byte[16]));
  50. testReset("Twofish", new TwofishEngine(), new TwofishEngine(), new KeyParameter(new byte[16]));
  51. testReset("NoekeonEngine", new NoekeonEngine(), new NoekeonEngine(), new KeyParameter(new byte[16]));
  52. testReset("SerpentEngine", new SerpentEngine(), new SerpentEngine(), new KeyParameter(new byte[16]));
  53. testReset("SEEDEngine", new SEEDEngine(), new SEEDEngine(), new KeyParameter(new byte[16]));
  54. testReset("CAST6Engine", new CAST6Engine(), new CAST6Engine(), new KeyParameter(new byte[16]));
  55. testReset("RC6Engine", new RC6Engine(), new RC6Engine(), new KeyParameter(new byte[16]));
  56. // 64 bit block ciphers
  57. testReset("DESEngine", new DESEngine(), new DESEngine(), new KeyParameter(new byte[8]));
  58. testReset("BlowfishEngine", new BlowfishEngine(), new BlowfishEngine(), new KeyParameter(new byte[8]));
  59. testReset("CAST5Engine", new CAST5Engine(), new CAST5Engine(), new KeyParameter(new byte[8]));
  60. testReset("DESedeEngine", new DESedeEngine(), new DESedeEngine(), new KeyParameter(new byte[24]));
  61. testReset("TEAEngine", new TEAEngine(), new TEAEngine(), new KeyParameter(new byte[16]));
  62. testReset("XTEAEngine", new XTEAEngine(), new XTEAEngine(), new KeyParameter(new byte[16]));
  63. // primitive block cipher modes (don't reset on processBlock)
  64. testModeReset("AES/CBC", new CBCBlockCipher(new AESEngine()), new CBCBlockCipher(new AESEngine()),
  65. new ParametersWithIV(new KeyParameter(new byte[16]), new byte[16]));
  66. testModeReset("AES/SIC", new SICBlockCipher(new AESEngine()), new SICBlockCipher(new AESEngine()),
  67. new ParametersWithIV(new KeyParameter(new byte[16]), new byte[16]));
  68. testModeReset("AES/CFB", new CFBBlockCipher(new AESEngine(), 128), new CFBBlockCipher(new AESEngine(), 128),
  69. new ParametersWithIV(new KeyParameter(new byte[16]), new byte[16]));
  70. testModeReset("AES/OFB", new OFBBlockCipher(new AESEngine(), 128), new OFBBlockCipher(new AESEngine(), 128),
  71. new ParametersWithIV(new KeyParameter(new byte[16]), new byte[16]));
  72. testModeReset("AES/GCTR", new GOFBBlockCipher(new DESEngine()), new GOFBBlockCipher(new DESEngine()),
  73. new ParametersWithIV(new KeyParameter(new byte[8]), new byte[8]));
  74. testModeReset("AES/OpenPGPCFB", new OpenPGPCFBBlockCipher(new AESEngine()), new OpenPGPCFBBlockCipher(
  75. new AESEngine()), new KeyParameter(new byte[16]));
  76. testModeReset("AES/PGPCFB", new PGPCFBBlockCipher(new AESEngine(), false), new PGPCFBBlockCipher(
  77. new AESEngine(), false), new KeyParameter(new byte[16]));
  78. // PGPCFB with IV is broken (it's also not a PRP, so probably shouldn't be a BlockCipher)
  79. // testModeReset("AES/PGPCFBwithIV", new PGPCFBBlockCipher(new AESEngine(), true), new
  80. // PGPCFBBlockCipher(
  81. // new AESEngine(), true), new ParametersWithIV(new KeyParameter(new byte[16]), new
  82. // byte[16]));
  83. // testModeReset("AES/PGPCFBwithIV_NoIV", new PGPCFBBlockCipher(new AESEngine(), true), new
  84. // PGPCFBBlockCipher(
  85. // new AESEngine(), true), new KeyParameter(new byte[16]));
  86. }
  87. private void testModeReset(String test, BlockCipher cipher1, BlockCipher cipher2, CipherParameters params)
  88. throws InvalidCipherTextException
  89. {
  90. testReset(test, false, cipher1, cipher2, params);
  91. }
  92. private void testReset(String test, BlockCipher cipher1, BlockCipher cipher2, CipherParameters params)
  93. throws InvalidCipherTextException
  94. {
  95. testReset(test, true, cipher1, cipher2, params);
  96. }
  97. private void testReset(String test,
  98. boolean testCryptReset,
  99. BlockCipher cipher1,
  100. BlockCipher cipher2,
  101. CipherParameters params)
  102. throws InvalidCipherTextException
  103. {
  104. cipher1.init(true, params);
  105. byte[] plaintext = new byte[cipher1.getBlockSize()];
  106. byte[] ciphertext = new byte[(cipher1.getAlgorithmName().indexOf("PGPCFBwithIV")) > -1 ? 2 * cipher1.getBlockSize() + 2
  107. : cipher1.getBlockSize()];
  108. // Establish baseline answer
  109. crypt(cipher1, true, plaintext, ciphertext);
  110. // Test encryption resets
  111. checkReset(test, testCryptReset, cipher1, params, true, plaintext, ciphertext);
  112. // Test decryption resets with fresh instance
  113. cipher2.init(false, params);
  114. checkReset(test, testCryptReset, cipher2, params, false, ciphertext, plaintext);
  115. }
  116. private void checkReset(String test,
  117. boolean testCryptReset,
  118. BlockCipher cipher,
  119. CipherParameters params,
  120. boolean encrypt,
  121. byte[] pretext,
  122. byte[] posttext)
  123. throws InvalidCipherTextException
  124. {
  125. // Do initial run
  126. byte[] output = new byte[posttext.length];
  127. crypt(cipher, encrypt, pretext, output);
  128. // Check encrypt resets cipher
  129. if (testCryptReset)
  130. {
  131. crypt(cipher, encrypt, pretext, output);
  132. if (!Arrays.areEqual(output, posttext))
  133. {
  134. fail(test + (encrypt ? " encrypt" : " decrypt") + " did not reset cipher.");
  135. }
  136. }
  137. // Check init resets data
  138. cipher.processBlock(pretext, 0, output, 0);
  139. cipher.init(encrypt, params);
  140. try
  141. {
  142. crypt(cipher, encrypt, pretext, output);
  143. }
  144. catch (DataLengthException e)
  145. {
  146. fail(test + " init did not reset data.");
  147. }
  148. if (!Arrays.areEqual(output, posttext))
  149. {
  150. fail(test + " init did not reset data.", new String(Hex.encode(posttext)), new String(Hex.encode(output)));
  151. }
  152. // Check reset resets data
  153. cipher.processBlock(pretext, 0, output, 0);
  154. cipher.reset();
  155. try
  156. {
  157. crypt(cipher, encrypt, pretext, output);
  158. }
  159. catch (DataLengthException e)
  160. {
  161. fail(test + " reset did not reset data.");
  162. }
  163. if (!Arrays.areEqual(output, posttext))
  164. {
  165. fail(test + " reset did not reset data.");
  166. }
  167. }
  168. private static void crypt(BlockCipher cipher1, boolean encrypt, byte[] plaintext, byte[] output)
  169. throws InvalidCipherTextException
  170. {
  171. cipher1.processBlock(plaintext, 0, output, 0);
  172. if ((cipher1.getAlgorithmName().indexOf("PGPCFBwithIV") > -1) && !encrypt)
  173. {
  174. // Process past IV in first block
  175. cipher1.processBlock(plaintext, cipher1.getBlockSize(), output, 0);
  176. }
  177. }
  178. public static void main(String[] args)
  179. {
  180. runTest(new BlockCipherResetTest());
  181. }
  182. }