3

My goal is simply to generate a temporary token that will be used in URLs for user identification, should I use OAuthProvider::generateToken or random_bytes?

From these answers :

Generate a single use token in PHP: random_bytes or openssl_random_pseudo_bytes?

and

best practice to generate random token for forgot password

It seems that random_bytes is a more recently updated option for PHP 7 when compared to openssl_random_pseudo_bytes. Is it the same when compared to OAuthProvider::generateToken?

Examples:

$rb_token = bin2hex(random_bytes($length));
$oa_token = bin2hex((new OAuthProvider())->generateToken($length, TRUE));
// TRUE = strong "/dev/random will be used for entropy"
CPHPython
  • 12,379
  • 5
  • 59
  • 71
  • Depends on portability, got to install OAuthProvider, random_bytes if you got php7 and openssl is generally available in most deployments, all create random bytes.. are you asking which is more random? Whats random? – Lawrence Cherone Apr 03 '18 at 12:48
  • Also forgot password tokens don't need to be cryptographically random. – Lawrence Cherone Apr 03 '18 at 12:51
  • 2
    @LawrenceCherone Are you saying it's ok to be able to guess a password reset token? – Gabor Lengyel Apr 03 '18 at 13:06
  • The odds of guessing a sane length nonce token and then correctly entering the email address for that token. It's far easier to just hack the person's email or brute force the account. Also, I didn't say guess, I said does not need to be cryptographically secure. Timing attacks and sidechanel attacks are not a problem with any of the above functions.. – Lawrence Cherone Apr 03 '18 at 13:13
  • 2
    @LawrenceCherone To "crack" a plain prng, the only thing you have to guess is the seed, which for example in c# Random() is 32 bits, in php it's 31 bits (php only uses signed). If you can try 1000 per second, you will have the correct one in 49 days *for sure*, and you have a reasonable chance to have it much earlier. I don't think that's good enough. And 1000/s is a conservative guess for any decent web application. – Gabor Lengyel Apr 03 '18 at 13:55
  • 1
    @LawrenceCherone As Gabor pointed out, from both possibilities I presented, I'd like to know which method has a lower probability of someone else "guessing" the token and why. – CPHPython Apr 03 '18 at 14:18

1 Answers1

3

I would go for random_bytes (if you use PHP < 7, a polyfill with a good reputations exists, random_compat). Differences in between /dev/urandom and /dev/random are negligible for your case (a more detailed explanation can be found there).

random_bytes use getrandom syscall or /dev/urandom, (source code), while OAuthProvider::generateToken() without strong mode seems to fallback to some unsecure implementation if the generated string is too short (source code, and source code of php_mt_rand). So random_bytes has a edge over usability (no unsafe mode), and on systems using getrandom syscall, as it should be the preferred method (detailled explanation here).

Another way to conclude is to look at some widely-used libraries: FOSOAuthServer bundle, for Symfony applications, uses random_bytes too.
Last but not least, I believe some PHP core function will also receive more scrutinity, and better support, than an extension.

romaricdrigon
  • 1,497
  • 12
  • 16
  • Thank you. Just a quick look at [`OAuthProvider::generateToken()` source](http://git.php.net/?p=pecl/web_services/oauth.git;a=blob;f=provider.c;h=0170ee1ad867d9dabc04253ac1074ff641714a87;hb=HEAD#l898) it seems it also uses `/dev/urandom` and `/dev/random` when **strong** is used. (Line 934 `fd = open(strong?"/dev/random":"/dev/urandom", O_RDONLY);`). – CPHPython Apr 12 '18 at 14:27
  • 1
    That's correct, `OAuthProvider::generateToken()` with strong mode and `random_bytes` are almost similar. Hence my conclusion over ease-of-use, but maybe I should edit my message to make it clearer? – romaricdrigon Apr 12 '18 at 14:30