23

I have same problem with Laravel 5.3 (on windows server). I did all possible attempts: checked .env file, config, artisan new key generation, cache: clear, config: clear, composer update, but the problem randomly persists.

Note that the same code with exactly same version of apache, mysql, php, doesn't generate this problem on Mac OS.

I found that the key (first parameter of Encrypter constractor) arrives "sometimes" empty and of course it fails. Most of the times the key is correct, but randomly the key arrives empty from EncryptionServiceProvider that in turns asks it to the app config.

So the only solution that worked for me was to add an if ($key) in EncryptionServiceProvider so that the Encryption constructor doesn't get called with empty key.

Of course is not a "clean" solution nor it explains the problem, but at least avoids to find the log file filled with the error:

RuntimeException: The only supported ciphers are AES-128-CBC and AES-256-CBC and pages are displayed correctly.

If this is a Laravel bug I don't know, but of course if someone could explain this I will be more then happy to know.

Below is my modified class: I just added the if ($key) line before new Encrypter:

class EncryptionServiceProvider extends ServiceProvider
{
    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton('encrypter', function ($app) {
            $config = $app->make('config')->get('app');

            // If the key starts with "base64:", we will need to decode the key before handing
            // it off to the encrypter. Keys may be base-64 encoded for presentation and we
            // want to make sure to convert them back to the raw bytes before encrypting.
            if (Str::startsWith($key = $config['key'], 'base64:')) {
                $key = base64_decode(substr($key, 7));
            }
        if ($key)
            return new Encrypter($key, $config['cipher']);
        });
    }
}

Further details and backtrace log:

Of course, as I wrote I checked, .env file, config, artisan new key generation, cache: clear, config: clear, composer update. This stuff is ok since it works 99% of the time but randomly I get the error.

Here the back trace:

[2017-01-09 10:25:40] test.ERROR: RuntimeException: The only supported ciphers are AES-128-CBC and AES-256-CBC with the correct key lengths. in C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Encryption\Encrypter.php:43

Stack trace:

#0 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Encryption\EncryptionServiceProvider.php(27): Illuminate\Encryption\Encrypter->__construct('', 'AES-256-CBC')
#1 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Container\Container.php(746): Illuminate\Encryption\EncryptionServiceProvider->Illuminate\Encryption\{closure}(Object(Illuminate\Foundation\Application), Array)
#2 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Container\Container.php(644): Illuminate\Container\Container->build(Object(Closure), Array)
#3 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Foundation\Application.php(709): Illuminate\Container\Container->make('encrypter', Array)
#4 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Container\Container.php(864): Illuminate\Foundation\Application->make('encrypter')
#5 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Container\Container.php(819): Illuminate\Container\Container->resolveClass(Object(ReflectionParameter))
#6 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Container\Container.php(788): Illuminate\Container\Container->getDependencies(Array, Array)
#7 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Container\Container.php(644): Illuminate\Container\Container->build('App\\Http\\Middle...', Array)
#8 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Foundation\Application.php(709): Illuminate\Container\Container->make('App\\Http\\Middle...', Array)
#9 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(127): Illuminate\Foundation\Application->make('App\\Http\\Middle...')
#10 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Routing\Pipeline.php(33): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#11 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\View\Middleware\ShareErrorsFromSession.php(49): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
#12 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(137): Illuminate\View\Middleware\ShareErrorsFromSession->handle(Object(Illuminate\Http\Request), Object(Closure))
#13 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Routing\Pipeline.php(33): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#14 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Session\Middleware\StartSession.php(64): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
#15 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(137): Illuminate\Session\Middleware\StartSession->handle(Object(Illuminate\Http\Request), Object(Closure))
#16 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Routing\Pipeline.php(33): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#17 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse.php(37): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
#18 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(137): Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse->handle(Object(Illuminate\Http\Request), Object(Closure))
#19 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Routing\Pipeline.php(33): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#20 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(104): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
#21 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Routing\Router.php(655): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#22 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Routing\Router.php(629): Illuminate\Routing\Router->runRouteWithinStack(Object(Illuminate\Routing\Route), Object(Illuminate\Http\Request))
#23 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Routing\Router.php(607): Illuminate\Routing\Router->dispatchToRoute(Object(Illuminate\Http\Request))
#24 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Foundation\Http\Kernel.php(268): Illuminate\Routing\Router->dispatch(Object(Illuminate\Http\Request))
#25 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Routing\Pipeline.php(53): Illuminate\Foundation\Http\Kernel->Illuminate\Foundation\Http\{closure}(Object(Illuminate\Http\Request))
#26 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode.php(46): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
#27 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(137): Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode->handle(Object(Illuminate\Http\Request), Object(Closure))
#28 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Routing\Pipeline.php(33): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#29 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(104): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
#30 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Foundation\Http\Kernel.php(150): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#31 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Foundation\Http\Kernel.php(117): Illuminate\Foundation\Http\Kernel->sendRequestThroughRouter(Object(Illuminate\Http\Request))
#32 C:\Apache24\htdocs\sph\public\index.php(53): Illuminate\Foundation\Http\Kernel->handle(Object(Illuminate\Http\Request))
#33 {main}  
6
  • Interested in this. Had this issue a couple of times and "simply" reinstalling the framework would resolve this. I really wonder why though. Commented Jan 9, 2017 at 15:49
  • Did you run php artisan key:generate? Commented Jan 9, 2017 at 16:04
  • Also, have you tried debug_print_backtrace(); when the key is null? It might be interesting to trace the call stack and error_log() the key value at every call. Commented Jan 9, 2017 at 16:09
  • I think that the issue is tied to Apache. Can you try the following to replicate the problem: create a route which returns encrypted random content. Flow: do a sleep(5); echo encrypt('test');. Meanwhile, open a new tab (same browser) and try to access the same route. Post the results. If my assumption is correct, the 2nd route will fail with the mentioned error. If that indeed happens, then it's because of Apache and that's the scenario you don't want. Commented Jan 9, 2017 at 16:20
  • problem **randomly** persists. Have you tried php artisan config:cache? Commented Jan 9, 2017 at 16:51

