Unexpected behavior of openssl_random_pseudo_bytes () resulting in a fatal loss of cryptographic strength

    Good day to all.

    Recently, in one of the projects, we encountered the following problem - the openssl_random_pseudo_bytes () function returned duplicate pseudorandom sequences!

    It cannot be, because it can never be! - Anyone who has read the documentation for this feature will tell. And, yes, $ crypto_strong regularly returned TRUE.

    And nevertheless - uniqueness errors when inserting into the database were strewed in batches and the log confirmed - 32-byte sequences were generated repeatedly at different intervals, from a day to a week. The investigation took a whole month. Now I am 99% sure that the reason is found - but I will be grateful if the Habrazhiteli confirm or refute my conclusions.

    And it was a combination of features of three products at once:
    • Apache working with prefork MPM
    • PHP with limited support for OpenSSL functions
    • And the OpenSSL library itself having a random fork-safety problem

    The simplified situation looks like this - Apache at start creates the first copy of the PCP that starts the OpenSSL random generator. And then Apache creates and uses forks, copying, among other things, the initial state of the random generator.
    Since the random generator is also tied to the PID of the process, the problem does not appear immediately. Since on Linux the typical maximum value for PID is 65536, then after about this number of requests to the web server, the generated pseudo-random sequences will begin to repeat. More precise technical details are best found in the OpenSLL Knowledge Base article already cited above .

    The problem is compounded by the fact that the best recommended control methods (Call RAND_seed after a fork and Call RAND_poll after a fork) are not applicable to PCPs, since these OpenSSL functions are simply not available from PCPs.

    Unfortunately, I could not find adequate materials on the network on this problem, with the exception of the already mentioned OpenSLL article, but it does not describe a specific bunch of Apache + PHP + OpenSSL. But there are plenty of articles that strongly recommend using openssl_random_pseudo_bytes () as a cryptographic RNG.

    But the king is naked!

    As a result, I had to simply abandon the use of openssl_random_pseudo_bytes () and switch to direct reading from / dev / urandom. Not the most brilliant solution - but sufficient in our case.

    Since the author is not an expert in the field of cryptography and my conclusions may be incorrect / incomplete, and the problem is more than serious, given the prevalence of recommendations for using openssl_random_pseudo_bytes (), I will definitely study all the comments of the experts and possibly correct / supplement (or delete, if fundamentally wrong) article. Also, if the conclusions are confirmed, it will be necessary to make additions to the PCP documentation and proposals for adding RAND_seed / RAND_poll and / or their calls when starting the script in the PCP.

    Important! Apache should work in prefork mode (MPM prefork). The version of the PCP with which the problem was checked is 5.5.x, but, presumably, it will play in any version with openssl_random_pseudo_bytes ()

    PS I unsubscribed at security@php.net - almost a month ago. No answer, no greetings. Or did not receive. Or ignored. I do not know.
    So I bring the article back online.

    Also popular now: