PluginProbe
FireBox – WooCommerce Popup Builder, Exit Intent Popup, Email Optin & Cart Abandonment / 3.1.10
FireBox – WooCommerce Popup Builder, Exit Intent Popup, Email Optin & Cart Abandonment v3.1.10
3.1.13 3.1.12 3.1.11 3.1.10 3.1.9 3.1.8 3.1.7 trunk 1.0.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 All 122 releases
firebox / Inc / Core / Helpers / Encryption.php

Encryption.php in FireBox – WooCommerce Popup Builder, Exit Intent Popup, Email Optin & Cart Abandonment 3.1.10, at Inc/Core/Helpers/Encryption.php

227 lines 5.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package FireBox
4 * @version 3.1.10
5 *
6 * @author FirePlugins <info@fireplugins.com>
7 * @link https://www.fireplugins.com
8 * @copyright Copyright © 2026 FirePlugins All Rights Reserved
9 * @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
10 */
11
12 namespace FireBox\Core\Helpers;
13
14 if (!defined('ABSPATH'))
15 {
16 exit; // Exit if accessed directly.
17 }
18
19 /**
20 * Encrypts integration credentials at rest.
21 *
22 * The key is derived from a fixed salt, which makes stored values portable: a site can be
23 * migrated, cloned or restored from a backup and its credentials remain readable. That is
24 * a deliberate trade — a key tied to the site (wp-config salts, say) would resist a
25 * database-only leak, but would silently invalidate every credential whenever those salts
26 * changed, which happens routinely during migrations.
27 *
28 * Be clear about what this does and does not buy: an attacker holding a database dump can
29 * derive the same key from the plugin source, so this is obfuscation at rest rather than
30 * a defence against disclosure. Treat the credentials themselves as the secret and rotate
31 * them if a dump ever leaks.
32 */
33 class Encryption
34 {
35 /**
36 * Salt the encryption key is derived from.
37 *
38 * Fixed on purpose, so encrypted values survive a site move. See the class docblock.
39 *
40 * @var string
41 */
42 private $salt = 'fbox_enc_3b7d50a8f9e84cb1a4627c8d6e1f90b3';
43
44 /**
45 * Cipher used for stored values.
46 *
47 * @var string
48 */
49 const CIPHER = 'aes-256-cbc';
50
51 /**
52 * Encrypt value for storage.
53 *
54 * @param string $value
55 *
56 * @return string|false Payload, '' for empty input, or false when encryption failed.
57 */
58 final public function encrypt($value = '')
59 {
60 $value = trim((string) $value);
61 if ($value === '')
62 {
63 return '';
64 }
65
66 $key = $this->getEncryptionKey();
67 if ($key === '')
68 {
69 return false;
70 }
71
72 $encrypted_payload = $this->encryptWithOpenSSL($value, $key);
73 if ($encrypted_payload === false)
74 {
75 /**
76 * Report the failure rather than returning the plaintext. Storing a raw
77 * credential under a name that implies encryption would leave it in the
78 * database in the clear with no signal to anyone.
79 */
80 return false;
81 }
82
83 return base64_encode($encrypted_payload);
84 }
85
86 /**
87 * Decrypt value from storage.
88 *
89 * @param mixed $value
90 *
91 * @return string
92 */
93 final public function decrypt($value)
94 {
95 $value = trim((string) $value);
96 if ($value === '')
97 {
98 return '';
99 }
100
101 $decoded = base64_decode($value, true);
102 if ($decoded === false || $decoded === '')
103 {
104 // Not a payload we produced; hand back the value as stored.
105 return $value;
106 }
107
108 $key = $this->getEncryptionKey();
109 if ($key === '')
110 {
111 return $value;
112 }
113
114 $decrypted = $this->decryptWithOpenSSL($decoded, $key);
115 if ($decrypted === '')
116 {
117 /**
118 * A value that is valid base64 but was never encrypted (a plaintext key that
119 * happens to decode) must come back unchanged rather than as an empty string.
120 */
121 return $value;
122 }
123
124 return trim((string) $decrypted);
125 }
126
127 /**
128 * Returns whether this platform can encrypt.
129 *
130 * @return bool
131 */
132 public static function isAvailable()
133 {
134 return function_exists('openssl_encrypt') && function_exists('openssl_cipher_iv_length');
135 }
136
137 /**
138 * Derives the encryption key.
139 *
140 * @return string Raw 32-byte key, or '' when the salt is unusable.
141 */
142 private function getEncryptionKey()
143 {
144 $salt = trim((string) $this->salt);
145 if ($salt === '')
146 {
147 return '';
148 }
149
150 return hash('sha256', $salt, true);
151 }
152
153 /**
154 * Encrypt plain text using OpenSSL.
155 *
156 * @param string $value
157 * @param string $key
158 *
159 * @return string|false
160 */
161 private function encryptWithOpenSSL($value = '', $key = '')
162 {
163 if (!self::isAvailable())
164 {
165 return false;
166 }
167
168 $iv_length = openssl_cipher_iv_length(self::CIPHER);
169 if (!is_int($iv_length) || $iv_length <= 0)
170 {
171 return false;
172 }
173
174 try
175 {
176 $iv = random_bytes($iv_length);
177 }
178 catch (\Exception $e)
179 {
180 return false;
181 }
182
183 $openssl_raw_data = defined('OPENSSL_RAW_DATA') ? OPENSSL_RAW_DATA : 1;
184 $encrypted = openssl_encrypt($value, self::CIPHER, $key, $openssl_raw_data, $iv);
185 if ($encrypted === false)
186 {
187 return false;
188 }
189
190 return $iv . $encrypted;
191 }
192
193 /**
194 * Decrypt OpenSSL encrypted payload.
195 *
196 * @param string $payload
197 * @param string $key
198 *
199 * @return string
200 */
201 private function decryptWithOpenSSL($payload = '', $key = '')
202 {
203 if (!function_exists('openssl_decrypt') || !function_exists('openssl_cipher_iv_length'))
204 {
205 return '';
206 }
207
208 $iv_length = openssl_cipher_iv_length(self::CIPHER);
209 if (!is_int($iv_length) || $iv_length <= 0 || strlen($payload) <= $iv_length)
210 {
211 return '';
212 }
213
214 $iv = substr($payload, 0, $iv_length);
215 $encrypted = substr($payload, $iv_length);
216 if ($iv === false || $encrypted === false)
217 {
218 return '';
219 }
220
221 $openssl_raw_data = defined('OPENSSL_RAW_DATA') ? OPENSSL_RAW_DATA : 1;
222 $decrypted = openssl_decrypt($encrypted, self::CIPHER, $key, $openssl_raw_data, $iv);
223
224 return $decrypted === false ? '' : (string) $decrypted;
225 }
226 }
227