php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #52523 mcrypt_create_iv not reliable on win: "Could not gather sufficient random data"
Submitted: 2010-08-03 13:37 UTC Modified: 2013-01-19 13:05 UTC
From: php-bugs at thequod dot de Assigned: pajoye (profile)
Status: Closed Package: mcrypt related
PHP Version: 5.3.3 OS: win32
Private report: No CVE-ID: None
 [2010-08-03 13:37 UTC] php-bugs at thequod dot de
Description:
------------
mcrypt_create_iv (or likely rather the underlying function php_win32_get_random_bytes) is not reliable on Windows with MCRYPT_DEV_RANDOM/MCRYPT_DEV_URANDOM.

Since 5.3.0 MCRYPT_DEV_RANDOM and MCRYPT_DEV_URANDOM became available on Windows platforms. (http://php.net/mcrypt_create_iv)

MCRYPT_RAND will still works, as with PHP prior to 5.3.0.

Test script:
---------------
The following code should loop forever, but does not do so on Windows (XP and Windows 7):

  php -r "$i=0; while( mcrypt_create_iv(16) !== false ) {echo ($i++).'.';};"


Expected result:
----------------
Infinite loop.

Actual result:
--------------
0.1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.
Fatal error: mcrypt_create_iv(): Could not gather sufficient random data in Command line code on line 1


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2010-08-03 15:55 UTC] pajoye@php.net
It is reliable as it fits in the mcrypt main goal, crypto safe output.

However, do you expect it to be blocking like /dev/random? By blocking that means it won't return until it gets the requested amount of random data.

I'd to say that this example is not realistic at all, or nobody should do that in a real world application. It is important to keep in mind that an app will do it once per request for example, allowing the system seed the random sources again between calls. That's almost not possible in your example and that defeats the whole idea behind such functions.
 [2010-08-03 16:05 UTC] php-bugs at thequod dot de
Yes, I expect it to be blocking, at least for a certain amount of time (why not for the maximum execution time?).

While the endless loop is unrealistic of course, it's only meant for demonstration; it may fail with the first call already, according to the following (cygwin code):
  while php -r "if( mcrypt_create_iv(16, MCRYPT_DEV_RANDOM) === false ) exit(1);"; do ; done
 [2010-08-03 16:16 UTC] pajoye@php.net
-Status: Open +Status: Assigned -Type: Bug +Type: Feature/Change Request -Operating System: Windows XP +Operating System: * -Assigned To: +Assigned To: pajoye
 [2010-08-03 16:16 UTC] pajoye@php.net
Yes, it can but very unlikely. The only case where it fails on the 1st iteration is when I do such loops in parallel.

Hard to fix and not sure it is worth the effort. One argued once about hi traffic site, but in this exact case the system activity provides enough rng data (not like your example).

Changing to feature request and we will see what can be done (as it is not windows specific, the timeout request).
 [2010-08-03 16:59 UTC] php-bugs at thequod dot de
JFI: it gets used in Typo3 to get random data (via generateRandomBytes).

Added in
http://github.com/typo3/typo3v4core/commit/00ce0fe45aa46b62e8aa499912c9e36483185737

Also, it appears to be blocking (at least for longer) on Linux; it takes up to a few seconds for each call, but appears to fail instantly on Windows.
(not sure though)
 [2010-08-03 17:07 UTC] php-bugs at thequod dot de
Windows:
% while php -r '$s = microtime(true); if( mcrypt_create_iv(16, MCRYPT_DEV_RANDOM) === false ) exit(1); $e = microtime(true); printf("%.5f\n", $e-$s);'; do true; done
0.00449
0.00454

Fatal error: mcrypt_create_iv(): Could not gather sufficient random data in Command line code on line 1


Linux:
# while php -r '$s = microtime(true); if( mcrypt_create_iv(16, MCRYPT_DEV_RANDOM) === false ) exit(1); $e = microtime(true); printf("%.2f\n", $e-$s);'; do true; done
0.00
3.51
3.56
4.03
3.58
4.06
3.71
5.12
4.19
3.41
3.87
3.91
3.74
5.09
4.26
3.71
3.78
4.41
5.48
5.09
6.50
4.14
3.58
3.83
6.02
3.74
3.87
4.68
6.92
4.52
6.01
...

Completely different machines though, of course.
 [2010-08-03 17:47 UTC] derick@php.net
This is a bug actually. /dev/random is supposed to wait as long as there is enough entropy. /dev/urandom cares less (and is a worse source of entropy). The behaviour on Windows needs to behave the same as on a Unix.
 [2010-08-03 17:47 UTC] derick@php.net
-Operating System: * +Operating System: win32
 [2010-08-03 18:11 UTC] pajoye@php.net
@derick
urandom is not crypto safe (to be more precised).

@thequod
About the patch in typo3, this code is wrong. They use urandom on non windows platform, then try alternatives on windows only.

Problem is that they first try COM (very slow), then try with mcrypt_create_iv and overwrite COM output (regardless if it worked well or not). MCrypt also always exists on windows with 5.3+, no need to test it (statically compiled). The openssl code won't be used either (never reached this condition).

However even if the openssl code was used, its logic is wrong. It considers  non strong (not crypto safe) output as invalid. But urandom is not crypto safe anyway. They should test for the openssl function in the 1st place then use fopen('urandom') and finally mcrypt and other options. Much better/cleaner.

About your last comment, that fits in the explanation I gave earlier. Nothing new.
 [2010-08-09 10:14 UTC] pajoye@php.net
Automatic comment from SVN on behalf of pajoye
Revision: http://svn.php.net/viewvc/?view=revision&revision=302024
Log: - #52523, fix logic (0 is perfectly valid as part of the data, bin data)
 [2010-08-09 10:14 UTC] pajoye@php.net
-Status: Assigned +Status: Closed
 [2010-08-09 10:14 UTC] pajoye@php.net
This bug has been fixed in SVN.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.


 [2011-06-14 10:28 UTC] seld@php.net
I'm still experiencing issues with 5.3.6. Calling the method with both  MCRYPT_DEV_RANDOM and MCRYPT_DEV_URANDOM results in the fatal error. IMO the first should block, and the second should just return non-crypto-safe data, but it should return *something*, and ideally do it fast.
 [2011-06-14 11:17 UTC] pajoye@php.net
There is no difference between the two on Windows. Both called the same function.

How do you get the error? Which windows version do you use?
 [2013-01-19 02:50 UTC] mah at everybody dot org
Just came across this while trying to install the latest MediaWiki on a host with PHP 5.3.5 phpinfo() reports has a system string of "Windows NT A1-WHW-B69 6.0 build 6002 (Windows Server 2008 Web Server Edition Service Pack 2) i586" and a build date of "Jan 5 2011 20:33:43".

Since this was on a hosted account, I didn't have the opportunity to upgrade PHP and I couldn't find a way to test for the bug without causing a fatal error.  If I had been able to do that, I would have added code to MediaWiki to test for the bug.

I was able to work-around the bug by modifying the installer source so that MCRYPT_RAND was used instead of MCRYPT_DEV_URANDOM.  For a package like MediaWiki, though, this is less than ideal.
 [2013-01-19 13:05 UTC] pajoye@php.net
@mah at everybody dot org

Again, there is zero difference between the two on Windows.

If you can 100% reproduce the problem, then I really need to know your 
configuration, windows version, php version, etc.

Also to test it, you can try using a simple script calling the mcrypt function 
directly instead of using mediawiki.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Nov 22 04:01:28 2024 UTC