On Jun 11, 2016, at 11:34 AM, Guido van Rossum <guido@python.org> wrote:

In terms of API design, I'd prefer a flag to os.urandom() indicating a preference for
- blocking
- raising an exception
- weaker random bits

If os.urandom can’t block on Linux, then I feel like it’d be saner to add os.getrandom(). I feel like these flags are going to confuse people, particularly when you take into account that all 3 of them are only going to really matter on Linux (and particularly on newer Linux) and for things like “blocking” it’s going to get confused with the blocking that /dev/random does on Linux.

Right now there are two ways to access the system CSPRNG on *nix, there is /dev/urandom pretty much always, and then there is getrandom() (or arc4random, etc, depending on the specific OS you’re on). 

Perhaps the right answer is to go back to making os.urandom always open(“/dev/urandom”).read() instead of trying to save a FD by using getrandom() and just add os.getrandom() which will interface with getrandom()/arc4random()/etc and always in blocking mode. Why always in blocking mode? Because it’s the only way to get consistent behavior across different platforms, all non Linux OSs either block or they otherwise ensure that it is initialized prior to it even being possible to access the CSPRNG.

Using this, code can be smarter about what to do in edge cases than we can reasonably be in os.urandom, for example see https://bpaste.net/show/41d89e520913.

The reasons I think this is preferable to adding parameters to os.urandom are:

* If we add parameters to os.urandom, you can’t feature detect their existence easily, you have to use version checks.
* With flags, unless we add even more flags we can’t dictate what should happen if we’re on a system where the person’s desired preference can’t be satisfied. We either have to just silently do something that may be wrong, or add more flags. By adding two functions people can pick which of the following they want with some programming (see example):

    * Just try to get the strongest random, but fall back to maybe not random if it’s early enough in boot process.
    * Fail on old Linux rather than possibly get insecure random.
    * Actually write cross platform code to prevent blocking (since only Linux allows you to not block)
        * Fail hard rather than block if we can’t get secure random bytes without blocking.
        * Soft fail and get “probably good enough” random from os.urandom on Linux.
        * Hard fail on non Linux if we would block since there’s no non-blocking and “probably good enough” interface.
        * Soft fail and get “probably good enough” random from os.urandom on Linux, and use time/pid/memory offsets on non Linux.
    * Just use the best source of random available to use on the system, and block rather than fail.

I don’t see any way to get the same wide set of options by just adding flags to os.urandom unless we add flags that work for every possible combination of what people may or may not want to.


Donald Stufft