package com.almasb.jencrypt; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; import java.security.SecureRandom; /** * Uses Advanced Encryption Standard. * * @author Almas Baimagambetov */ public final class AESEncryptor { private SecretKeyFactory factory = null; private SecureRandom random = new SecureRandom(); /** * Encrypts given bytes with AES algorithm and protects * it with given password * * @param data * @param password * @return encrypted data */ public byte[] encrypt(byte[] data, char[] password) throws AESException { byte[] salt = new byte[8]; random.nextBytes(salt); try { if (factory == null) factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); SecretKey tmp = factory.generateSecret(new PBEKeySpec(password, salt, 65536, 128)); SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES"); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, secret); byte[] iv = cipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV(); byte[] ciphertext = cipher.doFinal(data); byte[] encryptedData = new byte[8 + 16 + ciphertext.length]; int index = 0; for (int i = 0; i < salt.length; i++) encryptedData[index++] = salt[i]; for (int i = 0; i < iv.length; i++) encryptedData[index++] = iv[i]; for (int i = 0; i < ciphertext.length; i++) encryptedData[index++] = ciphertext[i]; return encryptedData; } catch (Exception e) { throw new AESException("Failed to encrypt: " + e); } } /** * Decrypts data which has been previously encrypted * * @param encryptedData * @param password * @return decrypted data */ public byte[] decrypt(byte[] encryptedData, char[] password) throws AESException { byte[] salt = new byte[8]; byte[] iv = new byte[16]; byte[] data = new byte[encryptedData.length - 16 - 8]; try { int index = 0; for (int i = 0; i < salt.length; i++) salt[i] = encryptedData[index++]; for (int i = 0; i < iv.length; i++) iv[i] = encryptedData[index++]; for (int i = 0; i < data.length; i++) data[i] = encryptedData[index++]; if (factory == null) factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); SecretKey tmp = factory.generateSecret(new PBEKeySpec(password, salt, 65536, 128)); SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES"); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv)); return cipher.doFinal(data); } catch (Exception e) { throw new AESException("Failed to decrypt: " + e); } } }