· 8 years ago · May 31, 2017, 12:12 PM
1package util.crypto;
2
3import java.io.IOException;
4import java.io.UnsupportedEncodingException;
5import java.security.AlgorithmParameters;
6import java.security.GeneralSecurityException;
7import java.security.NoSuchAlgorithmException;
8import java.security.spec.InvalidKeySpecException;
9import java.util.Base64;
10import javax.crypto.Cipher;
11import javax.crypto.SecretKey;
12import javax.crypto.SecretKeyFactory;
13import javax.crypto.spec.IvParameterSpec;
14import javax.crypto.spec.PBEKeySpec;
15import javax.crypto.spec.SecretKeySpec;
16
17
18/**
19 * User: rhmiller
20 * Date: 5/30/17
21 */
22public class ProtectedConfigFile {
23 public static void main(String[] args) throws Exception {
24 String password = System.getProperty("password");
25 if (password == null) {
26 throw new IllegalArgumentException("Run with -Dpassword=<password>");
27 }
28
29 // The salt (probably) can be stored along with the encrypted data
30 byte[] salt = "12345678".getBytes();
31
32 // Decreasing this speeds down startup time and can be useful during testing, but it also makes it easier for brute force attackers
33 int iterationCount = 40000;
34 // Other values give me java.security.InvalidKeyException: Illegal key size or default parameters
35 int keyLength = 128;
36 SecretKeySpec key = createSecretKey(System.getProperty("password").toCharArray(),
37 salt, iterationCount, keyLength);
38
39 String originalPassword = "secret";
40 System.out.println("Original password: " + originalPassword);
41 String encryptedPassword = encrypt(originalPassword, key);
42 System.out.println("Encrypted password: " + encryptedPassword);
43 String decryptedPassword = decrypt(encryptedPassword, key);
44 System.out.println("Decrypted password: " + decryptedPassword);
45 }
46
47 private static SecretKeySpec createSecretKey(char[] password, byte[] salt, int iterationCount, int keyLength) throws NoSuchAlgorithmException, InvalidKeySpecException {
48 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
49 PBEKeySpec keySpec = new PBEKeySpec(password, salt, iterationCount, keyLength);
50 SecretKey keyTmp = keyFactory.generateSecret(keySpec);
51 return new SecretKeySpec(keyTmp.getEncoded(), "AES");
52 }
53
54 private static String encrypt(String property, SecretKeySpec key) throws GeneralSecurityException, UnsupportedEncodingException {
55 Cipher pbeCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
56 pbeCipher.init(Cipher.ENCRYPT_MODE, key);
57 AlgorithmParameters parameters = pbeCipher.getParameters();
58 IvParameterSpec ivParameterSpec = parameters.getParameterSpec(IvParameterSpec.class);
59 byte[] cryptoText = pbeCipher.doFinal(property.getBytes("UTF-8"));
60 byte[] iv = ivParameterSpec.getIV();
61 return base64Encode(iv) + ":" + base64Encode(cryptoText);
62 }
63
64 private static String base64Encode(byte[] bytes) {
65 return Base64.getEncoder().encodeToString(bytes);
66 }
67
68 private static String decrypt(String string, SecretKeySpec key) throws GeneralSecurityException, IOException {
69 String iv = string.split(":")[0];
70 String property = string.split(":")[1];
71 Cipher pbeCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
72 pbeCipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(base64Decode(iv)));
73 return new String(pbeCipher.doFinal(base64Decode(property)), "UTF-8");
74 }
75
76 private static byte[] base64Decode(String property) throws IOException {
77 return Base64.getDecoder().decode(property);
78 }
79}