PluginProbe ʕ •ᴥ•ʔ
WP STAGING – WordPress Backup, Restore, Migration & Clone / 3.8.0
WP STAGING – WordPress Backup, Restore, Migration & Clone v3.8.0
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 2 years ago Capabilities.php 2 years ago DataEncryption.php 2 years ago Nonce.php 3 years ago UniqueIdentifier.php 3 years ago
DataEncryption.php
328 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
89 $padi = $pad[$x];
90 $encrypted .= chr(ord($value[$i]) ^ ord($padi));
91 }
92
93 return $this->setPrefixType('b64') . $this->normalizeBase64Encode($encrypted);
94 }
95
96 /**
97 * @param string $inputValue
98 * @return string
99 */
100 protected function base64Decrypt($inputValue)
101 {
102 if (!$this->isValidKeySalt() || !is_string($inputValue) || $inputValue === '' || !$this->isEncrypted($inputValue) || !$this->verifyPrefix($inputValue, 'b64')) {
103 return $inputValue;
104 }
105
106 $value = $this->stripPrefix($inputValue, 'b64');
107 $mykey = $this->key . $this->salt;
108
109 // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode
110 $pad = base64_decode($mykey);
111 $encrypted = $this->normalizeBase64Decode($value);
112 $encryptedLen = strlen($encrypted);
113 $decrypted = '';
114 $x = 0;
115 for ($i = 0; $i < $encryptedLen; $i++, $x++) {
116 if (!isset($pad[$x])) {
117 $x = 0;
118 }
119
120 $padi = $pad[$x];
121 $decrypted .= chr(ord($encrypted[$i]) ^ ord($padi));
122 }
123
124 $encpad = substr($mykey, 0, 12);
125 $enclen = strlen($encpad);
126 $envpad = substr($decrypted, 0, $enclen);
127
128 if ($encpad !== $envpad) {
129 return $inputValue;
130 }
131
132 $decrypted = substr($decrypted, $enclen);
133 return $decrypted;
134 }
135
136 /**
137 * @param string|int $value
138 * @return string
139 */
140 protected function sslEncrypt($value)
141 {
142 if (!$this->isValidKeySalt() || $value === '' || !$this->hasSsl || $this->isEncrypted($value)) {
143 return $value;
144 }
145
146 $method = 'aes-256-ctr';
147 $ivlen = openssl_cipher_iv_length($method);
148 $iv = openssl_random_pseudo_bytes($ivlen);
149
150 $rawValue = openssl_encrypt($value . $this->salt, $method, $this->key, 0, $iv);
151 if (!$rawValue) {
152 return $value;
153 }
154
155 return $this->setPrefixType('ssl') . $this->normalizeBase64Encode($iv . $rawValue);
156 }
157
158 /**
159 * @param string $inputValue
160 * @return string
161 */
162 protected function sslDecrypt($inputValue)
163 {
164 if (!$this->isValidKeySalt() || !is_string($inputValue) || $inputValue === '' || !$this->hasSsl || !$this->isEncrypted($inputValue) || !$this->verifyPrefix($inputValue, 'ssl')) {
165 return $inputValue;
166 }
167
168 $rawValue = $this->stripPrefix($inputValue, 'ssl');
169 $rawValue = $this->normalizeBase64Decode($rawValue);
170
171 $method = 'aes-256-ctr';
172 $ivlen = openssl_cipher_iv_length($method);
173 $iv = substr($rawValue, 0, $ivlen);
174
175 $rawValue = substr($rawValue, $ivlen);
176
177 $value = openssl_decrypt($rawValue, $method, $this->key, 0, $iv);
178 if (! $value || $this->salt !== substr($value, - strlen($this->salt))) {
179 return $inputValue;
180 }
181
182 return substr($value, 0, - strlen($this->salt));
183 }
184
185 /** @return true */
186 protected function disableUseSssl()
187 {
188 $this->hasSsl = false;
189 return true;
190 }
191
192 /**
193 * @param string $value
194 * @return string
195 */
196 public function setKey($value)
197 {
198 $this->key = (string)$value;
199 return $this->key;
200 }
201
202 /**
203 * @param string $value
204 * @return string
205 */
206 public function setSalt($value)
207 {
208 $this->salt = (string)$value;
209 return $this->salt;
210 }
211
212 /** @return string */
213 public function getKey()
214 {
215 return $this->key;
216 }
217
218 /** @return string */
219 public function getSalt()
220 {
221 return $this->salt;
222 }
223
224 /**
225 * @param string $value
226 * @param string $type
227 * @return bool
228 */
229 protected function verifyPrefix($value, $type)
230 {
231 $type = '!' . $type . '!';
232 return substr($value, 0, strlen($this->prefix . $type)) === $this->prefix . $type;
233 }
234
235 /**
236 * @param string $value
237 * @return bool
238 */
239 public function isEncrypted($value)
240 {
241 return preg_match('@^' . preg_quote($this->prefix, '@') . '!(b64|ssl)!([a-zA-Z0-9\-_]+)$@', $value);
242 }
243
244 /** @return bool */
245 protected function isValidKeySalt()
246 {
247 $key = $this->getKey();
248 $salt = $this->getSalt();
249 return (!empty($key) && is_string($key)) && (!empty($salt) && is_string($salt));
250 }
251
252 /** @return string */
253 protected function getPrefix()
254 {
255 return $this->prefix;
256 }
257
258 /**
259 * @param string $value
260 * @return string
261 */
262 protected function setPrefix($value)
263 {
264 $this->prefix = $value;
265 return $this->prefix;
266 }
267
268 /** @return string|false */
269 private function getDefaultKey()
270 {
271 if (defined('WPSTG_ENCRYPTION_KEY') && !empty(WPSTG_ENCRYPTION_KEY) && is_string(WPSTG_ENCRYPTION_KEY)) {
272 return WPSTG_ENCRYPTION_KEY;
273 }
274
275 return false;
276 }
277
278 /** @return string|false */
279 private function getDefaultSalt()
280 {
281 if (defined('WPSTG_ENCRYPTION_SALT') && !empty(WPSTG_ENCRYPTION_SALT) && is_string(WPSTG_ENCRYPTION_SALT)) {
282 return WPSTG_ENCRYPTION_SALT;
283 }
284
285 return false;
286 }
287
288 /**
289 * @param string $value
290 * @param string $type
291 * @return string
292 */
293 private function stripPrefix($value, $type)
294 {
295 $type = '!' . $type . '!';
296 return substr($value, strlen($this->prefix . $type));
297 }
298
299 /**
300 * @param string $type
301 * @return string
302 */
303 private function setPrefixType($type)
304 {
305 return $this->prefix . '!' . $type . '!';
306 }
307
308 /**
309 * @param string $value
310 * @return string
311 */
312 private function normalizeBase64Encode($value)
313 {
314 // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
315 return str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($value));
316 }
317
318 /**
319 * @param string $value
320 * @return string
321 */
322 private function normalizeBase64Decode($value)
323 {
324 // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode
325 return base64_decode(str_replace(['-', '_'], ['+', '/'], $value));
326 }
327 }
328