[Python-Dev] BDFL ruling request: should we block forever waiting for high-quality random bits?

Brett Cannon brett at python.org
Sat Jun 11 14:55:51 EDT 2016

On Sat, 11 Jun 2016 at 11:31 Donald Stufft <donald at stufft.io> wrote:

> On Jun 11, 2016, at 1:39 PM, Guido van Rossum <guido at python.org> wrote:
> 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.
> The problem is that someone writing software that does
> os.urandom(block=True) or os.urandom(exception=True) which gets some bytes
> doesn’t know if it got back cryptographically secure random because Python
> called getrandom() or if it got back cryptographically secure random
> because it called /dev/urandom and that gave it secure random because it’s
> on a platform that defines that as always returning secure or because it’s
> on Linux and the urandom pool is initialized or if it got back some random
> bytes that are not cryptographically secure because it fell back to reading
> /dev/urandom on Linux prior to the pool being initialized.
> The “silently does the wrong thing, even though I explicitly asked for it
> do something different” is something that I would consider to be a footgun
> and footgun’s in security sensitive code make me really worried.
> Outside of the security side of things, if someone goes “Ok I need some
> random bytes and I need to make sure it doesn’t block”, then doing
> ``os.random(block=False, exception=False)`` isn’t going to make sure that
> it doesn’t block except on Linux.
> In other words, it’s basically impossible to ensure you get the behavior
> you want with these flags which I feel like will make everyone unhappy
> (both the people who want to ensure non-blocking, and the people who want
> to ensure cryptographically secure). These flags are an attractive nuisance
> that look like they do the right thing, but silently don’t.
> Meanwhile if we have os.urandom that reads from /dev/urandom and
> os.getrandom() which reads from blocking random, then we make it both
> easier to ensure you get the behavior you want, either by using the
> function that best suits your needs:
> * If you just want the best the OS has to offer, os.getrandom falling back
> to os.urandom.
> * If you want to ensure you get cryptographically secure bytes,
> os.getrandom, falling back to os.urandom on non Linux platforms and
> erroring on Linux.
> * If you want to *ensure* that there’s no blocking, then os.urandom on
> Linux (or os.urandom wrapped with timeout code anywhere else, as that’s the
> only way to ensure not blocking cross platform).
> * If you just don’t care, YOLO it up with either os.urandom or
> os.getrandom or random.random.

I'm +1 w/ what Donald is suggesting here and below w/ proper documentation
in both the secrets and random modules to explain when to use what (i.e.
secrets for crypto-no-matter-what randomness, random for quick-and-dirty
randomness). This also includes any appropriate decoupling of the secrets
module from the random module so there's no reliance on the random module
in the docs of the secrets module beyond "this class has the same
interface", and letting the secrets module be the way people generally get
crypto randomness.


> 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.
> Sorry, to be more specific I meant the 3.4 behavior, which was
> open(“/dev/urandom”).read() on *nix and CryptGenRandom on Windows.
> Donald Stufft
> _______________________________________________
> Python-Dev mailing list
> Python-Dev at python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
> https://mail.python.org/mailman/options/python-dev/brett%40python.org
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20160611/e120057d/attachment.html>

More information about the Python-Dev mailing list