From 906424c1b6fd884bf2081bfe6dd0b1f9651c2801 Mon Sep 17 00:00:00 2001 From: Jeremy Benoist Date: Sun, 11 Jun 2017 23:05:19 +0200 Subject: Crypt site credential password --- src/Wallabag/CoreBundle/Command/InstallCommand.php | 2 + .../Controller/SiteCredentialController.php | 2 + .../DependencyInjection/Configuration.php | 2 + .../DependencyInjection/WallabagCoreExtension.php | 1 + src/Wallabag/CoreBundle/Entity/SiteCredential.php | 3 +- src/Wallabag/CoreBundle/Helper/CryptoProxy.php | 86 ++++++++++++++++++++++ .../Repository/SiteCredentialRepository.php | 20 ++++- .../CoreBundle/Resources/config/services.yml | 8 ++ 8 files changed, 121 insertions(+), 3 deletions(-) create mode 100644 src/Wallabag/CoreBundle/Helper/CryptoProxy.php (limited to 'src/Wallabag/CoreBundle') diff --git a/src/Wallabag/CoreBundle/Command/InstallCommand.php b/src/Wallabag/CoreBundle/Command/InstallCommand.php index 0f119377..eb725a59 100644 --- a/src/Wallabag/CoreBundle/Command/InstallCommand.php +++ b/src/Wallabag/CoreBundle/Command/InstallCommand.php @@ -313,6 +313,8 @@ class InstallCommand extends ContainerAwareCommand $this ->runCommand('doctrine:migrations:migrate', ['--no-interaction' => true]); + + return $this; } /** diff --git a/src/Wallabag/CoreBundle/Controller/SiteCredentialController.php b/src/Wallabag/CoreBundle/Controller/SiteCredentialController.php index dc8e723d..0bacafb7 100644 --- a/src/Wallabag/CoreBundle/Controller/SiteCredentialController.php +++ b/src/Wallabag/CoreBundle/Controller/SiteCredentialController.php @@ -45,6 +45,8 @@ class SiteCredentialController extends Controller $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { + $credential->setPassword($this->get('wallabag_core.helper.crypto_proxy')->crypt($credential->getPassword())); + $em = $this->getDoctrine()->getManager(); $em->persist($credential); $em->flush($credential); diff --git a/src/Wallabag/CoreBundle/DependencyInjection/Configuration.php b/src/Wallabag/CoreBundle/DependencyInjection/Configuration.php index 33df92d3..a9791f6b 100644 --- a/src/Wallabag/CoreBundle/DependencyInjection/Configuration.php +++ b/src/Wallabag/CoreBundle/DependencyInjection/Configuration.php @@ -63,6 +63,8 @@ class Configuration implements ConfigurationInterface ->end() ->end() ->end() + ->scalarNode('encryption_key_path') + ->end() ->end() ; diff --git a/src/Wallabag/CoreBundle/DependencyInjection/WallabagCoreExtension.php b/src/Wallabag/CoreBundle/DependencyInjection/WallabagCoreExtension.php index b4d8a386..532ce238 100644 --- a/src/Wallabag/CoreBundle/DependencyInjection/WallabagCoreExtension.php +++ b/src/Wallabag/CoreBundle/DependencyInjection/WallabagCoreExtension.php @@ -29,6 +29,7 @@ class WallabagCoreExtension extends Extension $container->setParameter('wallabag_core.fetching_error_message_title', $config['fetching_error_message_title']); $container->setParameter('wallabag_core.api_limit_mass_actions', $config['api_limit_mass_actions']); $container->setParameter('wallabag_core.default_internal_settings', $config['default_internal_settings']); + $container->setParameter('wallabag_core.site_credentials.encryption_key_path', $config['encryption_key_path']); $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); $loader->load('services.yml'); diff --git a/src/Wallabag/CoreBundle/Entity/SiteCredential.php b/src/Wallabag/CoreBundle/Entity/SiteCredential.php index 85ee07d4..732d9506 100644 --- a/src/Wallabag/CoreBundle/Entity/SiteCredential.php +++ b/src/Wallabag/CoreBundle/Entity/SiteCredential.php @@ -46,8 +46,7 @@ class SiteCredential * @var string * * @Assert\NotBlank() - * @Assert\Length(max=255) - * @ORM\Column(name="password", type="string", length=255) + * @ORM\Column(name="password", type="text") */ private $password; diff --git a/src/Wallabag/CoreBundle/Helper/CryptoProxy.php b/src/Wallabag/CoreBundle/Helper/CryptoProxy.php new file mode 100644 index 00000000..d0a9b85c --- /dev/null +++ b/src/Wallabag/CoreBundle/Helper/CryptoProxy.php @@ -0,0 +1,86 @@ +logger = $logger; + + if (!file_exists($encryptionKeyPath)) { + $key = Key::createNewRandomKey(); + + file_put_contents($encryptionKeyPath, $key->saveToAsciiSafeString()); + chmod($encryptionKeyPath, 0600); + } + + $this->encryptionKey = file_get_contents($encryptionKeyPath); + } + + /** + * Ensure the given value will be crypted. + * + * @param string $secretValue Secret valye to crypt + * + * @return string + */ + public function crypt($secretValue) + { + $this->logger->debug('Crypto: crypting value: '.$this->mask($secretValue)); + + return Crypto::encrypt($secretValue, $this->loadKey()); + } + + /** + * Ensure the given crypted value will be decrypted. + * + * @param string $cryptedValue The value to be decrypted + * + * @return string + */ + public function decrypt($cryptedValue) + { + $this->logger->debug('Crypto: decrypting value: '.$this->mask($cryptedValue)); + + try { + return Crypto::decrypt($cryptedValue, $this->loadKey()); + } catch (WrongKeyOrModifiedCiphertextException $e) { + throw new \RuntimeException('Decrypt fail: '.$e->getMessage()); + } + } + + /** + * Load the private key. + * + * @return string + */ + private function loadKey() + { + return Key::loadFromAsciiSafeString($this->encryptionKey); + } + + /** + * Keep first and last character and put some stars in between. + * + * @param string $value Value to mask + * + * @return string + */ + private function mask($value) + { + return $value[0].'*****'.$value[strlen($value) - 1]; + } +} diff --git a/src/Wallabag/CoreBundle/Repository/SiteCredentialRepository.php b/src/Wallabag/CoreBundle/Repository/SiteCredentialRepository.php index 316ecc75..6f904f0a 100644 --- a/src/Wallabag/CoreBundle/Repository/SiteCredentialRepository.php +++ b/src/Wallabag/CoreBundle/Repository/SiteCredentialRepository.php @@ -2,11 +2,20 @@ namespace Wallabag\CoreBundle\Repository; +use Wallabag\CoreBundle\Helper\CryptoProxy; + /** * SiteCredentialRepository. */ class SiteCredentialRepository extends \Doctrine\ORM\EntityRepository { + private $cryptoProxy; + + public function setCrypto(CryptoProxy $cryptoProxy) + { + $this->cryptoProxy = $cryptoProxy; + } + /** * Retrieve one username/password for the given host and userId. * @@ -17,12 +26,21 @@ class SiteCredentialRepository extends \Doctrine\ORM\EntityRepository */ public function findOneByHostAndUser($host, $userId) { - return $this->createQueryBuilder('s') + $res = $this->createQueryBuilder('s') ->select('s.username', 's.password') ->where('s.host = :hostname')->setParameter('hostname', $host) ->andWhere('s.user = :userId')->setParameter('userId', $userId) ->setMaxResults(1) ->getQuery() ->getOneOrNullResult(); + + if (null === $res) { + return; + } + + // decrypt password before returning it + $res['password'] = $this->cryptoProxy->decrypt($res['password']); + + return $res; } } diff --git a/src/Wallabag/CoreBundle/Resources/config/services.yml b/src/Wallabag/CoreBundle/Resources/config/services.yml index 09bc77fe..e09b0f18 100644 --- a/src/Wallabag/CoreBundle/Resources/config/services.yml +++ b/src/Wallabag/CoreBundle/Resources/config/services.yml @@ -126,6 +126,8 @@ services: factory: [ "@doctrine.orm.default_entity_manager", getRepository ] arguments: - WallabagCoreBundle:SiteCredential + calls: + - [ setCrypto, [ "@wallabag_core.helper.crypto_proxy" ] ] wallabag_core.helper.entries_export: class: Wallabag\CoreBundle\Helper\EntriesExport @@ -208,3 +210,9 @@ services: wallabag_core.entry.download_images.client: class: GuzzleHttp\Client + + wallabag_core.helper.crypto_proxy: + class: Wallabag\CoreBundle\Helper\CryptoProxy + arguments: + - "%wallabag_core.site_credentials.encryption_key_path%" + - "@logger" -- cgit v1.2.3