PluginProbe ʕ •ᴥ•ʔ
WP 2FA – Two-factor authentication for WordPress / 2.6.0
WP 2FA – Two-factor authentication for WordPress v2.6.0
4.0.0 1.7.1 2.0.0 2.0.1 2.1.0 2.2.0 2.2.1 2.3.0 2.4.0 2.4.1 2.4.2 2.5.0 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.7.0 2.8.0 2.9.0 2.9.1 2.9.2 2.9.3 3.0.0 3.0.1 3.1.0 3.1.1 3.1.1.2 trunk 1.2.0 1.3.0 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.5.2 1.6.0 1.6.1 1.6.2 1.7.0
wp-2fa / includes / classes / Authenticator / class-open-ssl.php
wp-2fa / includes / classes / Authenticator Last commit date
class-authentication.php 2 years ago class-login.php 2 years ago class-open-ssl.php 2 years ago class-reset-passord.php 2 years ago index.php 5 years ago
class-open-ssl.php
198 lines
1 <?php
2 /**
3 * Open SSL encrypt / decrypt class.
4 *
5 * @package wp2fa
6 * @copyright %%YEAR%% Melapress
7 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
8 * @link https://wordpress.org/plugins/wp-2fa/
9 */
10
11 declare(strict_types=1);
12
13 namespace WP2FA\Authenticator;
14
15 use WP2FA\WP2FA;
16 use WP2FA\Utils\Debugging;
17
18 use function WP2FA\Core\wp_salt;
19
20 /**
21 * Open_SSL - Class for encryption and decryption of the string using open_ssl method
22 *
23 * @since 2.0.0
24 */
25 if ( ! class_exists( '\WP2FA\Authenticator\Open_SSL' ) ) {
26
27 /**
28 * Responsible for SSL operations
29 */
30 class Open_SSL {
31
32 const CIPHER_METHOD = 'aes-256-ctr';
33 const BLOCK_BYTE_SIZE = 16;
34 const DIGEST_ALGORITHM = 'SHA256';
35 const SECRET_KEY_PREFIX = 'lsc_';
36
37 /**
38 * Internal cache var for the PHP ssl functions availability
39 *
40 * @var mixed|boolean
41 *
42 * @since 2.0.0
43 */
44 private static $ssl_enabled = null;
45
46 /**
47 * Encrypts given text
48 *
49 * @param string $text - Text to be encrypted.
50 *
51 * @return string
52 *
53 * @since 2.0.0
54 */
55 public static function encrypt( string $text ): string {
56 Debugging::log( 'Encrypting a text: ' . $text );
57 Debugging::log( 'Will use the following salt: ' . wp_salt() );
58 if ( self::is_ssl_available() ) {
59 $iv = self::secure_random( self::BLOCK_BYTE_SIZE );
60 $key = \openssl_digest( \base64_decode( wp_salt() ), self::DIGEST_ALGORITHM, true ); //phpcs:ignore
61 $text = \openssl_encrypt(
62 $text,
63 self::CIPHER_METHOD,
64 $key,
65 OPENSSL_RAW_DATA,
66 $iv
67 );
68
69 $text = \base64_encode( $iv . $text ); //phpcs:ignore
70 }
71 Debugging::log( 'Encrypted text: ' . $text );
72
73 return $text;
74 }
75
76 /**
77 * Decrypts crypt text
78 *
79 * @param string $text - Encrypted text to be decrypted.
80 *
81 * @return string
82 *
83 * @since 2.0.0
84 */
85 public static function decrypt( string $text ): string {
86 Debugging::log( 'Decrypting a text: ' . $text );
87 Debugging::log( 'Will use the following salt: ' . wp_salt() );
88
89 if ( self::is_ssl_available() ) {
90 $decoded_base = \base64_decode( $text ); //phpcs:ignore
91
92 $key = \openssl_digest( \base64_decode( wp_salt() ), self::DIGEST_ALGORITHM, true ); //phpcs:ignore
93
94 $ivlen = \openssl_cipher_iv_length( self::CIPHER_METHOD );
95
96 $iv = \substr( $decoded_base, 0, $ivlen );
97 $ciphertext_raw = \substr( $decoded_base, $ivlen );
98 $text = \openssl_decrypt( $ciphertext_raw, self::CIPHER_METHOD, $key, OPENSSL_RAW_DATA, $iv );
99 }
100 Debugging::log( 'Decrypted text: ' . $text );
101
102 return $text;
103 }
104
105 /**
106 * Decrypts crypt text
107 *
108 * @param string $text - Encrypted text to be decrypted.
109 *
110 * @return string
111 *
112 * @since 2.0.0
113 */
114 public static function decrypt_legacy( string $text ): string {
115 Debugging::log( 'Decrypting a text: ' . $text );
116
117 if ( self::is_ssl_available() ) {
118 $decoded_base = \base64_decode( $text ); //phpcs:ignore
119
120 $key = \openssl_digest( \base64_decode( WP2FA::get_secret_key() ), self::DIGEST_ALGORITHM, true ); //phpcs:ignore
121
122 $ivlen = \openssl_cipher_iv_length( self::CIPHER_METHOD );
123
124 $iv = \substr( $decoded_base, 0, $ivlen );
125 $ciphertext_raw = \substr( $decoded_base, $ivlen );
126 $text = \openssl_decrypt( $ciphertext_raw, self::CIPHER_METHOD, $key, OPENSSL_RAW_DATA, $iv );
127 }
128 Debugging::log( 'Decrypted text: ' . $text );
129
130 return $text;
131 }
132
133 /**
134 * Decrypts old wps_ secret strings
135 *
136 * @param string $text - The encrypted string.
137 *
138 * @return string
139 *
140 * @since 2.3.0
141 */
142 public static function decrypt_wps( string $text ): string {
143 Debugging::log( 'Decrypting a text: ' . $text );
144 Debugging::log( 'Will use the following salt: ' . \wp_salt() );
145
146 if ( self::is_ssl_available() ) {
147 $decoded_base = \base64_decode( $text ); //phpcs:ignore
148
149 $key = \openssl_digest( \base64_decode( \wp_salt() ), self::DIGEST_ALGORITHM, true ); //phpcs:ignore
150
151 $ivlen = \openssl_cipher_iv_length( self::CIPHER_METHOD );
152
153 $iv = \substr( $decoded_base, 0, $ivlen );
154 $ciphertext_raw = \substr( $decoded_base, $ivlen );
155 $text = \openssl_decrypt( $ciphertext_raw, self::CIPHER_METHOD, $key, OPENSSL_RAW_DATA, $iv );
156 }
157 Debugging::log( 'Decrypted text: ' . $text );
158
159 return $text;
160 }
161
162 /**
163 * Generates random bytes by given size
164 *
165 * @param integer $octets - Number of octets for use for random generator.
166 *
167 * @return string
168 *
169 * @since 2.0.0
170 */
171 public static function secure_random( int $octets = 0 ): string {
172 if ( 0 === $octets ) {
173 $octets = self::BLOCK_BYTE_SIZE;
174 }
175
176 return \random_bytes( $octets );
177 }
178
179 /**
180 * Checks the open ssl methods existence
181 *
182 * @return boolean
183 *
184 * @since 2.0.0
185 */
186 public static function is_ssl_available(): bool {
187 if ( null === self::$ssl_enabled ) {
188 self::$ssl_enabled = false;
189 if ( \function_exists( 'openssl_encrypt' ) ) {
190 self::$ssl_enabled = true;
191 }
192 }
193
194 return self::$ssl_enabled;
195 }
196 }
197 }
198