Skip to content

Instantly share code, notes, and snippets.

@divinity76
Created August 31, 2019 08:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save divinity76/c7dfdb0c78b91908df9267ecbdfc7b20 to your computer and use it in GitHub Desktop.
Save divinity76/c7dfdb0c78b91908df9267ecbdfc7b20 to your computer and use it in GitHub Desktop.
php5-compatible php-based password generator page
<?php
$max_password_length = 100;
?>
<form action="" method="POST">
password length: <input type="number" name="password_length" value="15" max="<?php echo $max_password_length;?>" /><br/>
uppercase: <input type="checkbox" name="uppercase" checked /><br/>
lowercase: <input type="checkbox" name="lowercase" checked /><br/>
numbers: <input type="checkbox" name="numbers" checked /><br/>
semi-indistinguishable characters (1Il oO0): <input type="checkbox" name="indistinguishable" unchecked /><br/>
<input type="submit" value="generate password">
</form>
<?php
if (!empty($_POST['password_length']))
{
$password_length = (int) abs((int) $_POST['password_length']);
if ($password_length > $max_password_length)
{
die("error: max password length: {$max_password_length} characters");
}
$lowercase = !empty($_POST['lowercase']);
$uppercase = !empty($_POST['uppercase']);
$numbers = !empty($_POST['numbers']);
$indistinguishable = !empty($_POST['indistinguishable']);
if (!$lowercase && !$uppercase && !$numbers)
{
die("error: you must enable at least 1 of the following: lowercase, uppercase, or numbers.");
}
$illegal_chars = "+/=";
if (!$lowercase)
{
$illegal_chars .= "abcdefghijklmnopqrstuvwxyz";
}
if (!$uppercase)
{
$illegal_chars .= "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
}
if (!$numbers)
{
$illegal_chars .= "0123456789";
}
if(!$indistinguishable){
$illegal_chars.="1IloO0";//5S?
}
$rex = "/[" . preg_quote($illegal_chars, "/") . "]/";
$password = "";
$cryptographically_strong = true;
$tmp = null;
while (strlen($password) < $password_length)
{
$password .= preg_replace($rex, "", base64_encode(random_bytes_compat($max_password_length * 2, $tmp)));
if (!$tmp)
{
$cryptographically_strong = false;
}
}
$password = substr($password, 0, $password_length);
echo "cryptographically strong random generator: ";
if ($cryptographically_strong)
{
echo "<span style='color:green'>yes</span>";
}
else
{
echo "<span style='color:red'>!!NO!!</span>";
}
echo "<br/>password: <span style='background-color:grey'>" . hhb_tohtml($password) . "</span></br>";
}
die(); // end of page.
// convert any string to valid utf-8 html
function hhb_tohtml($str)
{
return htmlentities($str, ENT_QUOTES | ENT_HTML401 | ENT_SUBSTITUTE | ENT_DISALLOWED, 'UTF-8', true);
}
// php5-compatibile version of php7's random_bytes()
// $crypto_strong: a boolean value that determines if the algorithm used was "cryptographically strong"
function random_bytes_compat($length, &$crypto_strong = null)
{
$crypto_strong = false;
if (!is_int($length))
{
throw new \InvalidArgumentException("argument 1 must be an int, is " . gettype($length));
}
if ($length < 0)
{
throw new \InvalidArgumentException("length must be >= 0");
}
if (is_callable("random_bytes"))
{
$crypto_strong = true;
return random_bytes($length);
}
$ret = @file_get_contents("/dev/urandom", false, null, 0, $length);
if (is_string($ret) && strlen($ret) === $length)
{
$crypto_strong = true;
return $ret;
}
if (is_callable("openssl_random_pseudo_bytes"))
{
return openssl_random_pseudo_bytes($length, $crypto_strong);
}
// fallback to non-cryptographically-secure mt_rand() implementation...
$crypto_strong = false;
$ret = "";
for ($i = 0; $i < $length; ++$i)
{
$ret .= chr(mt_rand(0, 255));
}
return $ret;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment