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.

123 lines
3.9 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.regex.Pattern;
  8. public class PasswordValidator {
  9. int minLength = 6;
  10. boolean requireUppercase = true;
  11. boolean requireLowercase = true;
  12. boolean requireDigit = true;
  13. boolean checkPwned = true;
  14. private final Pattern uppercasePattern = Pattern.compile("^(?=.*[A-Z]).+$");
  15. private final Pattern lowercasePattern = Pattern.compile("^(?=.*[a-z]).+$");
  16. private final Pattern digitPattern = Pattern.compile("^(?=.*\\d).+$");
  17. private static final String pwnedPasswordsApiUrl = "https://api.pwnedpasswords.com/range/";
  18. public boolean validate(String password) {
  19. if (password.length() < minLength) {
  20. return false;
  21. } else if (requireUppercase && !uppercasePattern.matcher(password).matches()) {
  22. return false;
  23. } else if (requireLowercase && !lowercasePattern.matcher(password).matches()) {
  24. return false;
  25. } else if (requireDigit && !digitPattern.matcher(password).matches()) {
  26. return false;
  27. } else if (checkPwned && isPwned(password)) {
  28. return false;
  29. }
  30. return true;
  31. }
  32. public int getMinLength() {
  33. return minLength;
  34. }
  35. public void setMinLength(int minLength) {
  36. this.minLength = minLength;
  37. }
  38. public boolean isRequireUppercase() {
  39. return requireUppercase;
  40. }
  41. public void setRequireUppercase(boolean requireUppercase) {
  42. this.requireUppercase = requireUppercase;
  43. }
  44. public boolean isRequireLowercase() {
  45. return requireLowercase;
  46. }
  47. public void setRequireLowercase(boolean requireLowercase) {
  48. this.requireLowercase = requireLowercase;
  49. }
  50. public boolean isRequireDigit() {
  51. return requireDigit;
  52. }
  53. public void setRequireDigit(boolean requireDigit) {
  54. this.requireDigit = requireDigit;
  55. }
  56. public boolean isCheckPwned() {
  57. return checkPwned;
  58. }
  59. public void setCheckPwned(boolean checkPwned) {
  60. this.checkPwned = checkPwned;
  61. }
  62. public static String getSHA1Hash(String input) {
  63. if (input.length() > 0) {
  64. try {
  65. MessageDigest md = MessageDigest.getInstance("SHA-1");
  66. byte[] messageDigest = md.digest(input.getBytes());
  67. // Convert byte array into signum representation
  68. BigInteger no = new BigInteger(1, messageDigest);
  69. // Convert message digest into hex value
  70. StringBuilder hashtext = new StringBuilder();
  71. hashtext.append(no.toString(16));
  72. // Add preceding 0s to make it 32 bit
  73. while (hashtext.length() < 32) {
  74. hashtext.insert(0, "0");
  75. }
  76. return hashtext.toString();
  77. } catch (NoSuchAlgorithmException e) {
  78. e.printStackTrace();
  79. }
  80. }
  81. return null;
  82. }
  83. public static boolean isPwned(String password) {
  84. String sha1 = PasswordValidator.getSHA1Hash(password);
  85. if (sha1 != null) {
  86. String url = pwnedPasswordsApiUrl + sha1.substring(0, 5);
  87. try {
  88. String result = HttpApi.sendHttpGETRequest(url);
  89. BufferedReader bufReader = new BufferedReader(new StringReader(result));
  90. String line = null;
  91. while ((line = bufReader.readLine()) != null) {
  92. String[] lineSplit = line.split(":");
  93. if (lineSplit.length > 0 && sha1.toUpperCase().endsWith(lineSplit[0])) {
  94. return true;
  95. }
  96. }
  97. } catch (IOException e) {
  98. e.printStackTrace();
  99. }
  100. }
  101. return false;
  102. }
  103. }