Last active
November 21, 2023 12:35
-
-
Save raveren/5555297 to your computer and use it in GitHub Desktop.
Generate cryptographically secure random strings. Based on Kohana's Text::random() method and this answer: http://stackoverflow.com/a/13733588/179104
This file contains hidden or 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
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; | |
} |
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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: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