Skip to content

Commit

Permalink
Introducing backwards compatibility in CryptTrait for switching from …
Browse files Browse the repository at this point in the history
…password to Key object encryption key (amending thephpleague#814)
  • Loading branch information
EricTendian committed Sep 13, 2018
1 parent 27b956c commit 9ab143b
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 1 deletion.
8 changes: 7 additions & 1 deletion src/CryptTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,13 @@ protected function decrypt($encryptedData)
{
try {
if ($this->encryptionKey instanceof Key) {
return Crypto::decrypt($encryptedData, $this->encryptionKey);
try {
return Crypto::decrypt($encryptedData, $this->encryptionKey);
} catch (\Exception $e) {
// This may have been encrypted with encryptWithPassword(), pull
// the data out of the key and use that to decrypt
$this->encryptionKey = $this->encryptionKey->getRawBytes();
}
}

return Crypto::decryptWithPassword($encryptedData, $this->encryptionKey);
Expand Down
46 changes: 46 additions & 0 deletions tests/Utils/CryptTraitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace LeagueTests\Utils;

use Defuse\Crypto\Key;
use Defuse\Crypto\Encoding;
use LeagueTests\Stubs\CryptTraitStub;
use PHPUnit\Framework\TestCase;

Expand Down Expand Up @@ -38,4 +39,49 @@ private function encryptDecrypt()
$this->assertNotEquals($payload, $encrypted);
$this->assertEquals($payload, $plainText);
}

public function testEncryptWithPasswordDecryptBackwardsCompatibility()
{
$payload = 'this is a test';
$key = random_bytes(32);

// Set to our original password key
$this->cryptStub->setEncryptionKey($key);

// Encrypt with password
$encrypted = $this->cryptStub->doEncrypt($payload);

$this->assertNotEquals($payload, $encrypted);

// Switch to using a Key object - we must do this in a roundabout way as the Key object has a private constructor
$keyObject = Key::loadFromAsciiSafeString(
Encoding::saveBytesToChecksummedAsciiSafeString(
Key::KEY_CURRENT_VERSION,
$key
)
);
$this->cryptStub->setEncryptionKey($keyObject);

// Decrypt after we switched to a Key object, with the same underlying data
$plainText = $this->cryptStub->doDecrypt($encrypted);

// Verify the ciphertext encrypted with the old algorithm can be decrypted even after we switched to the new Key format
$this->assertEquals($payload, $plainText);
}

public function testEncryptWithPasswordDecryptBackwardsCompatibilityBadKey()
{
$payload = 'this is a test';

// Encrypt with password
$encrypted = $this->cryptStub->doEncrypt($payload);
$this->assertNotEquals($payload, $encrypted);

// Switch to using a Key object with different underlying data
$this->cryptStub->setEncryptionKey(Key::createNewRandomKey());

// This should fail to decrypt as we changed the key
$this->expectException(\LogicException::class);
$this->cryptStub->doDecrypt($encrypted);
}
}

0 comments on commit 9ab143b

Please sign in to comment.