Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[UtilitiesBundle] Cipher deprecations #1673

Merged
merged 4 commits into from
Dec 6, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
108 changes: 108 additions & 0 deletions src/Kunstmaan/UtilitiesBundle/Command/CipherCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<?php

namespace Kunstmaan\UtilitiesBundle\Command;

use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\ChoiceQuestion;
use Symfony\Component\Console\Question\Question;
use Symfony\Component\Filesystem\Filesystem;

class CipherCommand extends ContainerAwareCommand
{
private $cipher;

private static $methods = [
0 => '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;
}
}

}
56 changes: 44 additions & 12 deletions src/Kunstmaan/UtilitiesBundle/Helper/Cipher/Cipher.php
Original file line number Diff line number Diff line change
@@ -1,52 +1,84 @@
<?php

namespace Kunstmaan\UtilitiesBundle\Helper\Cipher;
use InvalidArgumentException;
namespace Kunstmaan\UtilitiesBundle\Helper\Cipher;

use Defuse\Crypto\Crypto;
use Defuse\Crypto\File;
use Defuse\Crypto\Key;
use Webmozart\Assert\Assert;

/**
* Cipher, this class can be used to encrypt and decrypt string values.
*/
class Cipher implements CipherInterface
{

/**
* @var string $secret
*/
private $secret;

/**
* @param string $secret
* @throws \Defuse\Crypto\Exception\EnvironmentIsBrokenException
* @throws \Defuse\Crypto\Exception\BadFormatException
*/
public function __construct($secret)
{
if (empty($secret)) {
throw new InvalidArgumentException("You need to configure a Cipher secret in your parameters.yml before you can use this!");
}
Assert::stringNotEmpty($secret, 'You need to configure a Cipher secret in your parameters.yml before you can use this!');

$this->secret = $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);
}

}
31 changes: 26 additions & 5 deletions src/Kunstmaan/UtilitiesBundle/Helper/Cipher/CipherInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);

}
15 changes: 10 additions & 5 deletions src/Kunstmaan/UtilitiesBundle/Helper/Cipher/UrlSafeCipher.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,28 @@ 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));
}

/**
* 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)
public function decrypt($value, $raw_binary=false)
{
return parent::decrypt($this->hex2bin($value));
return parent::decrypt($this->hex2bin($value), $raw_binary);
}

/**
Expand All @@ -49,7 +54,7 @@ public function hex2bin($hexString)
$pos++;
} else {
$code = hexdec(substr($hexString, $pos, 2));
$pos = $pos + 2;
$pos += 2;
$result .= chr($code);
}
}
Expand Down
12 changes: 6 additions & 6 deletions src/Kunstmaan/UtilitiesBundle/Tests/Helper/Cipher/CipherTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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()
{
Expand All @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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()
{
Expand All @@ -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()
{
Expand All @@ -50,7 +50,7 @@ public function testEncryptDecrypt()
}

/**
* @covers Kunstmaan\UtilitiesBundle\Helper\Cipher\UrlSafeCipher::hex2bin
* @covers \Kunstmaan\UtilitiesBundle\Helper\Cipher\UrlSafeCipher::hex2bin
*/
public function testHex2bin()
{
Expand Down