Skip to content

Commit 23052ee

Browse files
authored
Merge pull request #32 from modothprav/encrypt-decrypt
fix #23 fix #24 fix #31
2 parents 891efdd + 725c7c3 commit 23052ee

File tree

2 files changed

+91
-16
lines changed

2 files changed

+91
-16
lines changed

src/FileEncryptor.java

Lines changed: 90 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -34,34 +34,100 @@
3434
public class FileEncryptor {
3535
private static final Logger LOG = Logger.getLogger(FileEncryptor.class.getSimpleName());
3636

37-
private static final String ALGORITHM = "AES";
37+
private static final String DEFAULT_ALGORITHM = "AES";
38+
private static final int DEFAULT_KEY_LENGTH = 128;
3839
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";
4041
private static final int ITERATION_COUNT = 100000;
4142

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 ERROR_MSG = "\nValid Encryption command: java FileEncryptor enc [Passoword] [inputFile] [outputFile]\n"
50+
+ "\t\t\t java FileEncryptor enc [Algorithm] [Key length] [Password] [inputFile] [outputFile]\n"
51+
+ "\t\t\t java FileEncryptor enc [Algorithm] [Password] [inputFile] [outputFile]\n"
52+
+ "\t\t\t java FileEncryptor enc [Key length] [Password] [inputFile] [outputFile]\n\n"
53+
+ "Valid Decryption command: java FileEncryptor dec [Password] [inputFile] [outputFile]\n\n"
54+
+ "Valid Info command: java FileEncryptor info [filePath]\n\n"
55+
+ "Valid Key lengths: 128, 448, 192, 32 etc\n\n"
56+
+ "NOTE: The only algorithms accepted are AES and Blowfish\n"
57+
+ "NOTE: Must specify a valid Key length (in bits) with respect to the algorithm specified\n"
58+
+ "NOTE: The default Algorithm being used is " + DEFAULT_ALGORITHM + " and the Default Key Length is " + DEFAULT_KEY_LENGTH + " bits\n"
59+
+ "NOTE: If no Algorithm or Key length is specifed the Default values will be used\n";
60+
4261
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";
4662

47-
if (args.length < 4) { throw new IllegalArgumentException("Not Enough Argunments specified\n" + validCmdMsg); }
63+
if (args.length < 2) { throw new IllegalArgumentException("Not Enough Argunments specified\n" + ERROR_MSG); }
4864

4965
// Convert String arguments to char arrays
5066
char[][] charArgs = Util.getCharArguments(args);
5167

5268
// Clear String argunments
5369
Arrays.fill(args, null);
5470

71+
if (Arrays.equals(charArgs[0], "info".toCharArray())) {
72+
info(new String(charArgs[1]));
73+
return;
74+
}
75+
76+
if (charArgs.length < 4) { throw new IllegalArgumentException("Not Enough Argunments specified\n" + ERROR_MSG); }
77+
5578
// Options Available
5679
char[] enc = "enc".toCharArray();
5780
char[] dec = "dec".toCharArray();
5881

5982
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);
83+
throw new IllegalArgumentException("Neither enc (encrypt), dec (decrypt) or info option specified\n" + ERROR_MSG);
6184
}
6285

