diff --git a/composer.json b/composer.json index c91e1729ff..a4094f1135 100644 --- a/composer.json +++ b/composer.json @@ -48,7 +48,8 @@ "twig/extensions": "~1.0", "egulias/email-validator": "~1.2", "box/spout": "^2.5", - "ruflin/elastica": "^3.2" + "ruflin/elastica": "^3.2", + "defuse/php-encryption": "v2.1.0" }, "require-dev": { "behat/behat": "3.1.0rc1", diff --git a/src/Kunstmaan/UtilitiesBundle/Command/CipherCommand.php b/src/Kunstmaan/UtilitiesBundle/Command/CipherCommand.php new file mode 100644 index 0000000000..5442866eb5 --- /dev/null +++ b/src/Kunstmaan/UtilitiesBundle/Command/CipherCommand.php @@ -0,0 +1,108 @@ + 'Encrypt text', + 1 => 'Decrypt text', + 2 => 'Encrypt file', + 3 => 'Decrypt file' + ]; + + protected function configure() + { + $this->setName('kuma:cipher')->setDescription('Cipher utilities commands.'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $this->cipher = $this->getContainer()->get('kunstmaan_utilities.cipher'); + $helper = $this->getHelper('question'); + + $question = new ChoiceQuestion( + 'Please select the method you want to use', + self::$methods, + 0 + ); + + $question->setErrorMessage('Method %s is invalid.'); + $method = $helper->ask($input, $output, $question); + $method = array_search($method, self::$methods, true); + switch($method) + { + case 0: + case 1: + $question = new Question('Please enter the text: '); + $question->setValidator(function ($value) { + if (trim($value) === '') { + throw new \Exception('The text cannot be empty'); + } + return $value; + }); + $question->setMaxAttempts(3); + $text = $helper->ask($input, $output, $question); + $text = $method === 0 ? $this->cipher->encrypt($text) : $this->cipher->decrypt($text); + $output->writeln(sprintf('Result: %s', $text)); + break; + case 2: + case 3: + $fs = new Filesystem(); + + $question = new Question('Please enter the input file path: '); + $question->setValidator(function ($value) use($fs){ + if (trim($value) === '') { + throw new \Exception('The input file path cannot be empty'); + } + + if (false === $fs->exists($value)) { + throw new \Exception('The input file must exists'); + } + + if (is_dir($value)) { + throw new \Exception('The input file cannot be a dir'); + } + return $value; + }); + $question->setMaxAttempts(3); + $inputFilePath = $helper->ask($input, $output, $question); + + $question = new Question('Please enter the output file path: '); + $question->setValidator(function ($value){ + if (trim($value) === '') { + throw new \Exception('The output file path cannot be empty'); + } + + if (is_dir($value)) { + throw new \Exception('The output file path cannot be a dir'); + } + return $value; + }); + $question->setMaxAttempts(3); + $outputFilePath = $helper->ask($input, $output, $question); + + if($method === 2) { + $this->cipher->encryptFile($inputFilePath, $outputFilePath); + } else { + if (false === $fs->exists($outputFilePath)) { + $fs->touch($outputFilePath); + } + $this->cipher->decryptFile($inputFilePath, $outputFilePath); + } + + $output->writeln(sprintf('Check "%s" to see result', $outputFilePath)); + break; + } + } + +} diff --git a/src/Kunstmaan/UtilitiesBundle/Helper/Cipher/Cipher.php b/src/Kunstmaan/UtilitiesBundle/Helper/Cipher/Cipher.php index 05dd496971..e86530c2cf 100644 --- a/src/Kunstmaan/UtilitiesBundle/Helper/Cipher/Cipher.php +++ b/src/Kunstmaan/UtilitiesBundle/Helper/Cipher/Cipher.php @@ -1,14 +1,17 @@ secret = $secret; } @@ -29,24 +33,52 @@ public function __construct($secret) * Encrypt the given value to an unreadable string. * * @param string $value - * + * @param bool $raw_binary * @return string + * @throws \Defuse\Crypto\Exception\EnvironmentIsBrokenException */ - public function encrypt($value) + public function encrypt($value, $raw_binary=false) { - return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($this->secret), $value, MCRYPT_MODE_CBC, md5(md5($this->secret)))); + return Crypto::encryptWithPassword($value, $this->secret, $raw_binary); } /** * Decrypt the given value so that it's readable again. * * @param string $value - * + * @param bool $raw_binary * @return string + * @throws \Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException + * @throws \Defuse\Crypto\Exception\EnvironmentIsBrokenException + */ + public function decrypt($value, $raw_binary=false) + { + return Crypto::decryptWithPassword($value, $this->secret, $raw_binary); + } + + /** + * @param string $inputFile + * @param string $outputFile + * @return void + * @throws \Defuse\Crypto\Exception\IOException + * @throws \Defuse\Crypto\Exception\EnvironmentIsBrokenException + */ + public function encryptFile($inputFile, $outputFile) + { + File::encryptFileWithPassword($inputFile, $outputFile, $this->secret); + } + + /** + * @param string $inputFile + * @param string $outputFile + * @return void + * @throws \Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException + * @throws \Defuse\Crypto\Exception\IOException + * @throws \Defuse\Crypto\Exception\EnvironmentIsBrokenException */ - public function decrypt($value) + public function decryptFile($inputFile, $outputFile) { - return rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, md5($this->secret), base64_decode($value), MCRYPT_MODE_CBC, md5(md5($this->secret))), "\0"); + File::decryptFileWithPassword($inputFile, $outputFile, $this->secret); } } diff --git a/src/Kunstmaan/UtilitiesBundle/Helper/Cipher/CipherInterface.php b/src/Kunstmaan/UtilitiesBundle/Helper/Cipher/CipherInterface.php index 38304152a1..6ecc1ebda2 100644 --- a/src/Kunstmaan/UtilitiesBundle/Helper/Cipher/CipherInterface.php +++ b/src/Kunstmaan/UtilitiesBundle/Helper/Cipher/CipherInterface.php @@ -7,23 +7,44 @@ */ interface CipherInterface { - /** * Encrypt the given value to an unreadable string. * * @param string $value * + * @param bool $raw_binary * @return string */ - public function encrypt($value); + public function encrypt($value, $raw_binary=false); /** * Decrypt the given value so that it's readable again. * - * @param string $value - * + * @param $value + * @param $raw_binary * @return string + * @internal param string $value + * + */ + public function decrypt($value, $raw_binary=false); + + /** + * @param string $inputFile + * @param string $outputFile + * @return void + * @throws \Defuse\Crypto\Exception\IOException + * @throws \Defuse\Crypto\Exception\EnvironmentIsBrokenException + */ + public function encryptFile($inputFile, $outputFile); + + /** + * @param string $inputFile + * @param string $outputFile + * @return void + * @throws \Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException + * @throws \Defuse\Crypto\Exception\IOException + * @throws \Defuse\Crypto\Exception\EnvironmentIsBrokenException */ - public function decrypt($value); + public function decryptFile($inputFile, $outputFile); } diff --git a/src/Kunstmaan/UtilitiesBundle/Helper/Cipher/UrlSafeCipher.php b/src/Kunstmaan/UtilitiesBundle/Helper/Cipher/UrlSafeCipher.php index 6db8d8b102..2cc84b88f7 100644 --- a/src/Kunstmaan/UtilitiesBundle/Helper/Cipher/UrlSafeCipher.php +++ b/src/Kunstmaan/UtilitiesBundle/Helper/Cipher/UrlSafeCipher.php @@ -13,11 +13,13 @@ class UrlSafeCipher extends Cipher * * @param string $value * + * @param bool $raw_binary * @return string + * @throws \Defuse\Crypto\Exception\EnvironmentIsBrokenException */ - public function encrypt($value) + public function encrypt($value, $raw_binary=false) { - return bin2hex(parent::encrypt($value)); + return bin2hex(parent::encrypt($value, $raw_binary)); } /** @@ -25,11 +27,14 @@ public function encrypt($value) * * @param string $value * + * @param bool $raw_binary * @return string + * @throws \Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException + * @throws \Defuse\Crypto\Exception\EnvironmentIsBrokenException */ - public function decrypt($value) + public function decrypt($value, $raw_binary=false) { - return parent::decrypt($this->hex2bin($value)); + return parent::decrypt($this->hex2bin($value), $raw_binary); } /** @@ -49,7 +54,7 @@ public function hex2bin($hexString) $pos++; } else { $code = hexdec(substr($hexString, $pos, 2)); - $pos = $pos + 2; + $pos += 2; $result .= chr($code); } } diff --git a/src/Kunstmaan/UtilitiesBundle/Tests/Helper/Cipher/CipherTest.php b/src/Kunstmaan/UtilitiesBundle/Tests/Helper/Cipher/CipherTest.php index 49757ce6b0..759214f19c 100644 --- a/src/Kunstmaan/UtilitiesBundle/Tests/Helper/Cipher/CipherTest.php +++ b/src/Kunstmaan/UtilitiesBundle/Tests/Helper/Cipher/CipherTest.php @@ -10,8 +10,8 @@ class CipherTest extends \PHPUnit_Framework_TestCase { - const SECRET = "secret"; - const CONTENT = "This is a random sentence which will be encrypted and then decrypted!"; + const SECRET = 'secret'; + const CONTENT = 'This is a random sentence which will be encrypted and then decrypted!'; /** * @var Cipher @@ -22,7 +22,7 @@ class CipherTest extends \PHPUnit_Framework_TestCase * Sets up the fixture, for example, opens a network connection. * This method is called before a test is executed. * - * @covers Kunstmaan\UtilitiesBundle\Helper\Cipher\Cipher::__construct + * @covers \Kunstmaan\UtilitiesBundle\Helper\Cipher\Cipher::__construct */ protected function setUp() { @@ -38,10 +38,10 @@ protected function tearDown() } /** - * @covers Kunstmaan\UtilitiesBundle\Helper\Cipher\Cipher::encrypt - * @covers Kunstmaan\UtilitiesBundle\Helper\Cipher\Cipher::decrypt + * @covers \Kunstmaan\UtilitiesBundle\Helper\Cipher\Cipher::encrypt + * @covers \Kunstmaan\UtilitiesBundle\Helper\Cipher\Cipher::decrypt */ - public function testEncryptDecrypt() + public function testEncryptAndDecrypt() { $encryptedValue = $this->cipher->encrypt(self::CONTENT); $this->assertNotEquals(self::CONTENT, $encryptedValue); diff --git a/src/Kunstmaan/UtilitiesBundle/Tests/Helper/Cipher/UrlSafeCipherTest.php b/src/Kunstmaan/UtilitiesBundle/Tests/Helper/Cipher/UrlSafeCipherTest.php index dcfe43eb42..5c0119eb57 100644 --- a/src/Kunstmaan/UtilitiesBundle/Tests/Helper/Cipher/UrlSafeCipherTest.php +++ b/src/Kunstmaan/UtilitiesBundle/Tests/Helper/Cipher/UrlSafeCipherTest.php @@ -10,8 +10,8 @@ class UrlSafeCipherTest extends \PHPUnit_Framework_TestCase { - const SECRET = "secret"; - const CONTENT = "This is a random sentence which will be encrypted and then decrypted!"; + const SECRET = 'secret'; + const CONTENT = 'This is a random sentence which will be encrypted and then decrypted!'; /** * @var UrlSafeCipher @@ -22,7 +22,7 @@ class UrlSafeCipherTest extends \PHPUnit_Framework_TestCase * Sets up the fixture, for example, opens a network connection. * This method is called before a test is executed. * - * @covers Kunstmaan\UtilitiesBundle\Helper\Cipher\UrlSafeCipher::__construct + * @covers \Kunstmaan\UtilitiesBundle\Helper\Cipher\UrlSafeCipher::__construct */ protected function setUp() { @@ -38,8 +38,8 @@ protected function tearDown() } /** - * @covers Kunstmaan\UtilitiesBundle\Helper\Cipher\UrlSafeCipher::encrypt - * @covers Kunstmaan\UtilitiesBundle\Helper\Cipher\UrlSafeCipher::decrypt + * @covers \Kunstmaan\UtilitiesBundle\Helper\Cipher\UrlSafeCipher::encrypt + * @covers \Kunstmaan\UtilitiesBundle\Helper\Cipher\UrlSafeCipher::decrypt */ public function testEncryptDecrypt() { @@ -50,7 +50,7 @@ public function testEncryptDecrypt() } /** - * @covers Kunstmaan\UtilitiesBundle\Helper\Cipher\UrlSafeCipher::hex2bin + * @covers \Kunstmaan\UtilitiesBundle\Helper\Cipher\UrlSafeCipher::hex2bin */ public function testHex2bin() {