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.assertFalse;
23 import static org.junit.jupiter.api.Assertions.assertNotNull;
24 import static org.junit.jupiter.api.Assertions.assertThrows;
25 import static org.junit.jupiter.api.Assertions.assertTrue;
26 import static org.junit.jupiter.api.Assertions.fail;
27 import static org.junit.jupiter.api.Assumptions.assumeFalse;
28
29 import java.io.BufferedInputStream;
30 import java.io.ByteArrayInputStream;
31 import java.io.ByteArrayOutputStream;
32 import java.io.DataInputStream;
33 import java.io.IOException;
34 import java.io.InputStream;
35 import java.io.OutputStream;
36 import java.nio.ByteBuffer;
37 import java.nio.channels.Channels;
38 import java.nio.channels.ReadableByteChannel;
39 import java.security.Key;
40 import java.security.SecureRandom;
41 import java.security.spec.AlgorithmParameterSpec;
42 import java.util.Properties;
43 import java.util.Random;
44 import java.util.concurrent.TimeUnit;
45
46 import javax.crypto.spec.GCMParameterSpec;
47 import javax.crypto.spec.IvParameterSpec;
48
49 import org.apache.commons.crypto.Crypto;
50 import org.apache.commons.crypto.cipher.AbstractCipherTest;
51 import org.apache.commons.crypto.cipher.CryptoCipher;
52 import org.apache.commons.crypto.utils.AES;
53 import org.apache.commons.crypto.utils.ReflectionUtils;
54 import org.junit.jupiter.api.BeforeEach;
55 import org.junit.jupiter.api.Test;
56 import org.junit.jupiter.api.Timeout;
57
58 public abstract class AbstractCipherStreamTest {
59
60 protected static int defaultBufferSize = 8192;
61 protected static int smallBufferSize = 1024;
62 protected final int dataLen = 20000;
63 protected final byte[] data = new byte[dataLen];
64 protected byte[] encData;
65 private final Properties props = new Properties();
66 protected byte[] key = new byte[16];
67 protected byte[] iv = new byte[16];
68 protected int count = 10000;
69
70 protected String transformation;
71
72 public void assumeJniPresence(final String cipherClass) {
73 assumeFalse(AbstractCipherTest.OPENSSL_CIPHER_CLASSNAME.equals(cipherClass) && !Crypto.isNativeCodeLoaded());
74 }
75
76 @BeforeEach
77 public void before() throws Exception {
78 final Random random = new SecureRandom();
79 random.nextBytes(data);
80 random.nextBytes(key);
81 random.nextBytes(iv);
82 setUp();
83 prepareData();
84 }
85
86 private void byteBufferFinalReadCheck(final InputStream in, final ByteBuffer buf, final int bufPos)
87 throws Exception {
88 buf.position(bufPos);
89 int len = 0;
90 int n = 0;
91 do {
92 n = ((ReadableByteChannel) in).read(buf);
93 len += n;
94 } while (n > 0);
95 buf.rewind();
96 final byte[] readData = new byte[len + 1];
97 buf.get(readData);
98 final byte[] expectedData = new byte[len + 1];
99 System.arraycopy(data, 0, expectedData, 0, len + 1);
100 assertArrayEquals(readData, expectedData);
101 }
102
103 private void byteBufferReadCheck(final InputStream in, final ByteBuffer buf, final int bufPos)
104 throws Exception {
105 buf.position(bufPos);
106 final int n = ((ReadableByteChannel) in).read(buf);
107 assertEquals(bufPos + n, buf.position());
108 final byte[] readData = new byte[n];
109 buf.rewind();
110 buf.position(bufPos);
111 buf.get(readData);
112 final byte[] expectedData = new byte[n];
113 System.arraycopy(data, 0, expectedData, 0, n);
114 assertArrayEquals(readData, expectedData);
115
116 assertThrows(IndexOutOfBoundsException.class, () -> in.read(readData, -1, 0));
117 }
118
119 protected void doByteBufferRead(final String cipherClass, final boolean withChannel)
120 throws Exception {
121
122 assumeJniPresence(cipherClass);
123 ByteBuffer buf = ByteBuffer.allocate(dataLen + 100);
124
125 try (InputStream in = newCryptoInputStream(new ByteArrayInputStream(encData), getCipher(cipherClass),
126 defaultBufferSize, iv, withChannel)) {
127 byteBufferReadCheck(in, buf, 0);
128 }
129
130
131 try (InputStream in = newCryptoInputStream(new ByteArrayInputStream(encData), getCipher(cipherClass),
132 defaultBufferSize, iv, withChannel)) {
133 buf.clear();
134 byteBufferReadCheck(in, buf, 11);
135 }
136
137
138 try (InputStream in = newCryptoInputStream(new ByteArrayInputStream(encData), getCipher(cipherClass),
139 smallBufferSize, iv, withChannel)) {
140 buf.clear();
141 byteBufferReadCheck(in, buf, 0);
142 }
143
144
145 try (InputStream in = newCryptoInputStream(new ByteArrayInputStream(encData), getCipher(cipherClass),
146 smallBufferSize, iv, withChannel)) {
147 buf.clear();
148 byteBufferReadCheck(in, buf, 11);
149 }
150
151
152 try (InputStream in = newCryptoInputStream(new ByteArrayInputStream(encData), getCipher(cipherClass),
153 defaultBufferSize, iv, withChannel)) {
154 buf = ByteBuffer.allocateDirect(dataLen + 100);
155 byteBufferReadCheck(in, buf, 0);
156 }
157
158
159 try (InputStream in = newCryptoInputStream(new ByteArrayInputStream(encData), getCipher(cipherClass),
160 defaultBufferSize, iv, withChannel)) {
161 buf.clear();
162 byteBufferReadCheck(in, buf, 11);
163 }
164
165
166 try (InputStream in = newCryptoInputStream(new ByteArrayInputStream(encData), getCipher(cipherClass),
167 smallBufferSize, iv, withChannel)) {
168 buf.clear();
169 byteBufferReadCheck(in, buf, 0);
170 }
171
172
173 try (InputStream in = newCryptoInputStream(new ByteArrayInputStream(encData), getCipher(cipherClass),
174 smallBufferSize, iv, withChannel)) {
175 buf.clear();
176 byteBufferReadCheck(in, buf, 11);
177 }
178
179
180 try (InputStream in = newCryptoInputStream(new ByteArrayInputStream(encData), getCipher(cipherClass),
181 smallBufferSize, iv, withChannel)) {
182 buf.clear();
183 byteBufferFinalReadCheck(in, buf, 0);
184 }
185
186
187 try (InputStream in = newCryptoInputStream(new ByteArrayInputStream(encData), getCipher(cipherClass),
188 defaultBufferSize, iv, withChannel)) {
189 buf = ByteBuffer.allocate(100);
190 byteBufferReadCheck(in, buf, 0);
191 }
192
193
194 try (InputStream in = newCryptoInputStream(transformation, props, new ByteArrayInputStream(encData), key,
195 new IvParameterSpec(iv), withChannel)) {
196 buf = ByteBuffer.allocate(dataLen + 100);
197 byteBufferReadCheck(in, buf, 0);
198 }
199
200
201 try (InputStream in = newCryptoInputStream(transformation, props, new ByteArrayInputStream(encData), key,
202 new IvParameterSpec(iv), withChannel)) {
203 buf.clear();
204 byteBufferReadCheck(in, buf, 11);
205 }
206
207
208 try (InputStream in = newCryptoInputStream(transformation, props, new ByteArrayInputStream(encData), key,
209 new IvParameterSpec(iv), withChannel)) {
210 buf.clear();
211 byteBufferReadCheck(in, buf, 0);
212 }
213
214
215 try (InputStream in = newCryptoInputStream(transformation, props, new ByteArrayInputStream(encData), key,
216 new IvParameterSpec(iv), withChannel)) {
217 buf.clear();
218 byteBufferReadCheck(in, buf, 11);
219 }
220
221
222 try (InputStream in = newCryptoInputStream(transformation, props, new ByteArrayInputStream(encData), key,
223 new IvParameterSpec(iv), withChannel)) {
224 buf = ByteBuffer.allocateDirect(dataLen + 100);
225 byteBufferReadCheck(in, buf, 0);
226 }
227
228
229 try (InputStream in = newCryptoInputStream(transformation, props, new ByteArrayInputStream(encData), key,
230 new IvParameterSpec(iv), withChannel)) {
231 buf.clear();
232 byteBufferReadCheck(in, buf, 11);
233 }
234
235
236 try (InputStream in = newCryptoInputStream(transformation, props, new ByteArrayInputStream(encData), key,
237 new IvParameterSpec(iv), withChannel)) {
238 buf.clear();
239 byteBufferReadCheck(in, buf, 0);
240 }
241
242
243 try (InputStream in = newCryptoInputStream(transformation, props, new ByteArrayInputStream(encData), key,
244 new IvParameterSpec(iv), withChannel)) {
245 buf.clear();
246 byteBufferReadCheck(in, buf, 11);
247 }
248
249
250 try (InputStream in = newCryptoInputStream(transformation, props, new ByteArrayInputStream(encData), key,
251 new IvParameterSpec(iv), withChannel)) {
252 buf.clear();
253 byteBufferFinalReadCheck(in, buf, 0);
254 }
255
256
257 try (InputStream in = newCryptoInputStream(transformation, props, new ByteArrayInputStream(encData), key,
258 new IvParameterSpec(iv), withChannel)) {
259 buf = ByteBuffer.allocate(100);
260 byteBufferReadCheck(in, buf, 0);
261 }
262 }
263
264 private void doByteBufferWrite(final CryptoOutputStream out, final boolean withChannel) throws Exception {
265 ByteBuffer buf = ByteBuffer.allocateDirect(dataLen / 2);
266 buf.put(data, 0, dataLen / 2);
267 buf.flip();
268 final int n1 = out.write(buf);
269
270 buf.clear();
271 buf.put(data, n1, dataLen / 3);
272 buf.flip();
273 final int n2 = out.write(buf);
274
275 buf.clear();
276 buf.put(data, n1 + n2, dataLen - n1 - n2 - 1);
277 buf.flip();
278 final int n3 = out.write(buf);
279
280 out.write(1);
281
282 assertEquals(dataLen, n1 + n2 + n3 + 1);
283
284 assertThrows(IndexOutOfBoundsException.class, () -> out.write(data, 0, data.length + 1));
285 out.flush();
286
287 try (InputStream in = newCryptoInputStream(
288 new ByteArrayInputStream(encData), out.getCipher(),
289 defaultBufferSize, iv, withChannel)) {
290 buf = ByteBuffer.allocate(dataLen + 100);
291 byteBufferReadCheck(in, buf, 0);
292 }
293 }
294
295 protected void doByteBufferWrite(final String cipherClass,
296 final ByteArrayOutputStream baos, final boolean withChannel)
297 throws Exception {
298 assumeJniPresence(cipherClass);
299 baos.reset();
300 CryptoOutputStream out = newCryptoOutputStream(baos, getCipher(cipherClass), defaultBufferSize, iv, withChannel);
301 doByteBufferWrite(out, withChannel);
302
303 baos.reset();
304 try (final CryptoCipher cipher = getCipher(cipherClass)) {
305 final String transformation = cipher.getAlgorithm();
306 out = newCryptoOutputStream(transformation, props, baos, key, new IvParameterSpec(iv), withChannel);
307 doByteBufferWrite(out, withChannel);
308 out.write(1);
309 assertTrue(out.isOpen());
310
311 out = newCryptoOutputStream(transformation, props, baos, key, new IvParameterSpec(iv), withChannel);
312 out.close();
313 assertFalse(out.isOpen());
314 }
315 }
316
317 protected void doExceptionTest(final String cipherClass, final ByteArrayOutputStream baos,
318 final boolean withChannel) throws IOException {
319 assumeJniPresence(cipherClass);
320
321
322 Exception ex = assertThrows(IOException.class, () -> newCryptoInputStream(transformation, props, new ByteArrayInputStream(encData),
323 AES.newSecretKeySpec(key), new GCMParameterSpec(0, new byte[0]), withChannel));
324 assertEquals(ex.getMessage(),"Illegal parameters");
325
326 ex = assertThrows(IOException.class, () -> newCryptoOutputStream(transformation, props, baos,
327 AES.newSecretKeySpec(key), new GCMParameterSpec(0,
328 new byte[0]), withChannel));
329 assertEquals(ex.getMessage(),"Illegal parameters");
330
331
332 assertThrows(IOException.class, () -> newCryptoInputStream(transformation,props, new ByteArrayInputStream(encData),
333 AES.newSecretKeySpec(new byte[10]), new IvParameterSpec(iv), withChannel));
334
335 assertThrows(IOException.class, () -> newCryptoOutputStream(transformation, props, baos, new byte[10],
336 new IvParameterSpec(iv), withChannel));
337
338
339 InputStream closedIn;
340 try (final InputStream in = newCryptoInputStream(new ByteArrayInputStream(encData),
341 getCipher(cipherClass), defaultBufferSize, iv, withChannel)) {
342 closedIn = in;
343 }
344
345 ex = assertThrows(IOException.class, closedIn::read);
346 assertEquals(ex.getMessage(), "Stream closed");
347
348
349 try {
350 closedIn.close();
351 } catch (final IOException ioEx) {
352 fail("Should not throw exception closing a closed stream.");
353 }
354
355
356 final OutputStream out = newCryptoOutputStream(transformation, props, baos, key, new IvParameterSpec(iv),
357 withChannel);
358 out.close();
359
360 assertThrows(IOException.class, ((CryptoOutputStream) out)::checkStream);
361
362
363 try {
364 out.close();
365 } catch (final IOException ioEx) {
366 fail("Should not throw exception closing a closed stream.");
367 }
368
369
370 try {
371 CryptoInputStream.checkStreamCipher(getCipher(cipherClass));
372 } catch (final IOException ioEx) {
373 assertEquals(ioEx.getMessage(), "AES/CTR/NoPadding is required");
374 } finally {
375 closedIn.close();
376 }
377
378
379 try (final InputStream inNewCrytptoStr = newCryptoInputStream(new ByteArrayInputStream(encData),
380 getCipher(cipherClass), defaultBufferSize, iv, false)) {
381 closedIn.mark(0);
382 assertFalse(closedIn.markSupported());
383 ex = assertThrows(IOException.class, inNewCrytptoStr::reset);
384 assertEquals(ex.getMessage(), "mark/reset not supported");
385 }
386 }
387
388 protected void doFieldGetterTest(final String cipherClass, final ByteArrayOutputStream baos,
389 final boolean withChannel) throws Exception {
390 assumeJniPresence(cipherClass);
391
392 try (final CryptoCipher cipher = getCipher(cipherClass);
393 final CryptoInputStream in = newCryptoInputStream(new ByteArrayInputStream(encData), cipher, defaultBufferSize, iv, withChannel)) {
394
395 final Properties props = new Properties();
396 final String bufferSize = Integer.toString(defaultBufferSize / 2);
397 props.put(CryptoInputStream.STREAM_BUFFER_SIZE_KEY, bufferSize);
398
399 assertEquals(CryptoInputStream.getBufferSize(props), Integer.parseInt(bufferSize));
400 assertEquals(in.getBufferSize(), defaultBufferSize);
401 assertEquals(in.getCipher().getClass(), Class.forName(cipherClass));
402 assertEquals(in.getKey().getAlgorithm(), AES.ALGORITHM);
403 assertEquals(in.getParams().getClass(), IvParameterSpec.class);
404 assertNotNull(in.getInput());
405
406 try (final CryptoOutputStream out = newCryptoOutputStream(baos, getCipher(cipherClass), defaultBufferSize, iv, withChannel)) {
407 assertEquals(out.getOutBuffer().capacity(), defaultBufferSize + cipher.getBlockSize());
408 assertEquals(out.getInBuffer().capacity(), defaultBufferSize);
409 assertEquals(out.getBufferSize(), defaultBufferSize);
410 }
411 }
412 }
413
414 protected void doReadWriteTest(final int count, final String encCipherClass,
415 final String decCipherClass, final byte[] iv) throws IOException {
416 doReadWriteTestForInputStream(count, encCipherClass, decCipherClass, iv);
417 doReadWriteTestForReadableByteChannel(count, encCipherClass,
418 decCipherClass, iv);
419 }
420
421 private void doReadWriteTestForInputStream(final int count,
422 final String encCipherClass, final String decCipherClass, final byte[] iv)
423 throws IOException {
424 assumeJniPresence(encCipherClass);
425 assumeJniPresence(decCipherClass);
426
427 try (final CryptoCipher encCipher = getCipher(encCipherClass)) {
428
429
430 final SecureRandom random = new SecureRandom();
431 final byte[] originalData = new byte[count];
432 final byte[] decryptedData = new byte[count];
433 random.nextBytes(originalData);
434
435
436 final ByteArrayOutputStream encryptedData = new ByteArrayOutputStream();
437 try (CryptoOutputStream out = newCryptoOutputStream(encryptedData, encCipher, defaultBufferSize, iv, false)) {
438 out.write(originalData, 0, originalData.length);
439 out.flush();
440 }
441
442
443 try (final CryptoCipher decCipher = getCipher(decCipherClass)) {
444
445
446 try (CryptoInputStream in = newCryptoInputStream(new ByteArrayInputStream(encryptedData.toByteArray()), decCipher, defaultBufferSize, iv,
447 false)) {
448
449
450 int remainingToRead = count;
451 int offset = 0;
452 while (remainingToRead > 0) {
453 final int n = in.read(decryptedData, offset, decryptedData.length - offset);
454 if (n >= 0) {
455 remainingToRead -= n;
456 offset += n;
457 }
458 }
459
460 assertArrayEquals(originalData, decryptedData, "originalData and decryptedData not equal");
461 }
462
463
464 try (CryptoInputStream in = newCryptoInputStream(new ByteArrayInputStream(encryptedData.toByteArray()), decCipher, defaultBufferSize, iv,
465 false)) {
466
467
468 final DataInputStream originalIn = new DataInputStream(new BufferedInputStream(new ByteArrayInputStream(originalData)));
469 int expected;
470 do {
471 expected = originalIn.read();
472 assertEquals(expected, in.read(), "Decrypted stream read by byte does not match");
473 } while (expected != -1);
474
475
476 }
477 }
478 }
479 }
480
481 private void doReadWriteTestForReadableByteChannel(final int count,
482 final String encCipherClass, final String decCipherClass, final byte[] iv)
483 throws IOException {
484 assumeJniPresence(encCipherClass);
485 assumeJniPresence(decCipherClass);
486
487 try (final CryptoCipher encCipher = getCipher(encCipherClass)) {
488
489
490 final SecureRandom random = new SecureRandom();
491 final byte[] originalData = new byte[count];
492 final byte[] decryptedData = new byte[count];
493 random.nextBytes(originalData);
494
495
496 final ByteArrayOutputStream encryptedData = new ByteArrayOutputStream();
497 try (CryptoOutputStream out = newCryptoOutputStream(encryptedData, encCipher, defaultBufferSize, iv, true)) {
498 out.write(originalData, 0, originalData.length);
499 out.flush();
500 }
501
502
503 try (final CryptoCipher decCipher = getCipher(decCipherClass)) {
504
505
506 try (CryptoInputStream in = newCryptoInputStream(new ByteArrayInputStream(encryptedData.toByteArray()), decCipher, defaultBufferSize, iv,
507 true)) {
508
509
510 int remainingToRead = count;
511 int offset = 0;
512 while (remainingToRead > 0) {
513 final int n = in.read(decryptedData, offset, decryptedData.length - offset);
514 if (n >= 0) {
515 remainingToRead -= n;
516 offset += n;
517 }
518 }
519
520 assertArrayEquals(originalData, decryptedData);
521 }
522
523
524 try (CryptoInputStream in = newCryptoInputStream(new ByteArrayInputStream(encryptedData.toByteArray()), decCipher, defaultBufferSize, iv,
525 true)) {
526
527
528 final DataInputStream originalIn = new DataInputStream(new BufferedInputStream(new ByteArrayInputStream(originalData)));
529 int expected;
530 do {
531 expected = originalIn.read();
532 assertEquals(expected, in.read());
533 } while (expected != -1);
534
535
536 }
537 }
538 }
539 }
540
541 protected void doSkipTest(final String cipherClass, final boolean withChannel)
542 throws IOException {
543 assumeJniPresence(cipherClass);
544 try (@SuppressWarnings("resource")
545 InputStream in = newCryptoInputStream(
546 new ByteArrayInputStream(encData), getCipher(cipherClass),
547 defaultBufferSize, iv, withChannel)) {
548 final byte[] result = new byte[dataLen];
549 final int n1 = readAll(in, result, 0, dataLen / 5);
550
551 assertEquals(in.skip(0), 0);
552
553 long skipped = in.skip(dataLen / 5);
554 final int n2 = readAll(in, result, 0, dataLen);
555
556 assertEquals(dataLen, n1 + skipped + n2);
557 final byte[] readData = new byte[n2];
558 System.arraycopy(result, 0, readData, 0, n2);
559 final byte[] expectedData = new byte[n2];
560 System.arraycopy(data, dataLen - n2, expectedData, 0, n2);
561 assertArrayEquals(readData, expectedData);
562
563 final Exception e = assertThrows(IllegalArgumentException.class, () -> in.skip(-3));
564 assertTrue(e.getMessage().contains("Negative skip length"));
565
566
567 skipped = in.skip(3);
568 assertEquals(skipped, 0);
569 }
570 }
571
572 protected CryptoCipher getCipher(final String cipherClass) throws IOException {
573 try {
574 return (CryptoCipher) ReflectionUtils.newInstance(
575 ReflectionUtils.getClassByName(cipherClass), props,
576 transformation);
577 } catch (final ClassNotFoundException cnfe) {
578 throw new IOException("Illegal crypto cipher!");
579 }
580 }
581
582 protected CryptoInputStream newCryptoInputStream(final ByteArrayInputStream bais,
583 final CryptoCipher cipher, final int bufferSize, final byte[] iv, final boolean withChannel)
584 throws IOException {
585 if (withChannel) {
586 return new CryptoInputStream(Channels.newChannel(bais), cipher,
587 bufferSize, AES.newSecretKeySpec(key),
588 new IvParameterSpec(iv));
589 }
590 return new CryptoInputStream(bais, cipher, bufferSize,
591 AES.newSecretKeySpec(key), new IvParameterSpec(iv));
592 }
593
594 protected CryptoInputStream newCryptoInputStream(final String transformation, final Properties props,
595 final ByteArrayInputStream bais, final byte[] key, final AlgorithmParameterSpec params,
596 final boolean withChannel) throws IOException {
597 if (withChannel) {
598 return new CryptoInputStream(transformation, props, Channels.newChannel(bais), AES.newSecretKeySpec(key), params);
599 }
600 return new CryptoInputStream(transformation, props, bais, AES.newSecretKeySpec(key), params);
601 }
602
603 protected CryptoInputStream newCryptoInputStream(final String transformation,
604 final Properties props, final ByteArrayInputStream bais, final Key key,
605 final AlgorithmParameterSpec params, final boolean withChannel) throws IOException {
606 if (withChannel) {
607 return new CryptoInputStream(transformation, props, Channels.newChannel(bais), key, params);
608 }
609 return new CryptoInputStream(transformation, props, bais, key, params);
610 }
611
612 protected CryptoOutputStream newCryptoOutputStream(
613 final ByteArrayOutputStream baos, final CryptoCipher cipher, final int bufferSize,
614 final byte[] iv, final boolean withChannel) throws IOException {
615 if (withChannel) {
616 return new CryptoOutputStream(Channels.newChannel(baos), cipher,
617 bufferSize, AES.newSecretKeySpec(key),
618 new IvParameterSpec(iv));
619 }
620 return new CryptoOutputStream(baos, cipher, bufferSize,
621 AES.newSecretKeySpec(key), new IvParameterSpec(iv));
622 }
623
624 protected CryptoOutputStream newCryptoOutputStream(final String transformation,
625 final Properties props, final ByteArrayOutputStream baos, final byte[] key,
626 final AlgorithmParameterSpec param, final boolean withChannel) throws IOException {
627 if (withChannel) {
628 return new CryptoOutputStream(transformation, props, Channels.newChannel(baos),
629 AES.newSecretKeySpec(key), param);
630 }
631 return new CryptoOutputStream(transformation, props, baos, AES.newSecretKeySpec(key),
632 param);
633 }
634
635 protected CryptoOutputStream newCryptoOutputStream(final String transformation,
636 final Properties props, final ByteArrayOutputStream baos, final Key key,
637 final AlgorithmParameterSpec params, final boolean withChannel) throws IOException {
638 if (withChannel) {
639 return new CryptoOutputStream(transformation, props, Channels.newChannel(baos), key, params);
640 }
641 return new CryptoOutputStream(transformation, props, baos, key, params);
642 }
643
644 private void prepareData() throws IOException, ClassNotFoundException {
645 try (CryptoCipher cipher = (CryptoCipher) ReflectionUtils.newInstance(ReflectionUtils.getClassByName(AbstractCipherTest.JCE_CIPHER_CLASSNAME), props,
646 transformation)) {
647 final ByteArrayOutputStream baos = new ByteArrayOutputStream();
648 try (OutputStream out = new CryptoOutputStream(baos, cipher, defaultBufferSize, AES.newSecretKeySpec(key), new IvParameterSpec(iv))) {
649 out.write(data);
650 out.flush();
651 }
652 encData = baos.toByteArray();
653 }
654 }
655
656 private int readAll(final InputStream in, final byte[] b, final int offset, final int len)
657 throws IOException {
658 int n = 0;
659 int total = 0;
660 while (n != -1) {
661 total += n;
662 if (total >= len) {
663 break;
664 }
665 n = in.read(b, offset + total, len - total);
666 }
667
668 return total;
669 }
670
671 public abstract void setUp() throws IOException;
672
673
674 @Test
675 @Timeout(value = 120000, unit = TimeUnit.MILLISECONDS)
676 public void testByteBufferRead() throws Exception {
677 doByteBufferRead(AbstractCipherTest.JCE_CIPHER_CLASSNAME, false);
678 doByteBufferRead(AbstractCipherTest.OPENSSL_CIPHER_CLASSNAME, false);
679
680 doByteBufferRead(AbstractCipherTest.JCE_CIPHER_CLASSNAME, true);
681 doByteBufferRead(AbstractCipherTest.OPENSSL_CIPHER_CLASSNAME, true);
682 }
683
684
685 @Test
686 @Timeout(value = 120000, unit = TimeUnit.MILLISECONDS)
687 public void testByteBufferWrite() throws Exception {
688 final ByteArrayOutputStream baos = new ByteArrayOutputStream();
689 doByteBufferWrite(AbstractCipherTest.JCE_CIPHER_CLASSNAME, baos, false);
690 doByteBufferWrite(AbstractCipherTest.OPENSSL_CIPHER_CLASSNAME, baos, false);
691
692 doByteBufferWrite(AbstractCipherTest.JCE_CIPHER_CLASSNAME, baos, true);
693 doByteBufferWrite(AbstractCipherTest.OPENSSL_CIPHER_CLASSNAME, baos, true);
694 }
695
696 @Test
697 @Timeout(value = 120000, unit = TimeUnit.MILLISECONDS)
698 public void testExceptions() throws Exception {
699 final ByteArrayOutputStream baos = new ByteArrayOutputStream();
700 doExceptionTest(AbstractCipherTest.JCE_CIPHER_CLASSNAME, baos, false);
701 doExceptionTest(AbstractCipherTest.OPENSSL_CIPHER_CLASSNAME, baos, false);
702
703 doExceptionTest(AbstractCipherTest.JCE_CIPHER_CLASSNAME, baos, true);
704 doExceptionTest(AbstractCipherTest.OPENSSL_CIPHER_CLASSNAME, baos, true);
705 }
706
707 @Test
708 @Timeout(value = 120000, unit = TimeUnit.MILLISECONDS)
709 public void testFieldGetters() throws Exception {
710 final ByteArrayOutputStream baos = new ByteArrayOutputStream();
711 doFieldGetterTest(AbstractCipherTest.JCE_CIPHER_CLASSNAME, baos, false);
712 doFieldGetterTest(AbstractCipherTest.OPENSSL_CIPHER_CLASSNAME, baos, false);
713
714 doFieldGetterTest(AbstractCipherTest.JCE_CIPHER_CLASSNAME, baos, true);
715 doFieldGetterTest(AbstractCipherTest.OPENSSL_CIPHER_CLASSNAME, baos, true);
716 }
717
718 @Test
719 public void testReadWrite() throws Exception {
720 doReadWriteTest(0, AbstractCipherTest.JCE_CIPHER_CLASSNAME, AbstractCipherTest.JCE_CIPHER_CLASSNAME, iv);
721 doReadWriteTest(0, AbstractCipherTest.OPENSSL_CIPHER_CLASSNAME, AbstractCipherTest.OPENSSL_CIPHER_CLASSNAME, iv);
722 doReadWriteTest(count, AbstractCipherTest.JCE_CIPHER_CLASSNAME, AbstractCipherTest.JCE_CIPHER_CLASSNAME, iv);
723 doReadWriteTest(count, AbstractCipherTest.OPENSSL_CIPHER_CLASSNAME, AbstractCipherTest.OPENSSL_CIPHER_CLASSNAME, iv);
724 doReadWriteTest(count, AbstractCipherTest.JCE_CIPHER_CLASSNAME, AbstractCipherTest.OPENSSL_CIPHER_CLASSNAME, iv);
725 doReadWriteTest(count, AbstractCipherTest.OPENSSL_CIPHER_CLASSNAME, AbstractCipherTest.JCE_CIPHER_CLASSNAME, iv);
726
727 for (int i = 0; i < 8; i++) {
728 iv[8 + i] = (byte) 0xff;
729 }
730 doReadWriteTest(count, AbstractCipherTest.JCE_CIPHER_CLASSNAME, AbstractCipherTest.JCE_CIPHER_CLASSNAME, iv);
731 doReadWriteTest(count, AbstractCipherTest.OPENSSL_CIPHER_CLASSNAME, AbstractCipherTest.OPENSSL_CIPHER_CLASSNAME, iv);
732 doReadWriteTest(count, AbstractCipherTest.JCE_CIPHER_CLASSNAME, AbstractCipherTest.OPENSSL_CIPHER_CLASSNAME, iv);
733 doReadWriteTest(count, AbstractCipherTest.OPENSSL_CIPHER_CLASSNAME, AbstractCipherTest.JCE_CIPHER_CLASSNAME, iv);
734 }
735
736
737 @Test
738 @Timeout(value = 120000, unit = TimeUnit.MILLISECONDS)
739 public void testSkip() throws Exception {
740 doSkipTest(AbstractCipherTest.JCE_CIPHER_CLASSNAME, false);
741 doSkipTest(AbstractCipherTest.OPENSSL_CIPHER_CLASSNAME, false);
742
743 doSkipTest(AbstractCipherTest.JCE_CIPHER_CLASSNAME, true);
744 doSkipTest(AbstractCipherTest.OPENSSL_CIPHER_CLASSNAME, true);
745 }
746 }