Last active
February 3, 2019 04:53
-
-
Save mingtsay/49df26da9e6094b70e81 to your computer and use it in GitHub Desktop.
Password Generator by Ming Tsay
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
define('PWGEN_SYMBOLS', 0x01); | |
define('PWGEN_NUMBERS', 0x02); | |
define('PWGEN_LOWERS', 0x04); | |
define('PWGEN_UPPERS', 0x08); | |
define('PWGEN_EX_SIMILAR', 0x10); | |
define('PWGEN_EX_AMBIGUOUS', 0x20); | |
define('PWGEN_SEPARATOR_ARRAY', 0); | |
define('PWGEN_SEPARATOR_LF', 1); | |
define('PWGEN_SEPARATOR_CR', 2); | |
define('PWGEN_SEPARATOR_CRLF', 3); | |
define('PWGEN_SEPARATOR_TAB', 4); | |
define('PWGEN_SEPARATOR_COMMA', 5); | |
define('PWGEN_SEPARATOR_SEMICOLON', 6); | |
function pwgen($length = 16, $chars = 15, $counts = 1, $sep = 0) { | |
if (is_int($chars)) { | |
$symbols = '!#$%&*+-=?@^_' . (PWGEN_EX_SIMILAR & $chars ? '' : '|') . (PWGEN_EX_AMBIGUOUS & $chars ? '' : '{}[]()/\'"`~,;:.<>\\'); | |
$numbers = '23456789' . (PWGEN_EX_SIMILAR & $chars ? '' : '01'); | |
$lowers = 'abcdefghjkmnpqrstuvwxyz' . (PWGEN_EX_SIMILAR & $chars ? '' : 'ilo'); | |
$uppers = 'ABCDEFGHJKLMNPQRSTUVWXYZ' . (PWGEN_EX_SIMILAR & $chars ? '' : 'IO'); | |
$characters = (PWGEN_SYMBOLS & $chars ? $symbols : '') . (PWGEN_NUMBERS & $chars ? $numbers : '') . (PWGEN_LOWERS & $chars ? $lowers : '') . (PWGEN_UPPERS & $chars ? $uppers : ''); | |
} else $characters = $chars; | |
if (is_int($sep)) { | |
$separator = false; | |
switch ($sep) { | |
case PWGEN_SEPARATOR_LF: $separator = "\n"; break; | |
case PWGEN_SEPARATOR_CR: $separator = "\r"; break; | |
case PWGEN_SEPARATOR_CRLF: $separator = "\r\n"; break; | |
case PWGEN_SEPARATOR_TAB: $separator = "\t"; break; | |
case PWGEN_SEPARATOR_COMMA: $separator = ','; break; | |
case PWGEN_SEPARATOR_SEMICOLON: $separator = ';'; break; | |
} | |
} else $separator = $sep; | |
$pwgen = array(); | |
for ($i = 0; $i < $counts; ++$i) { | |
$randoms = random_ints(0, strlen($characters) - 1, $length); | |
$pw = ''; | |
foreach ($randoms as $random) $pw .= $characters[$random]; | |
$pwgen[] = $pw; | |
} | |
return false === $separator ? ($counts === 1 ? $pwgen[0] : $pwgen) : implode($separator, $pwgen); | |
} | |
if ('cli' === PHP_SAPI) { | |
$usage = 'Usage: php pwgen.php [options] | |
-l LENGTH --length=LENGTH Set password length. Default: -l16 | |
-c FLAGS --characters=CHARS Set the characters for generating. | |
Default: -cABLNSU | |
B --include-symbols Include symbols. (e.g. @#$%) | |
N --include-numbers Include numbers. (e.g. 123456) | |
L --include-lowers Include lowercase characters. | |
(e.g. abcdefgh) | |
U --include-uppers Include uppercase characters. | |
(e.g. ABCDEFGH) | |
S --exclude-similar Exclude similar characters. | |
(e.g. i,|,1,l,I,o,0,O) | |
A --exclude-ambiguous Exclude ambiguous characters. | |
({}[]()/\\\'"`~,;:.<>) | |
-n COUNTS --counts=COUNTS Amount of generating. Default: -n1 | |
-s FLAGS --separator=STR Set separator for generating more than | |
one password. Default: -sF | |
F --separator-lf "\n" | |
R --separator-cr "\r" | |
N --separator-newline "\r\n" | |
--separator-crlf "\r\n" | |
T --separator-tab "\t" | |
C --separator-comma "," | |
S --separator-semicolon ";" | |
-t --no-trailing Don\'t print the trailing newline | |
character. | |
-h --help Display this message. | |
'; | |
$args = array( | |
'length' => false, | |
'character-flag' => 0, | |
'characters' => '', | |
'counts' => false, | |
'separator-flag' => 0, | |
'separator' => '', | |
'no-trailing' => false, | |
'help' => false, | |
'error' => false, | |
); | |
$display_help = false; | |
for ($i = 1; $i < $argc; ++$i) { | |
$arg = $argv[$i]; | |
if ('-' === $arg[0]) { | |
if ('-' === $arg[1]) { | |
$e = explode('=', $arg, 2); | |
if (count($e) > 1) switch ($e[0]) { | |
case '--length': | |
if (!is_numeric($e[1])) { | |
$args['error'] = 'Invalid length: ' . $e[1]; | |
break 2; | |
} | |
$args['length'] = (int) $e[1]; | |
break; | |
case '--characters': | |
if ($args['character-flag']) { | |
$args['error'] = 'Cannot use `--characters` and `-c FLAGS` at the same time.'; | |
break 2; | |
} | |
$args['characters'] = $e[1]; | |
break; | |
case '--counts': | |
if (!is_numeric($e[1])) { | |
$args['error'] = 'Invalid counts: ' . $e[1]; | |
break 2; | |
} | |
$args['counts'] = (int) $e[1]; | |
break; | |
case '--separator': | |
if ($args['separator-flag']) { | |
$args['error'] = 'Cannot use `--separator` and `-s FLAG` at the same time.'; | |
break 2; | |
} | |
$args['separator'] = $e[1]; | |
break; | |
default: | |
$args['error'] = 'Unknown option: ' . $arg; | |
break 2; | |
} else { | |
if ('clude' === substr($arg, 4, 5) && $args['characters'] !== '') { | |
$args['error'] = 'Cannot use `--characters` and `-c FLAGS` at the same time.'; | |
break; | |
} | |
if ('separator' === substr($arg, 2, 9) && $args['separator'] !== '') { | |
$args['error'] = 'Cannot use `--separator` and `-s FLAG` at the same time.'; | |
break; | |
} | |
if ('separator' === substr($arg, 2, 9) && $args['separator-flag']) { | |
$args['error'] = 'Only one flag can be set for the separator.'; | |
break; | |
} | |
switch ($arg) { | |
case '--length': | |
case '--characters': | |
case '--counts': | |
case '--separator': | |
$args['error'] = "Error: option `$arg` must have a value."; | |
break 2; | |
case '--include-symbols': $args['character-flag'] += PWGEN_SYMBOLS; break; | |
case '--include-numbers': $args['character-flag'] += PWGEN_NUMBERS; break; | |
case '--include-lowers': $args['character-flag'] += PWGEN_LOWERS; break; | |
case '--include-uppers': $args['character-flag'] += PWGEN_UPPERS; break; | |
case '--exclude-similar': $args['character-flag'] += PWGEN_EX_SIMILAR; break; | |
case '--exclude-ambiguous': $args['character-flag'] += PWGEN_EX_AMBIGUOUS; break; | |
case '--separator-lf': $args['separator-flag'] = PWGEN_SEPARATOR_LF; break; | |
case '--separator-cr': $args['separator-flag'] = PWGEN_SEPARATOR_CR; break; | |
case '--separator-newline': | |
case '--separator-crlf': $args['separator-flag'] = PWGEN_SEPARATOR_CRLF; break; | |
case '--separator-tab': $args['separator-flag'] = PWGEN_SEPARATOR_TAB; break; | |
case '--separator-comma': $args['separator-flag'] = PWGEN_SEPARATOR_COMMA; break; | |
case '--separator-semicolon': $args['separator-flag'] = PWGEN_SEPARATOR_SEMICOLON; break; | |
break; | |
case '--no-trailing': | |
$args['no-trailing'] = true; | |
break; | |
case '--help': | |
$args['help'] = true; | |
break; | |
default: | |
$args['error'] = 'Unknown option: ' . $arg; | |
break 2; | |
} | |
} | |
} else { | |
$e = strlen($arg) > 2 ? substr($arg, 2) : ($argc > $i + 1 ? $argv[++$i] : ' '); | |
switch($arg[1]) { | |
case 'l': | |
if (!is_numeric($e)) { | |
$args['error'] = 'Invalid length: ' . $e; | |
break 2; | |
} | |
$args['length'] = (int) $e; | |
break; | |
case 'c': | |
if ($args['characters'] !== '') { | |
$args['error'] = 'Cannot use `--characters` and `-c FLAGS` at the same time.'; | |
break 2; | |
} | |
for ($j = 0; $j < strlen($e); ++$j) | |
switch ($e[$j]) { | |
case 'B': $args['character-flag'] += PWGEN_SYMBOLS; break; | |
case 'N': $args['character-flag'] += PWGEN_NUMBERS; break; | |
case 'L': $args['character-flag'] += PWGEN_LOWERS; break; | |
case 'U': $args['character-flag'] += PWGEN_UPPERS; break; | |
case 'S': $args['character-flag'] += PWGEN_EX_SIMILAR; break; | |
case 'A': $args['character-flag'] += PWGEN_EX_AMBIGUOUS; break; | |
default: | |
$args['error'] = 'Invalid character flag: ' . $e[$j]; | |
break 4; | |
} | |
break; | |
case 'n': | |
if (!is_numeric($e)) { | |
$args['error'] = 'Invalid counts: ' . $e; | |
break 2; | |
} | |
$args['counts'] = (int) $e; | |
break; | |
case 's': | |
if ($args['separator'] !== '') { | |
$args['error'] = 'Cannot use `--separator` and `-s FLAG` at the same time.'; | |
break 2; | |
} | |
if (strlen($e) > 1) { | |
$args['error'] = 'Only one flag can be set for the separator.'; | |
break 2; | |
} | |
switch ($e) { | |
case 'F': $args['separator-flag'] = PWGEN_SEPARATOR_LF; break; | |
case 'R': $args['separator-flag'] = PWGEN_SEPARATOR_CR; break; | |
case 'N': $args['separator-flag'] = PWGEN_SEPARATOR_CRLF; break; | |
case 'T': $args['separator-flag'] = PWGEN_SEPARATOR_TAB; break; | |
case 'C': $args['separator-flag'] = PWGEN_SEPARATOR_COMMA; break; | |
case 'S': $args['separator-flag'] = PWGEN_SEPARATOR_SEMICOLON; break; | |
default: | |
$args['error'] = 'Invalid separator flag: ' . $e; | |
break 3; | |
} | |
break; | |
case 't': | |
$args['no-trailing'] = true; | |
break 2; | |
case 'h': | |
$args['help'] = true; | |
break 2; | |
default: | |
$args['error'] = 'Unknown option: ' . $arg; | |
break 2; | |
} | |
} | |
} else { | |
$args['error'] = 'Unknown option: ' . $arg; | |
break; | |
} | |
} | |
if ($args['help'] || $args['error']) { | |
if ($args['error']) | |
fwrite(STDERR, $args['error'] . "\n\n"); | |
fwrite(STDERR, $usage); | |
exit(64); // EX_USAGE | |
} | |
$config = array( | |
'length' => 16, | |
'characters' => | |
PWGEN_SYMBOLS | | |
PWGEN_NUMBERS | | |
PWGEN_LOWERS | | |
PWGEN_UPPERS | | |
PWGEN_EX_SIMILAR | | |
PWGEN_EX_AMBIGUOUS, | |
'counts' => 1, | |
'separator' => PWGEN_SEPARATOR_LF, | |
); | |
if ($args['length'] !== false) $config['length'] = $args['length']; | |
if ($args['characters'] !== '') $config['characters'] = $args['characters']; | |
if ($args['character-flag']) $config['characters'] = $args['character-flag']; | |
if ($args['counts'] !== false) $config['counts'] = $args['counts']; | |
if ($args['separator'] !== '') $config['separator'] = $args['separator']; | |
if ($args['separator-flag']) $config['separator'] = $args['separator-flag']; | |
echo(pwgen($config['length'], $config['characters'], $config['counts'], $config['separator']) . ($args['no-trailing'] ? '' : "\n")); | |
} | |
function random_ints($min, $max, $count) { | |
$mod = $max - $min + 1; | |
$random = file_get_contents('/dev/urandom', false, null, -1, $count); | |
$result = array(); | |
for ($i = 0; $i < strlen($random); ++$i) | |
$result[] = hexdec(bin2hex($random[$i])) % $mod + $min; | |
return $result; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
pwgen - Generate password with /dev/urandom
Description
mixed pwgen( [ int $length = 16 [, mixed $chars = 15 [, int $counts = 1 [, mixed $sep = 0 ]]]] )
Parameters
See the usage for CLI below.
Return Values
Returns the generated password string. It returns an array when
counts
greater than 1 andsep
is set to zero.For CLI: