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..5ee0e1c
--- /dev/null
+++ b/tests/Cipher/TagAwareCipherTest.php
@@ -0,0 +1,128 @@
+decoratedCipher = $this->createMock(Cipher::class);
+ $this->encoder = $this->createMock(Encoder::class);
+
+ $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';
+
+ $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->cipherWithCustomEncoder->encrypt('plainText');
+
+ $this->assertEquals($encodedText, $result);
+ }
+
+ /**
+ * @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';
+
+ $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->cipherWithCustomEncoder->decrypt($encodedTextWithEncTags);
+
+ $this->assertEquals($decryptedText, $result);
+ }
+
+ /**
+ * @throws CipherException
+ */
+ public function testDecryptWithCustomEncoderAndWithoutEncryptedTag(): void
+ {
+ $this->encoder->expects($this->once())->method('decode');
+ $this->decoratedCipher->expects($this->never())->method('decrypt');
+
+ $result = $this->cipherWithCustomEncoder->decrypt('plainText');
+
+ $this->assertEquals('plainText', $result);
+ }
+}