6386
if (Arrays.equals(charArgs[0], enc)) { // Encrypt
64-
encrypt(charArgs[1], new String(charArgs[2]), new String(charArgs[3]));
87+
88+
char[] aes = "AES".toCharArray();
89+
char [] blowfish = "Blowfish".toCharArray();
90+
91+
int argIndex = 1; // will get incremented everytime a valid argument is encountered
92+
93+
// If no or incompatiable algorithm argument is specified the Default will be applied
94+
if (Arrays.equals(charArgs[argIndex], aes) || Arrays.equals(charArgs[argIndex], blowfish)) {
95+
ALGORITHM = new String(charArgs[1]);
96+
CIPHER = ALGORITHM + "/CBC/PKCS5PADDING";
97+
argIndex++;
98+
} else {
99+
ALGORITHM = DEFAULT_ALGORITHM;
100+
CIPHER = DEFAULT_CIPHER;
101+
}
102+
103+
// Determine blocksize for the IV
104+
if (ALGORITHM.equals("AES")) { BLOCKSIZE = 128; }
105+
if (ALGORITHM.equals("Blowfish")) { BLOCKSIZE = 64; }
106+
107+
// If no Key length specified then the Default will be applied
108+
try {
109+
// Perform Key length checks
110+
int keyLength = Integer.parseInt(new String(charArgs[argIndex]));
111+
if (keyLength % 8 != 0) { throw new IllegalArgumentException("Invalid Key Length: not divisible by 8"); }
112+
113+
if (ALGORITHM.equals("AES") && keyLength != 128 && keyLength != 192 && keyLength != 256) {
114+
throw new IllegalArgumentException("Invalid Key Length for AES Algorithm, valid key lengths are 128, 192 or 256 bits");
115+
}
116+
117+
if (ALGORITHM.equals("Blowfish") && (keyLength < 32 || keyLength > 448)) {
118+
throw new IllegalArgumentException("Invalid Key Length for Blowfish Algorithm, valid key lengths are between 32-448 bits");
119+
}
120+
121+
KEY_LENGTH = keyLength;
122+
argIndex++;
123+
} catch (NumberFormatException e) {
124+
KEY_LENGTH = DEFAULT_KEY_LENGTH;
125+
}
126+
127+
// Check if password and/or file paths have been specified
128+
if (argIndex + 2 >= charArgs.length) { throw new IllegalArgumentException("Not enough arguments specified" + ERROR_MSG); }
129+
130+
encrypt(charArgs[argIndex], new String(charArgs[argIndex + 1]), new String(charArgs[argIndex + 2]));
65131

66132
} else if (Arrays.equals(charArgs[0], dec)) { // Decrypt
67133
decrypt(charArgs[1], new String(charArgs[2]), new String(charArgs[3]));
@@ -97,13 +163,13 @@ public static void main(String[] args) throws Exception {
97163
public static void encrypt(char[] password, String inputPath, String outputPath) throws NoSuchAlgorithmException,
98164
NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IOException, InvalidKeySpecException {
99165
//Generate vector and salts
100-
final byte[] initVector = new byte[16], salt = new byte[16], macSalt = new byte[16];
166+
final byte[] initVector = new byte[BLOCKSIZE/8], salt = new byte[16], macSalt = new byte[16];
101167

102168
SecureRandom sr = new SecureRandom();
103169
sr.nextBytes(initVector); sr.nextBytes(salt); sr.nextBytes(macSalt);
104170

105171
// Get Keys from password
106-
final byte[] key = generateKey(password, salt, 128);
172+
final byte[] key = generateKey(password, salt, KEY_LENGTH);
107173
final byte[] macKey = generateKey(password, macSalt, 256);
108174

109175
// Password no longer needed
@@ -158,7 +224,11 @@ private static boolean writeEncryptedFile(Path inputPath, Path outputPath, Ciphe
158224

159225
try (FileOutputStream fout = new FileOutputStream(outputPath.toFile());) {
160226
// Write Metadata
161-
fout.write(cipher.getIV()); fout.write(salt); fout.write(macSalt); fout.write(mac);
227+
final byte[] algorithm = Util.convertCharToByte(ALGORITHM.toCharArray());
228+
229+
fout.write(BLOCKSIZE); fout.write(KEY_LENGTH/8); fout.write(algorithm.length);
230+
fout.write(algorithm); fout.write(cipher.getIV()); fout.write(salt);
231+
fout.write(macSalt); fout.write(mac);
162232

163233
try (CipherOutputStream cipherOut = new CipherOutputStream(fout, cipher);) {
164234
final byte[] bytes = new byte[1024];
@@ -232,13 +302,14 @@ public static void decrypt(char[] password, String inputPath, String outputPath)
232302
private static boolean writeDecryptedFile(Path inputPath, Path outputPath, char[] password) throws NoSuchAlgorithmException,
233303
NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, InvalidKeySpecException {
234304
try (InputStream encryptedData = Files.newInputStream(inputPath);){
235-
236305
// Read metadata from the input file
237-
final byte[] initVector = new byte[16], salt = new byte[16], macSalt = new byte[16], givenMac = new byte[32];
238-
306+
BLOCKSIZE = encryptedData.read(); KEY_LENGTH = encryptedData.read() * 8; int algoLength = encryptedData.read();
307+
ALGORITHM = new String(encryptedData.readNBytes(algoLength)); CIPHER = ALGORITHM + "/CBC/PKCS5PADDING";
308+
309+
final byte[] initVector = new byte[BLOCKSIZE/8], salt = new byte[16], macSalt = new byte[16], givenMac = new byte[32];
239310
encryptedData.read(initVector); encryptedData.read(salt); encryptedData.read(macSalt); encryptedData.read(givenMac);
240311

241-
final byte[] key = generateKey(password, salt, 128);
312+
final byte[] key = generateKey(password, salt, KEY_LENGTH);
242313
final byte[] macKey = generateKey(password, macSalt, 256);
243314

244315
// Password no longer needed
@@ -283,6 +354,10 @@ private static boolean writeDecryptedFile(Path inputPath, Path outputPath, char[
283354
return true;
284355
}
285356

357+
private static void info(String filepath) {
358+
System.out.println("INVOKED INFO");
359+
}
360+
286361
/**
287362
* Generates a Secret key with a specified password. The password is added with
288363
* a salt and iterated multiple times before being hased to increase entropy.

src/resources/plaintext.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
This is part three of the assignment
1+
This is part four of the assignment

0 commit comments

Comments
 (0)