On Jun 22, 2016, at 11:13 AM, Cory Benfield wrote:

>In a model like this, os.getrandom() would basically need to have, in its
>documentation, a recipe for using it in a general-purpose, cross-OS
>manner. That recipe would be, at minimum, an admonition to use the secrets
>module.
>
>However, if we’re going to implement an entire function in order to say “Do
>not use this, use secrets instead”, why are we bothering? Why add the API
>surface and a function that needs to be maintained? Why not just make the use
>of getrandom a private implementation detail of secrets?

Because the os module has traditionally surfaced lower-level operating system
functions, so os.getrandom() would be an extension of this.  That's also why I
advocate simplifying os.urandom() so that it reverts more or less to exposing
/dev/urandom to Python.  With perhaps a few exceptions, os doesn't provide
higher level APIs.

The point here is that, let's say you're an experienced Linux developer and
you know you want to use getrandom(2) in Python.  os.getrandom() is exactly
that.  It's completely analogous to why we provide, e.g. os.chroot() and such.

Now, let's say you just want some guaranteed high quality random bytes, and
you don't really know or care what's being used.  The lower level os functions
are *not* the right APIs to use, but secrets is.  That's why the documentation
points people over there for better, higher-level APIs, and it's there that we
have the freedom to change underlying implementation as needed to deliver on
the promised improved security.

>Making getrandom() a private detail of secrets has the advantage of freeing
>us from some backward compatibility concerns, which as we’ve identified are a
>real problem here.

I agree.

>Given that there’s no understandable use case where someone would write
>anything but "try: os.getrandom(); except AttributeError: os.urandom”, it
>doesn’t seem sensible to give people the option to get this wrong.

This doesn't follow though.  Again, it's about providing low-level Python
bindings to underlying operation system functions in os, and higher level APIs
with more cross-platform guarantees in secret.

>The other way to approach this is to have os.getrandom() do the appropriate
>dance, but others have suggested that the os module is intended only to be
>thin wrappers around things that the OS provides (a confusing argument given
>that closerange() exists, but that’s by the by).

As I mentioned, there are exceptions (os.makedirs() is the other one that
comes to mind), but I do think the rule for os should be -and has usually
traditionally been- exactly as you say.  OTOH, neither os.makedirs() nor
os.closerange() are that far removed from their lower level cousins, so that's
a practicality over purity justification.

>However, I don’t think I agree with your assertion that it’s a bad
>precedent. I think the bad precedent is introducing new functions that do
>what the old functions should have done.

I don't agree that any of this is what os.urandom() should have done.  It's
that people have used it for other purposes and changed what they think it
should have done.  Now we're redefining os.urandom() to fit that new purpose.
That's the bad precedence IMHO.

Cheers,
-Barry

Attachment: pgp7AmXQOgCmW.pgp
Description: OpenPGP digital signature

_______________________________________________
Security-SIG mailing list
Security-SIG@python.org
https://mail.python.org/mailman/listinfo/security-sig

Reply via email to