PluginProbe ʕ •ᴥ•ʔ
WP 2FA – Two-factor authentication for WordPress / 2.6.4
WP 2FA – Two-factor authentication for WordPress v2.6.4
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 2 years ago
class-open-ssl.php
195 lines
1 <?php
2 /**
3 * Open SSL encrypt / decrypt class.
4 *
5 * @package wp2fa
6 * @copyright 2024 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 if ( self::is_ssl_available() ) {
57 $iv = self::secure_random( self::BLOCK_BYTE_SIZE );
58 $key = \openssl_digest( \base64_decode( wp_salt() ), self::DIGEST_ALGORITHM, true ); //phpcs:ignore
59 $text = \openssl_encrypt(
60 $text,
61 self::CIPHER_METHOD,
62 $key,
63 OPENSSL_RAW_DATA,
64 $iv
65 );
66
67 $text = \base64_encode( $iv . $text ); //phpcs:ignore
68 }
69
70 return $text;
71 }
72
73 /**
74 * Decrypts crypt text
75 *
76 * @param string $text - Encrypted text to be decrypted.
77 *
78 * @return string
79 *
80 * @since 2.0.0
81 */
82 public static function decrypt( string $text ): string {
83 Debugging::log( 'Decrypting a text: ' . $text );
84 Debugging::log( 'Will use the following salt: ' . wp_salt() );
85
86 if ( self::is_ssl_available() ) {
87 $decoded_base = \base64_decode( $text ); //phpcs:ignore
88
89 $key = \openssl_digest( \base64_decode( wp_salt() ), self::DIGEST_ALGORITHM, true ); //phpcs:ignore
90
91 $ivlen = \openssl_cipher_iv_length( self::CIPHER_METHOD );
92
93 $iv = \substr( $decoded_base, 0, $ivlen );
94 $ciphertext_raw = \substr( $decoded_base, $ivlen );
95 $text = \openssl_decrypt( $ciphertext_raw, self::CIPHER_METHOD, $key, OPENSSL_RAW_DATA, $iv );
96 }
97 Debugging::log( 'Decrypted text: ' . $text );
98
99 return $text;
100 }
101
102 /**
103 * Decrypts crypt text
104 *
105 * @param string $text - Encrypted text to be decrypted.
106 *
107 * @return string
108 *
109 * @since 2.0.0
110 */
111 public static function decrypt_legacy( string $text ): string {
112 Debugging::log( 'Decrypting a text: ' . $text );
113
114 if ( self::is_ssl_available() ) {
115 $decoded_base = \base64_decode( $text ); //phpcs:ignore
116
117 $key = \openssl_digest( \base64_decode( WP2FA::get_secret_key() ), self::DIGEST_ALGORITHM, true ); //phpcs:ignore
118
119 $ivlen = \openssl_cipher_iv_length( self::CIPHER_METHOD );
120
121 $iv = \substr( $decoded_base, 0, $ivlen );
122 $ciphertext_raw = \substr( $decoded_base, $ivlen );
123 $text = \openssl_decrypt( $ciphertext_raw, self::CIPHER_METHOD, $key, OPENSSL_RAW_DATA, $iv );
124 }
125 Debugging::log( 'Decrypted text: ' . $text );
126
127 return $text;
128 }
129
130 /**
131 * Decrypts old wps_ secret strings
132 *
133 * @param string $text - The encrypted string.
134 *
135 * @return string
136 *
137 * @since 2.3.0
138 */
139 public static function decrypt_wps( string $text ): string {
140 Debugging::log( 'Decrypting a text: ' . $text );
141 Debugging::log( 'Will use the following salt: ' . \wp_salt() );
142
143 if ( self::is_ssl_available() ) {
144 $decoded_base = \base64_decode( $text ); //phpcs:ignore
145
146 $key = \openssl_digest( \base64_decode( \wp_salt() ), self::DIGEST_ALGORITHM, true ); //phpcs:ignore
147
148 $ivlen = \openssl_cipher_iv_length( self::CIPHER_METHOD );
149
150 $iv = \substr( $decoded_base, 0, $ivlen );
151 $ciphertext_raw = \substr( $decoded_base, $ivlen );
152 $text = \openssl_decrypt( $ciphertext_raw, self::CIPHER_METHOD, $key, OPENSSL_RAW_DATA, $iv );
153 }
154 Debugging::log( 'Decrypted text: ' . $text );
155
156 return $text;
157 }
158
159 /**
160 * Generates random bytes by given size
161 *
162 * @param integer $octets - Number of octets for use for random generator.
163 *
164 * @return string
165 *
166 * @since 2.0.0
167 */
168 public static function secure_random( int $octets = 0 ): string {
169 if ( 0 === $octets ) {
170 $octets = self::BLOCK_BYTE_SIZE;
171 }
172
173 return \random_bytes( $octets );
174 }
175
176 /**
177 * Checks the open ssl methods existence
178 *
179 * @return boolean
180 *
181 * @since 2.0.0
182 */
183 public static function is_ssl_available(): bool {
184 if ( null === self::$ssl_enabled ) {
185 self::$ssl_enabled = false;
186 if ( \function_exists( 'openssl_encrypt' ) ) {
187 self::$ssl_enabled = true;
188 }
189 }
190
191 return self::$ssl_enabled;
192 }
193 }
194 }
195