From 9c3f1208215de0ac552d5a21dde2fad346fbc487 Mon Sep 17 00:00:00 2001 From: Miljan Ilic Date: Fri, 15 Mar 2024 15:16:31 +0100 Subject: [PATCH 1/2] Add TagAwareCipher --- src/Cipher/TagAwareCipher.php | 48 +++++++++++++++ tests/Cipher/TagAwareCipherTest.php | 92 +++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+) create mode 100644 src/Cipher/TagAwareCipher.php create mode 100644 tests/Cipher/TagAwareCipherTest.php diff --git a/src/Cipher/TagAwareCipher.php b/src/Cipher/TagAwareCipher.php new file mode 100644 index 0000000..5ecd9ea --- /dev/null +++ b/src/Cipher/TagAwareCipher.php @@ -0,0 +1,48 @@ +encoder = new Base64Encoder(); + } else { + $this->encoder = $encoder; + } + } + + public function encrypt(#[SensitiveParameter] string $string): string + { + $encryptedString = $this->cipher->encrypt($string); + + return $this->encoder->encode('' . $encryptedString . ''); + } + + public function decrypt(#[SensitiveParameter] string $string): string + { + $data = $this->encoder->decode($string); + + if (!$this->shouldDecrypt($data)) { + return $string; + } + + preg_match('/^(.*)<\/ENC>$/', $data, $matches); + + return $this->cipher->decrypt($matches[1]); + } + + private function shouldDecrypt(string $string): bool + { + return preg_match('/^(.*)<\/ENC>$/', $string) === 1; + } +} diff --git a/tests/Cipher/TagAwareCipherTest.php b/tests/Cipher/TagAwareCipherTest.php new file mode 100644 index 0000000..fd8dba2 --- /dev/null +++ b/tests/Cipher/TagAwareCipherTest.php @@ -0,0 +1,92 @@ +decoratedCipher = $this->createMock(Cipher::class); + $this->encoder = $this->createMock(Encoder::class); + + $this->cipher = new TagAwareCipher($this->decoratedCipher, $this->encoder); + } + + /** + * @throws CipherException + */ + public function testEncrypt(): void + { + $encryptedText = 'encryptedText'; + $encodedText = 'encodedText'; + + $this->decoratedCipher->expects($this->once()) + ->method('encrypt') + ->with('plainText') + ->willReturn($encryptedText); + + $this->encoder->expects($this->once()) + ->method('encode') + ->with($this->stringContains('' . $encryptedText . '')) + ->willReturn($encodedText); + + + $result = $this->cipher->encrypt('plainText'); + + $this->assertEquals($encodedText, $result); + } + + /** + * @throws CipherException + */ + public function testDecryptWithEncryptedTag(): void + { + $encodedTextWithEncTags = 'encodedTextWithTags'; + $decryptedText = 'plainText'; + + $this->encoder->expects($this->once()) + ->method('decode') + ->with($encodedTextWithEncTags) + ->willReturn('encryptedText'); + + $this->decoratedCipher->expects($this->once()) + ->method('decrypt') + ->with($this->equalTo('encryptedText')) + ->willReturn($decryptedText); + + $result = $this->cipher->decrypt($encodedTextWithEncTags); + + $this->assertEquals($decryptedText, $result); + } + + + /** + * @throws CipherException + */ + public function testDecryptWithoutEncryptedTag(): void + { + $this->encoder->expects($this->once())->method('decode'); + $this->decoratedCipher->expects($this->never())->method('decrypt'); + + $result = $this->cipher->decrypt('plainText'); + + $this->assertEquals('plainText', $result); + } +} From 0218b2c108a02c49d06008dfc53f94d5df54769f Mon Sep 17 00:00:00 2001 From: Miljan Ilic Date: Fri, 15 Mar 2024 15:36:17 +0100 Subject: [PATCH 2/2] Improve Tag Aware Cipher Test --- tests/Cipher/TagAwareCipherTest.php | 48 +++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/tests/Cipher/TagAwareCipherTest.php b/tests/Cipher/TagAwareCipherTest.php index fd8dba2..5ee0e1c 100644 --- a/tests/Cipher/TagAwareCipherTest.php +++ b/tests/Cipher/TagAwareCipherTest.php @@ -20,19 +20,36 @@ class TagAwareCipherTest extends TestCase */ private $encoder; private TagAwareCipher $cipher; + private TagAwareCipher $cipherWithCustomEncoder; protected function setUp(): void { $this->decoratedCipher = $this->createMock(Cipher::class); $this->encoder = $this->createMock(Encoder::class); - $this->cipher = new TagAwareCipher($this->decoratedCipher, $this->encoder); + $this->cipher = new TagAwareCipher($this->decoratedCipher); + $this->cipherWithCustomEncoder = new TagAwareCipher($this->decoratedCipher, $this->encoder); } /** * @throws CipherException */ public function testEncrypt(): void + { + $this->decoratedCipher->expects($this->once()) + ->method('encrypt') + ->with('plainText') + ->willReturn('encryptedText'); + + $result = $this->cipher->encrypt('plainText'); + + $this->assertEquals(base64_encode('encryptedText'), $result); + } + + /** + * @throws CipherException + */ + public function testEncryptWithCustomEncoder(): void { $encryptedText = 'encryptedText'; $encodedText = 'encodedText'; @@ -48,7 +65,7 @@ public function testEncrypt(): void ->willReturn($encodedText); - $result = $this->cipher->encrypt('plainText'); + $result = $this->cipherWithCustomEncoder->encrypt('plainText'); $this->assertEquals($encodedText, $result); } @@ -57,6 +74,26 @@ public function testEncrypt(): void * @throws CipherException */ public function testDecryptWithEncryptedTag(): void + { + $encodedTextWithEncTags = base64_encode('encodedTextWithTags'); + $decryptedText = 'plainText'; + + $this->decoratedCipher->expects($this->once()) + ->method('decrypt') + ->with($this->equalTo('encodedTextWithTags')) + ->willReturn($decryptedText); + + $result = $this->cipher->decrypt($encodedTextWithEncTags); + + var_dump($result); + + $this->assertEquals($decryptedText, $result); + } + + /** + * @throws CipherException + */ + public function testDecryptWithCustomEncoderAndEncryptedTag(): void { $encodedTextWithEncTags = 'encodedTextWithTags'; $decryptedText = 'plainText'; @@ -71,21 +108,20 @@ public function testDecryptWithEncryptedTag(): void ->with($this->equalTo('encryptedText')) ->willReturn($decryptedText); - $result = $this->cipher->decrypt($encodedTextWithEncTags); + $result = $this->cipherWithCustomEncoder->decrypt($encodedTextWithEncTags); $this->assertEquals($decryptedText, $result); } - /** * @throws CipherException */ - public function testDecryptWithoutEncryptedTag(): void + public function testDecryptWithCustomEncoderAndWithoutEncryptedTag(): void { $this->encoder->expects($this->once())->method('decode'); $this->decoratedCipher->expects($this->never())->method('decrypt'); - $result = $this->cipher->decrypt('plainText'); + $result = $this->cipherWithCustomEncoder->decrypt('plainText'); $this->assertEquals('plainText', $result); }