1 | <?php |
||
2 | |||
3 | /* |
||
4 | * @copyright 2014 Mautic Contributors. All rights reserved |
||
5 | * @author Mautic |
||
6 | * |
||
7 | * @link http://mautic.org |
||
8 | * |
||
9 | * @license GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html |
||
10 | * |
||
11 | * http://www.warpconduit.net/2013/04/14/highly-secure-data-encryption-decryption-made-easy-with-php-mcrypt-rijndael-256-and-cbc/ |
||
12 | */ |
||
13 | |||
14 | namespace Mautic\CoreBundle\Helper; |
||
15 | |||
16 | use Mautic\CoreBundle\Security\Cryptography\Cipher\Symmetric\SymmetricCipherInterface; |
||
17 | use Mautic\CoreBundle\Security\Exception\Cryptography\Symmetric\InvalidDecryptionException; |
||
18 | |||
19 | class EncryptionHelper |
||
20 | { |
||
21 | /** @var SymmetricCipherInterface[] */ |
||
22 | private $availableCiphers; |
||
23 | |||
24 | /** @var string */ |
||
25 | private $key; |
||
26 | |||
27 | public function __construct( |
||
28 | CoreParametersHelper $coreParametersHelper |
||
29 | ) { |
||
30 | $nonCipherArgs = 1; |
||
31 | for ($i = $nonCipherArgs; $i < func_num_args(); ++$i) { |
||
32 | $possibleCipher = func_get_arg($i); |
||
33 | if (!($possibleCipher instanceof SymmetricCipherInterface)) { |
||
34 | throw new \InvalidArgumentException(get_class($possibleCipher).' has to implement '.SymmetricCipherInterface::class); |
||
35 | } |
||
36 | if (!$possibleCipher->isSupported()) { |
||
37 | continue; |
||
38 | } |
||
39 | $this->availableCiphers[] = $possibleCipher; |
||
40 | } |
||
41 | |||
42 | if (!$this->availableCiphers || 0 === count($this->availableCiphers)) { |
||
0 ignored issues
–
show
|
|||
43 | throw new \RuntimeException('None of possible cryptography libraries is supported'); |
||
44 | } |
||
45 | |||
46 | $this->key = $coreParametersHelper->get('mautic.secret_key'); |
||
47 | } |
||
48 | |||
49 | /** |
||
50 | * Returns a 64 character string. |
||
51 | * |
||
52 | * @return string |
||
53 | */ |
||
54 | public static function generateKey() |
||
55 | { |
||
56 | return hash('sha256', uniqid(mt_rand(), true)); |
||
57 | } |
||
58 | |||
59 | /** |
||
60 | * Encrypt string. |
||
61 | * |
||
62 | * @param mixed $data |
||
63 | * |
||
64 | * @return string |
||
65 | */ |
||
66 | public function encrypt($data) |
||
67 | { |
||
68 | $encryptionCipher = reset($this->availableCiphers); |
||
69 | $initVector = $encryptionCipher->getRandomInitVector(); |
||
70 | $encrypted = $encryptionCipher->encrypt(serialize($data), $this->key, $initVector); |
||
71 | |||
72 | return base64_encode($encrypted).'|'.base64_encode($initVector); |
||
73 | } |
||
74 | |||
75 | /** |
||
76 | * Decrypt string. |
||
77 | * Returns false in case of failed decryption. |
||
78 | * |
||
79 | * @param string $data |
||
80 | * @param bool $mainDecryptOnly |
||
81 | * |
||
82 | * @return mixed|false |
||
83 | */ |
||
84 | public function decrypt($data, $mainDecryptOnly = false) |
||
85 | { |
||
86 | $encryptData = explode('|', $data); |
||
87 | $encryptedMessage = base64_decode($encryptData[0]); |
||
88 | $initVector = base64_decode($encryptData[1]); |
||
89 | $mainTried = false; |
||
90 | foreach ($this->availableCiphers as $availableCipher) { |
||
91 | if ($mainDecryptOnly && $mainTried) { |
||
92 | return false; |
||
93 | } |
||
94 | try { |
||
95 | return Serializer::decode($availableCipher->decrypt($encryptedMessage, $this->key, $initVector)); |
||
96 | } catch (InvalidDecryptionException $ex) { |
||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
|
|||
97 | } |
||
98 | $mainTried = true; |
||
99 | } |
||
100 | |||
101 | return false; |
||
102 | } |
||
103 | } |
||
104 |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.