Skip to content

Commit 2cccac4

Browse files
Merge pull request #462 from mhingan/add-passwordEvaluator
Add PasswordStrengthEvaluator: evaluate and generate strong passwords
2 parents a6a3547 + 0dd23b7 commit 2cccac4

File tree

10 files changed

+213
-0
lines changed

10 files changed

+213
-0
lines changed

.idea/.gitignore

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/compiler.xml

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/jarRepositories.xml

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/misc.xml

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/vcs.xml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pom.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@
4848
</dynamicDependencies>
4949
</configuration>
5050
</plugin>
51+
<plugin>
52+
<groupId>org.apache.maven.plugins</groupId>
53+
<artifactId>maven-compiler-plugin</artifactId>
54+
<configuration>
55+
<source>11</source>
56+
<target>11</target>
57+
</configuration>
58+
</plugin>
5159
</plugins>
5260
</build>
5361
</project>
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
package PasswordEvaluator;
2+
3+
import java.io.*;
4+
import java.net.URI;
5+
import java.net.http.HttpClient;
6+
import java.net.http.HttpRequest;
7+
import java.net.http.HttpResponse;
8+
import java.util.Random;
9+
10+
/**
11+
* A utility class for evaluating the strength of passwords
12+
* and suggesting new secure passwords if needed.
13+
*/
14+
public class PasswordStrengthEvaluator {
15+
16+
private static final String LETTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
17+
18+
/**
19+
* Evaluates the strength of a given password based on multiple criteria:
20+
* - Length between 8 and 30 characters
21+
* - Contains both uppercase and lowercase letters
22+
* - Contains special characters (@, &, !)
23+
* - Is not a common password from a predefined list
24+
*
25+
* @param password the password to evaluate
26+
* @return a string representing the strength level (MAX, MIN, COMMON)
27+
* @throws IOException if there is a problem reading the common passwords file
28+
*/
29+
public static String evaluatePassword(String password) throws IOException {
30+
31+
boolean hasUppercase = password.matches(".*[A-Z].*");
32+
boolean hasLowercase = password.matches(".*[a-z].*");
33+
boolean hasSpecialChar = password.contains("@") || password.contains("&") || password.contains("!");
34+
int length = password.length();
35+
36+
boolean isCommon = isCommon(password);
37+
38+
if (!isCommon && length >= 8 && length < 30 && hasUppercase && hasLowercase && hasSpecialChar) {
39+
return "Password strength level: MAX";
40+
}
41+
42+
if (length < 8 || !hasUppercase || !hasLowercase || !hasSpecialChar || length >= 30) {
43+
suggetsPassword(12);
44+
return "Password strength level: MIN";
45+
}
46+
47+
if (isCommon) {
48+
return "Password strength level: COMMON" + suggetsPassword(12);
49+
}
50+
51+
return "Unable to determine password strength.";
52+
}
53+
54+
55+
/**
56+
* Checks whether a given password appears in a list of the most common passwords,
57+
* retrieved from a remote public file on GitHub. The comparison is exact, line by line.
58+
*
59+
* @param password the password to check
60+
* @return true if the password is exactly matched in the list, false otherwise
61+
* @throws RuntimeException if there is an error reading the remote password file
62+
*/
63+
public static boolean isCommon(String password) {
64+
String fileUrl = "https://raw.githubusercontent.com/danielmiessler/SecLists/refs/heads/master/Passwords/Common-Credentials/10-million-password-list-top-1000000.txt";
65+
66+
try {
67+
HttpClient client = HttpClient.newHttpClient();
68+
HttpRequest request = HttpRequest.newBuilder()
69+
.uri(URI.create(fileUrl))
70+
.build();
71+
72+
HttpResponse<InputStream> response = client.send(request, HttpResponse.BodyHandlers.ofInputStream());
73+
74+
try (BufferedReader reader = new BufferedReader(new InputStreamReader(response.body()))) {
75+
String line;
76+
while ((line = reader.readLine()) != null) {
77+
if (line.equals(password)) {
78+
return true;
79+
}
80+
}
81+
}
82+
83+
} catch (Exception e) {
84+
throw new RuntimeException("Error reading the common passwords file.", e);
85+
}
86+
87+
return false;
88+
}
89+
90+
91+
92+
93+
94+
/**
95+
* Suggests a secure random password of a specified length,
96+
* containing only uppercase and lowercase letters.
97+
*
98+
* If the requested length is less than 8, a password with 8 characters is suggested
99+
* and a warning message is returned.
100+
*
101+
* @param length the desired length of the suggested password
102+
* @return a suggested password or a warning message if the length is too short
103+
*/
104+
private static String suggetsPassword(int length) {
105+
Random random = new Random();
106+
StringBuilder password = new StringBuilder();
107+
StringBuilder provisionallyPassword = new StringBuilder();
108+
109+
if (length >= 8) {
110+
for (int i = 0; i < length; i++) {
111+
int index = random.nextInt(LETTERS.length());
112+
password.append(LETTERS.charAt(index));
113+
}
114+
return password.toString();
115+
} else {
116+
for (int i = 0; i < 8; i++) {
117+
int index = random.nextInt(LETTERS.length());
118+
provisionallyPassword.append(LETTERS.charAt(index));
119+
}
120+
return "Length must be between 8 and 30 characters. Suggested password with 8 characters: " + provisionallyPassword.toString();
121+
}
122+
}
123+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package PasswordEvaluator;
2+
3+
import java.io.IOException;
4+
import java.util.Scanner;
5+
6+
public class TestPasswordEvaluator {
7+
8+
9+
public static void main(String[] args) {
10+
Scanner scanner = new Scanner(System.in);
11+
System.out.println("Enter a password to evaluate:");
12+
String input = scanner.nextLine();
13+
14+
try {
15+
String result = PasswordStrengthEvaluator.evaluatePassword(input);
16+
System.out.println(result);
17+
} catch (IOException e) {
18+
System.out.println("Error: " + e.getMessage());
19+
}
20+
}
21+
}
22+
23+
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)