-
-
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; | |
} |
Will this produce unique value every time?
i know random, but will this be unique?
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
Thanks, simple and efficient :)