package cm.java.codec;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public final class AESCoder {
private static final int KEY_LENGTH = 16;
public static final String ALG_AES = "AES";
public static final String C_AES_CBC_PKCS5PADDING = "AES/CBC/PKCS5Padding";
/**
* 需要BC支持<br>
* BouncyCastleProvider provider = new BouncyCastleProvider(); <br>
* Security.addProvider(provider);
*/
public static final String C_AES_GCM = "AES/GCM/NoPadding";
/**
* BouncyCastleProvider
*/
public static final String PROVIDER_BC = "BC";
private AESCoder() {
}
public static SecretKey generateKey() throws NoSuchAlgorithmException {
return generateKey(KEY_LENGTH);
}
public static SecretKey generateKey(int keyLength) throws NoSuchAlgorithmException {
final SecureRandom random = new SecureRandom();
final KeyGenerator generator = KeyGenerator.getInstance(ALG_AES);
int keySizeBit = SecureUtil.convertSize(keyLength);
generator.init(keySizeBit, random);
return generator.generateKey();
}
public static SecretKey generateKey(char[] password, byte[] salt, int keyLength)
throws InvalidKeySpecException, NoSuchAlgorithmException {
SecretKey tmp = HashUtil.generateHash(password, salt, keyLength);
SecretKey secret = getSecretKey(tmp.getEncoded());
return secret;
}
public static SecretKey getSecretKey(byte[] key) {
SecretKey secret = new SecretKeySpec(key, ALG_AES);
return secret;
}
public static byte[] encrypt(byte[] key, byte[] iv, byte[] src) throws Exception {
SecretKey secret = getSecretKey(key);
return encrypt(secret, iv, src);
}
public static byte[] decrypt(byte[] key, byte[] iv, byte[] encrypted) throws Exception {
SecretKey secret = getSecretKey(key);
return decrypt(secret, iv, encrypted);
}
public static byte[] encrypt(SecretKey secretKey, byte[] iv, byte[] src) throws Exception {
return encrypt(C_AES_CBC_PKCS5PADDING, secretKey, iv, null, src);
}
public static byte[] decrypt(SecretKey secretKey, byte[] iv, byte[] src) throws Exception {
return decrypt(C_AES_CBC_PKCS5PADDING, secretKey, iv, null, src);
}
public static byte[] encrypt(String transformation, SecretKey secretKey, byte[] iv, byte[] aad, byte[] src) throws Exception {
return doFinal(transformation, Cipher.ENCRYPT_MODE, secretKey, iv, aad, src);
}
public static byte[] decrypt(String transformation, SecretKey secretKey, byte[] iv, byte[] aad, byte[] src) throws Exception {
return doFinal(transformation, Cipher.DECRYPT_MODE, secretKey, iv, aad, src);
}
private static byte[] doFinal(String transformation,
int opmode,
SecretKey secretKey,
byte[] iv,
byte[] aad,
byte[] src)
throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
IvParameterSpec ivSpec = getIv(iv);
Cipher cipher = Cipher.getInstance(transformation);
cipher.init(opmode, secretKey, ivSpec);
if (aad != null) {
cipher.updateAAD(aad);
}
byte[] dest = cipher.doFinal(src);
return dest;
}
private static IvParameterSpec getIv(byte[] iv) {
if (iv == null) {
return null;
} else {
return new IvParameterSpec(iv);
}
}
}