· 6 years ago · Mar 17, 2019, 01:24 PM
1import java.io.FileReader;
2import java.io.Console; // for hidden password input
3import java.util.Scanner; // for clear text input
4import java.security.MessageDigest; // for MD5
5import java.security.SecureRandom;
6import java.security.NoSuchAlgorithmException;
7import java.security.spec.InvalidKeySpecException;
8import javax.crypto.SecretKeyFactory;
9import javax.crypto.spec.PBEKeySpec;
10import javax.crypto.SecretKey;
11import javax.xml.bind.annotation.adapters.HexBinaryAdapter; // for Hex formatting of byte[]
12import com.opencsv.CSVReader; // library for reading CSV files (jar in +libs folder)
13
14public class LabSecurity {
15 private static final char[] characters = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
16 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
17
18 private static final int HASH_ITERS = 10000;
19 private static final int SALT_LENGTH = 32;
20 private static final int HASH_LENGTH = 512;
21
22 private boolean found;
23 private String match;
24
25 private MessageDigest md5; //implements the algorithm
26 private byte[] byteRepresentation;
27 private byte[] hash;
28 private String strHexHash;
29 private HexBinaryAdapter hba; //used to convert byte[] to String
30
31 /**
32 * Constructor for objects of class LabSecurity
33 */
34 public LabSecurity() {
35 try {
36 md5 = MessageDigest.getInstance("MD5");
37 hba = new HexBinaryAdapter();
38 } catch (NoSuchAlgorithmException nsae) {
39 }
40 }
41
42 public void tryMD5() {
43 try {
44 String str;
45 do {
46 System.out.println("Input a string to generate its MD5 hash (press enter to quit)");
47 Scanner terminalInput = new Scanner(System.in);
48 str = terminalInput.nextLine();
49 //Comment the 2 lines above and uncomment the 2 lines below to hide password input (will raise exception in IDE)
50 //Console console = System.console();
51 //str = new String(console.readPassword("Please enter your password: "));
52 if (!str.equals("")) {
53 System.out.println(encodeMD5(str));
54 }
55 } while (!str.equals(""));
56 } catch (Exception e) {
57 }
58
59 }
60
61 private String encodeMD5(final String input) throws Exception {
62 //convert the string to byte[] using the UFT-8 character encoding
63 byteRepresentation = input.getBytes("UTF-8");
64 //generate the hash
65 hash = md5.digest(byteRepresentation);
66 //HexBinaryAdapter's marshal method converts byte[] to String representation of hexadeciaml characters
67 strHexHash = hba.marshal(hash);
68 return strHexHash;
69 }
70
71 public void bruteForce(final String input) {
72 try {
73 CSVReader reader = new CSVReader(new FileReader(input));
74 String[] nextLine;
75 reader.readNext(); // skip first line containing headers
76 System.out.println("Brute force");
77 while ((nextLine = reader.readNext()) != null) {
78 // nextLine[] is an array of values from the line
79 System.out.print(nextLine[0] + " " + nextLine[1] + " ");
80 found = false;
81 // TODO call bruteForceRecursive
82 String password = "not found";
83 if (found) {
84 password = match;
85 }
86 System.out.println(password);
87 }
88 } catch (Exception e) {
89 }
90 }
91
92 /**
93 * Recursively explore all passwords shorter or equal to parameter <length>,
94 * made up of characters from the <characters> class variable
95 * to find the password which has the same MD5Â hash as parameter <hash>.
96 * The <found> global variable needs to be initialised to false prior to calling the method.
97 * Results are stored in the <found> and <match> global variables.
98 * <p>
99 * bruteForceRecursive(10, 0, "", <hash>) will try passwords
100 * of 10 or fewer characters until it finds one that hashes to <hash> or
101 * all passwords have been tried unsuccessfully.
102 */
103 private void bruteForceRecursive(final int length, final int position, final String baseString, final String hash) throws Exception {
104 // test whether baseString + any of the potential characters is the hash
105 for (int i = 0; i < characters.length & !found; i++) {
106 String attempt = baseString + characters[i];
107 found = hash.equals(encodeMD5(attempt));
108 if (found) {
109 match = attempt;
110 } else {
111 // if the last attempt was unsuccessful
112 // and the maximum password length is not reached
113 // then recursively call the method to try a longer password
114 if (position < length - 1) {
115 bruteForceRecursive(length, position + 1, attempt, hash);
116 }
117 }
118 }
119 }
120
121 public String generateHash(String password) {
122 String result = "";
123 return result;
124 }
125
126 private byte[] hashPassword(final char[] password, final byte[] salt, final int iterations, final int keyLength) {
127
128 try {
129 SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
130 PBEKeySpec spec = new PBEKeySpec(password, salt, iterations, keyLength);
131 SecretKey key = skf.generateSecret(spec);
132 byte[] res = key.getEncoded();
133 return res;
134 } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
135 throw new RuntimeException(e);
136 }
137 }
138
139
140}