AES in Java
Figured I should probably provide a full java crypto implementation for AES, given my recent ignite-style presentation.
Here’s an (untested) implementation of AES in Java using the vendor-provided algorithms.
I’ll leave it as an excercise to the reader to modify this to support different cryptography and padding algorithms, as well as any magic number support.
/**
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
**/
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class EncryptDecryptHandler {
private final byte[] key;
private final String algorithm = "AES";
private final String transform = "AES/CBC/PKCS5Padding";
private final SecureRandom rng = new SecureRandom();
private final int blockSize;
public EncryptDecryptHandler(byte[] key)
throws NoSuchAlgorithmException,
NoSuchPaddingException {
// should be 16, 24, or 32 bytes
switch (key.length) {
case 16:
case 24:
case 32:
this.key = key;
break;
default:
throw new UnsupportedOperationException
("Key size unsupported or insecure");
}
blockSize = Cipher.getInstance(transform).getBlockSize();
}
public byte[] encrypt(byte[] data)
throws IllegalBlockSizeException,
BadPaddingException,
InvalidKeyException,
InvalidAlgorithmParameterException,
NoSuchAlgorithmException,
NoSuchPaddingException {
Cipher encryptCipher = getEncryptCipher();
byte[] encrypted = encryptCipher.doFinal(data);
byte[] iv = encryptCipher.getIV();
byte[] result = new byte[encryptCipher.getIV().length + data.length];
System.arraycopy(iv, 0, result, 0, iv.length);
System.arraycopy(encrypted, 0, result, iv.length, encrypted.length);
return result;
}
public byte[] decrypt(byte[] data)
throws IllegalBlockSizeException,
BadPaddingException,
InvalidKeyException,
InvalidAlgorithmParameterException,
NoSuchAlgorithmException,
NoSuchPaddingException {
byte[] iv = new byte[blockSize];
System.arraycopy(data, 0, iv, 0, iv.length);
Cipher decryptCipher = getDecryptCipher(iv);
byte[] encrypted = new byte[data.length - iv.length];
System.arraycopy(data, iv.length, encrypted, 0, encrypted.length);
byte[] result = decryptCipher.doFinal(encrypted);
return result;
}
private Cipher getEncryptCipher()
throws InvalidKeyException,
InvalidAlgorithmParameterException,
NoSuchAlgorithmException,
NoSuchPaddingException {
Cipher result = Cipher.getInstance(transform);
byte[] iv = new byte[blockSize];
rng.nextBytes(iv);
SecretKeySpec keySpec = new SecretKeySpec(key, algorithm);
AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv);
result.init(Cipher.ENCRYPT_MODE, keySpec, paramSpec);
return result;
}
private Cipher getDecryptCipher(byte[] iv)
throws InvalidKeyException,
InvalidAlgorithmParameterException,
NoSuchAlgorithmException,
NoSuchPaddingException {
Cipher result = Cipher.getInstance(transform);
SecretKeySpec keySpec = new SecretKeySpec(key, algorithm);
AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv);
result.init(Cipher.DECRYPT_MODE, keySpec, paramSpec);
return result;
}
}
Just remember: if you are a U.S. citizen and you use a key larger than 16 bytes, you cannot export that software outside the country without express permission of U.S. Customs.
Have fun!