PluginProbe ʕ •ᴥ•ʔ
WP 2FA – Two-factor authentication for WordPress / 2.4.2
WP 2FA – Two-factor authentication for WordPress v2.4.2
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 3 years ago class-backup-codes.php 3 years ago class-backupcodes.php 3 years ago class-login.php 2 years ago class-open-ssl.php 3 years ago index.php 5 years ago
class-open-ssl.php
196 lines
1 <?php
2 /**
3 * Open SSL encrypt / decrypt class.
4 *
5 * @package wp2fa
6 * @copyright 2023 WP White Security
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 namespace WP2FA\Authenticator;
12
13 use WP2FA\WP2FA;
14 use WP2FA\Utils\Debugging;
15
16 use function WP2FA\Core\wp_salt;
17
18 /**
19 * Open_SSL - Class for encryption and decryption of the string using open_ssl method
20 *
21 * @since 2.0.0
22 */
23 if ( ! class_exists( '\WP2FA\Authenticator\Open_SSL' ) ) {
24
25 /**
26 * Responsible for SSL operations
27 */
28 class Open_SSL {
29
30 const CIPHER_METHOD = 'aes-256-ctr';
31 const BLOCK_BYTE_SIZE = 16;
32 const DIGEST_ALGORITHM = 'SHA256';
33 const SECRET_KEY_PREFIX = 'lsc_';
34
35 /**
36 * Internal cache var for the PHP ssl functions availability
37 *
38 * @var mixed|boolean
39 *
40 * @since 2.0.0
41 */
42 private static $ssl_enabled = null;
43
44 /**
45 * Encrypts given text
46 *
47 * @param string $text - Text to be encrypted.
48 *
49 * @return string
50 *
51 * @since 2.0.0
52 */
53 public static function encrypt( string $text ): string {
54 Debugging::log( 'Encrypting a text: ' . $text );
55 Debugging::log( 'Will use the following salt: ' . wp_salt() );
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 Debugging::log( 'Encrypted text: ' . $text );
70
71 return $text;
72 }
73
74 /**
75 * Decrypts crypt text
76 *
77 * @param string $text - Encrypted text to be decrypted.
78 *
79 * @return string
80 *
81 * @since 2.0.0
82 */
83 public static function decrypt( string $text ): string {
84 Debugging::log( 'Decrypting a text: ' . $text );
85 Debugging::log( 'Will use the following salt: ' . wp_salt() );
86
87 if ( self::is_ssl_available() ) {
88 $decoded_base = \base64_decode( $text ); //phpcs:ignore
89
90 $key = \openssl_digest( \base64_decode( wp_salt() ), self::DIGEST_ALGORITHM, true ); //phpcs:ignore
91
92 $ivlen = \openssl_cipher_iv_length( self::CIPHER_METHOD );
93
94 $iv = \substr( $decoded_base, 0, $ivlen );
95 $ciphertext_raw = \substr( $decoded_base, $ivlen );
96 $text = \openssl_decrypt( $ciphertext_raw, self::CIPHER_METHOD, $key, OPENSSL_RAW_DATA, $iv );
97 }
98 Debugging::log( 'Decrypted text: ' . $text );
99
100 return $text;
101 }
102
103 /**
104 * Decrypts crypt text
105 *
106 * @param string $text - Encrypted text to be decrypted.
107 *
108 * @return string
109 *
110 * @since 2.0.0
111 */
112 public static function decrypt_legacy( string $text ): string {
113 Debugging::log( 'Decrypting a text: ' . $text );
114
115 if ( self::is_ssl_available() ) {
116 $decoded_base = \base64_decode( $text ); //phpcs:ignore
117
118 $key = \openssl_digest( \base64_decode( WP2FA::get_secret_key() ), self::DIGEST_ALGORITHM, true ); //phpcs:ignore
119
120 $ivlen = \openssl_cipher_iv_length( self::CIPHER_METHOD );
121
122 $iv = \substr( $decoded_base, 0, $ivlen );
123 $ciphertext_raw = \substr( $decoded_base, $ivlen );
124 $text = \openssl_decrypt( $ciphertext_raw, self::CIPHER_METHOD, $key, OPENSSL_RAW_DATA, $iv );
125 }
126 Debugging::log( 'Decrypted text: ' . $text );
127
128 return $text;
129 }
130
131 /**
132 * Decrypts old wps_ secret strings
133 *
134 * @param string $text - The encrypted string.
135 *
136 * @return string
137 *
138 * @since 2.3.0
139 */
140 public static function decrypt_wps( string $text ): string {
141 Debugging::log( 'Decrypting a text: ' . $text );
142 Debugging::log( 'Will use the following salt: ' . \wp_salt() );
143
144 if ( self::is_ssl_available() ) {
145 $decoded_base = \base64_decode( $text ); //phpcs:ignore
146
147 $key = \openssl_digest( \base64_decode( \wp_salt() ), self::DIGEST_ALGORITHM, true ); //phpcs:ignore
148
149 $ivlen = \openssl_cipher_iv_length( self::CIPHER_METHOD );
150
151 $iv = \substr( $decoded_base, 0, $ivlen );
152 $ciphertext_raw = \substr( $decoded_base, $ivlen );
153 $text = \openssl_decrypt( $ciphertext_raw, self::CIPHER_METHOD, $key, OPENSSL_RAW_DATA, $iv );
154 }
155 Debugging::log( 'Decrypted text: ' . $text );
156
157 return $text;
158 }
159
160 /**
161 * Generates random bytes by given size
162 *
163 * @param integer $octets - Number of octets for use for random generator.
164 *
165 * @return string
166 *
167 * @since 2.0.0
168 */
169 public static function secure_random( int $octets = 0 ): string {
170 if ( 0 === $octets ) {
171 $octets = self::BLOCK_BYTE_SIZE;
172 }
173
174 return \random_bytes( $octets );
175 }
176
177 /**
178 * Checks the open ssl methods existence
179 *
180 * @return boolean
181 *
182 * @since 2.0.0
183 */
184 public static function is_ssl_available(): bool {
185 if ( null === self::$ssl_enabled ) {
186 self::$ssl_enabled = false;
187 if ( \function_exists( 'openssl_encrypt' ) ) {
188 self::$ssl_enabled = true;
189 }
190 }
191
192 return self::$ssl_enabled;
193 }
194 }
195 }
196