. */ namespace SP\Util; use Defuse\Crypto\Core; use Defuse\Crypto\Encoding; use Defuse\Crypto\Exception\EnvironmentIsBrokenException; /** * Class PasswordUtil * * @package SP\Util */ final class PasswordUtil { const CHARS = 'abcdefghijklmnopqrstuwxyz'; const CHARS_SPECIAL = '@$%&/()!_:.;{}^-'; const CHARS_NUMBER = '0123456789'; const FLAG_PASSWORD_NUMBER = 2; const FLAG_PASSWORD_SPECIAL = 4; const FLAG_PASSWORD_STRENGTH = 8; /** * Generate a ramdom password * * @param int $length Password length * @param int|null $flags Password chars included and checking strength flags * * @return string */ public static function randomPassword(int $length = 16, int $flags = null): string { if ($flags === null) { $flags = self::FLAG_PASSWORD_SPECIAL | self::FLAG_PASSWORD_NUMBER | self::FLAG_PASSWORD_STRENGTH; } $useSpecial = ($flags & self::FLAG_PASSWORD_SPECIAL) > 0; $useNumbers = ($flags & self::FLAG_PASSWORD_NUMBER) > 0; $alphabet = self::CHARS . strtoupper(self::CHARS); if ($useSpecial) { $alphabet .= self::CHARS_SPECIAL; } if ($useNumbers) { $alphabet .= self::CHARS_NUMBER; } /** * @return array */ $passGen = function () use ($alphabet, $length) { $pass = []; $alphaLength = strlen($alphabet) - 1; //put the length -1 in cache for ($i = 0; $i < $length; $i++) { $n = mt_rand(0, $alphaLength); $pass[] = $alphabet[$n]; } return $pass; }; if ($flags & self::FLAG_PASSWORD_STRENGTH) { do { $pass = $passGen(); $strength = self::checkStrength($pass); $res = $strength['lower'] > 0 && $strength['upper'] > 0; if ($useSpecial === true) { $res = $res && $strength['special'] > 0; } if ($useNumbers === true) { $res = $res && $strength['number'] > 0; } } while ($res === false); return implode('', $pass); } return implode($passGen()); } /** * @param array $pass * * @return array */ public static function checkStrength(array $pass): array { $charsUpper = strtoupper(self::CHARS); $strength = ['lower' => 0, 'upper' => 0, 'special' => 0, 'number' => 0]; foreach ($pass as $char) { $strength['lower'] += substr_count(self::CHARS, $char); $strength['upper'] += substr_count($charsUpper, $char); $strength['special'] += substr_count(self::CHARS_SPECIAL, $char); $strength['number'] += substr_count(self::CHARS_NUMBER, $char); } return $strength; } /** * Generar una cadena aleatoria usuando criptografía. * * @param int $length opcional, con la longitud de la cadena * * @return string * @throws EnvironmentIsBrokenException */ public static function generateRandomBytes(int $length = 30): string { return Encoding::binToHex(Core::secureRandom($length)); } }