diff options
Diffstat (limited to 'bcprov/src/main/java/org/bouncycastle/crypto/test/StreamCipherResetTest.java')
-rw-r--r-- | bcprov/src/main/java/org/bouncycastle/crypto/test/StreamCipherResetTest.java | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/test/StreamCipherResetTest.java b/bcprov/src/main/java/org/bouncycastle/crypto/test/StreamCipherResetTest.java new file mode 100644 index 0000000..092de5f --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/crypto/test/StreamCipherResetTest.java @@ -0,0 +1,133 @@ +package org.bouncycastle.crypto.test; + +import java.security.SecureRandom; + +import org.bouncycastle.crypto.CipherParameters; +import org.bouncycastle.crypto.InvalidCipherTextException; +import org.bouncycastle.crypto.StreamCipher; +import org.bouncycastle.crypto.engines.ChaChaEngine; +import org.bouncycastle.crypto.engines.Grain128Engine; +import org.bouncycastle.crypto.engines.Grainv1Engine; +import org.bouncycastle.crypto.engines.HC128Engine; +import org.bouncycastle.crypto.engines.HC256Engine; +import org.bouncycastle.crypto.engines.ISAACEngine; +import org.bouncycastle.crypto.engines.RC4Engine; +import org.bouncycastle.crypto.engines.Salsa20Engine; +import org.bouncycastle.crypto.engines.XSalsa20Engine; +import org.bouncycastle.crypto.params.KeyParameter; +import org.bouncycastle.crypto.params.ParametersWithIV; +import org.bouncycastle.util.Arrays; +import org.bouncycastle.util.encoders.Hex; +import org.bouncycastle.util.test.SimpleTest; + +/** + * Test whether block ciphers implement reset contract on init, encrypt/decrypt and reset. + */ +public class StreamCipherResetTest + extends SimpleTest +{ + public String getName() + { + return "Stream Cipher Reset"; + } + + public void performTest() + throws Exception + { + testReset(new Salsa20Engine(), new Salsa20Engine(), new ParametersWithIV(new KeyParameter(random(32)), + random(8))); + testReset(new Salsa20Engine(), new Salsa20Engine(), new ParametersWithIV(new KeyParameter(random(16)), + random(8))); + testReset(new XSalsa20Engine(), new XSalsa20Engine(), new ParametersWithIV(new KeyParameter(random(32)), + random(24))); + testReset(new ChaChaEngine(), new ChaChaEngine(), new ParametersWithIV(new KeyParameter(random(32)), random(8))); + testReset(new ChaChaEngine(), new ChaChaEngine(), new ParametersWithIV(new KeyParameter(random(16)), random(8))); + testReset(new RC4Engine(), new RC4Engine(), new KeyParameter(random(16))); + testReset(new ISAACEngine(), new ISAACEngine(), new KeyParameter(random(16))); + testReset(new HC128Engine(), new HC128Engine(), new ParametersWithIV(new KeyParameter(random(16)), random(16))); + testReset(new HC256Engine(), new HC256Engine(), new ParametersWithIV(new KeyParameter(random(16)), random(16))); + testReset(new Grainv1Engine(), new Grainv1Engine(), new ParametersWithIV(new KeyParameter(random(16)), + random(8))); + testReset(new Grain128Engine(), new Grain128Engine(), new ParametersWithIV(new KeyParameter(random(16)), + random(12))); + } + + private static final SecureRandom RAND = new SecureRandom(); + + private byte[] random(int size) + { + final byte[] data = new byte[size]; + RAND.nextBytes(data); + return data; + } + + private void testReset(StreamCipher cipher1, StreamCipher cipher2, CipherParameters params) + throws InvalidCipherTextException + { + cipher1.init(true, params); + + 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, params, true, plaintext, ciphertext); + + // Test decryption resets with fresh instance + cipher2.init(false, params); + checkReset(cipher2, params, false, ciphertext, plaintext); + } + + private void checkReset(StreamCipher cipher, + CipherParameters params, + boolean encrypt, + byte[] pretext, + byte[] posttext) + throws InvalidCipherTextException + { + // Do initial run + byte[] output = new byte[posttext.length]; + cipher.processBytes(pretext, 0, pretext.length, output, 0); + + // Check encrypt resets cipher + cipher.init(encrypt, params); + + try + { + cipher.processBytes(pretext, 0, pretext.length, output, 0); + } + catch (Exception e) + { + fail(cipher.getAlgorithmName() + " init did not reset: " + e.getMessage()); + } + if (!Arrays.areEqual(output, posttext)) + { + fail(cipher.getAlgorithmName() + " init did not reset.", new String(Hex.encode(posttext)), + new String(Hex.encode(output))); + } + + // Check reset resets data + cipher.reset(); + + try + { + cipher.processBytes(pretext, 0, pretext.length, output, 0); + } + catch (Exception e) + { + fail(cipher.getAlgorithmName() + " reset did not reset: " + e.getMessage()); + } + if (!Arrays.areEqual(output, posttext)) + { + fail(cipher.getAlgorithmName() + " reset did not reset."); + } + } + + public static void main(String[] args) + { + runTest(new StreamCipherResetTest()); + } + +} |