rfc:easy_userland_csprng

This is an old revision of the document!


PHP RFC: Easy User-land CSPRNG

Introduction

This RFC proposes adding an easy user-land API for a reliable CSPRNG in PHP.

The Problem

PHP is particularly bad at providing CSPRNG's in user-land. Users have a few options like openssl_random_pseudo_bytes() and mcrypt_create_iv() to generate pseudo-random bytes, but unfortunately system support for these functions varies.

The mcrypt_create_iv() function is provided by the MCrypt lib which is solid, but unmaintained. Since it is built into PHP as an extension, it might not be enabled in certain environments (like most versions of PHP on Mac OS X). The longer this lib goes unmaintained, the more likely it is to have a security hole discovered that goes unfixed. And on top of all that, there is a bounty on MCrypt's head!

The openssl_random_pseudo_bytes() function is provided by the OpenSSL lib which is being actively maintained but is hugely bloated and we've seen several major security issues pop up requiring the most-up-to-date version of the lib to stay secure. Moreover, in certain configurations, openssl_random_pseudo_bytes() will return bytes that are not cryptographically secure adding more required knowledge in user-land to ensure secure bytes.

Currently the most reliable way to grab pseudo-random bytes across systems is by using either of the libs mentioned above or falling back to a stream of bytes from /dev/urandom which is OS-specific and can fail when the open_basedir ini setting is set. This requires user-land apps to write potentially 100's of lines of code to simply generate pseudo-random bytes and there are several caveats that will not generate cryptographically secure bytes. And in some cases no reliable method can be found at all.

See the Facebook PHP SDK's implementation of a CSPRNG in PHP to understand how much code is needed in user-land to simply generate cryptographically secure pseudo-random bytes.

Proposal

There should be a user-land API to easily return an arbitrary length of cryptographically secure pseudo-random bytes directly from arc4random, getrandom or /dev/urandom and work on any supported server configuration or OS.

The initial proposal is to add two user-land functions that return the bytes as binary and integer.

$randBinary = random_bytes($bytes = 10);
 
$randomInt = random_int($maxInt = 900);

Backward Incompatible Changes

There would be no BC breaks.

Proposed PHP Version(s)

PHP 7

RFC Impact

To SAPIs

This RFC should not impact the SAPI's.

To Existing Extensions

No existing extensions be affected.

To Opcache

TODO Leigh - this one is all yours :) Please explain how you have verified your RFC's compatibility with opcache.

New Constants

There would be no new constants.

php.ini Defaults

There would be no new php.ini defaults.

Open Issues

  • Verify Windows support (@auroraeosrose?)
  • Implement support for arc4random / getrandom (Leigh)

Unaffected PHP Functionality

This change should not affect any of the existing rand() or mt_rand() functionality.

Future Scope

The concepts from the RFC could be used to:

  • Deprecate mcrypt_create_iv()
  • Improve session_id randomness generation

Patches and Tests

References

None so far.

Rejected Features

None so far.

Changelog

  • 0.0: Initial draft - need Leigh's input

Acknowledgements

Big thanks to Anthony Ferrara, Daniel Lowrey, Leigh, E. Smith and all the kids in the PHP room for all the help with this one!

rfc/easy_userland_csprng.1424470175.txt.gz · Last modified: 2017/09/22 13:28 (external edit)