patternjavaMinor
Brute force passwords in Java
Viewed 0 times
brutepasswordsforcejava
Problem
I made this little code to see what brute forcing is like. I made this with a complete guess on how it works. This code works fine but it seems to take much much longer than it really should. I have the
I have the
to see if I ever run into errors where would I run into it. The way my code works is that it loops chars^length times until it hits the password.
If there is any way I can improve this?
```
import java.util.Scanner;
import java.util.concurrent.TimeUnit;
public class Main {
static String newPass = "";
static String chars = "0123456789aABbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyzZ";
public static void main(String[] args) {
Scanner userIn = new Scanner(System.in);
String password = userIn.nextLine();
System.out.println("Is using symbols an option? if so type in [Y] if not type in [N]");
String choose = userIn.nextLine();
boolean decideSymb = true;
boolean again = true;
while (again == true) {
if (choose.equalsIgnoreCase("y")) {
again = false;
} else if (choose.equalsIgnoreCase("n")) {
again = false;
decideSymb = false;
} else {
System.out.println("Try again! \nIs using symbols an option? if so type in [Y] if not type in [N]");
choose = userIn.nextLine();
}
}
long start = System.currentTimeMillis();
crack(password, decideSymb);
long end = System.currentTimeMillis();
long milliSecs = TimeUnit.MILLISECONDS.toSeconds(end - start);
;
long secs = milliSecs / 1000;
long mins = secs / 60;
long hours = mins / 60;
long days = hours / 24;
long years = days / 365;
Scanner there so I can tell the program what password it is searching for. I have the timeMillis also just for personal reasons to see how long it takes to find a password.I have the
System.out.println(newPass);to see if I ever run into errors where would I run into it. The way my code works is that it loops chars^length times until it hits the password.
If there is any way I can improve this?
```
import java.util.Scanner;
import java.util.concurrent.TimeUnit;
public class Main {
static String newPass = "";
static String chars = "0123456789aABbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyzZ";
public static void main(String[] args) {
Scanner userIn = new Scanner(System.in);
String password = userIn.nextLine();
System.out.println("Is using symbols an option? if so type in [Y] if not type in [N]");
String choose = userIn.nextLine();
boolean decideSymb = true;
boolean again = true;
while (again == true) {
if (choose.equalsIgnoreCase("y")) {
again = false;
} else if (choose.equalsIgnoreCase("n")) {
again = false;
decideSymb = false;
} else {
System.out.println("Try again! \nIs using symbols an option? if so type in [Y] if not type in [N]");
choose = userIn.nextLine();
}
}
long start = System.currentTimeMillis();
crack(password, decideSymb);
long end = System.currentTimeMillis();
long milliSecs = TimeUnit.MILLISECONDS.toSeconds(end - start);
;
long secs = milliSecs / 1000;
long mins = secs / 60;
long hours = mins / 60;
long days = hours / 24;
long years = days / 365;
Solution
Do while you must
You have some awkward-feeling repeated code in here (the prompt for input). This can be refactored into a cleaner, more natural feeling
By changing this to a
The above loop will continuously ask for input until proper input is given.
Or use a pattern you can
Instead of using a loop to shorten the above code, you could use the
First, create a
The above regex should only pass for either y, n, Y, or N. Also, it may be better to compile the regex in the main method itself.
Then, in your code, instead of having the loop, you can simply write:
I believe this is a much better solution.
Too far for a single letter
You have two entirely separate conditional statements just to add a single character? That's a waste, and it makes your code look ugly.
Honestly, I don't think you'll even need to worry about that "s".
However, if you really want to have that "s" there, use a ternary instead:
The date is exactly...
This chunk of code here:
Doesn't belong. It should be extracted into a separate method that accepts the
with getters for each field. This will make your code more OO.
If you want to be extra OOP-y, you can put the method that generates the
Over-complicating the time printing
Again, you are over-complicating the time printing section. In my opinion, it is perfectly okay to have something like:
"It took 0 days, 0 hours, 24 minutes, 13 seconds, and 1 millisecond."
Those 0's there don't harm the UI at all. Instead of having that huge conditional chain in your code, you should just use
Going back to OOP, you could extract this into the
System.out.println("Is using symbols an option? if so type in [Y] if not type in [N]");
String choose = userIn.nextLine();
boolean decideSymb = true;
boolean again = true;
while (again == true) {
if (choose.equalsIgnoreCase("y")) {
again = false;
} else if (choose.equalsIgnoreCase("n")) {
again = false;
decideSymb = false;
} else {
System.out.println("Try again! \nIs using symbols an option? if so type in [Y] if not type in [N]");
choose = userIn.nextLine();
}
}You have some awkward-feeling repeated code in here (the prompt for input). This can be refactored into a cleaner, more natural feeling
do/while loop:do {
System.out.println("Is using symbols an option? if so type in [Y] if not type in [N]");
String choose = userIn.nextLine();
} while(!choose.equalsIgnoreCase("y") && !choose.equalsIgnoreCase("n"));By changing this to a
do/while, we were able to remove those clunky if statements along with the two flag variables.The above loop will continuously ask for input until proper input is given.
Or use a pattern you can
Instead of using a loop to shorten the above code, you could use the
Scanner's built-in next(Pattern pattern). This will ensure that you only get input that follows your specified pattern.First, create a
final Pattern in a class field so you can easily access it in the code:public static final Pattern yesOrNo = Pattern.compile("(y|n)", CASE_INSENSITIVE);The above regex should only pass for either y, n, Y, or N. Also, it may be better to compile the regex in the main method itself.
Then, in your code, instead of having the loop, you can simply write:
System.out.println("Is using symbols an option? if so type in [Y] if not type in [N]");
String choose = userIn.next(yesOrNo);I believe this is a much better solution.
Too far for a single letter
if (years == 1) {
System.out.println("it took\n" + years + "year\n" + days + " days\n" + hours + " hours\n" + mins
+ " mins\n" + secs + " secs\n" + milliSecs + " milliseconds\nto find the password");
} else {
System.out.println("it took\n" + years + "years\n" + days + " days\n" + hours + " hours\n" + mins
+ " mins\n" + secs + " secs\n" + milliSecs + " milliseconds\nto find the password");
}You have two entirely separate conditional statements just to add a single character? That's a waste, and it makes your code look ugly.
Honestly, I don't think you'll even need to worry about that "s".
- The chances of it being exactly
1are very low.
- It's such a small thing that most applications ignore.
However, if you really want to have that "s" there, use a ternary instead:
System.out.println("it took\n" + years + "year" + (years == 1 ? "s" : "") + "\n" + days + " days\n" + hours + " hours\n" + mins + " mins\n" + secs + " secs\n" + milliSecs + " milliseconds\nto find the password");The date is exactly...
This chunk of code here:
long secs = milliSecs / 1000;
long mins = secs / 60;
long hours = mins / 60;
long days = hours / 24;
long years = days / 365;
days -= (years * 365);
hours -= (days * 24);
mins -= (hours * 60);
secs -= (mins * 60);Doesn't belong. It should be extracted into a separate method that accepts the
milliSecs variable. As for returning, it could probably return a custom class that looks like this:public class TimeData {
private final long secs;
private final long mins;
...
}with getters for each field. This will make your code more OO.
If you want to be extra OOP-y, you can put the method that generates the
TimeData in this TimeData class, make it static, and have it return an instance of TimeData with filled data.Over-complicating the time printing
Again, you are over-complicating the time printing section. In my opinion, it is perfectly okay to have something like:
"It took 0 days, 0 hours, 24 minutes, 13 seconds, and 1 millisecond."
Those 0's there don't harm the UI at all. Instead of having that huge conditional chain in your code, you should just use
System.out.printf and print out all the time values you have.Going back to OOP, you could extract this into the
TimeData's toString method.Code Snippets
System.out.println("Is using symbols an option? if so type in [Y] if not type in [N]");
String choose = userIn.nextLine();
boolean decideSymb = true;
boolean again = true;
while (again == true) {
if (choose.equalsIgnoreCase("y")) {
again = false;
} else if (choose.equalsIgnoreCase("n")) {
again = false;
decideSymb = false;
} else {
System.out.println("Try again! \nIs using symbols an option? if so type in [Y] if not type in [N]");
choose = userIn.nextLine();
}
}do {
System.out.println("Is using symbols an option? if so type in [Y] if not type in [N]");
String choose = userIn.nextLine();
} while(!choose.equalsIgnoreCase("y") && !choose.equalsIgnoreCase("n"));public static final Pattern yesOrNo = Pattern.compile("(y|n)", CASE_INSENSITIVE);System.out.println("Is using symbols an option? if so type in [Y] if not type in [N]");
String choose = userIn.next(yesOrNo);if (years == 1) {
System.out.println("it took\n" + years + "year\n" + days + " days\n" + hours + " hours\n" + mins
+ " mins\n" + secs + " secs\n" + milliSecs + " milliseconds\nto find the password");
} else {
System.out.println("it took\n" + years + "years\n" + days + " days\n" + hours + " hours\n" + mins
+ " mins\n" + secs + " secs\n" + milliSecs + " milliseconds\nto find the password");
}Context
StackExchange Code Review Q#114594, answer score: 8
Revisions (0)
No revisions yet.