Skip to content

[13.x] Add specific encryption exceptions for invalid payloads and unsupported ciphers #56269

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

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/Illuminate/Contracts/Encryption/InvalidPayloadException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Illuminate\Contracts\Encryption;

use RuntimeException;

class InvalidPayloadException extends RuntimeException
{
//
}
10 changes: 10 additions & 0 deletions src/Illuminate/Contracts/Encryption/UnsupportedCipherException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Illuminate\Contracts\Encryption;

use RuntimeException;

class UnsupportedCipherException extends RuntimeException
{
//
}
11 changes: 6 additions & 5 deletions src/Illuminate/Encryption/Encrypter.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Contracts\Encryption\Encrypter as EncrypterContract;
use Illuminate\Contracts\Encryption\EncryptException;
use Illuminate\Contracts\Encryption\InvalidPayloadException;
use Illuminate\Contracts\Encryption\StringEncrypter;
use RuntimeException;
use Illuminate\Contracts\Encryption\UnsupportedCipherException;

class Encrypter implements EncrypterContract, StringEncrypter
{
Expand Down Expand Up @@ -58,7 +59,7 @@ public function __construct($key, $cipher = 'aes-128-cbc')
if (! static::supported($key, $cipher)) {
$ciphers = implode(', ', array_keys(self::$supportedCiphers));

throw new RuntimeException("Unsupported cipher or incorrect key length. Supported ciphers are: {$ciphers}.");
throw new UnsupportedCipherException("Unsupported cipher or incorrect key length. Supported ciphers are: {$ciphers}.");
}

$this->key = $key;
Expand Down Expand Up @@ -232,7 +233,7 @@ protected function hash(#[\SensitiveParameter] $iv, #[\SensitiveParameter] $valu
protected function getJsonPayload($payload)
{
if (! is_string($payload)) {
throw new DecryptException('The payload is invalid.');
throw new InvalidPayloadException('The payload is invalid.');
}

$payload = json_decode(base64_decode($payload), true);
Expand All @@ -241,7 +242,7 @@ protected function getJsonPayload($payload)
// assume it is invalid and bail out of the routine since we will not be able
// to decrypt the given value. We'll also check the MAC for this encryption.
if (! $this->validPayload($payload)) {
throw new DecryptException('The payload is invalid.');
throw new InvalidPayloadException('The payload is invalid.');
}

return $payload;
Expand Down Expand Up @@ -366,7 +367,7 @@ public function previousKeys(array $keys)
if (! static::supported($key, $this->cipher)) {
$ciphers = implode(', ', array_keys(self::$supportedCiphers));

throw new RuntimeException("Unsupported cipher or incorrect key length. Supported ciphers are: {$ciphers}.");
throw new UnsupportedCipherException("Unsupported cipher or incorrect key length. Supported ciphers are: {$ciphers}.");
}
}

Expand Down
17 changes: 9 additions & 8 deletions tests/Encryption/EncrypterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
namespace Illuminate\Tests\Encryption;

use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Contracts\Encryption\InvalidPayloadException;
use Illuminate\Contracts\Encryption\UnsupportedCipherException;
use Illuminate\Encryption\Encrypter;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use RuntimeException;

class EncrypterTest extends TestCase
{
Expand Down Expand Up @@ -156,39 +157,39 @@ public function testThatANonAeadCipherIncludesMac()

public function testDoNoAllowLongerKey()
{
$this->expectException(RuntimeException::class);
$this->expectException(UnsupportedCipherException::class);
$this->expectExceptionMessage('Unsupported cipher or incorrect key length. Supported ciphers are: aes-128-cbc, aes-256-cbc, aes-128-gcm, aes-256-gcm.');

new Encrypter(str_repeat('z', 32));
}

public function testWithBadKeyLength()
{
$this->expectException(RuntimeException::class);
$this->expectException(UnsupportedCipherException::class);
$this->expectExceptionMessage('Unsupported cipher or incorrect key length. Supported ciphers are: aes-128-cbc, aes-256-cbc, aes-128-gcm, aes-256-gcm.');

new Encrypter(str_repeat('a', 5));
}

public function testWithBadKeyLengthAlternativeCipher()
{
$this->expectException(RuntimeException::class);
$this->expectException(UnsupportedCipherException::class);
$this->expectExceptionMessage('Unsupported cipher or incorrect key length. Supported ciphers are: aes-128-cbc, aes-256-cbc, aes-128-gcm, aes-256-gcm.');

new Encrypter(str_repeat('a', 16), 'AES-256-GCM');
}

public function testWithUnsupportedCipher()
{
$this->expectException(RuntimeException::class);
$this->expectException(UnsupportedCipherException::class);
$this->expectExceptionMessage('Unsupported cipher or incorrect key length. Supported ciphers are: aes-128-cbc, aes-256-cbc, aes-128-gcm, aes-256-gcm.');

new Encrypter(str_repeat('c', 16), 'AES-256-CFB8');
}

public function testExceptionThrownWhenPayloadIsInvalid()
{
$this->expectException(DecryptException::class);
$this->expectException(InvalidPayloadException::class);
$this->expectExceptionMessage('The payload is invalid.');

$e = new Encrypter(str_repeat('a', 16));
Expand Down Expand Up @@ -221,7 +222,7 @@ public function testExceptionThrownWithDifferentKey()

public function testExceptionThrownWhenIvIsTooLong()
{
$this->expectException(DecryptException::class);
$this->expectException(InvalidPayloadException::class);
$this->expectExceptionMessage('The payload is invalid.');

$e = new Encrypter(str_repeat('a', 16));
Expand Down Expand Up @@ -263,7 +264,7 @@ public static function provideTamperedData()
#[DataProvider('provideTamperedData')]
public function testTamperedPayloadWillGetRejected($payload)
{
$this->expectException(DecryptException::class);
$this->expectException(InvalidPayloadException::class);
$this->expectExceptionMessage('The payload is invalid.');

$enc = new Encrypter(str_repeat('x', 16));
Expand Down
4 changes: 2 additions & 2 deletions tests/Integration/Queue/JobEncryptionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace Illuminate\Tests\Integration\Queue;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Contracts\Encryption\InvalidPayloadException;
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
Expand Down Expand Up @@ -50,7 +50,7 @@ public function testNonEncryptedJobPayloadIsStoredRaw()
{
Bus::dispatch(new JobEncryptionTestNonEncryptedJob);

$this->expectException(DecryptException::class);
$this->expectException(InvalidPayloadException::class);
$this->expectExceptionMessage('The payload is invalid');

$this->assertInstanceOf(JobEncryptionTestNonEncryptedJob::class,
Expand Down
Loading