-
-
Save raveren/5555297 to your computer and use it in GitHub Desktop.
function random_text( $type = 'alnum', $length = 8 ) | |
{ | |
switch ( $type ) { | |
case 'alnum': | |
$pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; | |
break; | |
case 'alpha': | |
$pool = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; | |
break; | |
case 'hexdec': | |
$pool = '0123456789abcdef'; | |
break; | |
case 'numeric': | |
$pool = '0123456789'; | |
break; | |
case 'nozero': | |
$pool = '123456789'; | |
break; | |
case 'distinct': | |
$pool = '2345679ACDEFHJKLMNPRSTUVWXYZ'; | |
break; | |
default: | |
$pool = (string) $type; | |
break; | |
} | |
$crypto_rand_secure = function ( $min, $max ) { | |
$range = $max - $min; | |
if ( $range < 0 ) return $min; // not so random... | |
$log = log( $range, 2 ); | |
$bytes = (int) ( $log / 8 ) + 1; // length in bytes | |
$bits = (int) $log + 1; // length in bits | |
$filter = (int) ( 1 << $bits ) - 1; // set all lower bits to 1 | |
do { | |
$rnd = hexdec( bin2hex( openssl_random_pseudo_bytes( $bytes ) ) ); | |
$rnd = $rnd & $filter; // discard irrelevant bits | |
} while ( $rnd >= $range ); | |
return $min + $rnd; | |
}; | |
$token = ""; | |
$max = strlen( $pool ); | |
for ( $i = 0; $i < $length; $i++ ) { | |
$token .= $pool[$crypto_rand_secure( 0, $max )]; | |
} | |
return $token; | |
} |
This code uses recommended methods like openssl and in my opinion is good. However You can see my implementation is very wide and generate passwords in all languages.
What can I say? Thank you.
Crypto Warning
openssl_random_pseudo_bytes
can return false, and this is not being considered here. If you are using modern PHP, just use random_int instead.
Returns the generated string of bytes on success, or FALSE on failure.
@catn3m0 this is used in multiple production environments for years and has never misbehaved - nor has been reported as such.
The false
on failure can be caused by a setup issue which you should fix with your php installation anyway.
EDIT: updated function [diff]
Thanks for upgrading to random_int
. There is detailed prior discussion on this at https://paragonie.com/blog/2015/07/how-safely-generate-random-strings-and-integers-in-php, paragonie/random_compat#5 which covers issues and fixes. To copy the summary:
Given the above, we cannot in good conscience recommend openssl_random_pseudo_bytes() as a CSPRNG. If you can use an alternative to openssl_random_pseudo_bytes(), please do so.
Look at the polyfill for a list of issues that need to be tackled for a secure CSPRNG in PHP. The current version refuses to fallback to OpenSSL.
It is much more tricker than the implementation here. People should just use https://github.com/paragonie/random_compat
1 out of 5-6 times, php throws this error:
Notice: Uninitialized string offset: 62
My fix was to remove the check for 'random_int'
if (function_exists('random_int')) {
$crypto_rand_secure = 'random_int';
} else { }
& just using the
$crypto_rand_secure = function ( $min, $max ) {
*******************************************
UPDATE: reverted to the age-old, tested function, seriously just go and use https://github.com/paragonie/random_compat
Will this produce unique value every time?
i know random, but will this be unique?