New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Python 3.6 on Windows doesn't seed Random() well enough #73271
Comments
Creating two Random() instances in quick succession produces the same sequence, but only on Windows on Python 3.6. On 3.5 or earlier, or on Mac/Linux, the randomization is good. Python 3.6.0 (v3.6.0:41df79263a11, Dec 23 2016, 07:18:10) [MSC v.1900 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import random; print(random.Random().randint(1, 999999), random.Random().randint(1, 999999))
903885 903885
>>> import random; print(*[random.Random().randint(1, 999999) for _ in range(2)])
996947 56476
>>> import random; print(*[random.Random().randint(1, 999999) for _ in range(2)])
793282 793282
>>> import random; print(*[random.Random().randint(1, 999999) for _ in range(2)])
519702 519702
>>> import random; print(*[random.Random().randint(1, 999999) for _ in range(2)])
230678 230678
>>> import random; print(*[random.Random().randint(1, 999999) for _ in range(3)])
474701 474701 474701
>>> import random; print(*[random.Random().randint(1, 999999) for _ in range(3)])
890942 890942 890942
>>> import random; print(*[random.Random().randint(1, 999999) for _ in range(3)])
997495 997495 997495
>>> import random; print(*[random.Random().randint(1, 999999) for _ in range(5)])
27803 27803 27803 27803 919401
>>> I would expect each of these runs to produce unique numbers, with no duplicates. |
Adding a time.sleep(0.001) (or maybe even just 0) between the calls prevents the problem. |
It's presumably failing to read nonblocking random from CrpytGen and falling back to seeding using time and pid. |
Can recreate under Python 3.6.0 (v3.6.0:41df79263a11, Dec 23 2016, 08:06:12) [MSC v.1900 64 bit (AMD64)] on win32 and on latest master. |
time.sleep(0) and time.sleep(0.0) acted the same for me and both exhibited matching 'random' values in some cases. (win10, python3.6) I also printed time.time() with each 'random' value and it wasn't a perfect match but matching times tended to go with matching 'random' values. |
Yes and no. CryptGenRandom is not failing, but it is nonetheless calling random_seed_time_pid: >>> r = random.Random()
Breakpoint 0 hit
python36_d!random_seed:
00000000`5e7277c0 4889542410 mov qword ptr [rsp+10h],rdx
ss:00000095`053ef0e8=0000000000000000
0:000> g
Breakpoint 1 hit
python36_d!random_seed_time_pid:
00000000`5e728910 48894c2408 mov qword ptr [rsp+8],rcx
ss:00000095`053ef040=000002319b6f3b88
0:000> kc 3
Call Site
python36_d!random_seed_time_pid
python36_d!random_seed
python36_d!random_new It looks like there's a bug in the new implementation of random_seed(): if (arg == NULL || arg == Py_None) {
if (random_seed_urandom(self) >= 0) {
PyErr_Clear();
/* Reading system entropy failed, fall back on the worst entropy:
use the current time and process identifier. */
random_seed_time_pid(self);
}
Py_RETURN_NONE;
} If random_seed_urandom fails, it returns -1, so this should be testing if the result is less than 0. |
Does this affect the secrets module at all? |
The secrets module uses SystemRandom, which overrides random() and getrandbits() to use os.urandom, so it's not affected. |
New changeset 0a55e039d25f by Benjamin Peterson in branch '3.6': New changeset fc3eab44765f by Benjamin Peterson in branch 'default': |
Oh, sorry, I introduced the bug in Python 3.6 with the PEP-524 (os.urandom() now blocks on Linux). Too bad that there is no simple way to write an unit test for that.
With the bug, or when the fix when _PyOS_URandomNonblock() fails, Random.seed() uses:
It's just that on Windows, the system clock has a resolution around 15 ms, whereas it has a resolution better than 1 us on Linux. So it's just that calling Random.seed() usually takes longer than the resolution of the system clock on Linux :-) Not really that the bug is specific to Windows. Thanks for the fix Benjamin! |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: