|
34 | 34 | public class FileEncryptor { |
35 | 35 | private static final Logger LOG = Logger.getLogger(FileEncryptor.class.getSimpleName()); |
36 | 36 |
|
37 | | - private static final String ALGORITHM = "AES"; |
| 37 | + private static final String DEFAULT_ALGORITHM = "AES"; |
| 38 | + private static final int DEFAULT_KEY_LENGTH = 128; |
38 | 39 | private static final String HASH_AlGORITHM = "HmacSHA256"; |
39 | | - private static final String CIPHER = "AES/CBC/PKCS5PADDING"; |
| 40 | + private static final String DEFAULT_CIPHER = "AES/CBC/PKCS5PADDING"; |
40 | 41 | private static final int ITERATION_COUNT = 100000; |
41 | 42 |
|
| 43 | + private static String ALGORITHM; |
| 44 | + private static String CIPHER; |
| 45 | + private static int KEY_LENGTH; |
| 46 | + private static int BLOCKSIZE; |
| 47 | + |
| 48 | + // Error Message |
| 49 | + private static final String validCmdMsg = "Valid Encryption commandL: java FileEncryptor enc [Passoword] [inputFile] [outputFile]\n" |
| 50 | + + "Valid Encryption command: java FileEncryptor enc [Algorithm] [Key length] [Password] [inputFile] [outputFile]\n" |
| 51 | + + "Valid Decryption command: java FileEncryptor dec [Password] [inputFile] [outputFile]\n" |
| 52 | + + "Valid Info command: java FileEncryptor info [filePath]\n" |
| 53 | + + "Valid Key lengths: 128. 448. 192. 32 etc" |
| 54 | + + "NOTE: The only algorithms accepted are AES and Blowfish\n" |
| 55 | + + "NOTE: Must specify a valid Key length (in bits) with respect to the algorithm specified\n" |
| 56 | + + "NOTE: The default Algorithm being used is " + DEFAULT_ALGORITHM + " and the Default Key Length is " + DEFAULT_KEY_LENGTH; |
| 57 | + |
42 | 58 | public static void main(String[] args) throws Exception { |
43 | | - // Error Message |
44 | | - final String validCmdMsg = "Valid Encryption command: java FileEncryptor enc [Password] [inputFile] [outputFile]\n" |
45 | | - + "Valid Decryption command: java FileEncryptor dec [Password] [inputFile] [outputFile]\n"; |
46 | 59 |
|
47 | | - if (args.length < 4) { throw new IllegalArgumentException("Not Enough Argunments specified\n" + validCmdMsg); } |
| 60 | + if (args.length < 2) { throw new IllegalArgumentException("Not Enough Argunments specified\n" + validCmdMsg); } |
48 | 61 |
|
49 | 62 | // Convert String arguments to char arrays |
50 | 63 | char[][] charArgs = Util.getCharArguments(args); |
51 | 64 |
|
52 | 65 | // Clear String argunments |
53 | 66 | Arrays.fill(args, null); |
54 | 67 |
|
| 68 | + if (Arrays.equals(charArgs[0], "info".toCharArray())) { |
| 69 | + info(new String(charArgs[1])); |
| 70 | + return; |
| 71 | + } |
| 72 | + |
| 73 | + if (charArgs.length < 4) { throw new IllegalArgumentException("Not Enough Argunments specified\n" + validCmdMsg); } |
| 74 | + |
55 | 75 | // Options Available |
56 | 76 | char[] enc = "enc".toCharArray(); |
57 | 77 | char[] dec = "dec".toCharArray(); |
58 | 78 |
|
59 | 79 | if (!Arrays.equals(charArgs[0], enc) && !Arrays.equals(charArgs[0], dec)) { |
60 | | - throw new IllegalArgumentException("Neither enc (encrypt) or dec (decrypt) option specified\n" + validCmdMsg); |
| 80 | + throw new IllegalArgumentException("Neither enc (encrypt), dec (decrypt) or info option specified\n" + validCmdMsg); |
61 | 81 | } |
62 | 82 |
|
63 | 83 | if (Arrays.equals(charArgs[0], enc)) { // Encrypt |
64 | | - encrypt(charArgs[1], new String(charArgs[2]), new String(charArgs[3])); |
| 84 | + |
| 85 | + char[] aes = "AES".toCharArray(); |
| 86 | + char [] blowfish = "Blowfish".toCharArray(); |
| 87 | + |
| 88 | + int argIndex = 1; // will get incremented everytime a valid argument is encountered |
| 89 | + |
| 90 | + // If no algorithm argument is specified the Default will be applied |
| 91 | + if (Arrays.equals(charArgs[argIndex], aes) || Arrays.equals(charArgs[argIndex], blowfish)) { |
| 92 | + ALGORITHM = new String(charArgs[1]); |
| 93 | + CIPHER = ALGORITHM + "/CBC/PKCS5PADDING"; |
| 94 | + argIndex++; |
| 95 | + } else { |
| 96 | + ALGORITHM = DEFAULT_ALGORITHM; |
| 97 | + CIPHER = DEFAULT_CIPHER; |
| 98 | + } |
| 99 | + |
| 100 | + // Determine blocksize for the IV |
| 101 | + if (ALGORITHM.equals("AES")) { BLOCKSIZE = 128; } |
| 102 | + if (ALGORITHM.equals("Blowfish")) { BLOCKSIZE = 64; } |
| 103 | + |
| 104 | + // If no Key length specified then the Default will be applied |
| 105 | + try { |
| 106 | + int keyLength = Integer.parseInt(new String(charArgs[argIndex])); |
| 107 | + if (keyLength % 8 != 0) { throw new IllegalArgumentException("Invalid Key Length: not divisible by 8"); } |
| 108 | + |
| 109 | + if (ALGORITHM.equals("AES") && keyLength != 128 && keyLength != 192 && keyLength != 256) { |
| 110 | + throw new IllegalArgumentException("Invalid Key Length for AES Algorithm, valid key lengths are 128, 192 or 256 bits"); |
| 111 | + } |
| 112 | + |
| 113 | + if (ALGORITHM.equals("Blowfish") && (keyLength < 32 || keyLength > 448)) { |
| 114 | + throw new IllegalArgumentException("Invalid Key Length for Blowfish Algorithm, valid key lengths are between 32-448 bits"); |
| 115 | + } |
| 116 | + |
| 117 | + KEY_LENGTH = keyLength; |
| 118 | + |
| 119 | + argIndex++; |
| 120 | + } catch (NumberFormatException e) { |
| 121 | + KEY_LENGTH = DEFAULT_KEY_LENGTH; |
| 122 | + } |
| 123 | + |
| 124 | + encrypt(charArgs[argIndex], new String(charArgs[argIndex + 1]), new String(charArgs[argIndex + 2])); |
65 | 125 |
|
66 | 126 | } else if (Arrays.equals(charArgs[0], dec)) { // Decrypt |
| 127 | + ALGORITHM = DEFAULT_ALGORITHM; |
| 128 | + CIPHER = DEFAULT_CIPHER; |
67 | 129 | decrypt(charArgs[1], new String(charArgs[2]), new String(charArgs[3])); |
68 | 130 |
|
69 | 131 | } |
@@ -97,13 +159,14 @@ public static void main(String[] args) throws Exception { |
97 | 159 | public static void encrypt(char[] password, String inputPath, String outputPath) throws NoSuchAlgorithmException, |
98 | 160 | NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IOException, InvalidKeySpecException { |
99 | 161 | //Generate vector and salts |
100 | | - final byte[] initVector = new byte[16], salt = new byte[16], macSalt = new byte[16]; |
| 162 | + final byte[] initVector = new byte[BLOCKSIZE/8]; |
| 163 | + final byte[] salt = new byte[16], macSalt = new byte[16]; |
101 | 164 |
|
102 | 165 | SecureRandom sr = new SecureRandom(); |
103 | 166 | sr.nextBytes(initVector); sr.nextBytes(salt); sr.nextBytes(macSalt); |
104 | 167 |
|
105 | 168 | // Get Keys from password |
106 | | - final byte[] key = generateKey(password, salt, 128); |
| 169 | + final byte[] key = generateKey(password, salt, KEY_LENGTH); |
107 | 170 | final byte[] macKey = generateKey(password, macSalt, 256); |
108 | 171 |
|
109 | 172 | // Password no longer needed |
@@ -283,6 +346,10 @@ private static boolean writeDecryptedFile(Path inputPath, Path outputPath, char[ |
283 | 346 | return true; |
284 | 347 | } |
285 | 348 |
|
| 349 | + private static void info(String filepath) { |
| 350 | + System.out.println("INVOKED INFO"); |
| 351 | + } |
| 352 | + |
286 | 353 | /** |
287 | 354 | * Generates a Secret key with a specified password. The password is added with |
288 | 355 | * a salt and iterated multiple times before being hased to increase entropy. |
|
0 commit comments