How to solve PHP 7.0 Polyfill : There is no suitable CSPRNG installed on your system - paragonie/random_compat

This error appears due to the upgrade of the paragonie/random_compat dependency of your project (or a dependency of a dependency of your project) to 1.5 or a major version. Many developer have faced this problems working with Laravel and Symfony (symfony/polyfill-php70). The problem basically, as shown in the message there's no an updated PRNG on your system and you'll need to provide one.

A pseudorandom number generator (PRNG), also known as a deterministic random bit generator (DRBG), is an algorithm for generating a sequence of numbers whose properties approximate the properties of sequences of random numbers. From the version 1.3 of random_compat library, the library author (paragonie) warns about this problem here.

Removed openssl_random_pseudo_bytes() entirely. If you are using random_compat in PHP on a Unix-like OS but cannot access /dev/urandom, version 1.3+ will throw an Exception. If you want to trust OpenSSL, feel free to write your own fallback code. (see snippet at the solution #3).

In this article, we'll offer you 3 possible solutions to this error on your project.

Solution 1

Although you're not using directly this library, add it to your composer.json as a dependency. Require random_compat with the specific version 1.4:

{
    "require": {
       "paragonie/random_compat": "~1.4"
   },
}

Then run composer install (or composer-update if you're already using this library) and try to run your project again. If it didn't work try downgrading to 1.3, if it doesn't work neither, then i hope you have the rights to modify PHP settings in your server and go to the next possible solution.

Solution 2

This solution is most likely to work and may be your salvation if you're able to change the PHP settings in your server. As mentioned before, we need access to urandom in our project and we need to provide it using the PHP settings.

You only need to append /dev/urandom to your existing open_basedir configuration property.

In plesk you can achieve this task easily with an UI.

Open plesk, navigate to your domain and open PHP Settings.

PHP Settings Plesk

Go to common settings and focus on the open_basedir option.

Probably, there's already a default value in that input, you only need to copy that value and append the following string to the existing value:

Note

Files in the specified directories can be accessed by PHP scripts. To separate directories, use a colon (:) on Linux and a semicolon (;) on Windows.

As it seems there's a lot of people that doesn't read well:

  • For Linux (UNIX based) Servers: you need to append the dev/urandom extension with a colon (:) e.g :/dev/urandom
  • For Windows Servers: you need to append the dev/urandom with a semicolon (;) e.g ;/dev/urandom
#In linux use : (colon)
:/dev/urandom

# In windows use ; (semicolon)
;/dev/urandom

You can see an example of this solution on a Plesk server with Ubuntu (Unix) in the following image:

Plesk manager open_basedir path

Finally save your changes and try accesing to your project again. If you're sure that you add the urandom extension correctly and it doesn't works, then proceed with the last solution.

Solution 3

If you are in this point because not any of the previous possible solutions didn't worked for you, let me tell you that you're in a hurry because you don't have too much options left. As not any of the previous steps did work for you, then you have only the following options left:

A. Downgrade your project

If your project was already working and you decided to update your framework (Symfony or laravel etc), then you'll need to downgrade as you won't be able to provide support for urandom (random_bytes function).

B. Write your own fallback for random_bytes

As we mentioned, the library doesn't rely on the openssl_random_pseudo_bytes function anymore and uses instead random_bytes (function that throws the exception). The author says in the 1.3 release, you can write your own fallback to use openss_random_pseudo_bytes again by modifying the library and creating a try and catch statement where random_bytes is used:

<?php
try {
    $bytes = random_bytes(32);
} catch (Exception $ex) {
    $strong = false;
    $bytes = openssl_random_pseudo_bytes(32, $strong);
    if (!$strong) {
        throw $ex;
    }
}

Note that on Windows platforms using PHP < 5.3.0, the function openssl_random_pseudo_bytes isn't available, therefore you will need to make another workaround by using the CAPICOM ActiveX control. Although probably no one that uses PHP 5.3 will never face this exception (as all modern projects require a higher PHP version), you can check this snippet for more information in case you're using PHP < 5.3.0.

Have fun !

Become a more social person