/src/plugins/orangehrmAuthenticationPlugin/lib/utility/PasswordHelper.php

https://github.com/orangehrm/OrangeHRM · PHP · 148 lines · 86 code · 22 blank · 40 comment · 22 complexity · f6b16e5c494783645333b23dd2946313 MD5 · raw file

  1. <?php
  2. /*
  3. * OrangeHRM is a comprehensive Human Resource Management (HRM) System that captures
  4. * all the essential functionalities required for any enterprise.
  5. * Copyright (C) 2006 OrangeHRM Inc., http://www.orangehrm.com
  6. *
  7. * OrangeHRM is free software; you can redistribute it and/or modify it under the terms of
  8. * the GNU General Public License as published by the Free Software Foundation; either
  9. * version 2 of the License, or (at your option) any later version.
  10. *
  11. * OrangeHRM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  12. * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. * See the GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along with this program;
  16. * if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  17. * Boston, MA 02110-1301, USA
  18. */
  19. /**
  20. * Password Helper
  21. */
  22. use ZxcvbnPhp\Zxcvbn;
  23. class PasswordHelper {
  24. const VERY_WEAK = 0;
  25. const WEAK = 1;
  26. const BETTER = 2;
  27. const MEDIUM = 3;
  28. const STRONG = 4;
  29. const STRONGEST = 5;
  30. const PASSWORD_MAX_LENGTH = 64;
  31. const PASSWORD_MIN_LENGTH = 8;
  32. private $authenticationConfigService;
  33. public function getPasswordStrength($password){
  34. if(isset($password) && !empty($password)){
  35. $strength = $this->calculatePasswordStrength($password);
  36. if ($strength >= self::MEDIUM) {
  37. $allCharacterClassesIncluded = $this->checkForDifferentCharacterClasses($password);
  38. if (!$allCharacterClassesIncluded) {
  39. return self::BETTER;
  40. }
  41. return $strength;
  42. }
  43. return $strength;
  44. }
  45. return self::VERY_WEAK;
  46. }
  47. public function calculatePasswordStrength($password){
  48. $zxcvbn = new Zxcvbn();
  49. $strength = $zxcvbn->passwordStrength($password);
  50. if($strength['crack_time']< pow(10, 0))return self::VERY_WEAK;
  51. if($strength['crack_time']< pow(10, 2))return self::WEAK;
  52. if($strength['crack_time']< pow(10, 4))return self::BETTER;
  53. if($strength['crack_time']< pow(10, 6))return self::MEDIUM;
  54. if($strength['crack_time']< pow(10, 9))return self::STRONG;
  55. if($strength['crack_time']>= pow(10, 9))return self::STRONGEST;
  56. return self::VERY_WEAK;
  57. }
  58. /**
  59. * Checks that the password contains at least one character from each of the following character sets:
  60. * 1. lower case characters
  61. * 2. upper case characters
  62. * 3. digits
  63. * 4. special characters
  64. *
  65. * @return true if password contains one character from each set.
  66. */
  67. protected function checkForDifferentCharacterClasses($password) {
  68. $score = 0;
  69. if (preg_match('/[a-z]/', $password)) { // contains lower case characters
  70. $score++;
  71. }
  72. if (preg_match('/[A-Z]/', $password)) { // contains upper case characters
  73. $score++;
  74. }
  75. if (preg_match('/\d/', $password)) { // contains digit(s)
  76. $score++;
  77. }
  78. if (preg_match('/[\'\/~`\!@#\$%\^&\*\(\)_\-\+=\{\}\[\]\|;:"\<\>,\.\?\\\]/', $password)) { // contains special character(s)
  79. $score++;
  80. }
  81. return $score == 4;
  82. }
  83. public function isPasswordStrongWithEnforcement($password){
  84. if($this->getSecurityAuthenticationConfigService()->isPasswordStengthEnforced()){
  85. return $this->getPasswordStrength($password) >= $this->getSecurityAuthenticationConfigService()->getRequiredPasswordStength() && strlen($password)>=self::PASSWORD_MIN_LENGTH;
  86. }
  87. return true;
  88. }
  89. public function getColorClass($score){
  90. return $this->getSecurityAuthenticationConfigService()->getPasswordStrengths()[$score];
  91. }
  92. /**
  93. *
  94. * @return SecurityAuthenticationConfigService
  95. */
  96. public function getSecurityAuthenticationConfigService() {
  97. if (!isset($this->authenticationConfigService)) {
  98. $this->authenticationConfigService = new SecurityAuthenticationConfigService();
  99. }
  100. return $this->authenticationConfigService;
  101. }
  102. /**
  103. * @param mixed SecurityAuthenticationConfigService
  104. */
  105. public function setSecurityAuthenticationConfigService($authenticationConfigService)
  106. {
  107. $this->authenticationConfigService = $authenticationConfigService;
  108. }
  109. /**
  110. * @param string $password
  111. * @return string validationMsg
  112. */
  113. public function getCustomValidationBasedOnPassword($password)
  114. {
  115. if(strlen($password) >= self::PASSWORD_MIN_LENGTH && strlen($password) < self::PASSWORD_MAX_LENGTH){
  116. if(!$this->isPasswordStrongWithEnforcement($password)) {
  117. if ($this->checkForDifferentCharacterClasses($password)) {
  118. return __("Your password meets the minimum requirements, but it could be guessable. Try a different password.");
  119. }else{
  120. return __("Your password must contain a lower-case letter, an upper-case letter, a digit and a special character. Try a different password.");
  121. }
  122. }
  123. }
  124. return "";
  125. }
  126. }