From 27fe36e71e01dacd1d7b373294795876e3c49c3d Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Wed, 16 Dec 2020 16:26:15 -0800 Subject: [PATCH] (dev/core#2258) CryptoToken - More defense against malformed input --- Civi/Crypto/CryptoToken.php | 6 ++--- tests/phpunit/Civi/Crypto/CryptoTokenTest.php | 25 +++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/Civi/Crypto/CryptoToken.php b/Civi/Crypto/CryptoToken.php index 93fe284fc8..e45f962b9f 100644 --- a/Civi/Crypto/CryptoToken.php +++ b/Civi/Crypto/CryptoToken.php @@ -118,9 +118,9 @@ class CryptoToken { /** @var CryptoRegistry $registry */ $registry = \Civi::service('crypto.registry'); - $parts = explode($this->delim, $token); - if ($parts[1] !== self::VERSION_1) { - throw new CryptoException("Unrecognized encoding"); + $parts = explode($this->delim, $token, 4); + if (count($parts) !== 4 || $parts[1] !== self::VERSION_1) { + throw new CryptoException("Cannot decrypt token. Invalid format."); } $keyId = $parts[2]; $cipherText = base64_decode($parts[3]); diff --git a/tests/phpunit/Civi/Crypto/CryptoTokenTest.php b/tests/phpunit/Civi/Crypto/CryptoTokenTest.php index 64d3e310a9..fa949ca5cd 100644 --- a/tests/phpunit/Civi/Crypto/CryptoTokenTest.php +++ b/tests/phpunit/Civi/Crypto/CryptoTokenTest.php @@ -11,6 +11,8 @@ namespace Civi\Crypto; +use Civi\Crypto\Exception\CryptoException; + /** * Test major use-cases of the 'crypto.token' service. */ @@ -35,6 +37,29 @@ class CryptoTokenTest extends \CiviUnitTestCase { $this->assertTrue($token->isPlainText("\n")); } + public function testDecryptInvalid() { + $cryptoToken = \Civi::service('crypto.token'); + try { + $cryptoToken->decrypt(chr(2) . 'CTK0' . chr(2)); + $this->fail("Expected CryptoException"); + } + catch (CryptoException $e) { + $this->assertRegExp(';Cannot decrypt token. Invalid format.;', $e->getMessage()); + } + + $goodExample = $cryptoToken->encrypt('mess with me', 'UNIT-TEST'); + $this->assertEquals('mess with me', $cryptoToken->decrypt($goodExample)); + + try { + $badExample = preg_replace(';CTK0;', 'ctk9', $goodExample); + $cryptoToken->decrypt($badExample); + $this->fail("Expected CryptoException"); + } + catch (CryptoException $e) { + $this->assertRegExp(';Cannot decrypt token. Invalid format.;', $e->getMessage()); + } + } + public function getExampleTokens() { return [ // [ 'Plain text', 'Encryption Key ID', 'expectTokenRegex', 'expectTokenLen', 'expectPlain' ] -- 2.25.1