Completed
Branch yet-another-batch-of-ui-fixes (371f49)
by
unknown
30:27 queued 22:46
created
core/services/encryption/openssl/OpenSSL.php 2 patches
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -120,7 +120,7 @@  discard block
 block discarded – undo
120 120
      */
121 121
     public function canUseNotice()
122 122
     {
123
-        if (! $this->openssl_installed) {
123
+        if ( ! $this->openssl_installed) {
124 124
             return esc_html__(
125 125
                 'The PHP openssl server extension is required to use Openssl encryption. Please contact your hosting provider regarding this issue.',
126 126
                 'event_espresso'
@@ -219,7 +219,7 @@  discard block
 block discarded – undo
219 219
      */
220 220
     protected function getHashAlgorithm()
221 221
     {
222
-        if (! $this->hash_algorithm) {
222
+        if ( ! $this->hash_algorithm) {
223 223
             // get installed hashing algorithms
224 224
             $hash_algorithms = hash_algos();
225 225
             // filter array for "sha" algorithms
Please login to merge, or discard this patch.
Indentation   +262 added lines, -262 removed lines patch added patch discarded remove patch
@@ -17,266 +17,266 @@
 block discarded – undo
17 17
  */
18 18
 abstract class OpenSSL implements EncryptionMethodInterface
19 19
 {
20
-    /**
21
-     * the default OPENSSL digest method to use
22
-     */
23
-    const DEFAULT_DIGEST_METHOD = 'sha512';
24
-
25
-    /**
26
-     * separates the encrypted text from the initialization vector
27
-     */
28
-    const IV_DELIMITER = ':iv:';
29
-
30
-    /**
31
-     * @var Base64Encoder
32
-     */
33
-    protected $base64_encoder;
34
-
35
-    /**
36
-     * @var CipherMethod
37
-     */
38
-    protected $cipher_method;
39
-
40
-    /**
41
-     * @var array $digest_methods
42
-     */
43
-    private $digest_methods = [];
44
-
45
-    /**
46
-     * @var EncryptionKeyManagerInterface
47
-     */
48
-    protected $encryption_key_manager;
49
-
50
-    /**
51
-     * @var boolean
52
-     */
53
-    private $openssl_installed;
54
-
55
-    /**
56
-     * @var string
57
-     */
58
-    private $min_php_version;
59
-
60
-    /**
61
-     * @var string
62
-     */
63
-    private $hash_algorithm;
64
-
65
-
66
-    /**
67
-     * To use custom a cipher method and/or encryption keys:
68
-     *  - extend this class
69
-     *  - configure a new CipherMethod / EncryptionKeyManager in the constructor
70
-     *  - pass those to this constructor, like so:
71
-     *
72
-     *      public function __construct(Base64Encoder $base64_encoder) {
73
-     *          parent::__construct(
74
-     *              $base64_encoder,
75
-     *              new CipherMethod(CIPHER_METHOD, CIPHER_METHOD_OPTION_NAME)
76
-     *              new EncryptionKeyManager(CUSTOM_KEY_ID, CUSTOM_KEYS_OPTION_NAME)
77
-     *          );
78
-     *      }
79
-     *
80
-     * @param Base64Encoder                      $base64_encoder
81
-     * @param CipherMethod                       $cipher_method
82
-     * @param EncryptionKeyManagerInterface|null $encryption_key_manager
83
-     * @param string                             $min_php_version
84
-     */
85
-    protected function __construct(
86
-        Base64Encoder $base64_encoder,
87
-        CipherMethod $cipher_method,
88
-        EncryptionKeyManagerInterface $encryption_key_manager,
89
-        $min_php_version
90
-    ) {
91
-        $this->base64_encoder         = $base64_encoder;
92
-        $this->cipher_method          = $cipher_method;
93
-        $this->encryption_key_manager = $encryption_key_manager;
94
-        $this->min_php_version        = $min_php_version;
95
-        $this->openssl_installed      = extension_loaded('openssl');
96
-    }
97
-
98
-
99
-    /**
100
-     * @return bool
101
-     */
102
-    public function isCryptographicallySecure()
103
-    {
104
-        return true;
105
-    }
106
-
107
-
108
-    /**
109
-     * @return bool
110
-     */
111
-    public function canUse()
112
-    {
113
-        return $this->openssl_installed && version_compare(PHP_VERSION, $this->min_php_version, '>=');
114
-    }
115
-
116
-
117
-    /**
118
-     * @return string
119
-     */
120
-    public function canUseNotice()
121
-    {
122
-        if (! $this->openssl_installed) {
123
-            return esc_html__(
124
-                'The PHP openssl server extension is required to use Openssl encryption. Please contact your hosting provider regarding this issue.',
125
-                'event_espresso'
126
-            );
127
-        }
128
-        if (version_compare(PHP_VERSION, $this->min_php_version, '<')) {
129
-            return sprintf(
130
-                esc_html__(
131
-                    'PHP version %1$s or greater is required to use Openssl encryption. Please contact your hosting provider regarding this issue.',
132
-                    'event_espresso'
133
-                ),
134
-                $this->min_php_version
135
-            );
136
-        }
137
-        return sprintf(
138
-            esc_html__('OpenSSL v1 encryption using %1$s is available for use.', 'event_espresso'),
139
-            OpenSSLv1::CIPHER_METHOD
140
-        );
141
-    }
142
-
143
-
144
-    /**
145
-     * Computes the digest hash value using the specified digest method.
146
-     * If that digest method fails to produce a valid hash value,
147
-     * then we'll grab the next digest method and recursively try again until something works.
148
-     *
149
-     * @param string $encryption_key
150
-     * @param string $digest_method
151
-     * @param bool   $return_raw_data
152
-     * @return string
153
-     * @throws RuntimeException
154
-     */
155
-    protected function getDigestHashValue(
156
-        $encryption_key,
157
-        $digest_method = OpenSSL::DEFAULT_DIGEST_METHOD,
158
-        $return_raw_data = false
159
-    ) {
160
-        $digest_hash_value = openssl_digest($encryption_key, $digest_method, $return_raw_data);
161
-        if ($digest_hash_value === false) {
162
-            return $this->getDigestHashValue($this->getDigestMethod());
163
-        }
164
-        return $digest_hash_value;
165
-    }
166
-
167
-
168
-    /**
169
-     * Returns the NEXT element in the $digest_methods array.
170
-     * If the $digest_methods array is empty, then we populate it
171
-     * with the available values returned from openssl_get_md_methods().
172
-     *
173
-     * @return string
174
-     * @throws RuntimeException
175
-     */
176
-    private function getDigestMethod()
177
-    {
178
-        $digest_method = prev($this->digest_methods);
179
-        if (empty($this->digest_methods)) {
180
-            $this->digest_methods = openssl_get_md_methods();
181
-            $digest_method        = end($this->digest_methods);
182
-        }
183
-        if ($digest_method === false) {
184
-            throw new RuntimeException(
185
-                esc_html__(
186
-                    'OpenSSL support appears to be enabled on the server, but no digest methods are available. Please contact the server administrator.',
187
-                    'event_espresso'
188
-                )
189
-            );
190
-        }
191
-        return $digest_method;
192
-    }
193
-
194
-
195
-    /**
196
-     * @param string $encryption_key
197
-     * @return int
198
-     */
199
-    protected function calculateHashLength($encryption_key)
200
-    {
201
-        // get existing key length
202
-        $prev_key_length = $this->encryption_key_manager->keyLength();
203
-        // set it to something HUGE
204
-        $this->encryption_key_manager->setKeyLength(512);
205
-        // generate a new weak key, which should just be a really long random string
206
-        $test_text = $this->encryption_key_manager->generateEncryptionKey(false);
207
-        // generate a hash using our test string and our real $encryption_key
208
-        $hash = hash_hmac($this->getHashAlgorithm(), $test_text, $encryption_key, true);
209
-        // reset key length back to original value
210
-        $this->encryption_key_manager->setKeyLength($prev_key_length);
211
-        // return the length of the hash
212
-        return strlen($hash);
213
-    }
214
-
215
-
216
-    /**
217
-     * @return string
218
-     */
219
-    protected function getHashAlgorithm()
220
-    {
221
-        if (! $this->hash_algorithm) {
222
-            // get installed hashing algorithms
223
-            $hash_algorithms = hash_algos();
224
-            // filter array for "sha" algorithms
225
-            $hash_algorithms = preg_grep('/^sha\d{3}$/i', $hash_algorithms);
226
-            // if no sha algorithms are installed, then just use md5
227
-            if (empty($hash_algorithms)) {
228
-                $this->hash_algorithm = 'md5';
229
-                return $this->hash_algorithm;
230
-            }
231
-            // sort ascending using "natural ordering"
232
-            sort($hash_algorithms, SORT_NATURAL);
233
-            // return last item from array, which should be the strongest installed sha hash
234
-            $this->hash_algorithm = array_pop($hash_algorithms);
235
-        }
236
-        return $this->hash_algorithm;
237
-    }
238
-
239
-
240
-    /**
241
-     * @param string $encrypted_text
242
-     * @throws RuntimeException
243
-     */
244
-    protected function validateEncryption($encrypted_text)
245
-    {
246
-        if ($encrypted_text === false) {
247
-            throw new RuntimeException(
248
-                sprintf(
249
-                    esc_html__('The following error occurred during OpenSSL encryption: %1$s', 'event_espresso'),
250
-                    $this->getOpenSslError()
251
-                )
252
-            );
253
-        }
254
-    }
255
-
256
-
257
-    /**
258
-     * @return false|string
259
-     */
260
-    private function getOpenSslError()
261
-    {
262
-        $error = openssl_error_string();
263
-        return $error ?: esc_html__('Unknown Error', 'event_espresso');
264
-    }
265
-
266
-
267
-    /**
268
-     * @param string $encrypted_text
269
-     * @throws RuntimeException
270
-     */
271
-    protected function validateDecryption($encrypted_text)
272
-    {
273
-        if ($encrypted_text === false) {
274
-            throw new RuntimeException(
275
-                sprintf(
276
-                    esc_html__('OpenSSL decryption failed for the following reason: %1$s', 'event_espresso'),
277
-                    $this->getOpenSslError()
278
-                )
279
-            );
280
-        }
281
-    }
20
+	/**
21
+	 * the default OPENSSL digest method to use
22
+	 */
23
+	const DEFAULT_DIGEST_METHOD = 'sha512';
24
+
25
+	/**
26
+	 * separates the encrypted text from the initialization vector
27
+	 */
28
+	const IV_DELIMITER = ':iv:';
29
+
30
+	/**
31
+	 * @var Base64Encoder
32
+	 */
33
+	protected $base64_encoder;
34
+
35
+	/**
36
+	 * @var CipherMethod
37
+	 */
38
+	protected $cipher_method;
39
+
40
+	/**
41
+	 * @var array $digest_methods
42
+	 */
43
+	private $digest_methods = [];
44
+
45
+	/**
46
+	 * @var EncryptionKeyManagerInterface
47
+	 */
48
+	protected $encryption_key_manager;
49
+
50
+	/**
51
+	 * @var boolean
52
+	 */
53
+	private $openssl_installed;
54
+
55
+	/**
56
+	 * @var string
57
+	 */
58
+	private $min_php_version;
59
+
60
+	/**
61
+	 * @var string
62
+	 */
63
+	private $hash_algorithm;
64
+
65
+
66
+	/**
67
+	 * To use custom a cipher method and/or encryption keys:
68
+	 *  - extend this class
69
+	 *  - configure a new CipherMethod / EncryptionKeyManager in the constructor
70
+	 *  - pass those to this constructor, like so:
71
+	 *
72
+	 *      public function __construct(Base64Encoder $base64_encoder) {
73
+	 *          parent::__construct(
74
+	 *              $base64_encoder,
75
+	 *              new CipherMethod(CIPHER_METHOD, CIPHER_METHOD_OPTION_NAME)
76
+	 *              new EncryptionKeyManager(CUSTOM_KEY_ID, CUSTOM_KEYS_OPTION_NAME)
77
+	 *          );
78
+	 *      }
79
+	 *
80
+	 * @param Base64Encoder                      $base64_encoder
81
+	 * @param CipherMethod                       $cipher_method
82
+	 * @param EncryptionKeyManagerInterface|null $encryption_key_manager
83
+	 * @param string                             $min_php_version
84
+	 */
85
+	protected function __construct(
86
+		Base64Encoder $base64_encoder,
87
+		CipherMethod $cipher_method,
88
+		EncryptionKeyManagerInterface $encryption_key_manager,
89
+		$min_php_version
90
+	) {
91
+		$this->base64_encoder         = $base64_encoder;
92
+		$this->cipher_method          = $cipher_method;
93
+		$this->encryption_key_manager = $encryption_key_manager;
94
+		$this->min_php_version        = $min_php_version;
95
+		$this->openssl_installed      = extension_loaded('openssl');
96
+	}
97
+
98
+
99
+	/**
100
+	 * @return bool
101
+	 */
102
+	public function isCryptographicallySecure()
103
+	{
104
+		return true;
105
+	}
106
+
107
+
108
+	/**
109
+	 * @return bool
110
+	 */
111
+	public function canUse()
112
+	{
113
+		return $this->openssl_installed && version_compare(PHP_VERSION, $this->min_php_version, '>=');
114
+	}
115
+
116
+
117
+	/**
118
+	 * @return string
119
+	 */
120
+	public function canUseNotice()
121
+	{
122
+		if (! $this->openssl_installed) {
123
+			return esc_html__(
124
+				'The PHP openssl server extension is required to use Openssl encryption. Please contact your hosting provider regarding this issue.',
125
+				'event_espresso'
126
+			);
127
+		}
128
+		if (version_compare(PHP_VERSION, $this->min_php_version, '<')) {
129
+			return sprintf(
130
+				esc_html__(
131
+					'PHP version %1$s or greater is required to use Openssl encryption. Please contact your hosting provider regarding this issue.',
132
+					'event_espresso'
133
+				),
134
+				$this->min_php_version
135
+			);
136
+		}
137
+		return sprintf(
138
+			esc_html__('OpenSSL v1 encryption using %1$s is available for use.', 'event_espresso'),
139
+			OpenSSLv1::CIPHER_METHOD
140
+		);
141
+	}
142
+
143
+
144
+	/**
145
+	 * Computes the digest hash value using the specified digest method.
146
+	 * If that digest method fails to produce a valid hash value,
147
+	 * then we'll grab the next digest method and recursively try again until something works.
148
+	 *
149
+	 * @param string $encryption_key
150
+	 * @param string $digest_method
151
+	 * @param bool   $return_raw_data
152
+	 * @return string
153
+	 * @throws RuntimeException
154
+	 */
155
+	protected function getDigestHashValue(
156
+		$encryption_key,
157
+		$digest_method = OpenSSL::DEFAULT_DIGEST_METHOD,
158
+		$return_raw_data = false
159
+	) {
160
+		$digest_hash_value = openssl_digest($encryption_key, $digest_method, $return_raw_data);
161
+		if ($digest_hash_value === false) {
162
+			return $this->getDigestHashValue($this->getDigestMethod());
163
+		}
164
+		return $digest_hash_value;
165
+	}
166
+
167
+
168
+	/**
169
+	 * Returns the NEXT element in the $digest_methods array.
170
+	 * If the $digest_methods array is empty, then we populate it
171
+	 * with the available values returned from openssl_get_md_methods().
172
+	 *
173
+	 * @return string
174
+	 * @throws RuntimeException
175
+	 */
176
+	private function getDigestMethod()
177
+	{
178
+		$digest_method = prev($this->digest_methods);
179
+		if (empty($this->digest_methods)) {
180
+			$this->digest_methods = openssl_get_md_methods();
181
+			$digest_method        = end($this->digest_methods);
182
+		}
183
+		if ($digest_method === false) {
184
+			throw new RuntimeException(
185
+				esc_html__(
186
+					'OpenSSL support appears to be enabled on the server, but no digest methods are available. Please contact the server administrator.',
187
+					'event_espresso'
188
+				)
189
+			);
190
+		}
191
+		return $digest_method;
192
+	}
193
+
194
+
195
+	/**
196
+	 * @param string $encryption_key
197
+	 * @return int
198
+	 */
199
+	protected function calculateHashLength($encryption_key)
200
+	{
201
+		// get existing key length
202
+		$prev_key_length = $this->encryption_key_manager->keyLength();
203
+		// set it to something HUGE
204
+		$this->encryption_key_manager->setKeyLength(512);
205
+		// generate a new weak key, which should just be a really long random string
206
+		$test_text = $this->encryption_key_manager->generateEncryptionKey(false);
207
+		// generate a hash using our test string and our real $encryption_key
208
+		$hash = hash_hmac($this->getHashAlgorithm(), $test_text, $encryption_key, true);
209
+		// reset key length back to original value
210
+		$this->encryption_key_manager->setKeyLength($prev_key_length);
211
+		// return the length of the hash
212
+		return strlen($hash);
213
+	}
214
+
215
+
216
+	/**
217
+	 * @return string
218
+	 */
219
+	protected function getHashAlgorithm()
220
+	{
221
+		if (! $this->hash_algorithm) {
222
+			// get installed hashing algorithms
223
+			$hash_algorithms = hash_algos();
224
+			// filter array for "sha" algorithms
225
+			$hash_algorithms = preg_grep('/^sha\d{3}$/i', $hash_algorithms);
226
+			// if no sha algorithms are installed, then just use md5
227
+			if (empty($hash_algorithms)) {
228
+				$this->hash_algorithm = 'md5';
229
+				return $this->hash_algorithm;
230
+			}
231
+			// sort ascending using "natural ordering"
232
+			sort($hash_algorithms, SORT_NATURAL);
233
+			// return last item from array, which should be the strongest installed sha hash
234
+			$this->hash_algorithm = array_pop($hash_algorithms);
235
+		}
236
+		return $this->hash_algorithm;
237
+	}
238
+
239
+
240
+	/**
241
+	 * @param string $encrypted_text
242
+	 * @throws RuntimeException
243
+	 */
244
+	protected function validateEncryption($encrypted_text)
245
+	{
246
+		if ($encrypted_text === false) {
247
+			throw new RuntimeException(
248
+				sprintf(
249
+					esc_html__('The following error occurred during OpenSSL encryption: %1$s', 'event_espresso'),
250
+					$this->getOpenSslError()
251
+				)
252
+			);
253
+		}
254
+	}
255
+
256
+
257
+	/**
258
+	 * @return false|string
259
+	 */
260
+	private function getOpenSslError()
261
+	{
262
+		$error = openssl_error_string();
263
+		return $error ?: esc_html__('Unknown Error', 'event_espresso');
264
+	}
265
+
266
+
267
+	/**
268
+	 * @param string $encrypted_text
269
+	 * @throws RuntimeException
270
+	 */
271
+	protected function validateDecryption($encrypted_text)
272
+	{
273
+		if ($encrypted_text === false) {
274
+			throw new RuntimeException(
275
+				sprintf(
276
+					esc_html__('OpenSSL decryption failed for the following reason: %1$s', 'event_espresso'),
277
+					$this->getOpenSslError()
278
+				)
279
+			);
280
+		}
281
+	}
282 282
 }
Please login to merge, or discard this patch.
core/services/json/JsonDataNodeHandler.php 2 patches
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -78,7 +78,7 @@  discard block
 block discarded – undo
78 78
                 if ($child_node instanceof PrimaryJsonDataNode || $depth > 512) {
79 79
                     continue;
80 80
                 }
81
-                $data[ $child_node_name ] = $child_node instanceof JsonDataNode
81
+                $data[$child_node_name] = $child_node instanceof JsonDataNode
82 82
                     // feed data node back into this function
83 83
                     ? $this->initializeDataNodes($child_node, $depth)
84 84
                     // or assign data directly
@@ -94,15 +94,15 @@  discard block
 block discarded – undo
94 94
      */
95 95
     public function printDataNode()
96 96
     {
97
-        if (!$this->primary_data_node instanceof PrimaryJsonDataNode) {
97
+        if ( ! $this->primary_data_node instanceof PrimaryJsonDataNode) {
98 98
             return;
99 99
         }
100 100
         // validate that the domain, node name, and target script are set
101 101
         $domain = $this->primary_data_node->domain();
102 102
         $node_name = $this->primary_data_node->nodeName();
103
-        $data_valid =  $this->validator->validateCriticalProperty($domain, 'domain route', false)
103
+        $data_valid = $this->validator->validateCriticalProperty($domain, 'domain route', false)
104 104
                        && $this->validator->validateCriticalProperty($node_name, 'node name', false);
105
-        if (! $data_valid) {
105
+        if ( ! $data_valid) {
106 106
             return;
107 107
         }
108 108
         // initialize and parse data from primary data node
@@ -132,7 +132,7 @@  discard block
 block discarded – undo
132 132
             $this->setPrimaryDataNode($data_node);
133 133
         }
134 134
         // and don't allow other nodes to be set until a primary is set
135
-        if (! $this->primary_data_node instanceof PrimaryJsonDataNode) {
135
+        if ( ! $this->primary_data_node instanceof PrimaryJsonDataNode) {
136 136
             throw new DomainException(
137 137
                 esc_html__(
138 138
                     'A PrimaryJsonDataNode needs to be set before data nodes can be added.',
Please login to merge, or discard this patch.
Indentation   +123 added lines, -123 removed lines patch added patch discarded remove patch
@@ -17,127 +17,127 @@
 block discarded – undo
17 17
  */
18 18
 class JsonDataNodeHandler
19 19
 {
20
-    /**
21
-     * @var PrimaryJsonDataNode $primary_data_node
22
-     */
23
-    private $primary_data_node;
24
-
25
-    /**
26
-     * @var JsonDataNodeValidator $validator
27
-     */
28
-    private $validator;
29
-
30
-
31
-    /**
32
-     * @param JsonDataNodeValidator $validator
33
-     */
34
-    public function __construct(JsonDataNodeValidator $validator)
35
-    {
36
-        $this->validator = $validator;
37
-    }
38
-
39
-
40
-    /**
41
-     * @param JsonDataNode $data_node
42
-     * @throws DomainException
43
-     */
44
-    public function addDataNode(JsonDataNode $data_node)
45
-    {
46
-        if ($data_node->isNotInitialized()) {
47
-            $this->validatePrimaryDataNode($data_node);
48
-            $this->primary_data_node->addDataNode($data_node);
49
-        }
50
-    }
51
-
52
-
53
-    /**
54
-     * @param PrimaryJsonDataNode $primary_data_node
55
-     */
56
-    public function setPrimaryDataNode(PrimaryJsonDataNode $primary_data_node)
57
-    {
58
-        $this->primary_data_node = $primary_data_node;
59
-    }
60
-
61
-
62
-    /**
63
-     * @param JsonDataNode $data_node
64
-     * @param int                $depth
65
-     * @return array
66
-     */
67
-    private function initializeDataNodes(JsonDataNode $data_node, int $depth = 0): array
68
-    {
69
-        $depth++;
70
-        $data = [];
71
-        // initialize the data node if not done already
72
-        if ($data_node->isNotInitialized()) {
73
-            $data_node->initialize();
74
-            // loop thru the data node's data array
75
-            foreach ($data_node->data(true) as $child_node_name => $child_node) {
76
-                // don't parse node if it's the primary, OR if depth has exceeded wp_json_encode() limit
77
-                if ($child_node instanceof PrimaryJsonDataNode || $depth > 512) {
78
-                    continue;
79
-                }
80
-                $data[ $child_node_name ] = $child_node instanceof JsonDataNode
81
-                    // feed data node back into this function
82
-                    ? $this->initializeDataNodes($child_node, $depth)
83
-                    // or assign data directly
84
-                    : $child_node;
85
-            }
86
-        }
87
-        return $data;
88
-    }
89
-
90
-
91
-    /**
92
-     * @throws DomainException
93
-     */
94
-    public function printDataNode()
95
-    {
96
-        if (!$this->primary_data_node instanceof PrimaryJsonDataNode) {
97
-            return;
98
-        }
99
-        // validate that the domain, node name, and target script are set
100
-        $domain = $this->primary_data_node->domain();
101
-        $node_name = $this->primary_data_node->nodeName();
102
-        $data_valid =  $this->validator->validateCriticalProperty($domain, 'domain route', false)
103
-                       && $this->validator->validateCriticalProperty($node_name, 'node name', false);
104
-        if (! $data_valid) {
105
-            return;
106
-        }
107
-        // initialize and parse data from primary data node
108
-        $data = $this->initializeDataNodes($this->primary_data_node);
109
-        // this prepends the current domain "use case" to the front of the array
110
-        $data = ['domain' => $domain] + $data;
111
-        // add legacy i18n strings
112
-        $data['eei18n'] = EE_Registry::$i18n_js_strings;
113
-        // and finally, print the JSON encoded data to the DOM
114
-        printf(
115
-            "<script type='text/javascript' id='%s'>\nvar %s = %s\n</script>\n",
116
-            $node_name,
117
-            $node_name,
118
-            json_encode($data)
119
-        );
120
-    }
121
-
122
-
123
-    /**
124
-     * @param JsonDataNode $data_node
125
-     * @throws DomainException
126
-     */
127
-    private function validatePrimaryDataNode(JsonDataNode $data_node)
128
-    {
129
-        // set primary data node if that's what the incoming node is
130
-        if ($data_node instanceof PrimaryJsonDataNode) {
131
-            $this->setPrimaryDataNode($data_node);
132
-        }
133
-        // and don't allow other nodes to be set until a primary is set
134
-        if (! $this->primary_data_node instanceof PrimaryJsonDataNode) {
135
-            throw new DomainException(
136
-                esc_html__(
137
-                    'A PrimaryJsonDataNode needs to be set before data nodes can be added.',
138
-                    'event_espresso'
139
-                )
140
-            );
141
-        }
142
-    }
20
+	/**
21
+	 * @var PrimaryJsonDataNode $primary_data_node
22
+	 */
23
+	private $primary_data_node;
24
+
25
+	/**
26
+	 * @var JsonDataNodeValidator $validator
27
+	 */
28
+	private $validator;
29
+
30
+
31
+	/**
32
+	 * @param JsonDataNodeValidator $validator
33
+	 */
34
+	public function __construct(JsonDataNodeValidator $validator)
35
+	{
36
+		$this->validator = $validator;
37
+	}
38
+
39
+
40
+	/**
41
+	 * @param JsonDataNode $data_node
42
+	 * @throws DomainException
43
+	 */
44
+	public function addDataNode(JsonDataNode $data_node)
45
+	{
46
+		if ($data_node->isNotInitialized()) {
47
+			$this->validatePrimaryDataNode($data_node);
48
+			$this->primary_data_node->addDataNode($data_node);
49
+		}
50
+	}
51
+
52
+
53
+	/**
54
+	 * @param PrimaryJsonDataNode $primary_data_node
55
+	 */
56
+	public function setPrimaryDataNode(PrimaryJsonDataNode $primary_data_node)
57
+	{
58
+		$this->primary_data_node = $primary_data_node;
59
+	}
60
+
61
+
62
+	/**
63
+	 * @param JsonDataNode $data_node
64
+	 * @param int                $depth
65
+	 * @return array
66
+	 */
67
+	private function initializeDataNodes(JsonDataNode $data_node, int $depth = 0): array
68
+	{
69
+		$depth++;
70
+		$data = [];
71
+		// initialize the data node if not done already
72
+		if ($data_node->isNotInitialized()) {
73
+			$data_node->initialize();
74
+			// loop thru the data node's data array
75
+			foreach ($data_node->data(true) as $child_node_name => $child_node) {
76
+				// don't parse node if it's the primary, OR if depth has exceeded wp_json_encode() limit
77
+				if ($child_node instanceof PrimaryJsonDataNode || $depth > 512) {
78
+					continue;
79
+				}
80
+				$data[ $child_node_name ] = $child_node instanceof JsonDataNode
81
+					// feed data node back into this function
82
+					? $this->initializeDataNodes($child_node, $depth)
83
+					// or assign data directly
84
+					: $child_node;
85
+			}
86
+		}
87
+		return $data;
88
+	}
89
+
90
+
91
+	/**
92
+	 * @throws DomainException
93
+	 */
94
+	public function printDataNode()
95
+	{
96
+		if (!$this->primary_data_node instanceof PrimaryJsonDataNode) {
97
+			return;
98
+		}
99
+		// validate that the domain, node name, and target script are set
100
+		$domain = $this->primary_data_node->domain();
101
+		$node_name = $this->primary_data_node->nodeName();
102
+		$data_valid =  $this->validator->validateCriticalProperty($domain, 'domain route', false)
103
+					   && $this->validator->validateCriticalProperty($node_name, 'node name', false);
104
+		if (! $data_valid) {
105
+			return;
106
+		}
107
+		// initialize and parse data from primary data node
108
+		$data = $this->initializeDataNodes($this->primary_data_node);
109
+		// this prepends the current domain "use case" to the front of the array
110
+		$data = ['domain' => $domain] + $data;
111
+		// add legacy i18n strings
112
+		$data['eei18n'] = EE_Registry::$i18n_js_strings;
113
+		// and finally, print the JSON encoded data to the DOM
114
+		printf(
115
+			"<script type='text/javascript' id='%s'>\nvar %s = %s\n</script>\n",
116
+			$node_name,
117
+			$node_name,
118
+			json_encode($data)
119
+		);
120
+	}
121
+
122
+
123
+	/**
124
+	 * @param JsonDataNode $data_node
125
+	 * @throws DomainException
126
+	 */
127
+	private function validatePrimaryDataNode(JsonDataNode $data_node)
128
+	{
129
+		// set primary data node if that's what the incoming node is
130
+		if ($data_node instanceof PrimaryJsonDataNode) {
131
+			$this->setPrimaryDataNode($data_node);
132
+		}
133
+		// and don't allow other nodes to be set until a primary is set
134
+		if (! $this->primary_data_node instanceof PrimaryJsonDataNode) {
135
+			throw new DomainException(
136
+				esc_html__(
137
+					'A PrimaryJsonDataNode needs to be set before data nodes can be added.',
138
+					'event_espresso'
139
+				)
140
+			);
141
+		}
142
+	}
143 143
 }
Please login to merge, or discard this patch.
core/services/encryption/openssl/OpenSSLv1.php 2 patches
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -122,7 +122,7 @@
 block discarded – undo
122 122
         // hash the raw encrypted text
123 123
         $hmac = hash_hmac($this->getHashAlgorithm(), $encrypted_text, $key, true);
124 124
         // concatenate everything into one big string and encode it again
125
-        return $this->base64_encoder->encodeString($iv . $hmac . $encrypted_text);
125
+        return $this->base64_encoder->encodeString($iv.$hmac.$encrypted_text);
126 126
     }
127 127
 
128 128
 
Please login to merge, or discard this patch.
Indentation   +142 added lines, -142 removed lines patch added patch discarded remove patch
@@ -17,155 +17,155 @@
 block discarded – undo
17 17
  */
18 18
 class OpenSSLv1 extends OpenSSL
19 19
 {
20
-    /**
21
-     * name used for a default encryption key in case no others are set
22
-     */
23
-    const DEFAULT_ENCRYPTION_KEY_ID = 'default_openssl_v1_key';
20
+	/**
21
+	 * name used for a default encryption key in case no others are set
22
+	 */
23
+	const DEFAULT_ENCRYPTION_KEY_ID = 'default_openssl_v1_key';
24 24
 
25
-    /**
26
-     * name used for saving encryption keys to the wp_options table
27
-     */
28
-    const ENCRYPTION_KEYS_OPTION_NAME = 'ee_openssl_v1_encryption_keys';
25
+	/**
26
+	 * name used for saving encryption keys to the wp_options table
27
+	 */
28
+	const ENCRYPTION_KEYS_OPTION_NAME = 'ee_openssl_v1_encryption_keys';
29 29
 
30
-    /**
31
-     * the OPENSSL cipher method used
32
-     */
33
-    const CIPHER_METHOD = 'aes-128-cbc';
30
+	/**
31
+	 * the OPENSSL cipher method used
32
+	 */
33
+	const CIPHER_METHOD = 'aes-128-cbc';
34 34
 
35
-    /**
36
-     * WP "options_name" used to store a verified available cipher method
37
-     */
38
-    const CIPHER_METHOD_OPTION_NAME = 'ee_openssl_v1_cipher_method';
35
+	/**
36
+	 * WP "options_name" used to store a verified available cipher method
37
+	 */
38
+	const CIPHER_METHOD_OPTION_NAME = 'ee_openssl_v1_cipher_method';
39 39
 
40 40
 
41
-    /**
42
-     * To use custom a cipher method and/or encryption keys and/or minimum PHP version:
43
-     *  - extend this class
44
-     *  - configure a new CipherMethod / EncryptionKeyManager in the constructor
45
-     *  - pass those to this constructor, like so:
46
-     *
47
-     *      public function __construct(Base64Encoder $base64_encoder) {
48
-     *          parent::__construct(
49
-     *              $base64_encoder,
50
-     *              new CipherMethod(CIPHER_METHOD, CIPHER_METHOD_OPTION_NAME),
51
-     *              new EncryptionKeyManager(CUSTOM_KEY_ID, CUSTOM_KEYS_OPTION_NAME),
52
-     *              '7.1.0'
53
-     *          );
54
-     *      }
55
-     *
56
-     * @param Base64Encoder                      $base64_encoder
57
-     * @param CipherMethod|null                  $cipher_method
58
-     * @param EncryptionKeyManagerInterface|null $encryption_key_manager
59
-     * @param string                             $min_php_version defaults to 5.3.0 (when openssl added)
60
-     */
61
-    public function __construct(
62
-        Base64Encoder $base64_encoder,
63
-        CipherMethod $cipher_method = null,
64
-        EncryptionKeyManagerInterface $encryption_key_manager = null,
65
-        $min_php_version = '5.3.0'
66
-    ) {
67
-        parent::__construct(
68
-            $base64_encoder,
69
-            $cipher_method instanceof CipherMethod
70
-                ? $cipher_method
71
-                : new CipherMethod(
72
-                    OpenSSLv1::CIPHER_METHOD,
73
-                    OpenSSLv1::CIPHER_METHOD_OPTION_NAME
74
-                ),
75
-            $encryption_key_manager instanceof EncryptionKeyManager
76
-                ? $encryption_key_manager
77
-                : new EncryptionKeyManager(
78
-                    $base64_encoder,
79
-                    OpenSSLv1::DEFAULT_ENCRYPTION_KEY_ID,
80
-                    OpenSSLv1::ENCRYPTION_KEYS_OPTION_NAME
81
-                ),
82
-            $min_php_version
83
-        );
84
-    }
41
+	/**
42
+	 * To use custom a cipher method and/or encryption keys and/or minimum PHP version:
43
+	 *  - extend this class
44
+	 *  - configure a new CipherMethod / EncryptionKeyManager in the constructor
45
+	 *  - pass those to this constructor, like so:
46
+	 *
47
+	 *      public function __construct(Base64Encoder $base64_encoder) {
48
+	 *          parent::__construct(
49
+	 *              $base64_encoder,
50
+	 *              new CipherMethod(CIPHER_METHOD, CIPHER_METHOD_OPTION_NAME),
51
+	 *              new EncryptionKeyManager(CUSTOM_KEY_ID, CUSTOM_KEYS_OPTION_NAME),
52
+	 *              '7.1.0'
53
+	 *          );
54
+	 *      }
55
+	 *
56
+	 * @param Base64Encoder                      $base64_encoder
57
+	 * @param CipherMethod|null                  $cipher_method
58
+	 * @param EncryptionKeyManagerInterface|null $encryption_key_manager
59
+	 * @param string                             $min_php_version defaults to 5.3.0 (when openssl added)
60
+	 */
61
+	public function __construct(
62
+		Base64Encoder $base64_encoder,
63
+		CipherMethod $cipher_method = null,
64
+		EncryptionKeyManagerInterface $encryption_key_manager = null,
65
+		$min_php_version = '5.3.0'
66
+	) {
67
+		parent::__construct(
68
+			$base64_encoder,
69
+			$cipher_method instanceof CipherMethod
70
+				? $cipher_method
71
+				: new CipherMethod(
72
+					OpenSSLv1::CIPHER_METHOD,
73
+					OpenSSLv1::CIPHER_METHOD_OPTION_NAME
74
+				),
75
+			$encryption_key_manager instanceof EncryptionKeyManager
76
+				? $encryption_key_manager
77
+				: new EncryptionKeyManager(
78
+					$base64_encoder,
79
+					OpenSSLv1::DEFAULT_ENCRYPTION_KEY_ID,
80
+					OpenSSLv1::ENCRYPTION_KEYS_OPTION_NAME
81
+				),
82
+			$min_php_version
83
+		);
84
+	}
85 85
 
86 86
 
87
-    /**
88
-     * encrypts data
89
-     *
90
-     * @param string $text_to_encrypt           - the text to be encrypted
91
-     * @param string $encryption_key_identifier - cryptographically secure passphrase. will generate if necessary
92
-     * @return string
93
-     */
94
-    public function encrypt($text_to_encrypt, $encryption_key_identifier = '')
95
-    {
96
-        $cipher_method  = $this->cipher_method->getCipherMethod();
97
-        $encryption_key = $this->encryption_key_manager->getEncryptionKey($encryption_key_identifier);
98
-        // get initialization vector size
99
-        $iv_length = openssl_cipher_iv_length($cipher_method);
100
-        // generate initialization vector.
101
-        // The second parameter ("crypto_strong") is passed by reference,
102
-        // and is used to determines if the algorithm used was "cryptographically strong"
103
-        // openssl_random_pseudo_bytes() will toggle it to either true or false
104
-        $iv = openssl_random_pseudo_bytes($iv_length, $is_strong);
105
-        if ($iv === false || $is_strong === false) {
106
-            throw new RuntimeException(
107
-                esc_html__('Failed to generate OpenSSL initialization vector.', 'event_espresso')
108
-            );
109
-        }
110
-        $key = $this->getDigestHashValue($encryption_key);
111
-        // encrypt it
112
-        $encrypted_text = openssl_encrypt(
113
-            $this->base64_encoder->encodeString($text_to_encrypt), // encode to remove special characters
114
-            $cipher_method,
115
-            $key,
116
-            0,
117
-            $iv
118
-        );
119
-        $this->validateEncryption($encrypted_text);
120
-        $encrypted_text = trim($encrypted_text);
121
-        // hash the raw encrypted text
122
-        $hmac = hash_hmac($this->getHashAlgorithm(), $encrypted_text, $key, true);
123
-        // concatenate everything into one big string and encode it again
124
-        return $this->base64_encoder->encodeString($iv . $hmac . $encrypted_text);
125
-    }
87
+	/**
88
+	 * encrypts data
89
+	 *
90
+	 * @param string $text_to_encrypt           - the text to be encrypted
91
+	 * @param string $encryption_key_identifier - cryptographically secure passphrase. will generate if necessary
92
+	 * @return string
93
+	 */
94
+	public function encrypt($text_to_encrypt, $encryption_key_identifier = '')
95
+	{
96
+		$cipher_method  = $this->cipher_method->getCipherMethod();
97
+		$encryption_key = $this->encryption_key_manager->getEncryptionKey($encryption_key_identifier);
98
+		// get initialization vector size
99
+		$iv_length = openssl_cipher_iv_length($cipher_method);
100
+		// generate initialization vector.
101
+		// The second parameter ("crypto_strong") is passed by reference,
102
+		// and is used to determines if the algorithm used was "cryptographically strong"
103
+		// openssl_random_pseudo_bytes() will toggle it to either true or false
104
+		$iv = openssl_random_pseudo_bytes($iv_length, $is_strong);
105
+		if ($iv === false || $is_strong === false) {
106
+			throw new RuntimeException(
107
+				esc_html__('Failed to generate OpenSSL initialization vector.', 'event_espresso')
108
+			);
109
+		}
110
+		$key = $this->getDigestHashValue($encryption_key);
111
+		// encrypt it
112
+		$encrypted_text = openssl_encrypt(
113
+			$this->base64_encoder->encodeString($text_to_encrypt), // encode to remove special characters
114
+			$cipher_method,
115
+			$key,
116
+			0,
117
+			$iv
118
+		);
119
+		$this->validateEncryption($encrypted_text);
120
+		$encrypted_text = trim($encrypted_text);
121
+		// hash the raw encrypted text
122
+		$hmac = hash_hmac($this->getHashAlgorithm(), $encrypted_text, $key, true);
123
+		// concatenate everything into one big string and encode it again
124
+		return $this->base64_encoder->encodeString($iv . $hmac . $encrypted_text);
125
+	}
126 126
 
127 127
 
128
-    /**
129
-     * decrypts data
130
-     *
131
-     * @param string $encrypted_text            - the text to be decrypted
132
-     * @param string $encryption_key_identifier - cryptographically secure passphrase. will use default if necessary
133
-     * @return string
134
-     */
135
-    public function decrypt($encrypted_text, $encryption_key_identifier = '')
136
-    {
137
-        $cipher_method  = $this->cipher_method->getCipherMethod();
138
-        $encryption_key = $this->encryption_key_manager->getEncryptionKey($encryption_key_identifier);
139
-        $key            = $this->getDigestHashValue($encryption_key);
140
-        // decode our concatenated string
141
-        $encrypted_text = $this->base64_encoder->decodeString($encrypted_text);
142
-        // get the string lengths used for the hash and iv
143
-        $hash_length = $this->calculateHashLength($encryption_key);
144
-        $iv_length   = openssl_cipher_iv_length($cipher_method);
145
-        // use the above lengths to snip the required values from the decoded string
146
-        $iv                 = substr($encrypted_text, 0, $iv_length);
147
-        $hmac               = substr($encrypted_text, $iv_length, $hash_length);
148
-        $encrypted_text_raw = substr($encrypted_text, $iv_length + $hash_length);
149
-        // rehash the original raw encrypted text
150
-        $rehash_mac = hash_hmac($this->getHashAlgorithm(), $encrypted_text_raw, $key, true);
151
-        // timing attack safe comparison to determine if anything has changed
152
-        if (hash_equals($hmac, $rehash_mac)) {
153
-            // looks good, decrypt it, trim it, and return it
154
-            $decrypted_text = openssl_decrypt(
155
-                $encrypted_text_raw,
156
-                $this->cipher_method->getCipherMethod(),
157
-                $key,
158
-                0,
159
-                $iv
160
-            );
161
-            $this->validateDecryption($decrypted_text);
162
-            return trim($this->base64_encoder->decodeString($decrypted_text));
163
-        }
164
-        throw new RuntimeException(
165
-            esc_html__(
166
-                'Decryption failed because a hash comparison of the original text and the decrypted text was not the same, meaning something in the system or the encrypted data has changed.',
167
-                'event_espresso'
168
-            )
169
-        );
170
-    }
128
+	/**
129
+	 * decrypts data
130
+	 *
131
+	 * @param string $encrypted_text            - the text to be decrypted
132
+	 * @param string $encryption_key_identifier - cryptographically secure passphrase. will use default if necessary
133
+	 * @return string
134
+	 */
135
+	public function decrypt($encrypted_text, $encryption_key_identifier = '')
136
+	{
137
+		$cipher_method  = $this->cipher_method->getCipherMethod();
138
+		$encryption_key = $this->encryption_key_manager->getEncryptionKey($encryption_key_identifier);
139
+		$key            = $this->getDigestHashValue($encryption_key);
140
+		// decode our concatenated string
141
+		$encrypted_text = $this->base64_encoder->decodeString($encrypted_text);
142
+		// get the string lengths used for the hash and iv
143
+		$hash_length = $this->calculateHashLength($encryption_key);
144
+		$iv_length   = openssl_cipher_iv_length($cipher_method);
145
+		// use the above lengths to snip the required values from the decoded string
146
+		$iv                 = substr($encrypted_text, 0, $iv_length);
147
+		$hmac               = substr($encrypted_text, $iv_length, $hash_length);
148
+		$encrypted_text_raw = substr($encrypted_text, $iv_length + $hash_length);
149
+		// rehash the original raw encrypted text
150
+		$rehash_mac = hash_hmac($this->getHashAlgorithm(), $encrypted_text_raw, $key, true);
151
+		// timing attack safe comparison to determine if anything has changed
152
+		if (hash_equals($hmac, $rehash_mac)) {
153
+			// looks good, decrypt it, trim it, and return it
154
+			$decrypted_text = openssl_decrypt(
155
+				$encrypted_text_raw,
156
+				$this->cipher_method->getCipherMethod(),
157
+				$key,
158
+				0,
159
+				$iv
160
+			);
161
+			$this->validateDecryption($decrypted_text);
162
+			return trim($this->base64_encoder->decodeString($decrypted_text));
163
+		}
164
+		throw new RuntimeException(
165
+			esc_html__(
166
+				'Decryption failed because a hash comparison of the original text and the decrypted text was not the same, meaning something in the system or the encrypted data has changed.',
167
+				'event_espresso'
168
+			)
169
+		);
170
+	}
171 171
 }
Please login to merge, or discard this patch.
core/services/encryption/openssl/CipherMethod.php 2 patches
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -159,7 +159,7 @@  discard block
 block discarded – undo
159 159
             update_option($this->cipher_method_option_name, $cipher_method_to_test);
160 160
         }
161 161
         // if we previously removed this cipher method from the list of valid ones, then let's put it back
162
-        if (! in_array($cipher_method_to_test, $this->cipher_methods, true)) {
162
+        if ( ! in_array($cipher_method_to_test, $this->cipher_methods, true)) {
163 163
             array_unshift($this->cipher_methods, $cipher_method_to_test);
164 164
         }
165 165
         return $cipher_method_to_test;
@@ -189,7 +189,7 @@  discard block
 block discarded – undo
189 189
         ) {
190 190
             return true;
191 191
         }
192
-        if (! $throw_exception) {
192
+        if ( ! $throw_exception) {
193 193
             return false;
194 194
         }
195 195
         throw new RuntimeException(
Please login to merge, or discard this patch.
Indentation   +202 added lines, -202 removed lines patch added patch discarded remove patch
@@ -14,206 +14,206 @@
 block discarded – undo
14 14
  */
15 15
 class CipherMethod
16 16
 {
17
-    /**
18
-     * @var string
19
-     */
20
-    protected $cipher_method_option_name;
21
-
22
-    /**
23
-     * list of cipher methods that we consider usable,
24
-     * essentially all of the installed_cipher_methods minus weak_algorithms
25
-     *
26
-     * @var array
27
-     */
28
-    protected $cipher_methods = [];
29
-
30
-    /**
31
-     * @var string
32
-     */
33
-    protected $default_cipher_method;
34
-
35
-    /**
36
-     * list of ALL cipher methods available on the server
37
-     *
38
-     * @var array
39
-     */
40
-    protected $installed_cipher_methods;
41
-
42
-    /**
43
-     * the OpenSSL cipher method to use. default: AES-128-CBC
44
-     *
45
-     * @var string
46
-     */
47
-    protected $validated_cipher_method;
48
-
49
-    /**
50
-     * as early as Aug 2016, Openssl declared the following weak: RC2, RC4, DES, 3DES, MD5 based
51
-     * and ECB mode should be avoided
52
-     *
53
-     * @var array
54
-     */
55
-    protected $weak_algorithms = ['des', 'ecb', 'md5', 'rc2', 'rc4'];
56
-
57
-
58
-    /**
59
-     * @param string $default_cipher_method
60
-     * @param string $cipher_method_option_name
61
-     */
62
-    public function __construct($default_cipher_method, $cipher_method_option_name)
63
-    {
64
-        $this->default_cipher_method     = $default_cipher_method;
65
-        $this->cipher_method_option_name = $cipher_method_option_name;
66
-        $this->installed_cipher_methods  = openssl_get_cipher_methods();
67
-    }
68
-
69
-
70
-    /**
71
-     * Returns a cipher method that has been verified to work.
72
-     * First checks if the cached cipher has been set already and if so, returns that.
73
-     * Then tests the incoming default and returns that if it's good.
74
-     * If not, then it retrieves the previously tested and saved cipher method.
75
-     * But if that doesn't exist, then calls getAvailableCipherMethod()
76
-     * to see what is available on the server, and returns the results.
77
-     *
78
-     * @param string $cipher_method
79
-     * @param bool   $load_alternate [optional] if TRUE, will load the default cipher method (or any strong algorithm)
80
-     *                               if the requested cipher method is not installed or invalid.
81
-     *                               if FALSE, will throw an exception if the requested cipher method is not valid.
82
-     * @return string
83
-     * @throws RuntimeException
84
-     */
85
-    public function getCipherMethod($cipher_method = null, $load_alternate = true)
86
-    {
87
-        if (empty($cipher_method) && $this->validated_cipher_method !== null) {
88
-            return $this->validated_cipher_method;
89
-        }
90
-        // if nothing specific was requested and it's ok to load an alternate, then grab the system default
91
-        if (empty($cipher_method) && $load_alternate) {
92
-            $cipher_method = $this->default_cipher_method;
93
-        }
94
-        // verify that the cipher method can produce an initialization vector.
95
-        // but if the requested is invalid and we don't want to load an alternate, then throw an exception
96
-        $throw_exception = ! $load_alternate;
97
-        if ($this->validateCipherMethod($cipher_method, $throw_exception) === false) {
98
-            // nope? ... ok let's see what we can find
99
-            $cipher_method = $this->getAvailableCipherMethod();
100
-        }
101
-        // if nothing has been previously validated, then save the currently requested cipher which appears to be good
102
-        if ($this->validated_cipher_method === null) {
103
-            $this->validated_cipher_method = $cipher_method;
104
-        }
105
-        return $cipher_method;
106
-    }
107
-
108
-
109
-    /**
110
-     * returns true if the selected cipher method either uses Galois/Counter Mode (GCM)
111
-     * or Counter with CBC-MAC (CCM) authenticated encryption modes
112
-     * (also need to be using PHP 7.1 or greater to actually use authenticated encryption modes)
113
-     *
114
-     * @return bool
115
-     */
116
-    public function usesAuthenticatedEncryptionMode()
117
-    {
118
-        return PHP_VERSION_ID >= 70100
119
-               && (
120
-                   stripos($this->validated_cipher_method, 'gcm') !== false
121
-                   || stripos($this->validated_cipher_method, 'ccm') !== false
122
-               );
123
-    }
124
-
125
-
126
-    /**
127
-     * @param string $cipher_method
128
-     * @return string
129
-     * @throws RuntimeException
130
-     */
131
-    protected function getAvailableCipherMethod($cipher_method = null)
132
-    {
133
-        // if nothing was supplied, the get what we found in the past to work
134
-        $cipher_method_to_test = $cipher_method ?: get_option($this->cipher_method_option_name, '');
135
-        // verify that the incoming cipher method exists and can produce an initialization vector
136
-        if ($this->validateCipherMethod($cipher_method_to_test) === false) {
137
-            // what? there's no list?
138
-            if (empty($this->cipher_methods)) {
139
-                // generate that list and cache it
140
-                $this->cipher_methods = $this->getAvailableStrongCipherMethods();
141
-            }
142
-            // then grab the first item from the list (we'll add it back later if it is good)
143
-            $cipher_method_to_test = array_shift($this->cipher_methods);
144
-            if ($cipher_method_to_test === null) {
145
-                throw new RuntimeException(
146
-                    esc_html__(
147
-                        'OpenSSL support appears to be enabled on the server, but no cipher methods are available. Please contact the server administrator.',
148
-                        'event_espresso'
149
-                    )
150
-                );
151
-            }
152
-            // verify that the next cipher method works
153
-            return $this->getAvailableCipherMethod($cipher_method_to_test);
154
-        }
155
-        // if we've gotten this far, then we found an available cipher method that works
156
-        // so save that for next time, if it's not the same as what's there already
157
-        if ($cipher_method_to_test !== $cipher_method) {
158
-            update_option($this->cipher_method_option_name, $cipher_method_to_test);
159
-        }
160
-        // if we previously removed this cipher method from the list of valid ones, then let's put it back
161
-        if (! in_array($cipher_method_to_test, $this->cipher_methods, true)) {
162
-            array_unshift($this->cipher_methods, $cipher_method_to_test);
163
-        }
164
-        return $cipher_method_to_test;
165
-    }
166
-
167
-
168
-    /**
169
-     * @return array
170
-     */
171
-    protected function getAvailableStrongCipherMethods()
172
-    {
173
-        return array_filter($this->installed_cipher_methods, [$this, 'weakAlgorithmFilter']);
174
-    }
175
-
176
-
177
-    /**
178
-     * @param string $cipher_method
179
-     * @param false  $throw_exception
180
-     * @return bool
181
-     */
182
-    protected function validateCipherMethod($cipher_method, $throw_exception = false)
183
-    {
184
-        // verify that the requested cipher method is actually installed and can produce an initialization vector
185
-        if (
186
-            in_array($cipher_method, $this->installed_cipher_methods, true)
187
-            && openssl_cipher_iv_length($cipher_method) !== false
188
-        ) {
189
-            return true;
190
-        }
191
-        if (! $throw_exception) {
192
-            return false;
193
-        }
194
-        throw new RuntimeException(
195
-            sprintf(
196
-                esc_html__(
197
-                    'The requested OpenSSL cipher method "%1$s" is invalid or not installed on the server. Please contact the server administrator.',
198
-                    'event_espresso'
199
-                ),
200
-                $cipher_method
201
-            )
202
-        );
203
-    }
204
-
205
-
206
-    /**
207
-     * @see https://www.php.net/manual/en/function.openssl-get-cipher-methods.php#example-890
208
-     * @param string $cipher_method
209
-     */
210
-    protected function weakAlgorithmFilter($cipher_method)
211
-    {
212
-        foreach ($this->weak_algorithms as $weak_algorithm) {
213
-            if (stripos($cipher_method, $weak_algorithm) !== false) {
214
-                return false;
215
-            }
216
-        }
217
-        return true;
218
-    }
17
+	/**
18
+	 * @var string
19
+	 */
20
+	protected $cipher_method_option_name;
21
+
22
+	/**
23
+	 * list of cipher methods that we consider usable,
24
+	 * essentially all of the installed_cipher_methods minus weak_algorithms
25
+	 *
26
+	 * @var array
27
+	 */
28
+	protected $cipher_methods = [];
29
+
30
+	/**
31
+	 * @var string
32
+	 */
33
+	protected $default_cipher_method;
34
+
35
+	/**
36
+	 * list of ALL cipher methods available on the server
37
+	 *
38
+	 * @var array
39
+	 */
40
+	protected $installed_cipher_methods;
41
+
42
+	/**
43
+	 * the OpenSSL cipher method to use. default: AES-128-CBC
44
+	 *
45
+	 * @var string
46
+	 */
47
+	protected $validated_cipher_method;
48
+
49
+	/**
50
+	 * as early as Aug 2016, Openssl declared the following weak: RC2, RC4, DES, 3DES, MD5 based
51
+	 * and ECB mode should be avoided
52
+	 *
53
+	 * @var array
54
+	 */
55
+	protected $weak_algorithms = ['des', 'ecb', 'md5', 'rc2', 'rc4'];
56
+
57
+
58
+	/**
59
+	 * @param string $default_cipher_method
60
+	 * @param string $cipher_method_option_name
61
+	 */
62
+	public function __construct($default_cipher_method, $cipher_method_option_name)
63
+	{
64
+		$this->default_cipher_method     = $default_cipher_method;
65
+		$this->cipher_method_option_name = $cipher_method_option_name;
66
+		$this->installed_cipher_methods  = openssl_get_cipher_methods();
67
+	}
68
+
69
+
70
+	/**
71
+	 * Returns a cipher method that has been verified to work.
72
+	 * First checks if the cached cipher has been set already and if so, returns that.
73
+	 * Then tests the incoming default and returns that if it's good.
74
+	 * If not, then it retrieves the previously tested and saved cipher method.
75
+	 * But if that doesn't exist, then calls getAvailableCipherMethod()
76
+	 * to see what is available on the server, and returns the results.
77
+	 *
78
+	 * @param string $cipher_method
79
+	 * @param bool   $load_alternate [optional] if TRUE, will load the default cipher method (or any strong algorithm)
80
+	 *                               if the requested cipher method is not installed or invalid.
81
+	 *                               if FALSE, will throw an exception if the requested cipher method is not valid.
82
+	 * @return string
83
+	 * @throws RuntimeException
84
+	 */
85
+	public function getCipherMethod($cipher_method = null, $load_alternate = true)
86
+	{
87
+		if (empty($cipher_method) && $this->validated_cipher_method !== null) {
88
+			return $this->validated_cipher_method;
89
+		}
90
+		// if nothing specific was requested and it's ok to load an alternate, then grab the system default
91
+		if (empty($cipher_method) && $load_alternate) {
92
+			$cipher_method = $this->default_cipher_method;
93
+		}
94
+		// verify that the cipher method can produce an initialization vector.
95
+		// but if the requested is invalid and we don't want to load an alternate, then throw an exception
96
+		$throw_exception = ! $load_alternate;
97
+		if ($this->validateCipherMethod($cipher_method, $throw_exception) === false) {
98
+			// nope? ... ok let's see what we can find
99
+			$cipher_method = $this->getAvailableCipherMethod();
100
+		}
101
+		// if nothing has been previously validated, then save the currently requested cipher which appears to be good
102
+		if ($this->validated_cipher_method === null) {
103
+			$this->validated_cipher_method = $cipher_method;
104
+		}
105
+		return $cipher_method;
106
+	}
107
+
108
+
109
+	/**
110
+	 * returns true if the selected cipher method either uses Galois/Counter Mode (GCM)
111
+	 * or Counter with CBC-MAC (CCM) authenticated encryption modes
112
+	 * (also need to be using PHP 7.1 or greater to actually use authenticated encryption modes)
113
+	 *
114
+	 * @return bool
115
+	 */
116
+	public function usesAuthenticatedEncryptionMode()
117
+	{
118
+		return PHP_VERSION_ID >= 70100
119
+			   && (
120
+				   stripos($this->validated_cipher_method, 'gcm') !== false
121
+				   || stripos($this->validated_cipher_method, 'ccm') !== false
122
+			   );
123
+	}
124
+
125
+
126
+	/**
127
+	 * @param string $cipher_method
128
+	 * @return string
129
+	 * @throws RuntimeException
130
+	 */
131
+	protected function getAvailableCipherMethod($cipher_method = null)
132
+	{
133
+		// if nothing was supplied, the get what we found in the past to work
134
+		$cipher_method_to_test = $cipher_method ?: get_option($this->cipher_method_option_name, '');
135
+		// verify that the incoming cipher method exists and can produce an initialization vector
136
+		if ($this->validateCipherMethod($cipher_method_to_test) === false) {
137
+			// what? there's no list?
138
+			if (empty($this->cipher_methods)) {
139
+				// generate that list and cache it
140
+				$this->cipher_methods = $this->getAvailableStrongCipherMethods();
141
+			}
142
+			// then grab the first item from the list (we'll add it back later if it is good)
143
+			$cipher_method_to_test = array_shift($this->cipher_methods);
144
+			if ($cipher_method_to_test === null) {
145
+				throw new RuntimeException(
146
+					esc_html__(
147
+						'OpenSSL support appears to be enabled on the server, but no cipher methods are available. Please contact the server administrator.',
148
+						'event_espresso'
149
+					)
150
+				);
151
+			}
152
+			// verify that the next cipher method works
153
+			return $this->getAvailableCipherMethod($cipher_method_to_test);
154
+		}
155
+		// if we've gotten this far, then we found an available cipher method that works
156
+		// so save that for next time, if it's not the same as what's there already
157
+		if ($cipher_method_to_test !== $cipher_method) {
158
+			update_option($this->cipher_method_option_name, $cipher_method_to_test);
159
+		}
160
+		// if we previously removed this cipher method from the list of valid ones, then let's put it back
161
+		if (! in_array($cipher_method_to_test, $this->cipher_methods, true)) {
162
+			array_unshift($this->cipher_methods, $cipher_method_to_test);
163
+		}
164
+		return $cipher_method_to_test;
165
+	}
166
+
167
+
168
+	/**
169
+	 * @return array
170
+	 */
171
+	protected function getAvailableStrongCipherMethods()
172
+	{
173
+		return array_filter($this->installed_cipher_methods, [$this, 'weakAlgorithmFilter']);
174
+	}
175
+
176
+
177
+	/**
178
+	 * @param string $cipher_method
179
+	 * @param false  $throw_exception
180
+	 * @return bool
181
+	 */
182
+	protected function validateCipherMethod($cipher_method, $throw_exception = false)
183
+	{
184
+		// verify that the requested cipher method is actually installed and can produce an initialization vector
185
+		if (
186
+			in_array($cipher_method, $this->installed_cipher_methods, true)
187
+			&& openssl_cipher_iv_length($cipher_method) !== false
188
+		) {
189
+			return true;
190
+		}
191
+		if (! $throw_exception) {
192
+			return false;
193
+		}
194
+		throw new RuntimeException(
195
+			sprintf(
196
+				esc_html__(
197
+					'The requested OpenSSL cipher method "%1$s" is invalid or not installed on the server. Please contact the server administrator.',
198
+					'event_espresso'
199
+				),
200
+				$cipher_method
201
+			)
202
+		);
203
+	}
204
+
205
+
206
+	/**
207
+	 * @see https://www.php.net/manual/en/function.openssl-get-cipher-methods.php#example-890
208
+	 * @param string $cipher_method
209
+	 */
210
+	protected function weakAlgorithmFilter($cipher_method)
211
+	{
212
+		foreach ($this->weak_algorithms as $weak_algorithm) {
213
+			if (stripos($cipher_method, $weak_algorithm) !== false) {
214
+				return false;
215
+			}
216
+		}
217
+		return true;
218
+	}
219 219
 }
Please login to merge, or discard this patch.
core/services/encryption/openssl/OpenSSLv2.php 2 patches
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -143,7 +143,7 @@  discard block
 block discarded – undo
143 143
         );
144 144
         $this->validateEncryption($encrypted_text);
145 145
         // concatenate everything into one big string
146
-        return $iv . $tag . $encrypted_text;
146
+        return $iv.$tag.$encrypted_text;
147 147
     }
148 148
 
149 149
 
@@ -165,7 +165,7 @@  discard block
 block discarded – undo
165 165
         );
166 166
         $this->validateEncryption($encrypted_text);
167 167
         // prepend the initialization vector
168
-        return $iv . $encrypted_text;
168
+        return $iv.$encrypted_text;
169 169
     }
170 170
 
171 171
 
Please login to merge, or discard this patch.
Indentation   +217 added lines, -217 removed lines patch added patch discarded remove patch
@@ -23,221 +23,221 @@
 block discarded – undo
23 23
  */
24 24
 class OpenSSLv2 extends OpenSSL
25 25
 {
26
-    /**
27
-     * name used for a default encryption key in case no others are set
28
-     */
29
-    const DEFAULT_ENCRYPTION_KEY_ID = 'default_openssl_v2_key';
30
-
31
-    /**
32
-     * name used for saving encryption keys to the wp_options table
33
-     */
34
-    const ENCRYPTION_KEYS_OPTION_NAME = 'ee_openssl_v2_encryption_keys';
35
-
36
-    /**
37
-     * the OPENSSL cipher method used
38
-     */
39
-    const CIPHER_METHOD = 'aes-256-gcm';
40
-
41
-    /**
42
-     * WP "options_name" used to store a verified available cipher method
43
-     */
44
-    const CIPHER_METHOD_OPTION_NAME = 'ee_openssl_v2_cipher_method';
45
-
46
-    /**
47
-     * The length of the authentication tag. Its value can be between 4 and 16 for GCM mode.
48
-     */
49
-    const AUTH_TAG_LENGTH = 16;
50
-
51
-
52
-    /**
53
-     * To use custom a cipher method and/or encryption keys and/or minimum PHP version:
54
-     *  - extend this class
55
-     *  - configure a new CipherMethod / EncryptionKeyManager in the constructor
56
-     *  - pass those to this constructor, like so:
57
-     *
58
-     *      public function __construct(Base64Encoder $base64_encoder) {
59
-     *          parent::__construct(
60
-     *              $base64_encoder,
61
-     *              new CipherMethod(CIPHER_METHOD, CIPHER_METHOD_OPTION_NAME),
62
-     *              new EncryptionKeyManager(CUSTOM_KEY_ID, CUSTOM_KEYS_OPTION_NAME),
63
-     *              '7.1.0'
64
-     *          );
65
-     *      }
66
-     *
67
-     * @param Base64Encoder                      $base64_encoder
68
-     * @param CipherMethod|null                  $cipher_method
69
-     * @param EncryptionKeyManagerInterface|null $encryption_key_manager
70
-     * @param string                             $min_php_version defaults to 7.1.0
71
-     *                                                            (when openssl auth tag and random_bytes() were added)
72
-     */
73
-    public function __construct(
74
-        Base64Encoder $base64_encoder,
75
-        CipherMethod $cipher_method = null,
76
-        EncryptionKeyManagerInterface $encryption_key_manager = null,
77
-        $min_php_version = '7.1.0'
78
-    ) {
79
-        parent::__construct(
80
-            $base64_encoder,
81
-            $cipher_method instanceof CipherMethod
82
-                ? $cipher_method
83
-                : new CipherMethod(
84
-                    OpenSSLv2::CIPHER_METHOD,
85
-                    OpenSSLv2::CIPHER_METHOD_OPTION_NAME
86
-                ),
87
-            $encryption_key_manager instanceof EncryptionKeyManager
88
-                ? $encryption_key_manager
89
-                : new EncryptionKeyManager(
90
-                    $base64_encoder,
91
-                    OpenSSLv2::DEFAULT_ENCRYPTION_KEY_ID,
92
-                    OpenSSLv2::ENCRYPTION_KEYS_OPTION_NAME
93
-                ),
94
-            $min_php_version
95
-        );
96
-    }
97
-
98
-
99
-    /**
100
-     * encrypts data
101
-     *
102
-     * @param string $text_to_encrypt           - the text to be encrypted
103
-     * @param string $encryption_key_identifier - [optional] cryptographically secure passphrase. generated if not set
104
-     * @param string $aad                       - [optional] additional authentication data
105
-     * @return string
106
-     * @throws Exception
107
-     */
108
-    public function encrypt($text_to_encrypt, $encryption_key_identifier = '', $aad = '')
109
-    {
110
-        $cipher_method  = $this->cipher_method->getCipherMethod();
111
-        $encryption_key = $this->encryption_key_manager->getEncryptionKey($encryption_key_identifier);
112
-        // generate initialization vector for the cipher method.
113
-        $iv = random_bytes(openssl_cipher_iv_length($cipher_method));
114
-        // encrypt it (encode to remove special characters)
115
-        $text_to_encrypt = $this->base64_encoder->encodeString($text_to_encrypt);
116
-        $encrypted_text  = $this->cipher_method->usesAuthenticatedEncryptionMode()
117
-            ? $this->authenticatedEncrypt($text_to_encrypt, $cipher_method, $encryption_key, $iv, $aad)
118
-            : $this->nonAuthenticatedEncrypt($text_to_encrypt, $cipher_method, $encryption_key, $iv);
119
-        return $this->base64_encoder->encodeString($encrypted_text);
120
-    }
121
-
122
-
123
-    /**
124
-     * @param string $text_to_encrypt - the text to be encrypted
125
-     * @param string $cipher_method   - the OpenSSL cipher method used during encryption
126
-     * @param string $encryption_key  - cryptographically secure passphrase uses default if not set
127
-     * @param string $iv              - the initialization vector
128
-     * @param string $aad             - additional authentication data
129
-     * @return string
130
-     */
131
-    private function authenticatedEncrypt($text_to_encrypt, $cipher_method, $encryption_key, $iv, $aad)
132
-    {
133
-        $encrypted_text = openssl_encrypt(
134
-            $text_to_encrypt,
135
-            $cipher_method,
136
-            $this->getDigestHashValue($encryption_key, OpenSSL::DEFAULT_DIGEST_METHOD, OPENSSL_RAW_DATA),
137
-            0,
138
-            $iv,
139
-            $tag,
140
-            $aad,
141
-            OpenSSLv2::AUTH_TAG_LENGTH
142
-        );
143
-        $this->validateEncryption($encrypted_text);
144
-        // concatenate everything into one big string
145
-        return $iv . $tag . $encrypted_text;
146
-    }
147
-
148
-
149
-    /**
150
-     * @param string $text_to_encrypt - the text to be encrypted
151
-     * @param string $cipher_method   - the OpenSSL cipher method used during encryption
152
-     * @param string $encryption_key  - cryptographically secure passphrase uses default if not set
153
-     * @param string $iv              - the initialization vector
154
-     * @return string
155
-     */
156
-    private function nonAuthenticatedEncrypt($text_to_encrypt, $cipher_method, $encryption_key, $iv)
157
-    {
158
-        $encrypted_text = openssl_encrypt(
159
-            $text_to_encrypt,
160
-            $cipher_method,
161
-            $this->getDigestHashValue($encryption_key),
162
-            0,
163
-            $iv
164
-        );
165
-        $this->validateEncryption($encrypted_text);
166
-        // prepend the initialization vector
167
-        return $iv . $encrypted_text;
168
-    }
169
-
170
-
171
-    /**
172
-     * decrypts data
173
-     *
174
-     * @param string $encrypted_text            - the text to be decrypted
175
-     * @param string $encryption_key_identifier - [optional] cryptographically secure passphrase uses default if not set
176
-     * @param string $aad                       - [optional] additional authentication data
177
-     * @return string
178
-     */
179
-    public function decrypt($encrypted_text, $encryption_key_identifier = '', $aad = '')
180
-    {
181
-        $cipher_method  = $this->cipher_method->getCipherMethod();
182
-        $encryption_key = $this->encryption_key_manager->getEncryptionKey($encryption_key_identifier);
183
-        // maybe decode
184
-        $encrypted_text = $this->base64_encoder->decodeString($encrypted_text);
185
-        $iv_length      = openssl_cipher_iv_length($cipher_method);
186
-        // use the iv length to snip it from the decoded string
187
-        $iv = substr($encrypted_text, 0, $iv_length);
188
-        // then remove it from the rest of the decoded string
189
-        $encrypted_text = substr($encrypted_text, $iv_length);
190
-        // decrypt it
191
-        $decrypted_text = $this->cipher_method->usesAuthenticatedEncryptionMode()
192
-            ? $this->authenticatedDecrypt($encrypted_text, $cipher_method, $encryption_key, $iv, $aad)
193
-            : $this->nonAuthenticatedDecrypt($encrypted_text, $cipher_method, $encryption_key, $iv);
194
-
195
-        $this->validateDecryption($decrypted_text);
196
-        return trim($this->base64_encoder->decodeString($decrypted_text));
197
-    }
198
-
199
-
200
-    /**
201
-     * @param string $encrypted_text - the text to be decrypted
202
-     * @param string $cipher_method  - the OpenSSL cipher method used during encryption
203
-     * @param string $encryption_key - cryptographically secure passphrase uses default if not set
204
-     * @param string $iv             - the initialization vector
205
-     * @param string $aad            - additional authentication data
206
-     * @return string|false
207
-     */
208
-    private function authenticatedDecrypt($encrypted_text, $cipher_method, $encryption_key, $iv, $aad)
209
-    {
210
-        // use the tag length to snip it from the decoded string
211
-        $tag = substr($encrypted_text, 0, OpenSSLv2::AUTH_TAG_LENGTH);
212
-        // then remove it from the rest of the decoded string
213
-        $encrypted_text = substr($encrypted_text, OpenSSLv2::AUTH_TAG_LENGTH);
214
-        return openssl_decrypt(
215
-            $encrypted_text,
216
-            $cipher_method,
217
-            $this->getDigestHashValue($encryption_key, OpenSSL::DEFAULT_DIGEST_METHOD, OPENSSL_RAW_DATA),
218
-            0,
219
-            $iv,
220
-            $tag,
221
-            $aad
222
-        );
223
-    }
224
-
225
-
226
-    /**
227
-     * @param string $encrypted_text - the text to be decrypted
228
-     * @param string $cipher_method  - the OpenSSL cipher method used during encryption
229
-     * @param string $encryption_key - cryptographically secure passphrase uses default if not set
230
-     * @param string $iv             - the initialization vector
231
-     * @return string|false
232
-     */
233
-    private function nonAuthenticatedDecrypt($encrypted_text, $cipher_method, $encryption_key, $iv)
234
-    {
235
-        return openssl_decrypt(
236
-            $encrypted_text,
237
-            $cipher_method,
238
-            $this->getDigestHashValue($encryption_key),
239
-            0,
240
-            $iv
241
-        );
242
-    }
26
+	/**
27
+	 * name used for a default encryption key in case no others are set
28
+	 */
29
+	const DEFAULT_ENCRYPTION_KEY_ID = 'default_openssl_v2_key';
30
+
31
+	/**
32
+	 * name used for saving encryption keys to the wp_options table
33
+	 */
34
+	const ENCRYPTION_KEYS_OPTION_NAME = 'ee_openssl_v2_encryption_keys';
35
+
36
+	/**
37
+	 * the OPENSSL cipher method used
38
+	 */
39
+	const CIPHER_METHOD = 'aes-256-gcm';
40
+
41
+	/**
42
+	 * WP "options_name" used to store a verified available cipher method
43
+	 */
44
+	const CIPHER_METHOD_OPTION_NAME = 'ee_openssl_v2_cipher_method';
45
+
46
+	/**
47
+	 * The length of the authentication tag. Its value can be between 4 and 16 for GCM mode.
48
+	 */
49
+	const AUTH_TAG_LENGTH = 16;
50
+
51
+
52
+	/**
53
+	 * To use custom a cipher method and/or encryption keys and/or minimum PHP version:
54
+	 *  - extend this class
55
+	 *  - configure a new CipherMethod / EncryptionKeyManager in the constructor
56
+	 *  - pass those to this constructor, like so:
57
+	 *
58
+	 *      public function __construct(Base64Encoder $base64_encoder) {
59
+	 *          parent::__construct(
60
+	 *              $base64_encoder,
61
+	 *              new CipherMethod(CIPHER_METHOD, CIPHER_METHOD_OPTION_NAME),
62
+	 *              new EncryptionKeyManager(CUSTOM_KEY_ID, CUSTOM_KEYS_OPTION_NAME),
63
+	 *              '7.1.0'
64
+	 *          );
65
+	 *      }
66
+	 *
67
+	 * @param Base64Encoder                      $base64_encoder
68
+	 * @param CipherMethod|null                  $cipher_method
69
+	 * @param EncryptionKeyManagerInterface|null $encryption_key_manager
70
+	 * @param string                             $min_php_version defaults to 7.1.0
71
+	 *                                                            (when openssl auth tag and random_bytes() were added)
72
+	 */
73
+	public function __construct(
74
+		Base64Encoder $base64_encoder,
75
+		CipherMethod $cipher_method = null,
76
+		EncryptionKeyManagerInterface $encryption_key_manager = null,
77
+		$min_php_version = '7.1.0'
78
+	) {
79
+		parent::__construct(
80
+			$base64_encoder,
81
+			$cipher_method instanceof CipherMethod
82
+				? $cipher_method
83
+				: new CipherMethod(
84
+					OpenSSLv2::CIPHER_METHOD,
85
+					OpenSSLv2::CIPHER_METHOD_OPTION_NAME
86
+				),
87
+			$encryption_key_manager instanceof EncryptionKeyManager
88
+				? $encryption_key_manager
89
+				: new EncryptionKeyManager(
90
+					$base64_encoder,
91
+					OpenSSLv2::DEFAULT_ENCRYPTION_KEY_ID,
92
+					OpenSSLv2::ENCRYPTION_KEYS_OPTION_NAME
93
+				),
94
+			$min_php_version
95
+		);
96
+	}
97
+
98
+
99
+	/**
100
+	 * encrypts data
101
+	 *
102
+	 * @param string $text_to_encrypt           - the text to be encrypted
103
+	 * @param string $encryption_key_identifier - [optional] cryptographically secure passphrase. generated if not set
104
+	 * @param string $aad                       - [optional] additional authentication data
105
+	 * @return string
106
+	 * @throws Exception
107
+	 */
108
+	public function encrypt($text_to_encrypt, $encryption_key_identifier = '', $aad = '')
109
+	{
110
+		$cipher_method  = $this->cipher_method->getCipherMethod();
111
+		$encryption_key = $this->encryption_key_manager->getEncryptionKey($encryption_key_identifier);
112
+		// generate initialization vector for the cipher method.
113
+		$iv = random_bytes(openssl_cipher_iv_length($cipher_method));
114
+		// encrypt it (encode to remove special characters)
115
+		$text_to_encrypt = $this->base64_encoder->encodeString($text_to_encrypt);
116
+		$encrypted_text  = $this->cipher_method->usesAuthenticatedEncryptionMode()
117
+			? $this->authenticatedEncrypt($text_to_encrypt, $cipher_method, $encryption_key, $iv, $aad)
118
+			: $this->nonAuthenticatedEncrypt($text_to_encrypt, $cipher_method, $encryption_key, $iv);
119
+		return $this->base64_encoder->encodeString($encrypted_text);
120
+	}
121
+
122
+
123
+	/**
124
+	 * @param string $text_to_encrypt - the text to be encrypted
125
+	 * @param string $cipher_method   - the OpenSSL cipher method used during encryption
126
+	 * @param string $encryption_key  - cryptographically secure passphrase uses default if not set
127
+	 * @param string $iv              - the initialization vector
128
+	 * @param string $aad             - additional authentication data
129
+	 * @return string
130
+	 */
131
+	private function authenticatedEncrypt($text_to_encrypt, $cipher_method, $encryption_key, $iv, $aad)
132
+	{
133
+		$encrypted_text = openssl_encrypt(
134
+			$text_to_encrypt,
135
+			$cipher_method,
136
+			$this->getDigestHashValue($encryption_key, OpenSSL::DEFAULT_DIGEST_METHOD, OPENSSL_RAW_DATA),
137
+			0,
138
+			$iv,
139
+			$tag,
140
+			$aad,
141
+			OpenSSLv2::AUTH_TAG_LENGTH
142
+		);
143
+		$this->validateEncryption($encrypted_text);
144
+		// concatenate everything into one big string
145
+		return $iv . $tag . $encrypted_text;
146
+	}
147
+
148
+
149
+	/**
150
+	 * @param string $text_to_encrypt - the text to be encrypted
151
+	 * @param string $cipher_method   - the OpenSSL cipher method used during encryption
152
+	 * @param string $encryption_key  - cryptographically secure passphrase uses default if not set
153
+	 * @param string $iv              - the initialization vector
154
+	 * @return string
155
+	 */
156
+	private function nonAuthenticatedEncrypt($text_to_encrypt, $cipher_method, $encryption_key, $iv)
157
+	{
158
+		$encrypted_text = openssl_encrypt(
159
+			$text_to_encrypt,
160
+			$cipher_method,
161
+			$this->getDigestHashValue($encryption_key),
162
+			0,
163
+			$iv
164
+		);
165
+		$this->validateEncryption($encrypted_text);
166
+		// prepend the initialization vector
167
+		return $iv . $encrypted_text;
168
+	}
169
+
170
+
171
+	/**
172
+	 * decrypts data
173
+	 *
174
+	 * @param string $encrypted_text            - the text to be decrypted
175
+	 * @param string $encryption_key_identifier - [optional] cryptographically secure passphrase uses default if not set
176
+	 * @param string $aad                       - [optional] additional authentication data
177
+	 * @return string
178
+	 */
179
+	public function decrypt($encrypted_text, $encryption_key_identifier = '', $aad = '')
180
+	{
181
+		$cipher_method  = $this->cipher_method->getCipherMethod();
182
+		$encryption_key = $this->encryption_key_manager->getEncryptionKey($encryption_key_identifier);
183
+		// maybe decode
184
+		$encrypted_text = $this->base64_encoder->decodeString($encrypted_text);
185
+		$iv_length      = openssl_cipher_iv_length($cipher_method);
186
+		// use the iv length to snip it from the decoded string
187
+		$iv = substr($encrypted_text, 0, $iv_length);
188
+		// then remove it from the rest of the decoded string
189
+		$encrypted_text = substr($encrypted_text, $iv_length);
190
+		// decrypt it
191
+		$decrypted_text = $this->cipher_method->usesAuthenticatedEncryptionMode()
192
+			? $this->authenticatedDecrypt($encrypted_text, $cipher_method, $encryption_key, $iv, $aad)
193
+			: $this->nonAuthenticatedDecrypt($encrypted_text, $cipher_method, $encryption_key, $iv);
194
+
195
+		$this->validateDecryption($decrypted_text);
196
+		return trim($this->base64_encoder->decodeString($decrypted_text));
197
+	}
198
+
199
+
200
+	/**
201
+	 * @param string $encrypted_text - the text to be decrypted
202
+	 * @param string $cipher_method  - the OpenSSL cipher method used during encryption
203
+	 * @param string $encryption_key - cryptographically secure passphrase uses default if not set
204
+	 * @param string $iv             - the initialization vector
205
+	 * @param string $aad            - additional authentication data
206
+	 * @return string|false
207
+	 */
208
+	private function authenticatedDecrypt($encrypted_text, $cipher_method, $encryption_key, $iv, $aad)
209
+	{
210
+		// use the tag length to snip it from the decoded string
211
+		$tag = substr($encrypted_text, 0, OpenSSLv2::AUTH_TAG_LENGTH);
212
+		// then remove it from the rest of the decoded string
213
+		$encrypted_text = substr($encrypted_text, OpenSSLv2::AUTH_TAG_LENGTH);
214
+		return openssl_decrypt(
215
+			$encrypted_text,
216
+			$cipher_method,
217
+			$this->getDigestHashValue($encryption_key, OpenSSL::DEFAULT_DIGEST_METHOD, OPENSSL_RAW_DATA),
218
+			0,
219
+			$iv,
220
+			$tag,
221
+			$aad
222
+		);
223
+	}
224
+
225
+
226
+	/**
227
+	 * @param string $encrypted_text - the text to be decrypted
228
+	 * @param string $cipher_method  - the OpenSSL cipher method used during encryption
229
+	 * @param string $encryption_key - cryptographically secure passphrase uses default if not set
230
+	 * @param string $iv             - the initialization vector
231
+	 * @return string|false
232
+	 */
233
+	private function nonAuthenticatedDecrypt($encrypted_text, $cipher_method, $encryption_key, $iv)
234
+	{
235
+		return openssl_decrypt(
236
+			$encrypted_text,
237
+			$cipher_method,
238
+			$this->getDigestHashValue($encryption_key),
239
+			0,
240
+			$iv
241
+		);
242
+	}
243 243
 }
Please login to merge, or discard this patch.
core/services/encryption/Base64Encoder.php 2 patches
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -129,7 +129,7 @@  discard block
 block discarded – undo
129 129
      */
130 130
     public function isValidBase64OrFail($encoded_string)
131 131
     {
132
-        if (! $this->isValidBase64($encoded_string)) {
132
+        if ( ! $this->isValidBase64($encoded_string)) {
133 133
             throw new RuntimeException(
134 134
                 esc_html__(
135 135
                     'Base 64 decoding failed because the supplied string is not valid or was not base64 encoded.',
@@ -148,7 +148,7 @@  discard block
 block discarded – undo
148 148
     public function isValidBase64($string)
149 149
     {
150 150
         // ensure data is a string
151
-        if (! is_string($string) || ! $this->use_base64_encode) {
151
+        if ( ! is_string($string) || ! $this->use_base64_encode) {
152 152
             return false;
153 153
         }
154 154
         // first check if we're dealing with an actual valid base64 encoded string
Please login to merge, or discard this patch.
Indentation   +144 added lines, -144 removed lines patch added patch discarded remove patch
@@ -14,148 +14,148 @@
 block discarded – undo
14 14
  */
15 15
 class Base64Encoder
16 16
 {
17
-    /**
18
-     * @var boolean
19
-     */
20
-    protected $use_base64_encode;
21
-
22
-
23
-    public function __construct()
24
-    {
25
-        $this->use_base64_encode = function_exists('base64_encode');
26
-    }
27
-
28
-
29
-    /**
30
-     * encodes string with PHP's base64 encoding
31
-     *
32
-     * @see http://php.net/manual/en/function.base64-encode.php
33
-     * @param string $text_string the text to be encoded
34
-     * @return string
35
-     */
36
-    public function encodeString($text_string = '')
37
-    {
38
-        // you give me nothing??? GET OUT !
39
-        if (empty($text_string) || ! $this->use_base64_encode) {
40
-            return $text_string;
41
-        }
42
-        // encode
43
-        return base64_encode($text_string);
44
-    }
45
-
46
-
47
-    /**
48
-     * decodes string that has been encoded with PHP's base64 encoding
49
-     *
50
-     * @see http://php.net/manual/en/function.base64-encode.php
51
-     * @param string $encoded_string the text to be decoded
52
-     * @return string
53
-     * @throws RuntimeException
54
-     */
55
-    public function decodeString($encoded_string = '')
56
-    {
57
-        // you give me nothing??? GET OUT !
58
-        if (empty($encoded_string)) {
59
-            return $encoded_string;
60
-        }
61
-        $this->isValidBase64OrFail($encoded_string);
62
-        return $this->decode($encoded_string);
63
-    }
64
-
65
-
66
-    /**
67
-     * @param string $encoded_string the text to be decoded
68
-     * @return string
69
-     * @throws RuntimeException
70
-     */
71
-    private function decode($encoded_string)
72
-    {
73
-        $decoded_string = base64_decode($encoded_string);
74
-        if ($decoded_string === false) {
75
-            throw new RuntimeException(
76
-                esc_html__('Base 64 decoding failed.', 'event_espresso')
77
-            );
78
-        }
79
-        return $decoded_string;
80
-    }
81
-
82
-
83
-    /**
84
-     * encodes  url string with PHP's base64 encoding
85
-     *
86
-     * @see http://php.net/manual/en/function.base64-encode.php
87
-     * @param string $text_string the text to be encoded
88
-     * @return string
89
-     */
90
-    public function encodeUrl($text_string = '')
91
-    {
92
-        // you give me nothing??? GET OUT !
93
-        if (empty($text_string) || ! $this->use_base64_encode) {
94
-            return $text_string;
95
-        }
96
-        // encode
97
-        $encoded_string = base64_encode($text_string);
98
-        // remove some chars to make encoding more URL friendly
99
-        return rtrim(strtr($encoded_string, '+/', '-_'), '=');
100
-    }
101
-
102
-
103
-    /**
104
-     * decodes  url string that has been encoded with PHP's base64 encoding
105
-     *
106
-     * @see http://php.net/manual/en/function.base64-encode.php
107
-     * @param string $encoded_string the text to be decoded
108
-     * @return string
109
-     * @throws RuntimeException
110
-     */
111
-    public function decodeUrl($encoded_string = '')
112
-    {
113
-        // you give me nothing??? GET OUT !
114
-        if (empty($encoded_string)) {
115
-            return $encoded_string;
116
-        }
117
-        // replace previously removed characters
118
-        $encoded_string = strtr($encoded_string, '-_', '+/');
119
-        $encoded_string .= str_repeat('=', 3 - (3 + strlen($encoded_string)) % 4);
120
-        $this->isValidBase64OrFail($encoded_string);
121
-        return $this->decode($encoded_string);
122
-    }
123
-
124
-
125
-    /**
126
-     * @param string $encoded_string the text to be decoded
127
-     * @throws RuntimeException
128
-     */
129
-    public function isValidBase64OrFail($encoded_string)
130
-    {
131
-        if (! $this->isValidBase64($encoded_string)) {
132
-            throw new RuntimeException(
133
-                esc_html__(
134
-                    'Base 64 decoding failed because the supplied string is not valid or was not base64 encoded.',
135
-                    'event_espresso'
136
-                )
137
-            );
138
-        }
139
-    }
140
-
141
-
142
-    /**
143
-     * @see https://stackoverflow.com/a/51877882
144
-     * @param $string
145
-     * @return bool
146
-     */
147
-    public function isValidBase64($string)
148
-    {
149
-        // ensure data is a string
150
-        if (! is_string($string) || ! $this->use_base64_encode) {
151
-            return false;
152
-        }
153
-        // first check if we're dealing with an actual valid base64 encoded string
154
-        $decoded = base64_decode($string, true);
155
-        if ($decoded === false) {
156
-            return false;
157
-        }
158
-        // finally, re-encode and compare it to original one
159
-        return base64_encode($decoded) === $string;
160
-    }
17
+	/**
18
+	 * @var boolean
19
+	 */
20
+	protected $use_base64_encode;
21
+
22
+
23
+	public function __construct()
24
+	{
25
+		$this->use_base64_encode = function_exists('base64_encode');
26
+	}
27
+
28
+
29
+	/**
30
+	 * encodes string with PHP's base64 encoding
31
+	 *
32
+	 * @see http://php.net/manual/en/function.base64-encode.php
33
+	 * @param string $text_string the text to be encoded
34
+	 * @return string
35
+	 */
36
+	public function encodeString($text_string = '')
37
+	{
38
+		// you give me nothing??? GET OUT !
39
+		if (empty($text_string) || ! $this->use_base64_encode) {
40
+			return $text_string;
41
+		}
42
+		// encode
43
+		return base64_encode($text_string);
44
+	}
45
+
46
+
47
+	/**
48
+	 * decodes string that has been encoded with PHP's base64 encoding
49
+	 *
50
+	 * @see http://php.net/manual/en/function.base64-encode.php
51
+	 * @param string $encoded_string the text to be decoded
52
+	 * @return string
53
+	 * @throws RuntimeException
54
+	 */
55
+	public function decodeString($encoded_string = '')
56
+	{
57
+		// you give me nothing??? GET OUT !
58
+		if (empty($encoded_string)) {
59
+			return $encoded_string;
60
+		}
61
+		$this->isValidBase64OrFail($encoded_string);
62
+		return $this->decode($encoded_string);
63
+	}
64
+
65
+
66
+	/**
67
+	 * @param string $encoded_string the text to be decoded
68
+	 * @return string
69
+	 * @throws RuntimeException
70
+	 */
71
+	private function decode($encoded_string)
72
+	{
73
+		$decoded_string = base64_decode($encoded_string);
74
+		if ($decoded_string === false) {
75
+			throw new RuntimeException(
76
+				esc_html__('Base 64 decoding failed.', 'event_espresso')
77
+			);
78
+		}
79
+		return $decoded_string;
80
+	}
81
+
82
+
83
+	/**
84
+	 * encodes  url string with PHP's base64 encoding
85
+	 *
86
+	 * @see http://php.net/manual/en/function.base64-encode.php
87
+	 * @param string $text_string the text to be encoded
88
+	 * @return string
89
+	 */
90
+	public function encodeUrl($text_string = '')
91
+	{
92
+		// you give me nothing??? GET OUT !
93
+		if (empty($text_string) || ! $this->use_base64_encode) {
94
+			return $text_string;
95
+		}
96
+		// encode
97
+		$encoded_string = base64_encode($text_string);
98
+		// remove some chars to make encoding more URL friendly
99
+		return rtrim(strtr($encoded_string, '+/', '-_'), '=');
100
+	}
101
+
102
+
103
+	/**
104
+	 * decodes  url string that has been encoded with PHP's base64 encoding
105
+	 *
106
+	 * @see http://php.net/manual/en/function.base64-encode.php
107
+	 * @param string $encoded_string the text to be decoded
108
+	 * @return string
109
+	 * @throws RuntimeException
110
+	 */
111
+	public function decodeUrl($encoded_string = '')
112
+	{
113
+		// you give me nothing??? GET OUT !
114
+		if (empty($encoded_string)) {
115
+			return $encoded_string;
116
+		}
117
+		// replace previously removed characters
118
+		$encoded_string = strtr($encoded_string, '-_', '+/');
119
+		$encoded_string .= str_repeat('=', 3 - (3 + strlen($encoded_string)) % 4);
120
+		$this->isValidBase64OrFail($encoded_string);
121
+		return $this->decode($encoded_string);
122
+	}
123
+
124
+
125
+	/**
126
+	 * @param string $encoded_string the text to be decoded
127
+	 * @throws RuntimeException
128
+	 */
129
+	public function isValidBase64OrFail($encoded_string)
130
+	{
131
+		if (! $this->isValidBase64($encoded_string)) {
132
+			throw new RuntimeException(
133
+				esc_html__(
134
+					'Base 64 decoding failed because the supplied string is not valid or was not base64 encoded.',
135
+					'event_espresso'
136
+				)
137
+			);
138
+		}
139
+	}
140
+
141
+
142
+	/**
143
+	 * @see https://stackoverflow.com/a/51877882
144
+	 * @param $string
145
+	 * @return bool
146
+	 */
147
+	public function isValidBase64($string)
148
+	{
149
+		// ensure data is a string
150
+		if (! is_string($string) || ! $this->use_base64_encode) {
151
+			return false;
152
+		}
153
+		// first check if we're dealing with an actual valid base64 encoded string
154
+		$decoded = base64_decode($string, true);
155
+		if ($decoded === false) {
156
+			return false;
157
+		}
158
+		// finally, re-encode and compare it to original one
159
+		return base64_encode($decoded) === $string;
160
+	}
161 161
 }
Please login to merge, or discard this patch.
core/EE_Encryption.core.php 2 patches
Spacing   +13 added lines, -13 removed lines patch added patch discarded remove patch
@@ -103,7 +103,7 @@  discard block
 block discarded – undo
103 103
      */
104 104
     protected function __construct()
105 105
     {
106
-        if (! defined('ESPRESSO_ENCRYPT')) {
106
+        if ( ! defined('ESPRESSO_ENCRYPT')) {
107 107
             define('ESPRESSO_ENCRYPT', true);
108 108
         }
109 109
         if (extension_loaded('openssl')) {
@@ -125,7 +125,7 @@  discard block
 block discarded – undo
125 125
     public static function instance()
126 126
     {
127 127
         // check if class object is instantiated
128
-        if (! EE_Encryption::$_instance instanceof EE_Encryption) {
128
+        if ( ! EE_Encryption::$_instance instanceof EE_Encryption) {
129 129
             EE_Encryption::$_instance = new self();
130 130
         }
131 131
         return EE_Encryption::$_instance;
@@ -332,7 +332,7 @@  discard block
 block discarded – undo
332 332
             $iv
333 333
         );
334 334
         // append the initialization vector
335
-        $encrypted_text .= EE_Encryption::OPENSSL_IV_DELIMITER . $iv;
335
+        $encrypted_text .= EE_Encryption::OPENSSL_IV_DELIMITER.$iv;
336 336
         // trim and maybe encode
337 337
         return $this->_use_base64_encode
338 338
             ? trim(base64_encode($encrypted_text))
@@ -515,7 +515,7 @@  discard block
 block discarded – undo
515 515
         if (empty($text_string)) {
516 516
             return $text_string;
517 517
         }
518
-        $key_bits    = str_split(
518
+        $key_bits = str_split(
519 519
             str_pad(
520 520
                 '',
521 521
                 strlen($text_string),
@@ -525,8 +525,8 @@  discard block
 block discarded – undo
525 525
         );
526 526
         $string_bits = str_split($text_string);
527 527
         foreach ($string_bits as $k => $v) {
528
-            $temp              = ord($v) + ord($key_bits[ $k ]);
529
-            $string_bits[ $k ] = chr($temp > 255 ? ($temp - 256) : $temp);
528
+            $temp              = ord($v) + ord($key_bits[$k]);
529
+            $string_bits[$k] = chr($temp > 255 ? ($temp - 256) : $temp);
530 530
         }
531 531
         $encrypted_text = implode('', $string_bits);
532 532
         $encrypted_text .= EE_Encryption::ACME_ENCRYPTION_FLAG;
@@ -568,10 +568,10 @@  discard block
 block discarded – undo
568 568
                 STR_PAD_RIGHT
569 569
             )
570 570
         );
571
-        $string_bits    = str_split($encrypted_text);
571
+        $string_bits = str_split($encrypted_text);
572 572
         foreach ($string_bits as $k => $v) {
573
-            $temp              = ord($v) - ord($key_bits[ $k ]);
574
-            $string_bits[ $k ] = chr($temp < 0 ? ($temp + 256) : $temp);
573
+            $temp              = ord($v) - ord($key_bits[$k]);
574
+            $string_bits[$k] = chr($temp < 0 ? ($temp + 256) : $temp);
575 575
         }
576 576
         return implode('', $string_bits);
577 577
     }
@@ -585,16 +585,16 @@  discard block
 block discarded – undo
585 585
     protected function valid_base_64($string)
586 586
     {
587 587
         // ensure data is a string
588
-        if (! is_string($string) || ! $this->_use_base64_encode) {
588
+        if ( ! is_string($string) || ! $this->_use_base64_encode) {
589 589
             return false;
590 590
         }
591 591
         $decoded = base64_decode($string, true);
592 592
         // Check if there is no invalid character in string
593
-        if (! preg_match('/^[a-zA-Z0-9\/\r\n+]*={0,2}$/', $string)) {
593
+        if ( ! preg_match('/^[a-zA-Z0-9\/\r\n+]*={0,2}$/', $string)) {
594 594
             return false;
595 595
         }
596 596
         // Decode the string in strict mode and send the response
597
-        if (! base64_decode($string, true)) {
597
+        if ( ! base64_decode($string, true)) {
598 598
             return false;
599 599
         }
600 600
         // Encode and compare it to original one
@@ -614,7 +614,7 @@  discard block
 block discarded – undo
614 614
         $iterations    = ceil($length / 40);
615 615
         $random_string = '';
616 616
         for ($i = 0; $i < $iterations; $i++) {
617
-            $random_string .= sha1(microtime(true) . mt_rand(10000, 90000));
617
+            $random_string .= sha1(microtime(true).mt_rand(10000, 90000));
618 618
         }
619 619
         $random_string = substr($random_string, 0, $length);
620 620
         return $random_string;
Please login to merge, or discard this patch.
Indentation   +577 added lines, -577 removed lines patch added patch discarded remove patch
@@ -24,581 +24,581 @@
 block discarded – undo
24 24
  */
25 25
 class EE_Encryption implements InterminableInterface
26 26
 {
27
-    /**
28
-     * key used for saving the encryption key to the wp_options table
29
-     */
30
-    const ENCRYPTION_OPTION_KEY = 'ee_encryption_key';
31
-
32
-    /**
33
-     * the OPENSSL cipher method used
34
-     */
35
-    const OPENSSL_CIPHER_METHOD = 'AES-128-CBC';
36
-
37
-    /**
38
-     * WP "options_name" used to store a verified available cipher method
39
-     */
40
-    const OPENSSL_CIPHER_METHOD_OPTION_NAME = 'ee_openssl_cipher_method';
41
-
42
-    /**
43
-     * the OPENSSL digest method used
44
-     */
45
-    const OPENSSL_DIGEST_METHOD = 'sha512';
46
-
47
-    /**
48
-     * separates the encrypted text from the initialization vector
49
-     */
50
-    const OPENSSL_IV_DELIMITER = ':iv:';
51
-
52
-    /**
53
-     * appended to text encrypted using the acme encryption
54
-     */
55
-    const ACME_ENCRYPTION_FLAG = '::ae';
56
-
57
-
58
-    /**
59
-     * instance of the EE_Encryption object
60
-     */
61
-    protected static $_instance;
62
-
63
-    /**
64
-     * @var string $_encryption_key
65
-     */
66
-    protected $_encryption_key;
67
-
68
-    /**
69
-     * @var string $cipher_method
70
-     */
71
-    private $cipher_method = '';
72
-
73
-    /**
74
-     * @var array $cipher_methods
75
-     */
76
-    private $cipher_methods = [];
77
-
78
-    /**
79
-     * @var array $digest_methods
80
-     */
81
-    private $digest_methods = [];
82
-
83
-    /**
84
-     * @var boolean $_use_openssl_encrypt
85
-     */
86
-    protected $_use_openssl_encrypt = false;
87
-
88
-    /**
89
-     * @var boolean $_use_base64_encode
90
-     */
91
-    protected $_use_base64_encode = false;
92
-
93
-
94
-    /**
95
-     * protected constructor to prevent direct creation
96
-     */
97
-    protected function __construct()
98
-    {
99
-        if (! defined('ESPRESSO_ENCRYPT')) {
100
-            define('ESPRESSO_ENCRYPT', true);
101
-        }
102
-        if (extension_loaded('openssl')) {
103
-            $this->_use_openssl_encrypt = true;
104
-        }
105
-        if (function_exists('base64_encode')) {
106
-            $this->_use_base64_encode = true;
107
-        }
108
-    }
109
-
110
-
111
-    /**
112
-     * singleton method used to instantiate class object
113
-     *
114
-     * @return EE_Encryption
115
-     */
116
-    public static function instance()
117
-    {
118
-        // check if class object is instantiated
119
-        if (! EE_Encryption::$_instance instanceof EE_Encryption) {
120
-            EE_Encryption::$_instance = new self();
121
-        }
122
-        return EE_Encryption::$_instance;
123
-    }
124
-
125
-
126
-    /**
127
-     * get encryption key
128
-     *
129
-     * @return string
130
-     */
131
-    public function get_encryption_key()
132
-    {
133
-        // if encryption key has not been set
134
-        if (empty($this->_encryption_key)) {
135
-            // retrieve encryption_key from db
136
-            $this->_encryption_key = get_option(EE_Encryption::ENCRYPTION_OPTION_KEY, '');
137
-            // WHAT?? No encryption_key in the db ??
138
-            if ($this->_encryption_key === '') {
139
-                // let's make one. And md5 it to make it just the right size for a key
140
-                $new_key = md5($this->generate_random_string());
141
-                // now save it to the db for later
142
-                add_option(EE_Encryption::ENCRYPTION_OPTION_KEY, $new_key);
143
-                // here's the key - FINALLY !
144
-                $this->_encryption_key = $new_key;
145
-            }
146
-        }
147
-        return $this->_encryption_key;
148
-    }
149
-
150
-
151
-    /**
152
-     * encrypts data
153
-     *
154
-     * @param string $text_string - the text to be encrypted
155
-     * @return string
156
-     * @throws RuntimeException
157
-     */
158
-    public function encrypt($text_string = '')
159
-    {
160
-        // you give me nothing??? GET OUT !
161
-        if (empty($text_string)) {
162
-            return $text_string;
163
-        }
164
-        if ($this->_use_openssl_encrypt) {
165
-            $encrypted_text = $this->openssl_encrypt($text_string);
166
-        } else {
167
-            $encrypted_text = $this->acme_encrypt($text_string);
168
-        }
169
-        return $encrypted_text;
170
-    }
171
-
172
-
173
-    /**
174
-     * decrypts data
175
-     *
176
-     * @param string $encrypted_text - the text to be decrypted
177
-     * @return string
178
-     * @throws RuntimeException
179
-     */
180
-    public function decrypt($encrypted_text = '')
181
-    {
182
-        // you give me nothing??? GET OUT !
183
-        if (empty($encrypted_text)) {
184
-            return $encrypted_text;
185
-        }
186
-        // if PHP's mcrypt functions are installed then we'll use them
187
-        if ($this->_use_openssl_encrypt) {
188
-            $decrypted_text = $this->openssl_decrypt($encrypted_text);
189
-        } else {
190
-            $decrypted_text = $this->acme_decrypt($encrypted_text);
191
-        }
192
-        return $decrypted_text;
193
-    }
194
-
195
-
196
-    /**
197
-     * encodes string with PHP's base64 encoding
198
-     *
199
-     * @see http://php.net/manual/en/function.base64-encode.php
200
-     * @param string $text_string the text to be encoded
201
-     * @return string
202
-     */
203
-    public function base64_string_encode($text_string = '')
204
-    {
205
-        // you give me nothing??? GET OUT !
206
-        if (empty($text_string) || ! $this->_use_base64_encode) {
207
-            return $text_string;
208
-        }
209
-        // encode
210
-        return base64_encode($text_string);
211
-    }
212
-
213
-
214
-    /**
215
-     * decodes string that has been encoded with PHP's base64 encoding
216
-     *
217
-     * @see http://php.net/manual/en/function.base64-encode.php
218
-     * @param string $encoded_string the text to be decoded
219
-     * @return string
220
-     * @throws RuntimeException
221
-     */
222
-    public function base64_string_decode($encoded_string = '')
223
-    {
224
-        // you give me nothing??? GET OUT !
225
-        if (empty($encoded_string) || ! $this->valid_base_64($encoded_string)) {
226
-            return $encoded_string;
227
-        }
228
-        // decode
229
-        $decoded_string = base64_decode($encoded_string);
230
-        if ($decoded_string === false) {
231
-            throw new RuntimeException(
232
-                esc_html__('Base 64 decoding failed.', 'event_espresso')
233
-            );
234
-        }
235
-        return $decoded_string;
236
-    }
237
-
238
-
239
-    /**
240
-     * encodes  url string with PHP's base64 encoding
241
-     *
242
-     * @see http://php.net/manual/en/function.base64-encode.php
243
-     * @param string $text_string the text to be encoded
244
-     * @return string
245
-     */
246
-    public function base64_url_encode($text_string = '')
247
-    {
248
-        // you give me nothing??? GET OUT !
249
-        if (empty($text_string) || ! $this->_use_base64_encode) {
250
-            return $text_string;
251
-        }
252
-        // encode
253
-        $encoded_string = base64_encode($text_string);
254
-        // remove chars to make encoding more URL friendly
255
-        return strtr($encoded_string, '+/=', '-_,');
256
-    }
257
-
258
-
259
-    /**
260
-     * decodes  url string that has been encoded with PHP's base64 encoding
261
-     *
262
-     * @see http://php.net/manual/en/function.base64-encode.php
263
-     * @param string $encoded_string the text to be decoded
264
-     * @return string
265
-     * @throws RuntimeException
266
-     */
267
-    public function base64_url_decode($encoded_string = '')
268
-    {
269
-        // replace previously removed characters
270
-        $encoded_string = strtr($encoded_string, '-_,', '+/=');
271
-        // you give me nothing??? GET OUT !
272
-        if (empty($encoded_string) || ! $this->valid_base_64($encoded_string)) {
273
-            return $encoded_string;
274
-        }
275
-        // decode
276
-        $decoded_string = base64_decode($encoded_string);
277
-        if ($decoded_string === false) {
278
-            throw new RuntimeException(
279
-                esc_html__('Base 64 decoding failed.', 'event_espresso')
280
-            );
281
-        }
282
-        return $decoded_string;
283
-    }
284
-
285
-
286
-    /**
287
-     * encrypts data using PHP's openssl functions
288
-     *
289
-     * @param string $text_string the text to be encrypted
290
-     * @param string $cipher_method
291
-     * @param string $encryption_key
292
-     * @return string
293
-     * @throws RuntimeException
294
-     */
295
-    protected function openssl_encrypt(
296
-        $text_string = '',
297
-        $cipher_method = EE_Encryption::OPENSSL_CIPHER_METHOD,
298
-        $encryption_key = ''
299
-    ) {
300
-        // you give me nothing??? GET OUT !
301
-        if (empty($text_string)) {
302
-            return $text_string;
303
-        }
304
-        $this->cipher_method = $this->getCipherMethod($cipher_method);
305
-        // get initialization vector size
306
-        $iv_size = openssl_cipher_iv_length($this->cipher_method);
307
-        // generate initialization vector.
308
-        // The second parameter ("crypto_strong") is passed by reference,
309
-        // and is used to determines if the algorithm used was "cryptographically strong"
310
-        // openssl_random_pseudo_bytes() will toggle it to either true or false
311
-        $iv = openssl_random_pseudo_bytes($iv_size, $is_strong);
312
-        if ($iv === false || $is_strong === false) {
313
-            throw new RuntimeException(
314
-                esc_html__('Failed to generate OpenSSL initialization vector.', 'event_espresso')
315
-            );
316
-        }
317
-        // encrypt it
318
-        $encrypted_text = openssl_encrypt(
319
-            $text_string,
320
-            $this->cipher_method,
321
-            $this->getDigestHashValue(EE_Encryption::OPENSSL_DIGEST_METHOD, $encryption_key),
322
-            0,
323
-            $iv
324
-        );
325
-        // append the initialization vector
326
-        $encrypted_text .= EE_Encryption::OPENSSL_IV_DELIMITER . $iv;
327
-        // trim and maybe encode
328
-        return $this->_use_base64_encode
329
-            ? trim(base64_encode($encrypted_text))
330
-            : trim($encrypted_text);
331
-    }
332
-
333
-
334
-    /**
335
-     * Returns a cipher method that has been verified to work.
336
-     * First checks if the cached cipher has been set already and if so, returns that.
337
-     * Then tests the incoming default and returns that if it's good.
338
-     * If not, then it retrieves the previously tested and saved cipher method.
339
-     * But if that doesn't exist, then calls getAvailableCipherMethod()
340
-     * to see what is available on the server, and returns the results.
341
-     *
342
-     * @param string $cipher_method
343
-     * @return string
344
-     * @throws RuntimeException
345
-     */
346
-    protected function getCipherMethod($cipher_method = EE_Encryption::OPENSSL_CIPHER_METHOD)
347
-    {
348
-        if ($this->cipher_method !== '') {
349
-            return $this->cipher_method;
350
-        }
351
-        // verify that the default cipher method can produce an initialization vector
352
-        if (openssl_cipher_iv_length($cipher_method) === false) {
353
-            // nope? okay let's get what we found in the past to work
354
-            $cipher_method = get_option(EE_Encryption::OPENSSL_CIPHER_METHOD_OPTION_NAME, '');
355
-            // oops... haven't tested available cipher methods yet
356
-            if ($cipher_method === '' || openssl_cipher_iv_length($cipher_method) === false) {
357
-                $cipher_method = $this->getAvailableCipherMethod($cipher_method);
358
-            }
359
-        }
360
-        return $cipher_method;
361
-    }
362
-
363
-
364
-    /**
365
-     * @param string $cipher_method
366
-     * @return string
367
-     * @throws \RuntimeException
368
-     */
369
-    protected function getAvailableCipherMethod($cipher_method)
370
-    {
371
-        // verify that the incoming cipher method can produce an initialization vector
372
-        if (openssl_cipher_iv_length($cipher_method) === false) {
373
-            // nope? then check the next cipher in the list of available cipher methods
374
-            $cipher_method = next($this->cipher_methods);
375
-            // what? there's no list? then generate that list and cache it,
376
-            if (empty($this->cipher_methods)) {
377
-                $this->cipher_methods = openssl_get_cipher_methods();
378
-                // then grab the first item from the list
379
-                $cipher_method = reset($this->cipher_methods);
380
-            }
381
-            if ($cipher_method === false) {
382
-                throw new RuntimeException(
383
-                    esc_html__(
384
-                        'OpenSSL support appears to be enabled on the server, but no cipher methods are available. Please contact the server administrator.',
385
-                        'event_espresso'
386
-                    )
387
-                );
388
-            }
389
-            // verify that the next cipher method works
390
-            return $this->getAvailableCipherMethod($cipher_method);
391
-        }
392
-        // if we've gotten this far, then we found an available cipher method that works
393
-        // so save that for next time
394
-        update_option(
395
-            EE_Encryption::OPENSSL_CIPHER_METHOD_OPTION_NAME,
396
-            $cipher_method
397
-        );
398
-        return $cipher_method;
399
-    }
400
-
401
-
402
-    /**
403
-     * decrypts data that has been encrypted with PHP's openssl functions
404
-     *
405
-     * @param string $encrypted_text the text to be decrypted
406
-     * @param string $cipher_method
407
-     * @param string $encryption_key
408
-     * @return string
409
-     * @throws RuntimeException
410
-     */
411
-    protected function openssl_decrypt(
412
-        $encrypted_text = '',
413
-        $cipher_method = EE_Encryption::OPENSSL_CIPHER_METHOD,
414
-        $encryption_key = ''
415
-    ) {
416
-        // you give me nothing??? GET OUT !
417
-        if (empty($encrypted_text)) {
418
-            return $encrypted_text;
419
-        }
420
-        // decode
421
-        $encrypted_text       = $this->valid_base_64($encrypted_text)
422
-            ? $this->base64_url_decode($encrypted_text)
423
-            : $encrypted_text;
424
-        $encrypted_components = explode(
425
-            EE_Encryption::OPENSSL_IV_DELIMITER,
426
-            $encrypted_text,
427
-            2
428
-        );
429
-        // decrypt it
430
-        $decrypted_text = openssl_decrypt(
431
-            $encrypted_components[0],
432
-            $this->getCipherMethod($cipher_method),
433
-            $this->getDigestHashValue(EE_Encryption::OPENSSL_DIGEST_METHOD, $encryption_key),
434
-            0,
435
-            $encrypted_components[1]
436
-        );
437
-        $decrypted_text = trim($decrypted_text);
438
-        return $decrypted_text;
439
-    }
440
-
441
-
442
-    /**
443
-     * Computes the digest hash value using the specified digest method.
444
-     * If that digest method fails to produce a valid hash value,
445
-     * then we'll grab the next digest method and recursively try again until something works.
446
-     *
447
-     * @param string $digest_method
448
-     * @param string $encryption_key
449
-     * @return string
450
-     * @throws RuntimeException
451
-     */
452
-    protected function getDigestHashValue($digest_method = EE_Encryption::OPENSSL_DIGEST_METHOD, $encryption_key = '')
453
-    {
454
-        $encryption_key    = $encryption_key !== ''
455
-            ? $encryption_key
456
-            : $this->get_encryption_key();
457
-        $digest_hash_value = openssl_digest($encryption_key, $digest_method);
458
-        if ($digest_hash_value === false) {
459
-            return $this->getDigestHashValue($this->getDigestMethod());
460
-        }
461
-        return $digest_hash_value;
462
-    }
463
-
464
-
465
-    /**
466
-     * Returns the NEXT element in the $digest_methods array.
467
-     * If the $digest_methods array is empty, then we populate it
468
-     * with the available values returned from openssl_get_md_methods().
469
-     *
470
-     * @return string
471
-     * @throws \RuntimeException
472
-     */
473
-    protected function getDigestMethod()
474
-    {
475
-        $digest_method = prev($this->digest_methods);
476
-        if (empty($this->digest_methods)) {
477
-            $this->digest_methods = openssl_get_md_methods();
478
-            $digest_method        = end($this->digest_methods);
479
-        }
480
-        if ($digest_method === false) {
481
-            throw new RuntimeException(
482
-                esc_html__(
483
-                    'OpenSSL support appears to be enabled on the server, but no digest methods are available. Please contact the server administrator.',
484
-                    'event_espresso'
485
-                )
486
-            );
487
-        }
488
-        return $digest_method;
489
-    }
490
-
491
-
492
-    /**
493
-     * encrypts data for acme servers that didn't bother to install PHP mcrypt
494
-     *
495
-     * @see http://stackoverflow.com/questions/800922/how-to-encrypt-string-without-mcrypt-library-in-php
496
-     * @param string $text_string the text to be decrypted
497
-     * @return string
498
-     */
499
-    protected function acme_encrypt($text_string = '')
500
-    {
501
-        // you give me nothing??? GET OUT !
502
-        if (empty($text_string)) {
503
-            return $text_string;
504
-        }
505
-        $key_bits    = str_split(
506
-            str_pad(
507
-                '',
508
-                strlen($text_string),
509
-                $this->get_encryption_key(),
510
-                STR_PAD_RIGHT
511
-            )
512
-        );
513
-        $string_bits = str_split($text_string);
514
-        foreach ($string_bits as $k => $v) {
515
-            $temp              = ord($v) + ord($key_bits[ $k ]);
516
-            $string_bits[ $k ] = chr($temp > 255 ? ($temp - 256) : $temp);
517
-        }
518
-        $encrypted_text = implode('', $string_bits);
519
-        $encrypted_text .= EE_Encryption::ACME_ENCRYPTION_FLAG;
520
-        return $this->_use_base64_encode
521
-            ? base64_encode($encrypted_text)
522
-            : $encrypted_text;
523
-    }
524
-
525
-
526
-    /**
527
-     * decrypts data for acme servers that didn't bother to install PHP mcrypt
528
-     *
529
-     * @see http://stackoverflow.com/questions/800922/how-to-encrypt-string-without-mcrypt-library-in-php
530
-     * @param string $encrypted_text the text to be decrypted
531
-     * @return string
532
-     * @throws RuntimeException
533
-     */
534
-    protected function acme_decrypt($encrypted_text = '')
535
-    {
536
-        // you give me nothing??? GET OUT !
537
-        if (empty($encrypted_text)) {
538
-            return $encrypted_text;
539
-        }
540
-        // decode the data ?
541
-        $encrypted_text = $this->valid_base_64($encrypted_text)
542
-            ? $this->base64_url_decode($encrypted_text)
543
-            : $encrypted_text;
544
-        $encrypted_text = substr($encrypted_text, 0, -4);
545
-        $key_bits       = str_split(
546
-            str_pad(
547
-                '',
548
-                strlen($encrypted_text),
549
-                $this->get_encryption_key(),
550
-                STR_PAD_RIGHT
551
-            )
552
-        );
553
-        $string_bits    = str_split($encrypted_text);
554
-        foreach ($string_bits as $k => $v) {
555
-            $temp              = ord($v) - ord($key_bits[ $k ]);
556
-            $string_bits[ $k ] = chr($temp < 0 ? ($temp + 256) : $temp);
557
-        }
558
-        return implode('', $string_bits);
559
-    }
560
-
561
-
562
-    /**
563
-     * @see http://stackoverflow.com/questions/2556345/detect-base64-encoding-in-php#30231906
564
-     * @param $string
565
-     * @return bool
566
-     */
567
-    protected function valid_base_64($string)
568
-    {
569
-        // ensure data is a string
570
-        if (! is_string($string) || ! $this->_use_base64_encode) {
571
-            return false;
572
-        }
573
-        $decoded = base64_decode($string, true);
574
-        // Check if there is no invalid character in string
575
-        if (! preg_match('/^[a-zA-Z0-9\/\r\n+]*={0,2}$/', $string)) {
576
-            return false;
577
-        }
578
-        // Decode the string in strict mode and send the response
579
-        if (! base64_decode($string, true)) {
580
-            return false;
581
-        }
582
-        // Encode and compare it to original one
583
-        return base64_encode($decoded) === $string;
584
-    }
585
-
586
-
587
-    /**
588
-     * generate random string
589
-     *
590
-     * @see http://stackoverflow.com/questions/637278/what-is-the-best-way-to-generate-a-random-key-within-php
591
-     * @param int $length number of characters for random string
592
-     * @return string
593
-     */
594
-    public function generate_random_string($length = 40)
595
-    {
596
-        $iterations    = ceil($length / 40);
597
-        $random_string = '';
598
-        for ($i = 0; $i < $iterations; $i++) {
599
-            $random_string .= sha1(microtime(true) . mt_rand(10000, 90000));
600
-        }
601
-        $random_string = substr($random_string, 0, $length);
602
-        return $random_string;
603
-    }
27
+	/**
28
+	 * key used for saving the encryption key to the wp_options table
29
+	 */
30
+	const ENCRYPTION_OPTION_KEY = 'ee_encryption_key';
31
+
32
+	/**
33
+	 * the OPENSSL cipher method used
34
+	 */
35
+	const OPENSSL_CIPHER_METHOD = 'AES-128-CBC';
36
+
37
+	/**
38
+	 * WP "options_name" used to store a verified available cipher method
39
+	 */
40
+	const OPENSSL_CIPHER_METHOD_OPTION_NAME = 'ee_openssl_cipher_method';
41
+
42
+	/**
43
+	 * the OPENSSL digest method used
44
+	 */
45
+	const OPENSSL_DIGEST_METHOD = 'sha512';
46
+
47
+	/**
48
+	 * separates the encrypted text from the initialization vector
49
+	 */
50
+	const OPENSSL_IV_DELIMITER = ':iv:';
51
+
52
+	/**
53
+	 * appended to text encrypted using the acme encryption
54
+	 */
55
+	const ACME_ENCRYPTION_FLAG = '::ae';
56
+
57
+
58
+	/**
59
+	 * instance of the EE_Encryption object
60
+	 */
61
+	protected static $_instance;
62
+
63
+	/**
64
+	 * @var string $_encryption_key
65
+	 */
66
+	protected $_encryption_key;
67
+
68
+	/**
69
+	 * @var string $cipher_method
70
+	 */
71
+	private $cipher_method = '';
72
+
73
+	/**
74
+	 * @var array $cipher_methods
75
+	 */
76
+	private $cipher_methods = [];
77
+
78
+	/**
79
+	 * @var array $digest_methods
80
+	 */
81
+	private $digest_methods = [];
82
+
83
+	/**
84
+	 * @var boolean $_use_openssl_encrypt
85
+	 */
86
+	protected $_use_openssl_encrypt = false;
87
+
88
+	/**
89
+	 * @var boolean $_use_base64_encode
90
+	 */
91
+	protected $_use_base64_encode = false;
92
+
93
+
94
+	/**
95
+	 * protected constructor to prevent direct creation
96
+	 */
97
+	protected function __construct()
98
+	{
99
+		if (! defined('ESPRESSO_ENCRYPT')) {
100
+			define('ESPRESSO_ENCRYPT', true);
101
+		}
102
+		if (extension_loaded('openssl')) {
103
+			$this->_use_openssl_encrypt = true;
104
+		}
105
+		if (function_exists('base64_encode')) {
106
+			$this->_use_base64_encode = true;
107
+		}
108
+	}
109
+
110
+
111
+	/**
112
+	 * singleton method used to instantiate class object
113
+	 *
114
+	 * @return EE_Encryption
115
+	 */
116
+	public static function instance()
117
+	{
118
+		// check if class object is instantiated
119
+		if (! EE_Encryption::$_instance instanceof EE_Encryption) {
120
+			EE_Encryption::$_instance = new self();
121
+		}
122
+		return EE_Encryption::$_instance;
123
+	}
124
+
125
+
126
+	/**
127
+	 * get encryption key
128
+	 *
129
+	 * @return string
130
+	 */
131
+	public function get_encryption_key()
132
+	{
133
+		// if encryption key has not been set
134
+		if (empty($this->_encryption_key)) {
135
+			// retrieve encryption_key from db
136
+			$this->_encryption_key = get_option(EE_Encryption::ENCRYPTION_OPTION_KEY, '');
137
+			// WHAT?? No encryption_key in the db ??
138
+			if ($this->_encryption_key === '') {
139
+				// let's make one. And md5 it to make it just the right size for a key
140
+				$new_key = md5($this->generate_random_string());
141
+				// now save it to the db for later
142
+				add_option(EE_Encryption::ENCRYPTION_OPTION_KEY, $new_key);
143
+				// here's the key - FINALLY !
144
+				$this->_encryption_key = $new_key;
145
+			}
146
+		}
147
+		return $this->_encryption_key;
148
+	}
149
+
150
+
151
+	/**
152
+	 * encrypts data
153
+	 *
154
+	 * @param string $text_string - the text to be encrypted
155
+	 * @return string
156
+	 * @throws RuntimeException
157
+	 */
158
+	public function encrypt($text_string = '')
159
+	{
160
+		// you give me nothing??? GET OUT !
161
+		if (empty($text_string)) {
162
+			return $text_string;
163
+		}
164
+		if ($this->_use_openssl_encrypt) {
165
+			$encrypted_text = $this->openssl_encrypt($text_string);
166
+		} else {
167
+			$encrypted_text = $this->acme_encrypt($text_string);
168
+		}
169
+		return $encrypted_text;
170
+	}
171
+
172
+
173
+	/**
174
+	 * decrypts data
175
+	 *
176
+	 * @param string $encrypted_text - the text to be decrypted
177
+	 * @return string
178
+	 * @throws RuntimeException
179
+	 */
180
+	public function decrypt($encrypted_text = '')
181
+	{
182
+		// you give me nothing??? GET OUT !
183
+		if (empty($encrypted_text)) {
184
+			return $encrypted_text;
185
+		}
186
+		// if PHP's mcrypt functions are installed then we'll use them
187
+		if ($this->_use_openssl_encrypt) {
188
+			$decrypted_text = $this->openssl_decrypt($encrypted_text);
189
+		} else {
190
+			$decrypted_text = $this->acme_decrypt($encrypted_text);
191
+		}
192
+		return $decrypted_text;
193
+	}
194
+
195
+
196
+	/**
197
+	 * encodes string with PHP's base64 encoding
198
+	 *
199
+	 * @see http://php.net/manual/en/function.base64-encode.php
200
+	 * @param string $text_string the text to be encoded
201
+	 * @return string
202
+	 */
203
+	public function base64_string_encode($text_string = '')
204
+	{
205
+		// you give me nothing??? GET OUT !
206
+		if (empty($text_string) || ! $this->_use_base64_encode) {
207
+			return $text_string;
208
+		}
209
+		// encode
210
+		return base64_encode($text_string);
211
+	}
212
+
213
+
214
+	/**
215
+	 * decodes string that has been encoded with PHP's base64 encoding
216
+	 *
217
+	 * @see http://php.net/manual/en/function.base64-encode.php
218
+	 * @param string $encoded_string the text to be decoded
219
+	 * @return string
220
+	 * @throws RuntimeException
221
+	 */
222
+	public function base64_string_decode($encoded_string = '')
223
+	{
224
+		// you give me nothing??? GET OUT !
225
+		if (empty($encoded_string) || ! $this->valid_base_64($encoded_string)) {
226
+			return $encoded_string;
227
+		}
228
+		// decode
229
+		$decoded_string = base64_decode($encoded_string);
230
+		if ($decoded_string === false) {
231
+			throw new RuntimeException(
232
+				esc_html__('Base 64 decoding failed.', 'event_espresso')
233
+			);
234
+		}
235
+		return $decoded_string;
236
+	}
237
+
238
+
239
+	/**
240
+	 * encodes  url string with PHP's base64 encoding
241
+	 *
242
+	 * @see http://php.net/manual/en/function.base64-encode.php
243
+	 * @param string $text_string the text to be encoded
244
+	 * @return string
245
+	 */
246
+	public function base64_url_encode($text_string = '')
247
+	{
248
+		// you give me nothing??? GET OUT !
249
+		if (empty($text_string) || ! $this->_use_base64_encode) {
250
+			return $text_string;
251
+		}
252
+		// encode
253
+		$encoded_string = base64_encode($text_string);
254
+		// remove chars to make encoding more URL friendly
255
+		return strtr($encoded_string, '+/=', '-_,');
256
+	}
257
+
258
+
259
+	/**
260
+	 * decodes  url string that has been encoded with PHP's base64 encoding
261
+	 *
262
+	 * @see http://php.net/manual/en/function.base64-encode.php
263
+	 * @param string $encoded_string the text to be decoded
264
+	 * @return string
265
+	 * @throws RuntimeException
266
+	 */
267
+	public function base64_url_decode($encoded_string = '')
268
+	{
269
+		// replace previously removed characters
270
+		$encoded_string = strtr($encoded_string, '-_,', '+/=');
271
+		// you give me nothing??? GET OUT !
272
+		if (empty($encoded_string) || ! $this->valid_base_64($encoded_string)) {
273
+			return $encoded_string;
274
+		}
275
+		// decode
276
+		$decoded_string = base64_decode($encoded_string);
277
+		if ($decoded_string === false) {
278
+			throw new RuntimeException(
279
+				esc_html__('Base 64 decoding failed.', 'event_espresso')
280
+			);
281
+		}
282
+		return $decoded_string;
283
+	}
284
+
285
+
286
+	/**
287
+	 * encrypts data using PHP's openssl functions
288
+	 *
289
+	 * @param string $text_string the text to be encrypted
290
+	 * @param string $cipher_method
291
+	 * @param string $encryption_key
292
+	 * @return string
293
+	 * @throws RuntimeException
294
+	 */
295
+	protected function openssl_encrypt(
296
+		$text_string = '',
297
+		$cipher_method = EE_Encryption::OPENSSL_CIPHER_METHOD,
298
+		$encryption_key = ''
299
+	) {
300
+		// you give me nothing??? GET OUT !
301
+		if (empty($text_string)) {
302
+			return $text_string;
303
+		}
304
+		$this->cipher_method = $this->getCipherMethod($cipher_method);
305
+		// get initialization vector size
306
+		$iv_size = openssl_cipher_iv_length($this->cipher_method);
307
+		// generate initialization vector.
308
+		// The second parameter ("crypto_strong") is passed by reference,
309
+		// and is used to determines if the algorithm used was "cryptographically strong"
310
+		// openssl_random_pseudo_bytes() will toggle it to either true or false
311
+		$iv = openssl_random_pseudo_bytes($iv_size, $is_strong);
312
+		if ($iv === false || $is_strong === false) {
313
+			throw new RuntimeException(
314
+				esc_html__('Failed to generate OpenSSL initialization vector.', 'event_espresso')
315
+			);
316
+		}
317
+		// encrypt it
318
+		$encrypted_text = openssl_encrypt(
319
+			$text_string,
320
+			$this->cipher_method,
321
+			$this->getDigestHashValue(EE_Encryption::OPENSSL_DIGEST_METHOD, $encryption_key),
322
+			0,
323
+			$iv
324
+		);
325
+		// append the initialization vector
326
+		$encrypted_text .= EE_Encryption::OPENSSL_IV_DELIMITER . $iv;
327
+		// trim and maybe encode
328
+		return $this->_use_base64_encode
329
+			? trim(base64_encode($encrypted_text))
330
+			: trim($encrypted_text);
331
+	}
332
+
333
+
334
+	/**
335
+	 * Returns a cipher method that has been verified to work.
336
+	 * First checks if the cached cipher has been set already and if so, returns that.
337
+	 * Then tests the incoming default and returns that if it's good.
338
+	 * If not, then it retrieves the previously tested and saved cipher method.
339
+	 * But if that doesn't exist, then calls getAvailableCipherMethod()
340
+	 * to see what is available on the server, and returns the results.
341
+	 *
342
+	 * @param string $cipher_method
343
+	 * @return string
344
+	 * @throws RuntimeException
345
+	 */
346
+	protected function getCipherMethod($cipher_method = EE_Encryption::OPENSSL_CIPHER_METHOD)
347
+	{
348
+		if ($this->cipher_method !== '') {
349
+			return $this->cipher_method;
350
+		}
351
+		// verify that the default cipher method can produce an initialization vector
352
+		if (openssl_cipher_iv_length($cipher_method) === false) {
353
+			// nope? okay let's get what we found in the past to work
354
+			$cipher_method = get_option(EE_Encryption::OPENSSL_CIPHER_METHOD_OPTION_NAME, '');
355
+			// oops... haven't tested available cipher methods yet
356
+			if ($cipher_method === '' || openssl_cipher_iv_length($cipher_method) === false) {
357
+				$cipher_method = $this->getAvailableCipherMethod($cipher_method);
358
+			}
359
+		}
360
+		return $cipher_method;
361
+	}
362
+
363
+
364
+	/**
365
+	 * @param string $cipher_method
366
+	 * @return string
367
+	 * @throws \RuntimeException
368
+	 */
369
+	protected function getAvailableCipherMethod($cipher_method)
370
+	{
371
+		// verify that the incoming cipher method can produce an initialization vector
372
+		if (openssl_cipher_iv_length($cipher_method) === false) {
373
+			// nope? then check the next cipher in the list of available cipher methods
374
+			$cipher_method = next($this->cipher_methods);
375
+			// what? there's no list? then generate that list and cache it,
376
+			if (empty($this->cipher_methods)) {
377
+				$this->cipher_methods = openssl_get_cipher_methods();
378
+				// then grab the first item from the list
379
+				$cipher_method = reset($this->cipher_methods);
380
+			}
381
+			if ($cipher_method === false) {
382
+				throw new RuntimeException(
383
+					esc_html__(
384
+						'OpenSSL support appears to be enabled on the server, but no cipher methods are available. Please contact the server administrator.',
385
+						'event_espresso'
386
+					)
387
+				);
388
+			}
389
+			// verify that the next cipher method works
390
+			return $this->getAvailableCipherMethod($cipher_method);
391
+		}
392
+		// if we've gotten this far, then we found an available cipher method that works
393
+		// so save that for next time
394
+		update_option(
395
+			EE_Encryption::OPENSSL_CIPHER_METHOD_OPTION_NAME,
396
+			$cipher_method
397
+		);
398
+		return $cipher_method;
399
+	}
400
+
401
+
402
+	/**
403
+	 * decrypts data that has been encrypted with PHP's openssl functions
404
+	 *
405
+	 * @param string $encrypted_text the text to be decrypted
406
+	 * @param string $cipher_method
407
+	 * @param string $encryption_key
408
+	 * @return string
409
+	 * @throws RuntimeException
410
+	 */
411
+	protected function openssl_decrypt(
412
+		$encrypted_text = '',
413
+		$cipher_method = EE_Encryption::OPENSSL_CIPHER_METHOD,
414
+		$encryption_key = ''
415
+	) {
416
+		// you give me nothing??? GET OUT !
417
+		if (empty($encrypted_text)) {
418
+			return $encrypted_text;
419
+		}
420
+		// decode
421
+		$encrypted_text       = $this->valid_base_64($encrypted_text)
422
+			? $this->base64_url_decode($encrypted_text)
423
+			: $encrypted_text;
424
+		$encrypted_components = explode(
425
+			EE_Encryption::OPENSSL_IV_DELIMITER,
426
+			$encrypted_text,
427
+			2
428
+		);
429
+		// decrypt it
430
+		$decrypted_text = openssl_decrypt(
431
+			$encrypted_components[0],
432
+			$this->getCipherMethod($cipher_method),
433
+			$this->getDigestHashValue(EE_Encryption::OPENSSL_DIGEST_METHOD, $encryption_key),
434
+			0,
435
+			$encrypted_components[1]
436
+		);
437
+		$decrypted_text = trim($decrypted_text);
438
+		return $decrypted_text;
439
+	}
440
+
441
+
442
+	/**
443
+	 * Computes the digest hash value using the specified digest method.
444
+	 * If that digest method fails to produce a valid hash value,
445
+	 * then we'll grab the next digest method and recursively try again until something works.
446
+	 *
447
+	 * @param string $digest_method
448
+	 * @param string $encryption_key
449
+	 * @return string
450
+	 * @throws RuntimeException
451
+	 */
452
+	protected function getDigestHashValue($digest_method = EE_Encryption::OPENSSL_DIGEST_METHOD, $encryption_key = '')
453
+	{
454
+		$encryption_key    = $encryption_key !== ''
455
+			? $encryption_key
456
+			: $this->get_encryption_key();
457
+		$digest_hash_value = openssl_digest($encryption_key, $digest_method);
458
+		if ($digest_hash_value === false) {
459
+			return $this->getDigestHashValue($this->getDigestMethod());
460
+		}
461
+		return $digest_hash_value;
462
+	}
463
+
464
+
465
+	/**
466
+	 * Returns the NEXT element in the $digest_methods array.
467
+	 * If the $digest_methods array is empty, then we populate it
468
+	 * with the available values returned from openssl_get_md_methods().
469
+	 *
470
+	 * @return string
471
+	 * @throws \RuntimeException
472
+	 */
473
+	protected function getDigestMethod()
474
+	{
475
+		$digest_method = prev($this->digest_methods);
476
+		if (empty($this->digest_methods)) {
477
+			$this->digest_methods = openssl_get_md_methods();
478
+			$digest_method        = end($this->digest_methods);
479
+		}
480
+		if ($digest_method === false) {
481
+			throw new RuntimeException(
482
+				esc_html__(
483
+					'OpenSSL support appears to be enabled on the server, but no digest methods are available. Please contact the server administrator.',
484
+					'event_espresso'
485
+				)
486
+			);
487
+		}
488
+		return $digest_method;
489
+	}
490
+
491
+
492
+	/**
493
+	 * encrypts data for acme servers that didn't bother to install PHP mcrypt
494
+	 *
495
+	 * @see http://stackoverflow.com/questions/800922/how-to-encrypt-string-without-mcrypt-library-in-php
496
+	 * @param string $text_string the text to be decrypted
497
+	 * @return string
498
+	 */
499
+	protected function acme_encrypt($text_string = '')
500
+	{
501
+		// you give me nothing??? GET OUT !
502
+		if (empty($text_string)) {
503
+			return $text_string;
504
+		}
505
+		$key_bits    = str_split(
506
+			str_pad(
507
+				'',
508
+				strlen($text_string),
509
+				$this->get_encryption_key(),
510
+				STR_PAD_RIGHT
511
+			)
512
+		);
513
+		$string_bits = str_split($text_string);
514
+		foreach ($string_bits as $k => $v) {
515
+			$temp              = ord($v) + ord($key_bits[ $k ]);
516
+			$string_bits[ $k ] = chr($temp > 255 ? ($temp - 256) : $temp);
517
+		}
518
+		$encrypted_text = implode('', $string_bits);
519
+		$encrypted_text .= EE_Encryption::ACME_ENCRYPTION_FLAG;
520
+		return $this->_use_base64_encode
521
+			? base64_encode($encrypted_text)
522
+			: $encrypted_text;
523
+	}
524
+
525
+
526
+	/**
527
+	 * decrypts data for acme servers that didn't bother to install PHP mcrypt
528
+	 *
529
+	 * @see http://stackoverflow.com/questions/800922/how-to-encrypt-string-without-mcrypt-library-in-php
530
+	 * @param string $encrypted_text the text to be decrypted
531
+	 * @return string
532
+	 * @throws RuntimeException
533
+	 */
534
+	protected function acme_decrypt($encrypted_text = '')
535
+	{
536
+		// you give me nothing??? GET OUT !
537
+		if (empty($encrypted_text)) {
538
+			return $encrypted_text;
539
+		}
540
+		// decode the data ?
541
+		$encrypted_text = $this->valid_base_64($encrypted_text)
542
+			? $this->base64_url_decode($encrypted_text)
543
+			: $encrypted_text;
544
+		$encrypted_text = substr($encrypted_text, 0, -4);
545
+		$key_bits       = str_split(
546
+			str_pad(
547
+				'',
548
+				strlen($encrypted_text),
549
+				$this->get_encryption_key(),
550
+				STR_PAD_RIGHT
551
+			)
552
+		);
553
+		$string_bits    = str_split($encrypted_text);
554
+		foreach ($string_bits as $k => $v) {
555
+			$temp              = ord($v) - ord($key_bits[ $k ]);
556
+			$string_bits[ $k ] = chr($temp < 0 ? ($temp + 256) : $temp);
557
+		}
558
+		return implode('', $string_bits);
559
+	}
560
+
561
+
562
+	/**
563
+	 * @see http://stackoverflow.com/questions/2556345/detect-base64-encoding-in-php#30231906
564
+	 * @param $string
565
+	 * @return bool
566
+	 */
567
+	protected function valid_base_64($string)
568
+	{
569
+		// ensure data is a string
570
+		if (! is_string($string) || ! $this->_use_base64_encode) {
571
+			return false;
572
+		}
573
+		$decoded = base64_decode($string, true);
574
+		// Check if there is no invalid character in string
575
+		if (! preg_match('/^[a-zA-Z0-9\/\r\n+]*={0,2}$/', $string)) {
576
+			return false;
577
+		}
578
+		// Decode the string in strict mode and send the response
579
+		if (! base64_decode($string, true)) {
580
+			return false;
581
+		}
582
+		// Encode and compare it to original one
583
+		return base64_encode($decoded) === $string;
584
+	}
585
+
586
+
587
+	/**
588
+	 * generate random string
589
+	 *
590
+	 * @see http://stackoverflow.com/questions/637278/what-is-the-best-way-to-generate-a-random-key-within-php
591
+	 * @param int $length number of characters for random string
592
+	 * @return string
593
+	 */
594
+	public function generate_random_string($length = 40)
595
+	{
596
+		$iterations    = ceil($length / 40);
597
+		$random_string = '';
598
+		for ($i = 0; $i < $iterations; $i++) {
599
+			$random_string .= sha1(microtime(true) . mt_rand(10000, 90000));
600
+		}
601
+		$random_string = substr($random_string, 0, $length);
602
+		return $random_string;
603
+	}
604 604
 }
Please login to merge, or discard this patch.
core/services/json/JsonDataNode.php 2 patches
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -70,7 +70,7 @@  discard block
 block discarded – undo
70 70
     protected function addData(string $key, $data)
71 71
     {
72 72
         if ($this->validator->propertyNotSet($this->data, $key)) {
73
-            $this->data[ $key ] = $data;
73
+            $this->data[$key] = $data;
74 74
         }
75 75
     }
76 76
 
@@ -168,7 +168,7 @@  discard block
 block discarded – undo
168 168
             EEH_Array::is_associative_array($this->data)
169 169
                 ? uasort(
170 170
                     $this->data,
171
-                    function ($a, $b) {
171
+                    function($a, $b) {
172 172
                         // check if each incoming argument is a node and if they have an order set
173 173
                         // if so, then use that for our sorting comparison. otherwise use the node's name...
174 174
                         // unless it's NOT a node, in which case use the arg value if it is scalar, or 0 if not.
Please login to merge, or discard this patch.
Indentation   +246 added lines, -246 removed lines patch added patch discarded remove patch
@@ -18,250 +18,250 @@
 block discarded – undo
18 18
  */
19 19
 abstract class JsonDataNode implements JsonDataNodeInterface
20 20
 {
21
-    /**
22
-     * @var JsonDataNodeValidator
23
-     */
24
-    protected $validator;
25
-
26
-    /**
27
-     * @var array
28
-     */
29
-    private $data = [];
30
-
31
-    /**
32
-     * @var string
33
-     */
34
-    private $domain = '';
35
-
36
-    /**
37
-     * @var boolean
38
-     */
39
-    private $initialized = false;
40
-
41
-    /**
42
-     * @var string
43
-     */
44
-    private $node_name = '';
45
-
46
-    /**
47
-     * @var int
48
-     */
49
-    private $order = 50;
50
-
51
-
52
-    /**
53
-     * @param JsonDataNodeValidator $validator
54
-     * @throws DomainException
55
-     */
56
-    public function __construct(JsonDataNodeValidator $validator)
57
-    {
58
-        $this->validator = $validator;
59
-    }
60
-
61
-
62
-    /**
63
-     * for adding primitive data like arrays, integers, or strings
64
-     *
65
-     * @param string $key
66
-     * @param mixed  $data
67
-     * @throws DomainException
68
-     */
69
-    protected function addData(string $key, $data)
70
-    {
71
-        if ($this->validator->propertyNotSet($this->data, $key)) {
72
-            $this->data[ $key ] = $data;
73
-        }
74
-    }
75
-
76
-
77
-    /**
78
-     * for setting value of the entire data array for the node
79
-     *
80
-     * @param array $data
81
-     * @throws DomainException
82
-     */
83
-    protected function setDataArray(array $data)
84
-    {
85
-        if ($this->validator->dataArrayEmpty($this)) {
86
-            $this->data = $data;
87
-        }
88
-    }
89
-
90
-
91
-    /**
92
-     * for embedding other JsonDataNode objects within this one
93
-     *
94
-     * @param JsonDataNode $data_node
95
-     * @throws DomainException
96
-     */
97
-    public function addDataNode(JsonDataNode $data_node)
98
-    {
99
-        if ($data_node->isNotInitialized()) {
100
-            // $data_node->initialize();
101
-            $key = $data_node->nodeName();
102
-            $this->addData($key, $data_node);
103
-            // if the node being added specifies a domain (use case)
104
-            // and this is the primary data node, then set the domain
105
-            if ($this instanceof PrimaryJsonDataNode && $data_node->domain()) {
106
-                $this->setDomain($data_node->domain());
107
-            }
108
-        }
109
-    }
110
-
111
-
112
-    /**
113
-     * sets the domain (use case) that this data node provides data for
114
-     *
115
-     * @param string $domain
116
-     * @throws DomainException
117
-     */
118
-    protected function setDomain(string $domain)
119
-    {
120
-        if ($this->domain !== '') {
121
-            $this->validator->overwriteError($domain, 'domain route');
122
-        }
123
-        $this->domain = $domain;
124
-    }
125
-
126
-
127
-    /**
128
-     * used to mark the data node as having been processed
129
-     *
130
-     * @param bool $initialized
131
-     */
132
-    protected function setInitialized(bool $initialized)
133
-    {
134
-        $this->initialized = filter_var($initialized, FILTER_VALIDATE_BOOLEAN);
135
-    }
136
-
137
-
138
-    /**
139
-     * self explanatory (i hope)
140
-     *
141
-     * @param string $node_name
142
-     * @throws DomainException
143
-     */
144
-    protected function setNodeName(string $node_name)
145
-    {
146
-        $this->validator->validateCriticalProperty($node_name, 'node name');
147
-        $this->node_name = $node_name;
148
-        // by default set the data node order property by the alphabetical position of the first letter of its name
149
-        // we do this by passing the node name (in UPPERCASE) to ord() to get its ASCII position
150
-        // then we subtract 64 (cuz A has a position of 65) then multiply by 10 just to space things out a bit.
151
-        // this allows a data node to set its order upon construction to some other value
152
-        // so that it can squeak into whatever position it needs to be in, like 55
153
-        $this->setOrder((ord(strtoupper($this->node_name)) - 64) * 10);
154
-    }
155
-
156
-
157
-    /**
158
-     * the actual data in key value array format
159
-     *
160
-     * @param bool $sort
161
-     * @return array
162
-     */
163
-    public function data(bool $sort = false): array
164
-    {
165
-        if ($sort) {
166
-            // check if data array has non-numerical keys and use a custom sort algorithm, else sort by keys
167
-            EEH_Array::is_associative_array($this->data)
168
-                ? uasort(
169
-                    $this->data,
170
-                    function ($a, $b) {
171
-                        // check if each incoming argument is a node and if they have an order set
172
-                        // if so, then use that for our sorting comparison. otherwise use the node's name...
173
-                        // unless it's NOT a node, in which case use the arg value if it is scalar, or 0 if not.
174
-                        if ($a instanceof JsonDataNode) {
175
-                            $a_ord = $a->order() ?: $a->nodeName();
176
-                        } else {
177
-                            $a_ord = is_scalar($a) ?: 0;
178
-                        }
179
-                        if ($b instanceof JsonDataNode) {
180
-                            $b_ord = $b->order() ?: $b->nodeName();
181
-                        } else {
182
-                            $b_ord = is_scalar($b) ?: 0;
183
-                        }
184
-                        return $a_ord <=> $b_ord;
185
-                    }
186
-                )
187
-                // sort numerically indexed arrays by their keys
188
-                : ksort($this->data);
189
-        }
190
-        return $this->data;
191
-    }
192
-
193
-
194
-    /**
195
-     * the domain (use case) that this data node provides data for
196
-     *
197
-     * @return string
198
-     */
199
-    public function domain(): string
200
-    {
201
-        return $this->domain;
202
-    }
203
-
204
-
205
-    /**
206
-     * true if the data node has been initialized,
207
-     * which entails retrieving the required data and adding it to the data node data array
208
-     *
209
-     * @return bool
210
-     */
211
-    public function isInitialized(): bool
212
-    {
213
-        return $this->initialized;
214
-    }
215
-
216
-
217
-    /**
218
-     * true if the data node has NOT been initialized
219
-     *
220
-     * @return bool
221
-     */
222
-    public function isNotInitialized(): bool
223
-    {
224
-        return ! $this->initialized;
225
-    }
226
-
227
-
228
-    /**
229
-     * Specify data which should be serialized to JSON
230
-     *
231
-     * @link  https://php.net/manual/en/jsonserializable.jsonserialize.php
232
-     * @return array data which can be serialized by json_encode
233
-     */
234
-    public function jsonSerialize(): array
235
-    {
236
-        return $this->data;
237
-    }
238
-
239
-
240
-    /**
241
-     * self explanatory (i hope)
242
-     *
243
-     * @return string
244
-     */
245
-    public function nodeName(): string
246
-    {
247
-        return $this->node_name;
248
-    }
249
-
250
-
251
-    /**
252
-     * @return int
253
-     */
254
-    public function order(): ?int
255
-    {
256
-        return $this->order;
257
-    }
258
-
259
-
260
-    /**
261
-     * @param int $order
262
-     */
263
-    protected function setOrder(int $order): void
264
-    {
265
-        $this->order = absint($order);
266
-    }
21
+	/**
22
+	 * @var JsonDataNodeValidator
23
+	 */
24
+	protected $validator;
25
+
26
+	/**
27
+	 * @var array
28
+	 */
29
+	private $data = [];
30
+
31
+	/**
32
+	 * @var string
33
+	 */
34
+	private $domain = '';
35
+
36
+	/**
37
+	 * @var boolean
38
+	 */
39
+	private $initialized = false;
40
+
41
+	/**
42
+	 * @var string
43
+	 */
44
+	private $node_name = '';
45
+
46
+	/**
47
+	 * @var int
48
+	 */
49
+	private $order = 50;
50
+
51
+
52
+	/**
53
+	 * @param JsonDataNodeValidator $validator
54
+	 * @throws DomainException
55
+	 */
56
+	public function __construct(JsonDataNodeValidator $validator)
57
+	{
58
+		$this->validator = $validator;
59
+	}
60
+
61
+
62
+	/**
63
+	 * for adding primitive data like arrays, integers, or strings
64
+	 *
65
+	 * @param string $key
66
+	 * @param mixed  $data
67
+	 * @throws DomainException
68
+	 */
69
+	protected function addData(string $key, $data)
70
+	{
71
+		if ($this->validator->propertyNotSet($this->data, $key)) {
72
+			$this->data[ $key ] = $data;
73
+		}
74
+	}
75
+
76
+
77
+	/**
78
+	 * for setting value of the entire data array for the node
79
+	 *
80
+	 * @param array $data
81
+	 * @throws DomainException
82
+	 */
83
+	protected function setDataArray(array $data)
84
+	{
85
+		if ($this->validator->dataArrayEmpty($this)) {
86
+			$this->data = $data;
87
+		}
88
+	}
89
+
90
+
91
+	/**
92
+	 * for embedding other JsonDataNode objects within this one
93
+	 *
94
+	 * @param JsonDataNode $data_node
95
+	 * @throws DomainException
96
+	 */
97
+	public function addDataNode(JsonDataNode $data_node)
98
+	{
99
+		if ($data_node->isNotInitialized()) {
100
+			// $data_node->initialize();
101
+			$key = $data_node->nodeName();
102
+			$this->addData($key, $data_node);
103
+			// if the node being added specifies a domain (use case)
104
+			// and this is the primary data node, then set the domain
105
+			if ($this instanceof PrimaryJsonDataNode && $data_node->domain()) {
106
+				$this->setDomain($data_node->domain());
107
+			}
108
+		}
109
+	}
110
+
111
+
112
+	/**
113
+	 * sets the domain (use case) that this data node provides data for
114
+	 *
115
+	 * @param string $domain
116
+	 * @throws DomainException
117
+	 */
118
+	protected function setDomain(string $domain)
119
+	{
120
+		if ($this->domain !== '') {
121
+			$this->validator->overwriteError($domain, 'domain route');
122
+		}
123
+		$this->domain = $domain;
124
+	}
125
+
126
+
127
+	/**
128
+	 * used to mark the data node as having been processed
129
+	 *
130
+	 * @param bool $initialized
131
+	 */
132
+	protected function setInitialized(bool $initialized)
133
+	{
134
+		$this->initialized = filter_var($initialized, FILTER_VALIDATE_BOOLEAN);
135
+	}
136
+
137
+
138
+	/**
139
+	 * self explanatory (i hope)
140
+	 *
141
+	 * @param string $node_name
142
+	 * @throws DomainException
143
+	 */
144
+	protected function setNodeName(string $node_name)
145
+	{
146
+		$this->validator->validateCriticalProperty($node_name, 'node name');
147
+		$this->node_name = $node_name;
148
+		// by default set the data node order property by the alphabetical position of the first letter of its name
149
+		// we do this by passing the node name (in UPPERCASE) to ord() to get its ASCII position
150
+		// then we subtract 64 (cuz A has a position of 65) then multiply by 10 just to space things out a bit.
151
+		// this allows a data node to set its order upon construction to some other value
152
+		// so that it can squeak into whatever position it needs to be in, like 55
153
+		$this->setOrder((ord(strtoupper($this->node_name)) - 64) * 10);
154
+	}
155
+
156
+
157
+	/**
158
+	 * the actual data in key value array format
159
+	 *
160
+	 * @param bool $sort
161
+	 * @return array
162
+	 */
163
+	public function data(bool $sort = false): array
164
+	{
165
+		if ($sort) {
166
+			// check if data array has non-numerical keys and use a custom sort algorithm, else sort by keys
167
+			EEH_Array::is_associative_array($this->data)
168
+				? uasort(
169
+					$this->data,
170
+					function ($a, $b) {
171
+						// check if each incoming argument is a node and if they have an order set
172
+						// if so, then use that for our sorting comparison. otherwise use the node's name...
173
+						// unless it's NOT a node, in which case use the arg value if it is scalar, or 0 if not.
174
+						if ($a instanceof JsonDataNode) {
175
+							$a_ord = $a->order() ?: $a->nodeName();
176
+						} else {
177
+							$a_ord = is_scalar($a) ?: 0;
178
+						}
179
+						if ($b instanceof JsonDataNode) {
180
+							$b_ord = $b->order() ?: $b->nodeName();
181
+						} else {
182
+							$b_ord = is_scalar($b) ?: 0;
183
+						}
184
+						return $a_ord <=> $b_ord;
185
+					}
186
+				)
187
+				// sort numerically indexed arrays by their keys
188
+				: ksort($this->data);
189
+		}
190
+		return $this->data;
191
+	}
192
+
193
+
194
+	/**
195
+	 * the domain (use case) that this data node provides data for
196
+	 *
197
+	 * @return string
198
+	 */
199
+	public function domain(): string
200
+	{
201
+		return $this->domain;
202
+	}
203
+
204
+
205
+	/**
206
+	 * true if the data node has been initialized,
207
+	 * which entails retrieving the required data and adding it to the data node data array
208
+	 *
209
+	 * @return bool
210
+	 */
211
+	public function isInitialized(): bool
212
+	{
213
+		return $this->initialized;
214
+	}
215
+
216
+
217
+	/**
218
+	 * true if the data node has NOT been initialized
219
+	 *
220
+	 * @return bool
221
+	 */
222
+	public function isNotInitialized(): bool
223
+	{
224
+		return ! $this->initialized;
225
+	}
226
+
227
+
228
+	/**
229
+	 * Specify data which should be serialized to JSON
230
+	 *
231
+	 * @link  https://php.net/manual/en/jsonserializable.jsonserialize.php
232
+	 * @return array data which can be serialized by json_encode
233
+	 */
234
+	public function jsonSerialize(): array
235
+	{
236
+		return $this->data;
237
+	}
238
+
239
+
240
+	/**
241
+	 * self explanatory (i hope)
242
+	 *
243
+	 * @return string
244
+	 */
245
+	public function nodeName(): string
246
+	{
247
+		return $this->node_name;
248
+	}
249
+
250
+
251
+	/**
252
+	 * @return int
253
+	 */
254
+	public function order(): ?int
255
+	{
256
+		return $this->order;
257
+	}
258
+
259
+
260
+	/**
261
+	 * @param int $order
262
+	 */
263
+	protected function setOrder(int $order): void
264
+	{
265
+		$this->order = absint($order);
266
+	}
267 267
 }
Please login to merge, or discard this patch.
core/services/encryption/EncryptionKeyManagerInterface.php 1 patch
Indentation   +81 added lines, -81 removed lines patch added patch discarded remove patch
@@ -12,85 +12,85 @@
 block discarded – undo
12 12
  */
13 13
 interface EncryptionKeyManagerInterface
14 14
 {
15
-    /**
16
-     * add an encryption key
17
-     *
18
-     * @param string $encryption_key_identifier - name of the encryption key to use
19
-     * @param string $encryption_key            - cryptographically secure passphrase. will generate if necessary
20
-     * @param bool   $overwrite                 - prevents accidental overwriting of an existing key which would be bad
21
-     * @return bool
22
-     */
23
-    public function addEncryptionKey($encryption_key_identifier, $encryption_key = '', $overwrite = false);
24
-
25
-
26
-    /**
27
-     * returns true if encryption key has already been generated
28
-     *
29
-     * @param string $encryption_key_identifier - encryption key name
30
-     * @return bool
31
-     */
32
-    public function encryptionKeyExists($encryption_key_identifier = '');
33
-
34
-
35
-    /**
36
-     * returns cryptographically secure passphrase. will use default if necessary
37
-     *
38
-     * @param string $encryption_key_identifier - encryption key name. will use default if necessary
39
-     * @param bool   $generate                  - will generate a new key if the requested one does not exist
40
-     * @param bool   $throw_exception           - if TRUE (default), will throw an exception if key is not found
41
-     * @return string
42
-     */
43
-    public function getEncryptionKey($encryption_key_identifier = '', $generate = false, $throw_exception = true);
44
-
45
-
46
-    /**
47
-     * creates a new encryption key
48
-     *
49
-     * @param bool $strong if true (default) will attempt to generate a cryptographically secure key
50
-     * @return string
51
-     */
52
-    public function generateEncryptionKey($strong = true);
53
-
54
-
55
-    /**
56
-     * @return int
57
-     */
58
-    public function bitDepth();
59
-
60
-
61
-    /**
62
-     * @param int $bit_depth options are 64, 128, 192, or 256
63
-     */
64
-    public function setBitDepth($bit_depth);
65
-
66
-
67
-    /**
68
-     * @return int
69
-     */
70
-    public function keyLength();
71
-
72
-
73
-    /**
74
-     * @param int $key_length
75
-     */
76
-    public function setKeyLength($key_length);
77
-
78
-
79
-    /**
80
-     * deletes ALL existing encryption keys from the db
81
-     *
82
-     * @return bool true if keys successfully deleted, false otherwise.
83
-     */
84
-    public function removeAllEncryptionKeys();
85
-
86
-
87
-    /**
88
-     * deletes an existing encryption key from those saved in the db
89
-     *
90
-     * @param string $encryption_key_identifier encryption key name
91
-     * @return int  1: key removed successfully.
92
-     *              0: key did not exist.
93
-     *             -1: failed to remove key
94
-     */
95
-    public function removeEncryptionKey($encryption_key_identifier = '');
15
+	/**
16
+	 * add an encryption key
17
+	 *
18
+	 * @param string $encryption_key_identifier - name of the encryption key to use
19
+	 * @param string $encryption_key            - cryptographically secure passphrase. will generate if necessary
20
+	 * @param bool   $overwrite                 - prevents accidental overwriting of an existing key which would be bad
21
+	 * @return bool
22
+	 */
23
+	public function addEncryptionKey($encryption_key_identifier, $encryption_key = '', $overwrite = false);
24
+
25
+
26
+	/**
27
+	 * returns true if encryption key has already been generated
28
+	 *
29
+	 * @param string $encryption_key_identifier - encryption key name
30
+	 * @return bool
31
+	 */
32
+	public function encryptionKeyExists($encryption_key_identifier = '');
33
+
34
+
35
+	/**
36
+	 * returns cryptographically secure passphrase. will use default if necessary
37
+	 *
38
+	 * @param string $encryption_key_identifier - encryption key name. will use default if necessary
39
+	 * @param bool   $generate                  - will generate a new key if the requested one does not exist
40
+	 * @param bool   $throw_exception           - if TRUE (default), will throw an exception if key is not found
41
+	 * @return string
42
+	 */
43
+	public function getEncryptionKey($encryption_key_identifier = '', $generate = false, $throw_exception = true);
44
+
45
+
46
+	/**
47
+	 * creates a new encryption key
48
+	 *
49
+	 * @param bool $strong if true (default) will attempt to generate a cryptographically secure key
50
+	 * @return string
51
+	 */
52
+	public function generateEncryptionKey($strong = true);
53
+
54
+
55
+	/**
56
+	 * @return int
57
+	 */
58
+	public function bitDepth();
59
+
60
+
61
+	/**
62
+	 * @param int $bit_depth options are 64, 128, 192, or 256
63
+	 */
64
+	public function setBitDepth($bit_depth);
65
+
66
+
67
+	/**
68
+	 * @return int
69
+	 */
70
+	public function keyLength();
71
+
72
+
73
+	/**
74
+	 * @param int $key_length
75
+	 */
76
+	public function setKeyLength($key_length);
77
+
78
+
79
+	/**
80
+	 * deletes ALL existing encryption keys from the db
81
+	 *
82
+	 * @return bool true if keys successfully deleted, false otherwise.
83
+	 */
84
+	public function removeAllEncryptionKeys();
85
+
86
+
87
+	/**
88
+	 * deletes an existing encryption key from those saved in the db
89
+	 *
90
+	 * @param string $encryption_key_identifier encryption key name
91
+	 * @return int  1: key removed successfully.
92
+	 *              0: key did not exist.
93
+	 *             -1: failed to remove key
94
+	 */
95
+	public function removeEncryptionKey($encryption_key_identifier = '');
96 96
 }
Please login to merge, or discard this patch.