PluginProbe
Patchstack – WordPress & Plugins Security / 2.2.10
Patchstack – WordPress & Plugins Security v2.2.10
2.3.7 trunk 2.1.0 2.1.1 2.1.10 2.1.11 2.1.12 2.1.13 2.1.14 2.1.15 2.1.16 2.1.17 2.1.18 2.1.19 2.1.2 2.1.20 2.1.21 2.1.22 2.1.23 2.1.24 2.1.25 2.1.3 2.1.4 2.1.5 2.1.6 All 49 releases
← All changes | includes/2fa/rfc6238.php +119 -128 trunk2.2.10 View file →
@@ -1,128 +1,119 @@
1 -<?php
2 -
3 -// Do not allow the file to be called directly.
4 -if ( ! defined( 'ABSPATH' ) ) {
5 - exit;
6 -}
7 -
8 -require_once dirname( __FILE__ ) . '/base32.php';
9 -
10 -class TokenAuth6238 {
11 -
12 - /**
13 - * Verify the code & token.
14 - *
15 - * @param string $secretkey Secret clue (base 32).
16 - * @return bool True if success, false if failure
17 - */
18 - public static function verify( $secretkey, $code, $rangein30s = 3 ) {
19 - $key = Base32Static::decode( $secretkey );
20 - $unixtimestamp = time() / 30;
21 -
22 - // Without a valid decoded key there is nothing to verify against, and
23 - // passing an empty key to hash_hmac() is deprecated on PHP 8.1+.
24 - if ( ! is_string( $key ) || $key === '' ) {
25 - return false;
26 - }
27 -
28 - for ( $i = -( $rangein30s ); $i <= $rangein30s; $i++ ) {
29 - $checktime = (int) ( $unixtimestamp + $i );
30 - $thiskey = self::oath_hotp( $key, $checktime );
31 -
32 - // oath_truncate() returns an int, so zero-pad to 6 digits to match the
33 - // codes authenticator apps display (e.g. "012345").
34 - $computed = str_pad( (string) self::oath_truncate( $thiskey, 6 ), 6, '0', STR_PAD_LEFT );
35 - if ( self::stringEquals( $computed, (string) $code ) ) {
36 - return true;
37 - }
38 - }
39 -
40 - return false;
41 - }
42 -
43 - /**
44 - * Generate the random clue/key.
45 - *
46 - * @param integer $length
47 - * @return string
48 - */
49 - public static function generateRandomClue( $length = 16 ) {
50 - if ( function_exists( 'random_bytes' ) ) {
51 - return Base32Static::encode( random_bytes( 10 ) );
52 - }
53 -
54 - require_once dirname( __FILE__ ) . '/polyfill/lib/random.php';
55 - return Base32Static::encode( random_bytes( 10 ) );
56 - }
57 -
58 - /**
59 - *
60 - * @param string $key
61 - * @param integer $counter
62 - * @return string
63 - */
64 - private static function oath_hotp( $key, $counter ) {
65 - $cur_counter = [ 0, 0, 0, 0, 0, 0, 0, 0 ];
66 -
67 - for ( $i = 7; $i >= 0; $i-- ) { // C for unsigned char, * for repeating to the end of the input data
68 - $cur_counter[ $i ] = pack( 'C*', $counter );
69 - $counter = $counter >> 8;
70 - }
71 -
72 - $binary = implode( $cur_counter );
73 -
74 - // Pad to 8 characters
75 - $binary = str_pad( $binary, 8, chr( 0 ), STR_PAD_LEFT );
76 - return hash_hmac( 'sha1', $binary, $key );
77 - }
78 -
79 - /**
80 - * Truncate
81 - *
82 - * @param string $hash
83 - * @param integer $length
84 - * @return boolean
85 - */
86 - private static function oath_truncate( $hash, $length = 6 ) {
87 - $hashcharacters = str_split( $hash, 2 );
88 -
89 - for ( $j = 0; $j < count( $hashcharacters ); $j++ ) {
90 - $hmac_result[] = hexdec( $hashcharacters[ $j ] );
91 - }
92 -
93 - $offset = $hmac_result[19] & 0xf;
94 - return (
95 - ( ( $hmac_result[ $offset + 0 ] & 0x7f ) << 24 ) |
96 - ( ( $hmac_result[ $offset + 1 ] & 0xff ) << 16 ) |
97 - ( ( $hmac_result[ $offset + 2 ] & 0xff ) << 8 ) |
98 - ( $hmac_result[ $offset + 3 ] & 0xff )
99 - ) % pow( 10, $length );
100 - }
101 -
102 - /**
103 - * Compare 2 strings with each other.
104 - *
105 - * @param string $own
106 - * @param string $user
107 - * @return boolean
108 - */
109 - private static function stringEquals( $own, $user ) {
110 - if ( function_exists( 'hash_equals' ) ) {
111 - return hash_equals( $own, $user );
112 - }
113 -
114 - $safeLen = strlen( $own );
115 - $userLen = strlen( $user );
116 -
117 - if ( $userLen != $safeLen ) {
118 - return false;
119 - }
120 -
121 - $result = 0;
122 - for ( $i = 0; $i < $userLen; $i++ ) {
123 - $result |= ( ord( $own[$i] ) ^ ord( $user[$i] ) );
124 - }
125 -
126 - return $result === 0;
127 - }
128 -}
1 +<?php
2 +
3 +// Do not allow the file to be called directly.
4 +if ( ! defined( 'ABSPATH' ) ) {
5 + exit;
6 +}
7 +
8 +require_once dirname( __FILE__ ) . '/base32.php';
9 +
10 +class TokenAuth6238 {
11 +
12 + /**
13 + * Verify the code & token.
14 + *
15 + * @param string $secretkey Secret clue (base 32).
16 + * @return bool True if success, false if failure
17 + */
18 + public static function verify( $secretkey, $code, $rangein30s = 3 ) {
19 + $key = Base32Static::decode( $secretkey );
20 + $unixtimestamp = time() / 30;
21 +
22 + for ( $i = -( $rangein30s ); $i <= $rangein30s; $i++ ) {
23 + $checktime = (int) ( $unixtimestamp + $i );
24 + $thiskey = self::oath_hotp( $key, $checktime );
25 +
26 + if ( self::stringEquals( (string) self::oath_truncate( $thiskey, 6 ), (string) $code ) ) {
27 + return true;
28 + }
29 + }
30 +
31 + return false;
32 + }
33 +
34 + /**
35 + * Generate the random clue/key.
36 + *
37 + * @param integer $length
38 + * @return string
39 + */
40 + public static function generateRandomClue( $length = 16 ) {
41 + if ( function_exists( 'random_bytes' ) ) {
42 + return Base32Static::encode( random_bytes( 10 ) );
43 + }
44 +
45 + require_once dirname( __FILE__ ) . '/polyfill/lib/random.php';
46 + return Base32Static::encode( random_bytes( 10 ) );
47 + }
48 +
49 + /**
50 + *
51 + * @param string $key
52 + * @param integer $counter
53 + * @return string
54 + */
55 + private static function oath_hotp( $key, $counter ) {
56 + $cur_counter = [ 0, 0, 0, 0, 0, 0, 0, 0 ];
57 +
58 + for ( $i = 7; $i >= 0; $i-- ) { // C for unsigned char, * for repeating to the end of the input data
59 + $cur_counter[ $i ] = pack( 'C*', $counter );
60 + $counter = $counter >> 8;
61 + }
62 +
63 + $binary = implode( $cur_counter );
64 +
65 + // Pad to 8 characters
66 + str_pad( $binary, 8, chr( 0 ), STR_PAD_LEFT );
67 + return hash_hmac( 'sha1', $binary, $key );
68 + }
69 +
70 + /**
71 + * Truncate
72 + *
73 + * @param string $hash
74 + * @param integer $length
75 + * @return boolean
76 + */
77 + private static function oath_truncate( $hash, $length = 6 ) {
78 + $hashcharacters = str_split( $hash, 2 );
79 +
80 + for ( $j = 0; $j < count( $hashcharacters ); $j++ ) {
81 + $hmac_result[] = hexdec( $hashcharacters[ $j ] );
82 + }
83 +
84 + $offset = $hmac_result[19] & 0xf;
85 + return (
86 + ( ( $hmac_result[ $offset + 0 ] & 0x7f ) << 24 ) |
87 + ( ( $hmac_result[ $offset + 1 ] & 0xff ) << 16 ) |
88 + ( ( $hmac_result[ $offset + 2 ] & 0xff ) << 8 ) |
89 + ( $hmac_result[ $offset + 3 ] & 0xff )
90 + ) % pow( 10, $length );
91 + }
92 +
93 + /**
94 + * Compare 2 strings with each other.
95 + *
96 + * @param string $own
97 + * @param string $user
98 + * @return boolean
99 + */
100 + private static function stringEquals( $own, $user ) {
101 + if ( function_exists( 'hash_equals' ) ) {
102 + return hash_equals( $own, $user );
103 + }
104 +
105 + $safeLen = strlen( $own );
106 + $userLen = strlen( $user );
107 +
108 + if ( $userLen != $safeLen ) {
109 + return false;
110 + }
111 +
112 + $result = 0;
113 + for ( $i = 0; $i < $userLen; $i++ ) {
114 + $result |= ( ord( $own[$i] ) ^ ord( $user[$i] ) );
115 + }
116 +
117 + return $result === 0;
118 + }
119 +}