| @@ -15,9 +15,9 @@ | ||
| 15 | 15 | * @param string $secretkey Secret clue (base 32). |
| 16 | 16 | * @return bool True if success, false if failure |
| 17 | 17 | */ |
| 18 | 18 | public static function verify( $secretkey, $code, $rangein30s = 3 ) { |
| 19 | - $key = base32static::decode( $secretkey ); | |
| 19 | + $key = Base32Static::decode( $secretkey ); | |
| 20 | 20 | $unixtimestamp = time() / 30; |
| 21 | 21 | |
| 22 | 22 | for ( $i = -( $rangein30s ); $i <= $rangein30s; $i++ ) { |
| 23 | 23 | $checktime = (int) ( $unixtimestamp + $i ); |
| @@ -22,9 +22,9 @@ | ||
| 22 | 22 | for ( $i = -( $rangein30s ); $i <= $rangein30s; $i++ ) { |
| 23 | 23 | $checktime = (int) ( $unixtimestamp + $i ); |
| 24 | 24 | $thiskey = self::oath_hotp( $key, $checktime ); |
| 25 | 25 | |
| 26 | - if ( (int) $code == self::oath_truncate( $thiskey, 6 ) ) { | |
| 26 | + if ( self::stringEquals( (string) self::oath_truncate( $thiskey, 6 ), (string) $code ) ) { | |
| 27 | 27 | return true; |
| 28 | 28 | } |
| 29 | 29 | } |
| 30 | 30 | |
| @@ -37,15 +37,14 @@ | ||
| 37 | 37 | * @param integer $length |
| 38 | 38 | * @return string |
| 39 | 39 | */ |
| 40 | 40 | public static function generateRandomClue( $length = 16 ) { |
| 41 | - $b32 = '234567QWERTYUIOPASDFGHJKLZXCVBNM'; | |
| 42 | - $s = ''; | |
| 43 | - for ( $i = 0; $i < $length; $i++ ) { | |
| 44 | - $s .= $b32[ mt_rand( 0, 31 ) ]; | |
| 41 | + if ( function_exists( 'random_bytes' ) ) { | |
| 42 | + return Base32Static::encode( random_bytes( 10 ) ); | |
| 45 | 43 | } |
| 46 | - | |
| 47 | - return $s; | |
| 44 | + | |
| 45 | + require_once dirname( __FILE__ ) . '/polyfill/lib/random.php'; | |
| 46 | + return Base32Static::encode( random_bytes( 10 ) ); | |
| 48 | 47 | } |
| 49 | 48 | |
| 50 | 49 | /** |
| 51 | 50 | * |
| @@ -53,9 +52,9 @@ | ||
| 53 | 52 | * @param integer $counter |
| 54 | 53 | * @return string |
| 55 | 54 | */ |
| 56 | 55 | private static function oath_hotp( $key, $counter ) { |
| 57 | - $cur_counter = array( 0, 0, 0, 0, 0, 0, 0, 0 ); | |
| 56 | + $cur_counter = [ 0, 0, 0, 0, 0, 0, 0, 0 ]; | |
| 58 | 57 | |
| 59 | 58 | for ( $i = 7; $i >= 0; $i-- ) { // C for unsigned char, * for repeating to the end of the input data |
| 60 | 59 | $cur_counter[ $i ] = pack( 'C*', $counter ); |
| 61 | 60 | $counter = $counter >> 8; |
| @@ -88,6 +87,33 @@ | ||
| 88 | 87 | ( ( $hmac_result[ $offset + 1 ] & 0xff ) << 16 ) | |
| 89 | 88 | ( ( $hmac_result[ $offset + 2 ] & 0xff ) << 8 ) | |
| 90 | 89 | ( $hmac_result[ $offset + 3 ] & 0xff ) |
| 91 | 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; | |
| 92 | 118 | } |
| 93 | 119 | } |