Generating a random password in php
我正在尝试用PHP生成一个随机密码。
但是,我得到了所有的a,返回类型是类型array,我希望它是一个字符串。关于如何更正代码有什么想法吗?
谢谢。
1 2 3 4 5 6 7 8 |
Security warning:
rand() is not a cryptographically secure pseudorandom number generator. Look elsewhere for generating a cryptographically secure pseudorandom string in PHP.
试试这个(用
1 2 3 4 5 6 7 8 9 10 | function randomPassword() { $alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'; $pass = array(); //remember to declare $pass as an array $alphaLength = strlen($alphabet) - 1; //put the length -1 in cache for ($i = 0; $i < 8; $i++) { $n = rand(0, $alphaLength); $pass[] = $alphabet[$n]; } return implode($pass); //turn the array into a string } |
演示:http://codepad.org/ul8k4ayk
DR:
- 使用下面给出的
random_int() 和random_str() 。 - 如果没有
random_int() ,使用随机兼容。
说明:
由于正在生成密码,因此需要确保生成的密码是不可预测的,并且确保此属性存在于实现中的唯一方法是使用加密安全的伪随机数生成器(CSPRNG)。
对于随机字符串的一般情况,可以放宽对CSPRNG的要求,但当涉及到安全性时,则不必这样做。
在PHP中,密码生成的简单、安全和正确答案是使用randomlib,而不是重新发明轮子。这个图书馆已经过行业安全专家和我自己的审计。
对于喜欢自己发明解决方案的开发人员,php 7.0.0将为此提供
有了安全随机整数生成器,生成安全随机字符串比生成饼图更容易:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <?php /** * Generate a random string, using a cryptographically secure * pseudorandom number generator (random_int) * * For PHP 7, random_int is a PHP core function * For PHP 5.x, depends on https://github.com/paragonie/random_compat * * @param int $length How many characters do we want? * @param string $keyspace A string of all possible characters * to select from * @return string */ function random_str( $length, $keyspace = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' ) { $str = ''; $max = mb_strlen($keyspace, '8bit') - 1; if ($max < 1) { throw new Exception('$keyspace must be at least two characters long'); } for ($i = 0; $i < $length; ++$i) { $str .= $keyspace[random_int(0, $max)]; } return $str; } |
我知道你正试图以一种特定的方式生成你的密码,但你也可能想看看这个方法…
1 2 3 |
它是从php.net网站上获取的,它创建了一个字符串,该字符串的长度是您在openssl_random_pseudo_bytes函数中输入的数字的两倍。所以上面会创建一个4个字符长的密码。
简而言之…
1 |
将创建一个8个字符长的密码。
但是请注意,密码只包含数字0-9和小写字母a-f!
带2行的小代码。
演示:http://codepad.org/5rhmwnh
1 2 3 4 5 6 7 8 | function rand_string( $length ) { $chars ="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; return substr(str_shuffle($chars),0,$length); } echo rand_string(8); |
with rand_string you can define how much character will be create.
如果您使用的是PHP7,则可以使用
1 2 3 4 5 6 7 8 9 10 11 12 | function generate_password($length = 20){ $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'. '0123456789`-=~!@#$%^&*()_+,./<>?;:[]{}\|'; $str = ''; $max = strlen($chars) - 1; for ($i=0; $i < $length; $i++) $str .= $chars[random_int(0, $max)]; return $str; } |
Old answer below:
1 2 3 4 5 6 7 8 9 10 11 12 |
在一行中:
1 |
最好的选择是ircmaxell的randomlib库。
使用实例:
1 2 3 4 5 | $factory = new RandomLib\Factory; $generator = $factory->getGenerator(new SecurityLib\Strength(SecurityLib\Strength::MEDIUM)); $passwordLength = 8; // Or more $randomPassword = $generator->generateString($passwordLength); |
它产生的字符串比普通随机函数(如
你要的是
然而,
相反,从
我将发布一个答案,因为现有的一些答案很接近,但有一个:
- 一个比您想要的更小的字符空间,这样暴力强制更容易,或者对于相同的熵密码必须更长。
- 不被认为是密码安全的RNG
- 对于一些第三方图书馆的要求,我认为展示自己可能需要什么可能是很有趣的。
这个答案将避开
让我们把问题分解成以下几个组成部分:
在第一部分中,php>5.3.0提供了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | /** * @param int $length */ function strong_random_bytes($length) { $strong = false; // Flag for whether a strong algorithm was used $bytes = openssl_random_pseudo_bytes($length, $strong); if ( ! $strong) { // System did not use a cryptographically strong algorithm throw new Exception('Strong algorithm not available for PRNG.'); } return $bytes; } |
在第二部分中,我们将使用
1 |
对于额外的学分,如果我们想达到运营商问题中的确切规格,那么我们将不得不做更多的工作。我将放弃这里的基本转换方法,使用一个快速而肮脏的方法。两者都需要产生比结果中使用的随机性更大的随机性,因为62个条目的长字母表。
对于结果中的额外字符,我们可以简单地从结果字符串中丢弃它们。如果我们从字节字符串中的8个字节开始,那么高达25%的base64字符将是这些"不需要的"字符,因此简单地丢弃这些字符将导致一个不短于op所需的字符串。然后我们可以简单地将其截断,以得到精确的长度:
1 2 | $dirty_pass = base64_encode(strong_random_bytes(8))); $pass = substr(str_replace(['/', '+', '='], ['', '', ''], $dirty_pass, 0, 8); |
如果生成更长的密码,填充字符
如
编辑
正如我在评论中提到的,长度意味着暴力攻击比定时攻击更有效,因此它与担心"随机生成器的安全性"无关。安全性,特别是对于这个用例,需要补充可用性,因此上述解决方案实际上足以满足所需的问题。
但是,为了防止您在搜索安全随机字符串生成器(我假设有些人基于响应)时偶然发现这个答案,对于生成令牌之类的内容,下面是此类代码生成器的样子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | function base64urlEncode($data) { return rtrim(strtr(base64_encode($data), '+/', '-_'), '='); } function secureId($length = 32) { if (function_exists('openssl_random_pseudo_bytes')) { $bytes = openssl_random_pseudo_bytes($length); return rtrim(strtr(base64_encode($bytes), '+/', '0a'), '='); } else { // fallback to system bytes error_log("Missing support for openssl_random_pseudo_bytes"); $pr_bits = ''; $fp = @fopen('/dev/urandom', 'rb'); if ($fp !== false) { $pr_bits .= @fread($fp, $length); @fclose($fp); } if (strlen($pr_bits) < $length) { error_log('unable to read /dev/urandom'); throw new \Exception('unable to read /dev/urandom'); } return base64urlEncode($pr_bits); } } |
这基本上与更简单的
另一个(仅限Linux)
1 2 3 4 5 6 7 8 |
聪明一点:
在这里检查一下。
使用此简单代码生成12长度的med强密码
1 2 | $password_string = '!@#$%*&abcdefghijklmnpqrstuwxyzABCDEFGHJKLMNPQRSTUWXYZ23456789'; $password = substr(str_shuffle($password_string), 0, 12); |
尝试使用大写字母、小写字母、数字和特殊字符
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | function generatePassword($_len) { $_alphaSmall = 'abcdefghijklmnopqrstuvwxyz'; // small letters $_alphaCaps = strtoupper($_alphaSmall); // CAPITAL LETTERS $_numerics = '1234567890'; // numerics $_specialChars = '`~!@#$%^&*()-_=+]}[{;:,<.>/?\'"\|'; // Special Characters $_container = $_alphaSmall.$_alphaCaps.$_numerics.$_specialChars; // Contains all characters $password = ''; // will contain the desired pass for($i = 0; $i < $_len; $i++) { // Loop till the length mentioned $_rand = rand(0, strlen($_container) - 1); // Get Randomized Length $password .= substr($_container, $_rand, 1); // returns part of the string [ high tensile strength ;) ] } return $password; // Returns the generated Pass } |
Let's Say we need 10 Digit Pass
1 | echo generatePassword(10); |
示例输出:
,IZCQIV IV 7
@ WLQSFHT(D)
1!8 + 1 4 @ UD
快一号。简单、干净、一致的格式,如果您需要的话
1 |
这是基于本页的另一个答案,https://stackoverflow.com/a/21498316/525649。
这个答案只生成十六进制字符,
1 2 3 4 5 6 7 8 | str_shuffle( rtrim( base64_encode(bin2hex(openssl_random_pseudo_bytes(5))), '=' ). strtoupper(bin2hex(openssl_random_pseudo_bytes(7))). bin2hex(openssl_random_pseudo_bytes(13)) ) |
base64_encode 返回更广泛的字母数字字符rtrim 有时在末端移除= 。
实例:
32eFVfGDg891Be5e7293e54z1D23110M3ZU3FMjb30Z9a740Ej0jz4 b280R72b48eOm77a25YCj093DE5d9549Gc73Jg8TdD9Z0Nj4b98760 051b33654C0Eg201cfW0e6NA4b9614ze8D2FN49E12Y0zY557aUCb8 y67Q86ffd83G0z00M0Z152f7O2ADcY313gD7a774fc5FF069zdb5b7
这对于为用户创建一个界面来说不是非常可配置的,但是对于某些目的来说是可以的。增加字符数以说明缺少特殊字符。
就像评论里说的那样。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | <?php /** * @usage : * include_once($path . '/Password.php'); * $Password = new Password; * $pwd = $Password->createPassword(10); * return $pwd; * */ class Password { public function createPassword($length = 15) { $response = []; $response['pwd'] = $this->generate($length); $response['hashPwd'] = $this->hashPwd( $response['pwd'] ); return $response; } private function generate($length = 15) { $chars ="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*(){}/?,><"; return substr(str_shuffle($chars),0,$length); } private function hashPwd($pwd) { return hash('sha256', $pwd); } } ?> |
我创建了一个更全面、更安全的密码脚本。这将创建两个大写、两个小写、两个数字和两个特殊字符的组合。共8个字符。
1 2 3 4 5 6 7 8 | $char = [range('A','Z'),range('a','z'),range(0,9),['*','%','$','#','@','!','+','?','.']]; $pw = ''; for($a = 0; $a < count($char); $a++) { $randomkeys = array_rand($char[$a], 2); $pw .= $char[$a][$randomkeys[0]].$char[$a][$randomkeys[1]]; } $userPassword = str_shuffle($pw); |
如果您需要8个字符,1个大写字母和1个数字。
1 2 3 4 5 | $p_lc_letters = substr(str_shuffle('abcdefghijklmnopqrstuvwxyz'), 0, 6); // Generate 6 lowercase letters $p_uc_letters = substr(str_shuffle('ABCDEFGHIJKLMNOPQRSTUVWXYZ'), 0, 1); // Generate 1 uppercase letter $p_numbers = substr(str_shuffle('0123456789'), 0, 1); // Generate 1 number echo $password = substr(str_shuffle($p_lc_letters.''.$p_uc_letters.''.$p_numbers), 0, 8); |
1 2 3 4 5 6 7 8 9 10 | <?php // We can generate without large code.. $length = 8; $chars = array_merge(range(0,9), range('a','z'),range('A','Z'),['!','@','#','$','%','&','*','?']); //$chars = array_merge(range(0,1), range('A','Z')); shuffle($chars); $code = implode(array_slice($chars, 0, $length)); $arr = array($code); $password = implode("",$arr); echo $password; |
我一直想尝试实现我自己的"安全"和"随机"密码生成器。
我认为为函数提供一个
这里有一个函数,它执行一些检查以确保
如果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | <?php /** * Generates a random password with the given length and of the given type. * * @param int $length * @param string $type * @return string | null */ function random_password($length=8, $type='alpha_numeric') { if ($length < 1 || $length > 1024) return null; $lower = 'abcdefghijklmnopqrstuvwxy'; $upper = strtoupper($lower); $numbers = '1234567890'; $dash = '-'; $underscore = '_'; $symbols = '`~!@#$%^&*()+=[]\\{}|:";\'<>?,./'; switch ($type) { case 'lower': $chars = $lower; break; case 'upper': $chars = $upper; break; case 'numeric': $chars = $numbers; break; case 'alpha': $chars = $lower . $upper; break; case 'symbol': $chars = $symbols . $dash . $underscore; break; case 'alpha_numeric': $chars = $lower . $upper . $numbers; break; case 'alpha_numeric_dash': $chars = $lower . $upper . $numbers . $dash; break; case 'alpha_numeric_underscore': $chars = $lower . $upper . $numbers . $underscore; break; case 'alpha_numeric_dash_underscore': $chars = $lower . $upper . $numbers . $underscore . $dash; break; case 'all': $chars = $lower . $upper . $numbers . $underscore . $dash . $symbols; break; default: return null; } $min = 0; $max = strlen($chars) - 1; $password = ''; for ($i = 0; $i < $length; $i++) { $random = mt_rand($min, $max); $char = substr($chars, $random, 1); $password .= $char; } return $password; } |