/** * Set the password and the optional key * * @access public * @param string $password * @param string $key */ public function __construct($password, $key = '') {
// Set the password $this->_password = $password;
// Set the key $this->_key = $key;
}
/** * Call the constructor fluently * * @access public * @static * @param string $password * @param string key * @return PasswordValidator */ public static function setPassword($password, $key = '') { return new self($password, $key); }
/** * Check to see if the password is between 8 and 39 characters inclusive in length * * @access public * @var bool $key * @return bool */ public function isValidLength($key = false) {
// Select which of the password or key is to be validated $password = $key ? $this->_key : $this->_password;
// If the password is not between 8 and 39 characters inclusive in length then return false if (!isset($password[7]) || isset($password[39])) { return false; }
// Otherwise return true return true;
}
/** * Check to see if the password is correctly formed * * @access public * @var bool key * @return bool */ public function isValidSyntax($key = false) {
// Select which of the password or key is to be validated $password = $key ? $this->_key : $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]+$/sD', $password)) { return false; }
// Otherwise return true return true;
}
/** * Perform the validation check on the password's length and syntax * * @access public * @var bool $key * @return bool */ public function isValid($key = false) {
// If the length validation is successful then return the syntax validation result if ($this->isValidLength($key)) { return $this->isValidSyntax($key); }
// Otherwise return false return false;
}
/** * Set the salt * * @access public * @var string $salt * @return 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)); }
// Return the random salt return $this->_salt = $salt;
}
/** * Return the pepper if required * * @access private * @var bool $key * @return string */ private function _getPepper($key = false) {
// If the pepper is for the key then reverse it $pepper = $key ? strrev($this->_pepper) : $this->_pepper;
/** * Generate and return a key * * @access private * @return string */ private function _getKey() { return $this->_getPepper(true) . $this->_key . strrev($this->getSalt()); }
/** * Hash the the salt, the password, and the pepper using SHA 512 * * @access private * @return string */ private function _getHash() { return hash('sha512', $this->getSalt() . $this->_password . $this->_getPepper()); }
/** * Hash the password using an HMAC * * @access public * @return string */ public function getHash() { return hash('sha512', $this->_getKey() . $this->_getHash()); }
}
To instantiate the password validator, either use the new keyword or call the class statically using PasswordValidator::setPassword() passing as the first parameter the password and as the optional second parameter the key.
PHP Code:
$passwordValidator = new PasswordValidator('swordfish', '5W0rdF!$h');
To validate the password's length, which must be between 8 and 39 characters inclusive, call the isValidLength() method. To validate the password's syntax, which may only contain printable ASCII characters and must contain at least one lower-case alphabetic character, one upper-case alphabetic character, one digit, and one other character, call the isValidSyntax() method. To validate both, call the isValid() method. Passing a true parameter to any of these will validate the key.
To generate and return a salt, which is 39 characters in length and follows the same syntax rules as a valid password, call the getSalt() method. Generated salts are stored and returned if the method is called subsequent times. To generate a new salt pass a true parameter to the method.
To set an established salt, primarily used when verifying against an already hashed password, use the setSalt() method passing as the only parameter the salt. Calling getSalt() after setting a salt this way will return the set salt unless a true parameter is passed to the former.
PHP Code:
$passwordValidator->setSalt('g0ow;+}5HnM*G ;|%!@?px$W4,DK)(3WbE*iK:1'); // Set the salt
To return a hash of the password, which automatically generates a salt if one has not already been set and appends to the password a portion of the pepper to increase the total length to 78 characters, call the getHash() method. This uses an HMAC SHA 512 cryptographic hash function.
PHP Code:
$passwordValidator = new PasswordValidator('M1ch43L !$ 4w3S0m3', '4m ! RiT3?');
if ($passwordValidator->isValid() && $passwordValidator->isValid(true)) { $hash = $passwordValidator->getHash(); }
1. Is this the correct way to use an HMAC (I know there's a native hash_hmac function but decided on doing it my way instead)?
2. Should the key be longer than the 79 characters returned already? If so, should the same be true of the salt + password + pepper, and how many? 128?
i made this for adding salt to a password also for temporary passwords or pin numbers, could also be used for creating password reset keys
unique string chars or duplicated,
upper case, lowercase + numbers
Upper case + numbers
Numbers only
feel free to message me if you need help modifying it for your own needs
could easily be altered to generate lottery numbers etc
function:
PHP Code:
function GenCode($len,$type = 1,$uni = 0){ //Written by Arcticwarrio - 08-August-2012 //http://www.codingforums.com/member.php?u=147238 //GenCode(length of string,$type = 1, 2 or 3,unique chars?) //Unique Switch 1 for on 0 or ommited for off //Type Switch 1 = a-z, A-Z, 0-9 Usage: GenCode(8); or GenCode(8,1); //Type Switch 2 = A-Z, 0-9 Usage: GenCode(10,2); //Type Switch 2 = 0-9 Usage: GenCode(4,3);
//Reset Function $code =''; //Array of chars to choose from, feel free to add more arrays $codestring['1'] = array('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','1','2','3','4','5','6','7','8','9','0'); $codestring['2'] = array('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','1','2','3','4','5','6','7','8','9','0'); $codestring['3'] = array('1','2','3','4','5','6','7','8','9','0');
//see if the string should contain unique chars if ($uni == 1){ //check if theres enough chars to have a unique string if ($len > count($codestring[$type])-1){ echo "error length too long for unique string"; exit;} //loop for lenght of $len NOT allowing duplicate chars for ($i=1; $i<=$len; $i++){ //add char from chosen array to the end of the variable $code $tempx = $codestring[$type][rand(0,count($codestring[$type])-1)]; if (strstr($code, $tempx) != false){ $i--; }else{ $code .= $tempx; } }
}else{ //loop for lenght of $len allowing duplicate chars for ($i=1; $i<=$len; $i++){ //add char from chosen array to the end of the variable $code $code .= $codestring[$type][rand(0,count($codestring[$type])-1)]; } } //send $code back to where GenCode() was called from return $code; }
__________________
There are 10 types of people on CodingForums,
Those who understand Binary and those who dont.