From 9e79d225fa13ea61412deaf5c498f0487bb7386a Mon Sep 17 00:00:00 2001 From: gtbu Date: Fri, 1 Aug 2025 12:42:56 +0200 Subject: [PATCH] Update Nonce.php --- include/tool/Nonce.php | 93 +++++++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 43 deletions(-) diff --git a/include/tool/Nonce.php b/include/tool/Nonce.php index aaa6824..226bf65 100644 --- a/include/tool/Nonce.php +++ b/include/tool/Nonce.php @@ -4,88 +4,95 @@ namespace gp\tool; defined('is_running') or die('Not an entry point...'); +/** + * A class for creating and verifying nonces (numbers used once) , self-contained and uses the secure HMAC method for hashing + */ class Nonce{ + /** + * Hashing algorithm for the nonce. + */ + private const NONCE_ALGO = 'sha512'; + /** - * Generate a nerw nonce - * @param string $action Should be the same $action that is passed to Verify() - * @param bool $anon True if the nonce is being used for anonymous users - * @param int $factor Determines the length of time the generated nonce will be valid. The default 43200 will result in a 24hr period of time. - * @return string - * + * Generate a new nonce. + * @param string $action A string identifying the action. + * @param bool $anon True if the nonce is for an anonymous user. + * @param int $factor Determines the nonce's validity period. + * @return string The generated nonce. */ - public static function Create($action='none', $anon=false, $factor=43200){ + public static function Create($action = 'none', $anon = false, $factor = 43200){ global $gpAdmin; - $nonce = $action; - if( !$anon && !empty($gpAdmin['username']) ){ - $nonce .= $gpAdmin['username']; + $nonce_base = $action; + if (!$anon && !empty($gpAdmin['username'])) { + $nonce_base .= $gpAdmin['username']; } - return self::Hash($nonce, 0, $factor); + return self::Hash($nonce_base, 0, $factor); } /** - * Verify a nonce ($check_nonce) - * - * @param string $action Should be the same $action that is passed to new_nonce() - * @param mixed $check_nonce The user submitted nonce or false if $_REQUEST['_gpnonce'] can be used - * @param bool $anon True if the nonce is being used for anonymous users - * @param int $factor Determines the length of time the generated nonce will be valid. The default 43200 will result in a 24hr period of time. - * @return bool Return false if the $check_nonce did not pass. true if passed + * Verify a submitted nonce using a timing-attack-safe comparison. * + * @param string $action A string identifying the action. + * @param mixed $check_nonce The user-submitted nonce. If false, checks $_REQUEST['_gpnonce']. + * @param bool $anon True if the nonce is for an anonymous user. + * @param int $factor Determines the nonce's validity period. + * @return bool Returns true if the nonce is valid, false otherwise. */ - public static function Verify($action='none', $check_nonce=false, $anon=false, $factor=43200 ){ + public static function Verify($action = 'none', $check_nonce = false, $anon = false, $factor = 43200){ global $gpAdmin; - if( $check_nonce === false ){ - $check_nonce =& $_REQUEST['_gpnonce']; + if ($check_nonce === false) { + $check_nonce = $_REQUEST['_gpnonce'] ?? ''; } - if( empty($check_nonce) ){ + if (empty($check_nonce) || !is_string($check_nonce)) { return false; } - $nonce = $action; - if( !$anon ){ - if( empty($gpAdmin['username']) ){ + $nonce_base = $action; + if (!$anon) { + if (empty($gpAdmin['username'])) { return false; } - $nonce .= $gpAdmin['username']; + $nonce_base .= $gpAdmin['username']; } - - // Nonce generated 0-12 hours ago - if( self::Hash( $nonce, 0, $factor ) === $check_nonce ){ + + $expected_current = self::Hash($nonce_base, 0, $factor); + if (hash_equals($expected_current, $check_nonce)) { return true; } - // Nonce generated 12-24 hours ago - if( self::Hash( $nonce, 1, $factor ) === $check_nonce ){ + $expected_previous = self::Hash($nonce_base, 1, $factor); + if (hash_equals($expected_previous, $check_nonce)) { return true; } - // Invalid nonce return false; } - /** - * Generate a nonce hash - * - * @param string $nonce - * @param int $tick_offset - * @param int $factor Determines the length of time the generated nonce will be valid. The default 43200 will result in a 24hr period of time. + * Generates a nonce hash now using the secure HMAC method instead of the global \gp\tool::hash(). * + * @param string $nonce_base The base string for the nonce. + * @param int $tick_offset An offset for the time tick. + * @param int $factor Determines the nonce's validity period. + * @return string The calculated HMAC hash. */ - public static function Hash($nonce, $tick_offset=0, $factor=43200){ + public static function Hash($nonce_base, $tick_offset = 0, $factor = 43200){ global $config; - $nonce_tick = ceil(time() / $factor) - $tick_offset; - $nonce = $nonce . $config['gpuniq'] . $nonce_tick; + $nonce_tick = ceil(time() / $factor) - $tick_offset; - return \gp\tool::hash($nonce,gp_nonce_algo, 2); + $key = $config['gpuniq']; + + $data = $nonce_base . $nonce_tick; + + return hash_hmac(self::NONCE_ALGO, $data, $key); } -} +} \ No newline at end of file