seeddms-code/inc/inc.ClassPasswordStrength.php

368 lines
10 KiB
PHP

<?php
/*************************************************************************
* password_strength.class.php *
*************************************************************************
* *
* (c) 2008-2011 Wolf Software Limited <support@wolf-software.com> *
* All Rights Reserved. *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
*************************************************************************/
class Password_Strength
{
private $class_name = "Password Strength";
private $class_version = "1.0.0";
private $class_author = "Wolf Software";
private $class_source = "http://www.wolf-software.com/downloads/php-classes/security-classes/password-strength-class/";
private $password = '';
private $password_info = array();
private $password_length = 0;
private $score_precision = 2;
public function class_name()
{
return $this->class_name;
}
public function class_version()
{
return $this->class_version;
}
public function class_author()
{
return $this->class_author;
}
public function class_source()
{
return $this->class_source;
}
public function __construct()
{
}
public function simple_calculate()
{
$password = $this->password;
if($this->password_length < 8 ||
!preg_match('/[0-9]+/', $password) ||
!preg_match('/[a-z]+/', $password) ||
!preg_match('/[A-Z]+/', $password) ||
!preg_match('/[^0-9a-zA-Z]+/', $password))
{
$this->password_info['total_score'] = 0;
$this->password_info['rating_score'] = 0;
$this->password_info['rating'] = 'Insufficient';
}
else
{
$this->password_info['total_score'] = 100;
$this->password_info['rating_score'] = 100;
$this->password_info['rating'] = 'Good';
}
}
public function calculate()
{
$this->password_info = array();
$this->calculate_length();
$this->calculate_complexity();
$this->calculate_charset_complexity();
$this->calculate_entropy();
$this->password_info['password'] = $this->password;
$this->password_info['password_length'] = $this->password_length;
$total = 0;
$scoreCount = 0;
$keys = array_keys($this->password_info['details']);
foreach ($keys as $key)
{
if (preg_match('/score+$/', $key))
{
$total += intval($this->password_info['details'][$key]);
$scoreCount ++;
}
}
$rating_score = round($total / $scoreCount, $this->score_precision);
$score_info = $this->get_score_info($rating_score);
$this->password_info['total_score'] = $total;
$this->password_info['rating_score'] = $rating_score;
$this->password_info['rating'] = $score_info;
ksort($this->password_info);
ksort($this->password_info['details']);
}
public function get_all_info()
{
return $this->password_info;
}
public function get_score()
{
return $this->password_info['rating_score'];
}
public function get_rating()
{
return $this->password_info['rating'];
}
public function set_password($password)
{
$this->password = $password;
$this->password_length = strlen($password);
}
private function calculate_charset_complexity()
{
$password = $this->password;
$len = strlen($password);
$char = '';
$last_char = '';
$different_count = 0;
$score = 0;
if ($len <= 3)
{
$score = 2;
}
else
{
for ($i = 0; $i < $len; $i++)
{
$char = substr($password, $i, 1);
if ($i > 0)
{
$last_char = substr($password, $i - 1, 1);
}
if ($char != $last_char)
{
$different_count++;
}
}
if ($len <= 5)
{
$score = 10;
}
else if ($different_count == 1)
{
$score = 1;
$this->password_info['details']['length_score'] = min(min(floor(10 * $this->password_length / 10), 20), $this->password_info['details']['length_score']);
}
else if ($different_count == 2)
{
$score = 5;
$this->password_info['details']['length_score'] = min(min(floor(20 * $this->password_length / 10), 40), $this->password_info['details']['length_score']);
}
else if ($different_count == 3)
{
$score = 10;
$this->password_info['details']['length_score'] = min(min(floor(30 * $this->password_length / 10), 50), $this->password_info['details']['length_score']);
}
else
{
$score = round(max($this->password_info['details']['length_score'] / 10, $different_count / $len * 100), $this->score_precision);
}
}
$this->password_info['details']['charset_complexity_score'] = $score;
}
private function calculate_complexity()
{
$password = $this->password;
$score = 0;
if (preg_match('/^([0-9]+)+$/', $password))
{
$score = 10;
$this->password_info['details']['charset'] = 'numeric';
}
else if (preg_match('/^([a-z]+)+$/', $password))
{
$score = 30;
$this->password_info['details']['charset'] = 'alphabetic';
}
else if (preg_match('/^([a-z0-9]+)+$/i', $password))
{
if ((preg_match('/^([a-z]+)([0-9]+)+$/i', $password, $match)) || (preg_match('/^([0-9]+)([a-z]+)+$/i', $password, $match)))
{
$alpha = $match[1];
$numeric = $match[2];
$numeric_length = strlen($numeric);
if (($numeric == 111) || ($numeric == 123))
{
if (preg_match('/^([a-z]+)([0-9]+)+$/i', $password, $match))
{
$score = 31;
}
else
{
$score = 35;
}
$this->password_info['details']['common_numeric'] = true;
}
else if ($numeric_length == 1)
{
$score = 30;
}
else if ($numeric_length <= 3)
{
$score = 35;
}
else if ($numeric_length <= 5)
{
$score = 40;
}
else if ($numeric_length <= 10)
{
$score = 50;
}
else
{
$score = 60;
}
$this->password_info['details']['charset'] = 'alphanumeric';
}
else
{
$score = 80;
$this->password_info['details']['charset'] = 'alphanumeric';
}
}
else
{
$score = 100;
$this->password_info['details']['charset'] = 'alphanumeric + others';
}
$this->password_info['details']['charset_score'] = $score;
}
private function calculate_length()
{
$len = $this->password_length;
$score = 0;
if ($len == 0)
{
$score = 0;
}
else if ($len <= 3)
{
$score = 1;
}
else if ($len <= 4)
{
$score = 2;
}
else if ($len <= 5)
{
$score = 10;
}
else if ($len <= 6)
{
$score = 20;
}
else if ($len <= 8)
{
$score = 30;
}
else if ($len <= 10)
{
$score = 45;
}
else if ($len <= 15)
{
$score = 75;
}
else if ($len <= 18)
{
$score = 80;
}
else if ($len <= 20)
{
$score = 90;
}
else
{
$score = 100;
}
$this->password_info['details']['length_score'] = $score;
}
private function calculate_entropy()
{
$score = 0;
$password = $this->password;
$length = $this->password_length;
foreach (count_chars($password, 1) as $v)
{
$p = $v / $length;
$score -= $p * log($p)/log(2);
}
$this->password_info['details']['entropy_per_character'] = round($score, $this->score_precision);
$this->password_info['details']['entropy_score'] = round(($score * $length), $this->score_precision);
}
private function get_score_info($score)
{
if ($score <= 15)
{
$score_info = 'Very Bad';
}
else if ($score <= 35)
{
$score_info = 'Bad';
}
else if ($score <= 45)
{
$score_info = 'Medium - Bad';
}
else if ($score <= 55)
{
$score_info = 'Medium';
}
else if ($score <= 65)
{
$score_info = 'Medium - Good';
}
else if ($score <= 75)
{
$score_info = 'Good';
}
else if ($score <= 90)
{
$score_info = 'Very Good';
}
else
{
$score_info = 'Excellent';
}
return $score_info;
}
}
?>