| @@ -2,8 +2,52 @@ | ||
| 2 | 2 | if (!defined('ABSPATH')) exit; |
| 3 | 3 | |
| 4 | 4 | if (!class_exists('WPRWP2FAUtils')) : |
| 5 | 5 | class WPRWP2FAUtils { |
| 6 | + const BASE32_LOOKUP_TABLE = array( | |
| 7 | + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 7 | |
| 8 | + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 15 | |
| 9 | + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 23 | |
| 10 | + 'Y', 'Z', '2', '3', '4', '5', '6', '7', // 31 | |
| 11 | + '=', // padding char | |
| 12 | + ); | |
| 13 | + | |
| 14 | + public static function base32Decode($secret) { | |
| 15 | + $base32_chars = self::BASE32_LOOKUP_TABLE; | |
| 16 | + $base32_chars_flipped = array_flip($base32_chars); | |
| 17 | + | |
| 18 | + $padding_char_count = substr_count($secret, $base32_chars[32]); | |
| 19 | + $allowed_values = array(6, 4, 3, 1, 0); | |
| 20 | + if (!in_array($padding_char_count, $allowed_values)) { | |
| 21 | + return false; | |
| 22 | + } | |
| 23 | + for ($i = 0; $i < 4; ++$i) { | |
| 24 | + if ($padding_char_count == $allowed_values[$i] && | |
| 25 | + substr($secret, -($allowed_values[$i])) != str_repeat($base32_chars[32], $allowed_values[$i])) { | |
| 26 | + return false; | |
| 27 | + } | |
| 28 | + } | |
| 29 | + $secret = str_replace('=', '', $secret); | |
| 30 | + | |
| 31 | + $secret = str_split($secret); | |
| 32 | + $binary_string = ''; | |
| 33 | + for ($i = 0; $i < count($secret); $i = $i + 8) { | |
| 34 | + $x = ''; | |
| 35 | + if (!in_array($secret[$i], $base32_chars)) { | |
| 36 | + return false; | |
| 37 | + } | |
| 38 | + for ($j = 0; $j < 8; ++$j) { | |
| 39 | + $x .= str_pad(base_convert(@$base32_chars_flipped[@$secret[$i + $j]], 10, 2), 5, '0', STR_PAD_LEFT); | |
| 40 | + } | |
| 41 | + $eight_bits = str_split($x, 8); | |
| 42 | + for ($z = 0; $z < count($eight_bits); ++$z) { | |
| 43 | + $binary_string .= (($y = chr(base_convert($eight_bits[$z], 2, 10))) || ord($y) == 48) ? $y : ''; | |
| 44 | + } | |
| 45 | + } | |
| 46 | + | |
| 47 | + return $binary_string; | |
| 48 | + } | |
| 49 | + | |
| 6 | 50 | public static function getSecretInfo($info) { |
| 7 | 51 | $default_info = array('secret' => null, 'is_encrypted' => null); |
| 8 | 52 | |
| 9 | 53 | if (empty($info) || !array_key_exists('secret', $info) || empty($info['secret']) || |
| @@ -10,9 +54,9 @@ | ||
| 10 | 54 | !array_key_exists('is_encrypted', $info) || !is_bool($info['is_encrypted'])) { |
| 11 | 55 | return $default_info; |
| 12 | 56 | } |
| 13 | 57 | |
| 14 | - $secret = base64_decode($info['secret']); | |
| 58 | + $secret = base64_decode($info['secret'], true); | |
| 15 | 59 | if ($secret === false) { |
| 16 | 60 | return $default_info; |
| 17 | 61 | } |
| 18 | 62 | |