Skip to content

Commit

Permalink
add checkEntropyJSON function (#36)
Browse files Browse the repository at this point in the history
  • Loading branch information
David Coutadeur committed Aug 30, 2024
1 parent 40fbc2c commit 97c1200
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 24 deletions.
80 changes: 56 additions & 24 deletions src/Ltb/Password.php
Original file line number Diff line number Diff line change
Expand Up @@ -333,17 +333,17 @@ static function check_password_strength( $password,
$change_custompwdfield )
{
extract( $pwd_policy_config );

$result = "";

$length = mb_strlen($password, mb_detect_encoding($password));
preg_match_all("/[a-z]/", $password, $lower_res);
$lower = count( $lower_res[0] );
preg_match_all("/[A-Z]/", $password, $upper_res);
$upper = count( $upper_res[0] );
preg_match_all("/[0-9]/", $password, $digit_res);
$digit = count( $digit_res[0] );

$special = 0;
$special_at_ends = false;
if ( isset($pwd_special_chars) && !empty($pwd_special_chars) ) {
Expand All @@ -357,13 +357,13 @@ static function check_password_strength( $password,
);
}
}

$forbidden = 0;
if ( isset($pwd_forbidden_chars) && !empty($pwd_forbidden_chars) ) {
preg_match_all("/[$pwd_forbidden_chars]/", $password, $forbidden_res);
$forbidden = count( $forbidden_res[0] );
}

# Complexity: checks for lower, upper, special, digits
if ( $pwd_complexity ) {
$complex = 0;
Expand All @@ -373,37 +373,37 @@ static function check_password_strength( $password,
if ( $upper > 0 ) { $complex++; }
if ( $complex < $pwd_complexity ) { $result="notcomplex"; }
}

# Minimal length
if ( $pwd_min_length and $length < $pwd_min_length ) { $result="tooshort"; }

# Maximal length
if ( $pwd_max_length and $length > $pwd_max_length ) { $result="toobig"; }

# Minimal lower chars
if ( $pwd_min_lower and $lower < $pwd_min_lower ) { $result="minlower"; }

# Minimal upper chars
if ( $pwd_min_upper and $upper < $pwd_min_upper ) { $result="minupper"; }

# Minimal digit chars
if ( $pwd_min_digit and $digit < $pwd_min_digit ) { $result="mindigit"; }

# Minimal special chars
if ( $pwd_min_special and $special < $pwd_min_special ) { $result="minspecial"; }

# Forbidden chars
if ( $forbidden > 0 ) { $result="forbiddenchars"; }

# Special chars at beginning or end
if ( $special_at_ends > 0 && $special == 1 ) { $result="specialatends"; }

# Same as old password?
if ( $pwd_no_reuse and $password === $oldpassword ) { $result="sameasold"; }

# Same as login?
if ( $pwd_diff_login and $password === $login ) { $result="sameaslogin"; }

if ( $pwd_diff_last_min_chars > 0 and strlen($oldpassword) > 0 ) {
$similarities = similar_text($oldpassword, $password);
$check_len = strlen($oldpassword) < strlen($password) ?
Expand All @@ -412,7 +412,7 @@ static function check_password_strength( $password,
$new_chars = $check_len - $similarities;
if ($new_chars <= $pwd_diff_last_min_chars) { $result = "diffminchars"; }
}

# Contains forbidden words?
if ( !empty($pwd_forbidden_words) ) {
foreach( $pwd_forbidden_words as $disallowed ) {
Expand All @@ -422,7 +422,7 @@ static function check_password_strength( $password,
}
}
}

# Contains values from forbidden ldap fields?
if ( !empty($pwd_forbidden_ldap_fields) ) {
foreach ( $pwd_forbidden_ldap_fields as $field ) {
Expand All @@ -445,7 +445,7 @@ static function check_password_strength( $password,
}
}
}

# ensure that the new password is different from any other custom password field marked as unique
foreach ( $change_custompwdfield as $custompwdfield) {
if (isset($custompwdfield['pwd_policy_config']['pwd_unique_across_custom_password_fields']) &&
Expand All @@ -471,15 +471,15 @@ static function check_password_strength( $password,
}
}
}

# pwned?
if ($use_pwnedpasswords and version_compare(PHP_VERSION, '7.2.5') >= 0) {
$pwned_passwords = new PwnedPasswords;
$insecure = $pwned_passwords->isPwned($password);
if ($insecure) { $result="pwned"; }
}


# check entropy
$zxcvbn = new Zxcvbn();
if( isset($pwd_check_entropy) && $pwd_check_entropy == true )
Expand Down Expand Up @@ -508,10 +508,42 @@ static function check_password_strength( $password,
error_log("checkEntropy: missing required parameter pwd_min_entropy");
$result="insufficiententropy";
}

}

return $result;
}

/* Check user password against zxcvbn library
Input : new user base64-encoded password
Output: JSON response: { "level" => int, "message" => "msg" } */

static function checkEntropyJSON($password_base64)
{
$response_params = array();
$zxcvbn = new Zxcvbn();

if( ! isset($password_base64) || empty($password_base64))
{
error_log("checkEntropy: missing parameter password");
$response_params["level"] = "-1";
$response_params["message"] = "missing parameter password";
return json_encode($response_params);
}

$p = base64_decode($password_base64);
// force encoding to utf8, as iso-8859-1 is not supported by zxcvbn
$password = mb_convert_encoding($p, 'UTF-8', 'ISO-8859-1');
error_log("checkEntropy: password taken from submitted form");

$entropy = $zxcvbn->passwordStrength("$password");

$response_params["level"] = strval($entropy["score"]);
$response_params["message"] = $entropy['feedback']['warning'] ? strval($entropy['feedback']['warning']) : "";

error_log("checkEntropy: level " . $response_params["level"] . " msg: " . $response_params["message"]);

return json_encode($response_params);
}

}
39 changes: 39 additions & 0 deletions tests/Ltb/PasswordTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -371,5 +371,44 @@ public function testCheckPasswordStrengthStrongEntropy()

}

/**
* Test checkEntropyJSON function
*/
public function testCheckEntropyJSON()
{

$password_weak = "secret";
$password_weak_base64 = base64_encode($password_weak);

$password_strong = "jtK8hEhNgT3wwGiDY_z7XmI92fUbnemQ";
$password_strong_base64 = base64_encode($password_strong);

$result_error = json_encode(
array(
"level" => "-1",
"message" => "missing parameter password"
)
);

$result_weak = json_encode(
array(
"level" => "0",
"message" => "This is a top-100 common password"
)
);

$result_strong = json_encode(
array(
"level" => "4",
"message" => ""
)
);

$this->assertEquals($result_error, \Ltb\Password::checkEntropyJSON( "" ) );
$this->assertEquals($result_weak, \Ltb\Password::checkEntropyJSON( $password_weak_base64 ) );
$this->assertEquals($result_strong, \Ltb\Password::checkEntropyJSON( $password_strong_base64 ) );

}


}

0 comments on commit 97c1200

Please sign in to comment.