PluginProbe ʕ •ᴥ•ʔ
WP STAGING – WordPress Backup, Restore, Migration & Clone / 3.0.1
WP STAGING – WordPress Backup, Restore, Migration & Clone v3.0.1
4.9.1 4.9.0 4.8.1 trunk 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.10.0 3.2.0 3.3.1 3.3.2 3.3.3 3.4.1 3.4.3 3.5.0 3.6.0 3.7.1 3.8.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.8.6 3.8.7 3.9.0 3.9.1 3.9.2 3.9.3 3.9.4 4.0.0 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.0 4.7.0 4.7.1 4.7.2 4.7.3 4.8.0
wp-staging / Framework / Security / DataEncryption.php
wp-staging / Framework / Security Last commit date
AccessToken.php 2 years ago Auth.php 5 years ago Capabilities.php 5 years ago DataEncryption.php 3 years ago Nonce.php 3 years ago UniqueIdentifier.php 3 years ago
DataEncryption.php
326 lines
1 <?php
2
3 namespace WPStaging\Framework\Security;
4
5 /**
6 * Class Data Encryption
7 *
8 * Class responsible for encrypting and decrypting data
9 *
10 * @package WPStaging\Framework\Security
11 */
12 class DataEncryption
13 {
14 /** @var bool */
15 private $hasSsl;
16
17 /** @var string */
18 private $prefix;
19
20 /** @var string */
21 private $key;
22
23 /** @var string */
24 private $salt;
25
26 public function __construct()
27 {
28 if (!apply_filters('wpstg.framework.security.dataEncryption.useSsl', true)) {
29 $this->hasSsl = false;
30 } else {
31 $this->hasSsl = extension_loaded('openssl') && function_exists('openssl_encrypt') && function_exists('openssl_decrypt') && (bool)in_array('aes-256-ctr', openssl_get_cipher_methods());
32 }
33
34 $this->prefix = '!wpstg!';
35 $this->key = $this->getDefaultKey();
36 $this->salt = $this->getDefaultSalt();
37 }
38
39 /**
40 * @param string|int $value
41 * @return string
42 */
43 public function encrypt($value)
44 {
45 if ($this->hasSsl) {
46 return $this->sslEncrypt($value);
47 }
48
49 return $this->base64Encrypt($value);
50 }
51
52 /**
53 * @param string $value
54 * @return string
55 */
56 public function decrypt($value)
57 {
58 if ($this->verifyPrefix($value, 'ssl')) {
59 return $this->sslDecrypt($value);
60 }
61
62 return $this->base64Decrypt($value);
63 }
64
65 /**
66 * @param string|int $value
67 * @return string
68 */
69 protected function base64Encrypt($value)
70 {
71 if (!$this->isValidKeySalt() || $value === '' || $this->isEncrypted($value)) {
72 return $value;
73 }
74
75 $mykey = $this->key . $this->salt;
76 $encpad = substr($mykey, 0, 12);
77 $value = $encpad . $value;
78
79 // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode
80 $pad = base64_decode($mykey);
81 $valueLen = strlen($value);
82 $encrypted = '';
83 $x = 0;
84 for ($i = 0; $i < $valueLen; $i++, $x++) {
85 if (!isset($pad[$x])) {
86 $x = 0;
87 }
88 $padi = $pad[$x];
89 $encrypted .= chr(ord($value[$i]) ^ ord($padi));
90 }
91
92 return $this->setPrefixType('b64') . $this->normalizeBase64Encode($encrypted);
93 }
94
95 /**
96 * @param string $inputValue
97 * @return string
98 */
99 protected function base64Decrypt($inputValue)
100 {
101 if (!$this->isValidKeySalt() || !is_string($inputValue) || $inputValue === '' || !$this->isEncrypted($inputValue) || !$this->verifyPrefix($inputValue, 'b64')) {
102 return $inputValue;
103 }
104
105 $value = $this->stripPrefix($inputValue, 'b64');
106 $mykey = $this->key . $this->salt;
107
108 // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode
109 $pad = base64_decode($mykey);
110 $encrypted = $this->normalizeBase64Decode($value);
111 $encryptedLen = strlen($encrypted);
112 $decrypted = '';
113 $x = 0;
114 for ($i = 0; $i < $encryptedLen; $i++, $x++) {
115 if (!isset($pad[$x])) {
116 $x = 0;
117 }
118 $padi = $pad[$x];
119 $decrypted .= chr(ord($encrypted[$i]) ^ ord($padi));
120 }
121
122 $encpad = substr($mykey, 0, 12);
123 $enclen = strlen($encpad);
124 $envpad = substr($decrypted, 0, $enclen);
125
126 if ($encpad !== $envpad) {
127 return $inputValue;
128 }
129
130 $decrypted = substr($decrypted, $enclen);
131 return $decrypted;
132 }
133
134 /**
135 * @param string|int $value
136 * @return string
137 */
138 protected function sslEncrypt($value)
139 {
140 if (!$this->isValidKeySalt() || $value === '' || !$this->hasSsl || $this->isEncrypted($value)) {
141 return $value;
142 }
143
144 $method = 'aes-256-ctr';
145 $ivlen = openssl_cipher_iv_length($method);
146 $iv = openssl_random_pseudo_bytes($ivlen);
147
148 $rawValue = openssl_encrypt($value . $this->salt, $method, $this->key, 0, $iv);
149 if (!$rawValue) {
150 return $value;
151 }
152
153 return $this->setPrefixType('ssl') . $this->normalizeBase64Encode($iv . $rawValue);
154 }
155
156 /**
157 * @param string $inputValue
158 * @return string
159 */
160 protected function sslDecrypt($inputValue)
161 {
162 if (!$this->isValidKeySalt() || !is_string($inputValue) || $inputValue === '' || !$this->hasSsl || !$this->isEncrypted($inputValue) || !$this->verifyPrefix($inputValue, 'ssl')) {
163 return $inputValue;
164 }
165
166 $rawValue = $this->stripPrefix($inputValue, 'ssl');
167 $rawValue = $this->normalizeBase64Decode($rawValue);
168
169 $method = 'aes-256-ctr';
170 $ivlen = openssl_cipher_iv_length($method);
171 $iv = substr($rawValue, 0, $ivlen);
172
173 $rawValue = substr($rawValue, $ivlen);
174
175 $value = openssl_decrypt($rawValue, $method, $this->key, 0, $iv);
176 if (! $value || $this->salt !== substr($value, - strlen($this->salt))) {
177 return $inputValue;
178 }
179
180 return substr($value, 0, - strlen($this->salt));
181 }
182
183 /** @return true */
184 protected function disableUseSssl()
185 {
186 $this->hasSsl = false;
187 return true;
188 }
189
190 /**
191 * @param string $value
192 * @return string
193 */
194 public function setKey($value)
195 {
196 $this->key = (string)$value;
197 return $this->key;
198 }
199
200 /**
201 * @param string $value
202 * @return string
203 */
204 public function setSalt($value)
205 {
206 $this->salt = (string)$value;
207 return $this->salt;
208 }
209
210 /** @return string */
211 public function getKey()
212 {
213 return $this->key;
214 }
215
216 /** @return string */
217 public function getSalt()
218 {
219 return $this->salt;
220 }
221
222 /**
223 * @param string $value
224 * @param string $type
225 * @return bool
226 */
227 protected function verifyPrefix($value, $type)
228 {
229 $type = '!' . $type . '!';
230 return substr($value, 0, strlen($this->prefix . $type)) === $this->prefix . $type;
231 }
232
233 /**
234 * @param string $value
235 * @return bool
236 */
237 public function isEncrypted($value)
238 {
239 return preg_match('@^' . preg_quote($this->prefix, '@') . '!(b64|ssl)!([a-zA-Z0-9\-_]+)$@', $value);
240 }
241
242 /** @return bool */
243 protected function isValidKeySalt()
244 {
245 $key = $this->getKey();
246 $salt = $this->getSalt();
247 return (!empty($key) && is_string($key)) && (!empty($salt) && is_string($salt));
248 }
249
250 /** @return string */
251 protected function getPrefix()
252 {
253 return $this->prefix;
254 }
255
256 /**
257 * @param string $value
258 * @return string
259 */
260 protected function setPrefix($value)
261 {
262 $this->prefix = $value;
263 return $this->prefix;
264 }
265
266 /** @return string|false */
267 private function getDefaultKey()
268 {
269 if (defined('WPSTG_ENCRYPTION_KEY') && !empty(WPSTG_ENCRYPTION_KEY) && is_string(WPSTG_ENCRYPTION_KEY)) {
270 return WPSTG_ENCRYPTION_KEY;
271 }
272
273 return false;
274 }
275
276 /** @return string|false */
277 private function getDefaultSalt()
278 {
279 if (defined('WPSTG_ENCRYPTION_SALT') && !empty(WPSTG_ENCRYPTION_SALT) && is_string(WPSTG_ENCRYPTION_SALT)) {
280 return WPSTG_ENCRYPTION_SALT;
281 }
282
283 return false;
284 }
285
286 /**
287 * @param string $value
288 * @param string $type
289 * @return string
290 */
291 private function stripPrefix($value, $type)
292 {
293 $type = '!' . $type . '!';
294 return substr($value, strlen($this->prefix . $type));
295 }
296
297 /**
298 * @param string $type
299 * @return string
300 */
301 private function setPrefixType($type)
302 {
303 return $this->prefix . '!' . $type . '!';
304 }
305
306 /**
307 * @param string $value
308 * @return string
309 */
310 private function normalizeBase64Encode($value)
311 {
312 // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
313 return str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($value));
314 }
315
316 /**
317 * @param string $value
318 * @return string
319 */
320 private function normalizeBase64Decode($value)
321 {
322 // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode
323 return base64_decode(str_replace(['-', '_'], ['+', '/'], $value));
324 }
325 }
326