· 7 years ago · Dec 16, 2018, 01:38 PM
1import javax.crypto.*;
2import javax.crypto.spec.*;
3import java.security.*;
4import java.security.spec.*;
5import java.util.Base64;
6
7public class AES {
8
9 public static int iterations = 1000;
10 private static String seperator = ";";
11 private static int key_length = 256;
12 private static int salt_length = 64;
13
14 private static final String HASH_ALGORITHM = "PBKDF2WithHmacSHA256";
15 private static final String KEY_ALGORITHM = "AES";
16 private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";
17
18 public static void setSaltLength(int length) throws Exception {
19 if((length > 0) && ((length & (length - 1)) == 0))
20 salt_length = length;
21 else
22 throw new Exception("Invalid Salt Length");
23
24 }
25
26 public static void setKeyLength(int length) throws Exception {
27 if(length == 128 || length == 192 || length == 256)
28 key_length = length;
29 else
30 throw new Exception("Invalid Length");
31 }
32
33 public static void setSeperator(String s) throws Exception {
34 if(seperator.matches("[^+=/\w]"))
35 seperator = s;
36 else
37 throw new Exception("Invalid Seperator");
38 }
39
40 public static void setDurationOnCurrentComputer(int milliseconds){
41 char[] password = {'t', 'e', 's', 't'};
42 int i = 1;
43 long duration = 0;
44 while(duration < milliseconds) {
45 i*=2;
46 long t = System.currentTimeMillis();
47 byte[] salt = new byte[64];
48 new SecureRandom().nextBytes(salt);
49 try {
50 createKey(password, salt, i);
51 } catch (Exception e) {
52 e.printStackTrace();
53 }
54 duration = System.currentTimeMillis() - t;
55 System.out.println("i: " + i + " duration: " + duration);
56 }
57 iterations = i;
58 }
59
60 private static SecretKey createKey(char[] password, byte[] salt, int iterations) throws NoSuchAlgorithmException, InvalidKeySpecException {
61 SecretKeyFactory factory = SecretKeyFactory.getInstance(HASH_ALGORITHM);
62 KeySpec spec = new PBEKeySpec(password, salt, iterations, key_length);
63 SecretKey tmp = factory.generateSecret(spec);
64 return new SecretKeySpec(tmp.getEncoded(), KEY_ALGORITHM);
65 }
66
67 public static String encrypt(char[] password, byte[] data) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, InvalidParameterSpecException, BadPaddingException, IllegalBlockSizeException, InvalidKeySpecException {
68 Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
69 byte[] salt = new byte[salt_length];
70 new SecureRandom().nextBytes(salt);
71 cipher.init(Cipher.ENCRYPT_MODE, createKey(password, salt, iterations));
72 AlgorithmParameters params = cipher.getParameters();
73 byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
74 byte[] ciphertext = cipher.doFinal(data);
75 Base64.Encoder e = Base64.getEncoder();
76 return e.encodeToString((e.encodeToString(iv) + seperator + e.encodeToString(ciphertext) + seperator + e.encodeToString(salt)).getBytes());
77 }
78
79 public static String decrypt(char[] password, String ciphertext) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidKeySpecException {
80 Base64.Decoder d = Base64.getDecoder();
81 String[] data = new String(d.decode(ciphertext)).split(seperator);
82 Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
83 cipher.init(Cipher.DECRYPT_MODE, createKey(password, d.decode(data[2]), iterations), new IvParameterSpec(d.decode(data[0])));
84 return new String(cipher.doFinal(d.decode(data[1])));
85 }
86}