Utilities/test/dorkbox/util/crypto/AesTest.java

344 lines
11 KiB
Java

/*
* Copyright 2015 dorkbox, llc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dorkbox.util.crypto;
import static org.junit.Assert.fail;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.SecureRandom;
import java.util.Arrays;
import org.bouncycastle.crypto.engines.AESEngine;
import org.bouncycastle.crypto.engines.AESFastEngine;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.modes.GCMBlockCipher;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.junit.Test;
public class AesTest {
org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(this.getClass());
private static String entropySeed = "asdjhasdkljalksdfhlaks4356268909087s0dfgkjh255124515hasdg87";
@Test
public void AesGcm() throws IOException {
byte[] bytes = "hello, my name is inigo montoya".getBytes();
SecureRandom rand = new SecureRandom(entropySeed.getBytes());
GCMBlockCipher aesEngine = new GCMBlockCipher(new AESEngine());
byte[] key = new byte[32];
byte[] iv = new byte[16];
// note: the IV needs to be VERY unique!
rand.nextBytes(key); // 256bit key (32 bytes)
rand.nextBytes(iv); // 128bit block size (16 bytes)
byte[] encryptAES = CryptoAES.encrypt(aesEngine, key, iv, bytes, logger);
byte[] decryptAES = CryptoAES.decrypt(aesEngine, key, iv, encryptAES, logger);
if (Arrays.equals(bytes, encryptAES)) {
fail("bytes should not be equal");
}
if (!Arrays.equals(bytes, decryptAES)) {
fail("bytes not equal");
}
}
// Note: this is still tested, but DO NOT USE BLOCK MODE as it does NOT provide authentication. GCM does.
@SuppressWarnings("deprecation")
@Test
public void AesBlock() throws IOException {
byte[] bytes = "hello, my name is inigo montoya".getBytes();
SecureRandom rand = new SecureRandom(entropySeed.getBytes());
PaddedBufferedBlockCipher aesEngine = new PaddedBufferedBlockCipher(new CBCBlockCipher(new AESFastEngine()));
byte[] key = new byte[32];
byte[] iv = new byte[16];
// note: the IV needs to be VERY unique!
rand.nextBytes(key); // 256bit key
rand.nextBytes(iv); // 16bit block size
byte[] encryptAES = CryptoAES.encrypt(aesEngine, key, iv, bytes, logger);
byte[] decryptAES = CryptoAES.decrypt(aesEngine, key, iv, encryptAES, logger);
if (Arrays.equals(bytes, encryptAES)) {
fail("bytes should not be equal");
}
if (!Arrays.equals(bytes, decryptAES)) {
fail("bytes not equal");
}
}
@Test
public void AesGcmStream() throws IOException {
byte[] originalBytes = "hello, my name is inigo montoya".getBytes();
ByteArrayInputStream inputStream = new ByteArrayInputStream(originalBytes);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
SecureRandom rand = new SecureRandom(entropySeed.getBytes());
GCMBlockCipher aesEngine = new GCMBlockCipher(new AESEngine());
byte[] key = new byte[32];
byte[] iv = new byte[16];
// note: the IV needs to be VERY unique!
rand.nextBytes(key); // 256bit key
rand.nextBytes(iv); // 128bit block size
boolean success = CryptoAES.encryptStream(aesEngine, key, iv, inputStream, outputStream, logger);
if (!success) {
fail("crypto was not successful");
}
byte[] encryptBytes = outputStream.toByteArray();
inputStream = new ByteArrayInputStream(outputStream.toByteArray());
outputStream = new ByteArrayOutputStream();
success = CryptoAES.decryptStream(aesEngine, key, iv, inputStream, outputStream, logger);
if (!success) {
fail("crypto was not successful");
}
byte[] decryptBytes = outputStream.toByteArray();
if (Arrays.equals(originalBytes, encryptBytes)) {
fail("bytes should not be equal");
}
if (!Arrays.equals(originalBytes, decryptBytes)) {
fail("bytes not equal");
}
}
// Note: this is still tested, but DO NOT USE BLOCK MODE as it does NOT provide authentication. GCM does.
@SuppressWarnings("deprecation")
@Test
public void AesBlockStream() throws IOException {
byte[] originalBytes = "hello, my name is inigo montoya".getBytes();
ByteArrayInputStream inputStream = new ByteArrayInputStream(originalBytes);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
SecureRandom rand = new SecureRandom(entropySeed.getBytes());
PaddedBufferedBlockCipher aesEngine = new PaddedBufferedBlockCipher(new CBCBlockCipher(new AESFastEngine()));
byte[] key = new byte[32];
byte[] iv = new byte[16];
// note: the IV needs to be VERY unique!
rand.nextBytes(key); // 256bit key
rand.nextBytes(iv); // 128bit block size
boolean success = CryptoAES.encryptStream(aesEngine, key, iv, inputStream, outputStream, logger);
if (!success) {
fail("crypto was not successful");
}
byte[] encryptBytes = outputStream.toByteArray();
inputStream = new ByteArrayInputStream(outputStream.toByteArray());
outputStream = new ByteArrayOutputStream();
success = CryptoAES.decryptStream(aesEngine, key, iv, inputStream, outputStream, logger);
if (!success) {
fail("crypto was not successful");
}
byte[] decryptBytes = outputStream.toByteArray();
if (Arrays.equals(originalBytes, encryptBytes)) {
fail("bytes should not be equal");
}
if (!Arrays.equals(originalBytes, decryptBytes)) {
fail("bytes not equal");
}
}
@Test
public void AesWithIVGcm() throws IOException {
byte[] bytes = "hello, my name is inigo montoya".getBytes();
SecureRandom rand = new SecureRandom(entropySeed.getBytes());
GCMBlockCipher aesEngine = new GCMBlockCipher(new AESEngine());
byte[] key = new byte[32]; // 256bit key
byte[] iv = new byte[aesEngine.getUnderlyingCipher().getBlockSize()];
// note: the IV needs to be VERY unique!
rand.nextBytes(key);
rand.nextBytes(iv);
byte[] encryptAES = CryptoAES.encryptWithIV(aesEngine, key, iv, bytes, logger);
byte[] decryptAES = CryptoAES.decryptWithIV(aesEngine, key, encryptAES, logger);
if (Arrays.equals(bytes, encryptAES)) {
fail("bytes should not be equal");
}
if (!Arrays.equals(bytes, decryptAES)) {
fail("bytes not equal");
}
}
// Note: this is still tested, but DO NOT USE BLOCK MODE as it does NOT provide authentication. GCM does.
@SuppressWarnings("deprecation")
@Test
public void AesWithIVBlock() throws IOException {
byte[] bytes = "hello, my name is inigo montoya".getBytes();
SecureRandom rand = new SecureRandom(entropySeed.getBytes());
PaddedBufferedBlockCipher aesEngine = new PaddedBufferedBlockCipher(new CBCBlockCipher(new AESFastEngine()));
byte[] key = new byte[32]; // 256bit key
byte[] iv = new byte[aesEngine.getUnderlyingCipher().getBlockSize()];
// note: the IV needs to be VERY unique!
rand.nextBytes(key);
rand.nextBytes(iv);
byte[] encryptAES = CryptoAES.encryptWithIV(aesEngine, key, iv, bytes, logger);
byte[] decryptAES = CryptoAES.decryptWithIV(aesEngine, key, encryptAES, logger);
if (Arrays.equals(bytes, encryptAES)) {
fail("bytes should not be equal");
}
if (!Arrays.equals(bytes, decryptAES)) {
fail("bytes not equal");
}
}
@Test
public void AesWithIVGcmStream() throws IOException {
byte[] originalBytes = "hello, my name is inigo montoya".getBytes();
ByteArrayInputStream inputStream = new ByteArrayInputStream(originalBytes);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
SecureRandom rand = new SecureRandom(entropySeed.getBytes());
GCMBlockCipher aesEngine = new GCMBlockCipher(new AESEngine());
byte[] key = new byte[32];
byte[] iv = new byte[16];
// note: the IV needs to be VERY unique!
rand.nextBytes(key); // 256bit key
rand.nextBytes(iv); // 128bit block size
boolean success = CryptoAES.encryptStreamWithIV(aesEngine, key, iv, inputStream, outputStream, logger);
if (!success) {
fail("crypto was not successful");
}
byte[] encryptBytes = outputStream.toByteArray();
inputStream = new ByteArrayInputStream(outputStream.toByteArray());
outputStream = new ByteArrayOutputStream();
success = CryptoAES.decryptStreamWithIV(aesEngine, key, inputStream, outputStream, logger);
if (!success) {
fail("crypto was not successful");
}
byte[] decryptBytes = outputStream.toByteArray();
if (Arrays.equals(originalBytes, encryptBytes)) {
fail("bytes should not be equal");
}
if (!Arrays.equals(originalBytes, decryptBytes)) {
fail("bytes not equal");
}
}
// Note: this is still tested, but DO NOT USE BLOCK MODE as it does NOT provide authentication. GCM does.
@SuppressWarnings("deprecation")
@Test
public void AesWithIVBlockStream() throws IOException {
byte[] originalBytes = "hello, my name is inigo montoya".getBytes();
ByteArrayInputStream inputStream = new ByteArrayInputStream(originalBytes);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
SecureRandom rand = new SecureRandom(entropySeed.getBytes());
PaddedBufferedBlockCipher aesEngine = new PaddedBufferedBlockCipher(new CBCBlockCipher(new AESFastEngine()));
byte[] key = new byte[32];
byte[] iv = new byte[16];
// note: the IV needs to be VERY unique!
rand.nextBytes(key); // 256bit key
rand.nextBytes(iv); // 128bit block size
boolean success = CryptoAES.encryptStreamWithIV(aesEngine, key, iv, inputStream, outputStream, logger);
if (!success) {
fail("crypto was not successful");
}
byte[] encryptBytes = outputStream.toByteArray();
inputStream = new ByteArrayInputStream(outputStream.toByteArray());
outputStream = new ByteArrayOutputStream();
success = CryptoAES.decryptStreamWithIV(aesEngine, key, inputStream, outputStream, logger);
if (!success) {
fail("crypto was not successful");
}
byte[] decryptBytes = outputStream.toByteArray();
if (Arrays.equals(originalBytes, encryptBytes)) {
fail("bytes should not be equal");
}
if (!Arrays.equals(originalBytes, decryptBytes)) {
fail("bytes not equal");
}
}
}