Is the feature detection desire about being able to write code that runs on older Python versions or for platforms that just don't have getrandom()?

My assumption was that nobody would actually use these flags except the secrets module and people writing code that generates long-lived secrets -- and the latter category should be checking platform and versions anyway since they need the whole stack to be secure (if I understand Ted Ts'o's email right).

My assumption is also that the flags should be hints (perhaps only relevant on Linux) -- platforms that can't perform the action desired (because their system's API doesn't support it) would just do their default action, assuming the system API does the best it can.

I think the problem with making os.urandom() go back to always reading /dev/urandom is that we've come to rely on it on all platforms, so we've passed that station.

On Sat, Jun 11, 2016 at 10:15 AM, Donald Stufft <donald@stufft.io> wrote:

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






--
--Guido van Rossum (python.org/~guido)