4 Answers 4

11
+50

The issue occurs when using thread-safe versions of PHP on multi-threaded web servers, instead of multi-process web servers. You can read about the issue a little more on the Github issue here, Github issue here, and a PHP bug report here. There are a few more links, but they are just branched off from those few I posted.

The basic gist is that with the multi-threaded web server, you have a single process that handles multiple threads. However, the putenv()/getenv() methods are not thread safe, and change environment variables at the process level, so all threads under that process are affected.

So, you end up with something like this: (as described in this issue):

Request 1: {starts --- loads env --- work --- finishes}
Request 2:                             {starts ----- loads env --- work --- finishes}

So, request 1 comes in, loads the environment fine, and gets to work. While request 1 is working, request 2 comes in and starts on another thread. Before request 2 reads the environment variables, request 1 finishes and PHP clears out all variables set by putenv(). Now, request 2 attempts to read the environment, but gets null because the variables were cleared when request 1 finished.

This issue can be mitigated in two ways:

  1. Don't use a .env file in production. Set the environment variables directly, and disable phpdotenv. This is also suggested by the package itself:

    phpdotenv is made for development environments, and generally should not be used in production. In production, the actual environment variables should be set so that there is no overhead of loading the .env file on each request.

  2. Never use the env() method outside of config files, and make sure you cache your config files. By using this method, the environment is read once: when you create the config file cache. Every actual web request will read the data from the cache, and the environment variables will never be touched again.

Sign up to request clarification or add additional context in comments.

2 Comments

@cytsunny Just wondering if this answer is what you were looking for.
I up-voted. Just want to wait to see if there are better answer. (e.g. solving the problem when using .env without hack like the OP does) Will award you bounty if there are no other answer before bounty ends.
0

I installed Laravel 5.3 and I didn't found a .env file there. And boom.... That was the issue. I created .env file in root of application and ran

php artisan key:generate

in terminal and it generated base 64 encoded string in terminal. Copy that string in to .env file as

APP_KEY=base64:************************************************

where **** is generated encoded string. Run application again and it should work.

Comments

0

APP_KEY cipher if AES-256-CBC is selected, the length must be 32 characters.

'key' => env('APP_KEY'),

'cipher' => 'AES-256-CBC',

APP_KEY=base64:iT7PDx7j8yKVTj0AW81vTnEQmqLwnVfW => 32 characters

Comments

-2

It is so simple, copy the APP_KEY from .env file to config/app.php -> key or run command below:

php artisan key:generate

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.