You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

166 lines
5.4 KiB

  1. import java.io.BufferedReader;
  2. import java.io.IOException;
  3. import java.io.StringReader;
  4. import java.math.BigInteger;
  5. import java.security.MessageDigest;
  6. import java.security.NoSuchAlgorithmException;
  7. import java.util.Locale;
  8. import java.util.regex.Pattern;
  9. public class PasswordValidator {
  10. int minLength = 6;
  11. boolean requireUppercase = true;
  12. boolean requireLowercase = true;
  13. boolean requireDigit = true;
  14. boolean requireSpecialChar = true;
  15. boolean checkPwned = true;
  16. boolean checkWordlist = false;
  17. private final Pattern uppercasePattern = Pattern.compile("^(?=.*[A-Z]).+$");
  18. private final Pattern lowercasePattern = Pattern.compile("^(?=.*[a-z]).+$");
  19. private final Pattern digitPattern = Pattern.compile("^(?=.*\\d).+$");
  20. private final Pattern specialCharPattern = Pattern.compile("^(?=.*[.!?=@#$()%^&/*_\\-+]).+$");
  21. private static final String pwnedPasswordsApiUrl = "https://api.pwnedpasswords.com/range/";
  22. public boolean validate(String password) {
  23. if (password.length() < minLength) {
  24. return false;
  25. } else if (requireUppercase && !uppercasePattern.matcher(password).matches()) {
  26. return false;
  27. } else if (requireLowercase && !lowercasePattern.matcher(password).matches()) {
  28. return false;
  29. } else if (requireDigit && !digitPattern.matcher(password).matches()) {
  30. return false;
  31. } else if (requireSpecialChar && !specialCharPattern.matcher(password).matches()) {
  32. return false;
  33. } else if (checkWordlist && isInWordlist(password)) {
  34. return false;
  35. } else if (checkPwned && isPwned(password)) {
  36. return false;
  37. }
  38. return true;
  39. }
  40. public int getMinLength() {
  41. return minLength;
  42. }
  43. public void setMinLength(int minLength) {
  44. this.minLength = minLength;
  45. }
  46. public boolean isRequireUppercase() {
  47. return requireUppercase;
  48. }
  49. public void setRequireUppercase(boolean requireUppercase) {
  50. this.requireUppercase = requireUppercase;
  51. }
  52. public boolean isRequireLowercase() {
  53. return requireLowercase;
  54. }
  55. public void setRequireLowercase(boolean requireLowercase) {
  56. this.requireLowercase = requireLowercase;
  57. }
  58. public boolean isRequireDigit() {
  59. return requireDigit;
  60. }
  61. public void setRequireDigit(boolean requireDigit) {
  62. this.requireDigit = requireDigit;
  63. }
  64. public boolean isRequireSpecialChar() {
  65. return requireSpecialChar;
  66. }
  67. public void setRequireSpecialChar(boolean requireSpecialChar) {
  68. this.requireSpecialChar = requireSpecialChar;
  69. }
  70. public boolean isCheckPwned() {
  71. return checkPwned;
  72. }
  73. public void setCheckPwned(boolean checkPwned) {
  74. this.checkPwned = checkPwned;
  75. }
  76. public boolean isCheckWordlist() {
  77. return checkWordlist;
  78. }
  79. public void setCheckWordlist(boolean checkWordlist) {
  80. this.checkWordlist = checkWordlist;
  81. }
  82. public static String getSHA1Hash(String input) {
  83. if (input.length() > 0) {
  84. try {
  85. MessageDigest md = MessageDigest.getInstance("SHA-1");
  86. byte[] messageDigest = md.digest(input.getBytes());
  87. // Convert byte array into signum representation
  88. BigInteger no = new BigInteger(1, messageDigest);
  89. // Convert message digest into hex value
  90. StringBuilder hashtext = new StringBuilder();
  91. hashtext.append(no.toString(16));
  92. // Add preceding 0s to make it 32 bit
  93. while (hashtext.length() < 32) {
  94. hashtext.insert(0, "0");
  95. }
  96. return hashtext.toString();
  97. } catch (NoSuchAlgorithmException e) {
  98. e.printStackTrace();
  99. }
  100. }
  101. return null;
  102. }
  103. public static boolean isPwned(String password) {
  104. String sha1 = PasswordValidator.getSHA1Hash(password);
  105. if (sha1 != null) {
  106. String url = pwnedPasswordsApiUrl + sha1.substring(0, 5);
  107. try {
  108. String result = HttpApi.sendHttpGETRequest(url);
  109. BufferedReader bufReader = new BufferedReader(new StringReader(result));
  110. String line = null;
  111. while ((line = bufReader.readLine()) != null) {
  112. String[] lineSplit = line.split(":");
  113. if (lineSplit.length > 0 && sha1.toUpperCase().endsWith(lineSplit[0])) {
  114. return true;
  115. }
  116. }
  117. } catch (IOException e) {
  118. e.printStackTrace();
  119. }
  120. }
  121. return false;
  122. }
  123. public static boolean isInWordlist(String password) {
  124. try {
  125. String lowerPassword = password.toLowerCase();
  126. ResourceApi resourceApi = new ResourceApi();
  127. String germanWordlist = resourceApi.getFileFromResourceAsString("german_wordlist.txt");
  128. BufferedReader bufReader = new BufferedReader(new StringReader(germanWordlist));
  129. String line = null;
  130. while ((line = bufReader.readLine()) != null) {
  131. if (lowerPassword.contains(line.trim().toLowerCase())) {
  132. return true;
  133. }
  134. }
  135. } catch (IOException e) {
  136. e.printStackTrace();
  137. }
  138. return false;
  139. }
  140. }