1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.crypto.stream;
19
20 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
21 import static org.junit.jupiter.api.Assertions.assertEquals;
22 import static org.junit.jupiter.api.Assertions.assertNotNull;
23 import static org.junit.jupiter.api.Assertions.assertThrows;
24
25 import java.io.ByteArrayInputStream;
26 import java.io.ByteArrayOutputStream;
27 import java.io.IOException;
28 import java.nio.ByteBuffer;
29 import java.nio.channels.Channels;
30 import java.security.spec.AlgorithmParameterSpec;
31 import java.util.Properties;
32 import java.util.concurrent.TimeUnit;
33
34 import javax.crypto.ShortBufferException;
35 import javax.crypto.spec.IvParameterSpec;
36
37 import org.apache.commons.crypto.cipher.AbstractCipherTest;
38 import org.apache.commons.crypto.cipher.CryptoCipher;
39 import org.apache.commons.crypto.stream.input.ChannelInput;
40 import org.apache.commons.crypto.stream.input.StreamInput;
41 import org.apache.commons.crypto.stream.output.ChannelOutput;
42 import org.apache.commons.crypto.utils.AES;
43 import org.junit.jupiter.api.Test;
44 import org.junit.jupiter.api.Timeout;
45
46 public class CtrCryptoStreamTest extends AbstractCipherStreamTest {
47
48 protected void doDecryptTest(final String cipherClass, final boolean withChannel)
49 throws IOException {
50
51 final CtrCryptoInputStream in = newCryptoInputStream(new ByteArrayInputStream(encData),
52 getCipher(cipherClass), defaultBufferSize, iv, withChannel);
53
54 final ByteBuffer buf = ByteBuffer.allocateDirect(dataLen);
55 buf.put(encData);
56 buf.rewind();
57 in.decrypt(buf, 0, dataLen);
58 final byte[] readData = new byte[dataLen];
59 final byte[] expectedData = new byte[dataLen];
60 buf.get(readData);
61 System.arraycopy(data, 0, expectedData, 0, dataLen);
62 assertArrayEquals(readData, expectedData);
63 final Exception ex = assertThrows(IOException.class, () -> in.decryptBuffer(buf));
64 assertEquals(ex.getCause().getClass(), ShortBufferException.class);
65
66 }
67
68 @Override
69 protected void doFieldGetterTest(final String cipherClass, final ByteArrayOutputStream baos,
70 final boolean withChannel) throws Exception {
71 assumeJniPresence(cipherClass);
72
73 final StreamInput streamInput = new StreamInput(new ByteArrayInputStream(encData), 0);
74 Exception ex = assertThrows(UnsupportedOperationException.class, () -> streamInput.seek(0));
75 assertEquals(ex.getMessage(), "Seek is not supported by this implementation");
76
77 ex = assertThrows(UnsupportedOperationException.class, () -> streamInput.read(0, new byte[0], 0, 0));
78 assertEquals(ex.getMessage(), "Positioned read is not supported by this implementation");
79
80 assertEquals(streamInput.available(), encData.length);
81
82 final ChannelInput channelInput = new ChannelInput(Channels.newChannel(new ByteArrayInputStream(encData)));
83 ex = assertThrows(UnsupportedOperationException.class, () -> channelInput.seek(0));
84 assertEquals(ex.getMessage(), "Seek is not supported by this implementation");
85
86 ex = assertThrows(UnsupportedOperationException.class, () -> channelInput.read(0, new byte[0], 0, 0));
87 assertEquals(ex.getMessage(), "Positioned read is not supported by this implementation");
88 assertEquals(channelInput.available(), 0);
89
90 final CtrCryptoInputStream in = new CtrCryptoInputStream(channelInput, getCipher(cipherClass),
91 defaultBufferSize, key, iv);
92
93 final Properties props = new Properties();
94 final String bufferSize = "4096";
95 props.put(CryptoInputStream.STREAM_BUFFER_SIZE_KEY, bufferSize);
96 in.setStreamOffset(smallBufferSize);
97
98 assertEquals(CryptoInputStream.getBufferSize(props), Integer.parseInt(bufferSize));
99 assertEquals(smallBufferSize, in.getStreamOffset());
100 assertEquals(in.getBufferSize(), 8192);
101 assertEquals(in.getCipher().getClass(), Class.forName(cipherClass));
102 assertEquals(in.getKey().getAlgorithm(), AES.ALGORITHM);
103 assertEquals(in.getParams().getClass(), IvParameterSpec.class);
104 assertNotNull(in.getInput());
105
106 in.close();
107
108 final CtrCryptoOutputStream out = new CtrCryptoOutputStream(new ChannelOutput(
109 Channels.newChannel(baos)), getCipher(cipherClass),
110 Integer.parseInt(bufferSize), key, iv);
111 out.setStreamOffset(smallBufferSize);
112 assertEquals(out.getStreamOffset(), smallBufferSize);
113
114 out.close();
115 }
116
117 @Override
118 protected CtrCryptoInputStream newCryptoInputStream(
119 final ByteArrayInputStream bais, final CryptoCipher cipher, final int bufferSize,
120 final byte[] iv, final boolean withChannel) throws IOException {
121 if (withChannel) {
122 return new CtrCryptoInputStream(Channels.newChannel(bais), cipher,
123 bufferSize, key, iv);
124 }
125 return new CtrCryptoInputStream(bais, cipher, bufferSize, key, iv);
126 }
127
128 @Override
129 protected CryptoInputStream newCryptoInputStream(final String transformation, final Properties props,
130 final ByteArrayInputStream bais, final byte[] key, final AlgorithmParameterSpec params,
131 final boolean withChannel) throws IOException {
132 if (withChannel) {
133 return new CtrCryptoInputStream(props, Channels.newChannel(bais), key,
134 ((IvParameterSpec)params).getIV());
135 }
136 return new CtrCryptoInputStream(props, bais, key, ((IvParameterSpec)params).getIV());
137 }
138
139 @Override
140 protected CtrCryptoOutputStream newCryptoOutputStream(
141 final ByteArrayOutputStream baos, final CryptoCipher cipher, final int bufferSize,
142 final byte[] iv, final boolean withChannel) throws IOException {
143 if (withChannel) {
144 return new CtrCryptoOutputStream(Channels.newChannel(baos), cipher,
145 bufferSize, key, iv);
146 }
147 return new CtrCryptoOutputStream(baos, cipher, bufferSize, key, iv);
148 }
149
150 @Override
151 protected CtrCryptoOutputStream newCryptoOutputStream(final String transformation,
152 final Properties props, final ByteArrayOutputStream baos, final byte[] key,
153 final AlgorithmParameterSpec params, final boolean withChannel) throws IOException {
154 if (withChannel) {
155 return new CtrCryptoOutputStream(props, Channels.newChannel(baos), key,
156 ((IvParameterSpec)params).getIV());
157 }
158 return new CtrCryptoOutputStream(props, baos, key, ((IvParameterSpec)params).getIV());
159 }
160
161 @Override
162 public void setUp() {
163 transformation = AES.CTR_NO_PADDING;
164 }
165
166 @Test
167 @Timeout(value = 120000, unit = TimeUnit.MILLISECONDS)
168 public void testDecrypt() throws Exception {
169 doDecryptTest(AbstractCipherTest.JCE_CIPHER_CLASSNAME, false);
170 doDecryptTest(AbstractCipherTest.OPENSSL_CIPHER_CLASSNAME, false);
171
172 doDecryptTest(AbstractCipherTest.JCE_CIPHER_CLASSNAME, true);
173 doDecryptTest(AbstractCipherTest.OPENSSL_CIPHER_CLASSNAME, true);
174 }
175 }