where does os.urandom() get its entropy?

RESOLVED FIXED

Status

RESOLVED FIXED
8 years ago
8 years ago

People

(Reporter: warner, Assigned: warner)

Tracking

Firefox Tracking Flags

(Not tracked)

Details

(Assignee)

Description

8 years ago
Tarek mentioned to me this morning that Python's os.urandom() doesn't work on Windows, but Myk tested it just now and it looks like it's working properly. What gives? The big question, of course, is where is it getting the entropy from.

The task: dig into Python's os.urandom() implementation on Windows and make sure it's safely random.
(Assignee)

Updated

8 years ago
Assignee: nobody → warner-bugzilla
(Assignee)

Comment 1

8 years ago
Oh, for reference, the command I had Myk run (on his "win7 VM") was:

 python -c "import os; print os.urandom(8).encode('hex')"

and it reported a random hex number instead of an exception.
I was imprecise, the urandom() API exists but will fail in case the crypto API is not found, which is unlikely in modern Windows.

More details:

Under Win32: python uses the CryptAcquireContextA and the CryptGenRandom APIs (see http://en.wikipedia.org/wiki/CryptGenRandom). In case they are not found on some old flavor of Windows, a NotImplementedError is thrown.

Under OpenVMS: python uses the openssl random rountine (RAND_pseudo_bytes)

For all other platforms, it uses /dev/urandom, and if it fails to find the file, it throws an NotImplementedError as well.

So, the safest & most portable way to do the code is:

import os
try:
    print os.urandom(8).encode('hex')
except NotImplementedError:
    print alternative RNG - based on time.time() I guess
(Assignee)

Comment 4

8 years ago
Um, I wouldn't call that code "safe": for a function that's supposed to return a properly unguessable string, having a fallback which is not cryptographically strong is dangerous. I'll stick with straight os.urandom(), which (from what you said about Win32) should raise an exception rather than return non-random data.

For the server-core code, I can't tell if that's being used to generate an unguessable secret, or merely a well-distributed salt. Falling back to time.time() is ok for the salt, but not for a secret.. I'd advise naming the functions appropriately so that nobody accidentally uses the unsafe function in the future.

Based on what Tarek said about Win32, I'm satisfied that os.urandom() is safe. So I'm closing this ticket: investigation complete. thanks!
Status: NEW → RESOLVED
Last Resolved: 8 years ago
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.