In example below, we're going to create a symfony vendor bundle so that we can install it with composer to use it in our main project. This example uses encryption and decryption features.


Setup the vendor bundle


Install it


Inanzzz-MBP:Documents inanzzz$ composer create-project symfony/framework-standard-edition encrypt-decrypt

Create a bundle


Inanzzz-MacBook-Pro:encrypt-decrypt inanzzz$ php app/console generate:bundle --namespace=Security/CryptBundle

Clean it up


After removing certain files and directories from the application, you should end up with structure below.


encrypt-decrypt
src
Security
CryptBundle
DependencyInjection
Configuration.php
SecurityCryptExtension.php
SecurityCryptBundle.php
.htaccess
.gitignore
composer.json
LICENSE
README.md

Update composer.json


Replace the current content with the one below and run composer update.


{
"name": "inanzzz/encrypt-decrypt",
"license": "MIT",
"type": "library",
"description": "Used for encryption and decryption processes.",
"autoload": {
"psr-0": {
"Security\\CryptBundle": "src/"
}
},
"require": {
"php": ">=5.3.3",
"symfony/symfony": "2.6.*"
},
"minimum-stability": "stable"
}

Update .gitignore


/vendor/
/composer.phar
/composer.lock

CryptorServiceInterfare.php


# encrypt-decrypt/src/Security/CryptBundle/Service/CryptorServiceInterface.php

namespace Security\CryptBundle\Service;

interface CryptorServiceInterface
{
public function encrypt($value);

public function decrypt($value);
}

CryptorService.php


# encrypt-decrypt/src/Security/CryptBundle/Service/CryptorService.php

namespace Security\CryptBundle\Service;

use Security\CryptBundle\Exception\InvalidValueException;

class CryptorService implements CryptorServiceInterface
{
private $hash;
private $algorithm;
private $mode;
private $cipher;

public function __construct(
$secret = 'hgvER5445ds5sd@£$%',
$algorithm = 'rijndael-128',
$mode = 'ecb'
) {
$this->hash = sha1($secret);
$this->algorithm = $algorithm;
$this->mode = $mode;
}

public function encrypt($plainString)
{
$this->initiate($plainString);
$encryptedValue = mcrypt_generic($this->cipher, $plainString);
$this->finalise();

return base64_encode($encryptedValue);
}

public function decrypt($encryptedValue)
{
$decodedValue = base64_decode($encryptedValue, true);
if ($decodedValue === false) {
throw new InvalidValueException(sprintf('Given value [%s] is not a valid base64 string.', $encryptedValue));
}

$this->initiate($decodedValue);
$decryptedValue = mdecrypt_generic($this->cipher, $decodedValue);
$this->finalise();

return $decryptedValue;
}

private function initiate($value)
{
if (!is_string($value)) {
throw new InvalidValueException(sprintf('Given value [%s] is not a string.', $value));
}

if (mb_strlen($value) == 0) {
throw new InvalidValueException(sprintf('Given value [%s] is empty.', $value));
}

// Open the cipher
$this->cipher = mcrypt_module_open($this->algorithm, '', $this->mode, '');

// Get key size
$keySize = mcrypt_enc_get_key_size($this->cipher);
// Get key
$key = substr($this->hash, 0, $keySize);

// Get iv size
$ivSize = mcrypt_enc_get_iv_size($this->cipher);
// Get iv
$iv = mcrypt_create_iv($ivSize, MCRYPT_DEV_RANDOM);

// Initialise encryption
mcrypt_generic_init($this->cipher, $key, $iv);
}

private function finalise()
{
// Terminate encryption handler
mcrypt_generic_deinit($this->cipher);
// Close module
mcrypt_module_close($this->cipher);
}
}

InvalidValueException.php


# encrypt-decrypt/src/Security/CryptBundle/Exception/InvalidValueException.php

namespace Security\CryptBundle\Exception;

use RuntimeException;

class InvalidValueException extends RuntimeException
{
}

Services.yml


services:
security_crypt.service.cryptor:
class: Security\CryptBundle\Service\CryptorService
arguments:
- %security_crypt.secret%
- %security_crypt.algorithm%
- %security_crypt.mode%

Configuration.php


# encrypt-decrypt/src/Security/CryptBundle/DependencyInjection/Configuration.php

namespace Security\CryptBundle\DependencyInjection;

use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;

class Configuration implements ConfigurationInterface
{
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('security_crypt');

$rootNode
->children()
->scalarNode('secret')->isRequired()->cannotBeEmpty()->end()
->scalarNode('algorithm')->isRequired()->cannotBeEmpty()->end()
->scalarNode('mode')->isRequired()->cannotBeEmpty()->end()
->end();

return $treeBuilder;
}
}

SecurityCryptExtension.php


# encrypt-decrypt/src/Security/CryptBundle/DependencyInjection/SecurityCryptExtension.php

namespace Security\CryptBundle\DependencyInjection;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;

class SecurityCryptExtension extends Extension
{
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);

$container->setParameter('security_crypt.secret', $config['secret']);
$container->setParameter('security_crypt.algorithm', $config['algorithm']);
$container->setParameter('security_crypt.mode', $config['mode']);

$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('services.yml');
}
}

Current structure


We should now have structure below.


encrypt-decrypt
src
Security
CryptBundle
DependencyInjection
Configuration.php
SecurityCryptExtension.php
Exception
InvalidValueException.php
Resources
config
service.yml
Service
CryptorServiceInterface.php
CryptorService.php
SecurityCryptBundle.php
.htaccess
.gitignore
composer.json
LICENSE
README.md

Setup remote Git repo and push


First of all, create a remote Git repo named as encrypt-decrypt then follow the steps below to initiate it so that you can start developing it.


Inanzzz-MBP:encrypt-decrypt inanzzz$ git init
Inanzzz-MBP:encrypt-decrypt inanzzz$ git add --all
Inanzzz-MBP:encrypt-decrypt inanzzz$ git commit -m 'First commit'
Inanzzz-MBP:encrypt-decrypt inanzzz$ git remote add origin https://github.com/Inanzzz/encrypt-decrypt.git
Inanzzz-MBP:encrypt-decrypt inanzzz$ git push -u origin master

Main application


Update composer.json


Add parts below to current content and run composer update inanzzz/encrypt-decrypt.


{
...
"repositories": [
{
"type": "git",
"url": "git@github.com:Inanzzz/encrypt-decrypt.git"
},
...
],
"require": {
...
"inanzzz/encrypt-decrypt": "dev-master"
...
},
"minimum-stability": "stable"
...
}

If you want you can change repositories block with the one below.


{
"repositories": [
{
"type": "vcs",
"url": "https://github.com/Inanzzz/encrypt-decrypt.git"
}
}

If you want to get rid of repositories block then you need to submit your new package/bundle to Packagist. Everytime you update your bundle, you must login and update the Packagist by "Force Update" button or setup an "auto update" task.


Update AppKernel.php


After registering the bundle, you can access its service with security_crypt.service.cryptor service name.


new Security\CryptBundle\SecurityCryptBundle()

Update config.yml


security_crypt:
secret: my_secret_value
algorithm: rijndael-128
mode: ecb

Test


Now you can inject security_crypt.service.cryptor service to anywhere you want in your application. Encrypted value is over decrypted value.


prJZvmy/gkLwAFjTBuI9Wg==
Hello
XrMKs6vAxB20JuYc0+vXOw==
Bye