Code: Select all
/**
* Squiloople Framework
*
* LICENSE: Feel free to use and redistribute this code.
*
* @author Michael Rushton <michael@squiloople.com>
* @link http://squiloople.com/
* @category Squiloople
* @package Models
* @subpackage Validators
* @version 1.0
* @copyright Copyright © 2011 Michael Rushton
*/
// Define the namespace
namespace Models\Validators;
/**
* Password Validator
*
* Hash or validate passwords
*/
final class PasswordValidator
{
/**
* The password to hash or validate
*
* @access private
* @var string $_password
*/
private $_password;
/**
* The salt
*
* @access private
* @var string $_salt
*/
private $_salt;
/**
* The pepper
*
* @access private
* @var string $_pepper
*/
private $_pepper = 'Sz^3X6r[UyvV~2]_0stT}8`uY7RwZx4{q|Q91W5';
/**
* Set the password
*
* @access public
* @param string $password
* @param string $key
*/
public function __construct($password)
{
$this->_password = $password;
}
/**
* Call the constructor fluently
*
* @access public
* @static
* @param string $password
* @return \Models\Validators\PasswordValidator
*/
public static function setPassword($password)
{
return new self($password);
}
/**
* Check to see if the password is between 8 and 39 characters inclusive in length
*
* @access public
* @return bool
*/
public function isValidLength()
{
// If the password is not between 8 and 39 characters inclusive in length then return false
if (!isset($this->_password[7]) || isset($this->_password[39]))
{
return false;
}
// Otherwise return true
return true;
}
/**
* Check to see if the password (or the salt) is correctly formed
*
* @access public
* @var bool $salt
* @return bool
*/
public function isValidSyntax($salt = false)
{
// Validate the salt if required else the password
$password = $salt ?: $this->_password;
// Return false if the password does not contain at least two characters of each case, two digits, and two other characters
if (!preg_match('/^(?=(?:.*[a-z]){2})(?=(?:.*[A-Z]){2})(?=(?:.*[0-9]){2})(?=(?:.*[^a-zA-Z0-9]){2})[\x20-\x7E]+$/D', $password))
{
return false;
}
// Otherwise return true
return true;
}
/**
* Validate the password's length and syntax
*
* @access public
* @return bool
*/
public function isValid()
{
// If the length validation is successful then return the syntax validation result
if ($this->isValidLength())
{
return $this->isValidSyntax();
}
// Otherwise return false
return false;
}
/**
* Set the salt
*
* @access public
* @var string $salt
* @return \Models\Validators\PasswordValidator
*/
public function setSalt($salt)
{
// Set the salt
$this->_salt = $salt;
// Return itself
return $this;
}
/**
* Generate and return a salt
*
* @access public
* @var bool $reset
* @return string
*/
public function getSalt($reset = false)
{
// If a salt has been set and a reset is not required then return the stored salt
if (!$reset && isset($this->_salt))
{
return $this->_salt;
}
// Reset the salt
$salt = '';
// Generate a random salt of 39 printable ASCII characters
for ($i = 1; $i <= 39; ++$i)
{
$salt .= chr(mt_rand(32, 126));
}
// If the salt does not have the correct syntax then regenerate
if (!$this->isValidSyntax($salt))
{
$this->getSalt(true);
}
// Return the random salt
return $this->_salt = $salt;
}
/**
* Return the pepper portion
*
* @access private
* @return string
*/
private function _getPepper()
{
return substr($this->_pepper, 0, 39 - strlen($this->_password));
}
/**
* Hash the password using an HMAC
*
* @access public
* @return string
*/
public function getHMAC()
{
return hash_hmac('sha512', $this->_password . $this->_getPepper(), $this->getSalt());
}
}Code: Select all
$passwordValidator = new PasswordValidator('swordfish');Code: Select all
$passwordValidator = PasswordValidator::setPassword('swordfish');
$passwordValidator->isValidLength(); // Returns true
$passwordValidator->isValidSyntax(); // Returns false
$passwordValidator->isValid() // Returns falseCode: Select all
$passwordValidator->getSalt(); // Returns h&%G8\SThz7\P"$j>nB[Fpip{_rS{(f{2DEw>4R
$passwordValidator->getSalt(); // Returns h&%G8\SThz7\P"$j>nB[Fpip{_rS{(f{2DEw>4R
$passwordValidator->getSalt(true) // Returns g0ow;+}5HnM*G ;|%!@?px$W4,DK)(3WbE*iK:1Code: Select all
$passwordValidator->setSalt('g0ow;+}5HnM*G ;|%!@?px$W4,DK)(3WbE*iK:1'); // Set the saltCode: Select all
$passwordValidator = new PasswordValidator('M1ch43L !$ 4w3S0m3');
if ($passwordValidator->isValid() && $passwordValidator->isValid(true))
{
$hash = $passwordValidator->getHash();
}
// Returns: 645995e153424619fb6f6194f6d60c323a678470388f91c4a84ae713d56b3d00e9feb46040f92df799b00e689c6a9e285eb378ac6475193e13e715e53a3cb854Thanks.