diff options
-rw-r--r-- | system/libraries/Encryption.php | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/system/libraries/Encryption.php b/system/libraries/Encryption.php index 36975e585..f5950ee46 100644 --- a/system/libraries/Encryption.php +++ b/system/libraries/Encryption.php @@ -481,17 +481,31 @@ class CI_Encryption { if (isset($params['hmac_digest'])) { - isset($params['hmac_key']) OR $params['hmac_key'] = $this->hkdf($this->_key, 'sha512', NULL, NULL, 'authentication'); - // This might look illogical, but it is done during encryption as well ... // The 'base64' value is effectively an inverted "raw data" parameter $digest_size = ($params['base64']) ? $this->_digests[$params['hmac_digest']] * 2 : $this->_digests[$params['hmac_digest']]; - $hmac = substr($data, 0, $digest_size); + + if (strlen($data) <= $digest_size) + { + return FALSE; + } + + $hmac_input = substr($data, 0, $digest_size); $data = substr($data, $digest_size); - if ($hmac !== hash_hmac($params['hmac_digest'], $data, $params['hmac_key'], ! $params['base64'])) + isset($params['hmac_key']) OR $params['hmac_key'] = $this->hkdf($this->_key, 'sha512', NULL, NULL, 'authentication'); + $hmac_check = hash_hmac($params['hmac_digest'], $data, $params['hmac_key'], ! $params['base64']); + + // Time-attack-safe comparison + $diff = 0; + for ($i = 0; $i < $digest_size; $i++) + { + $diff |= ord($hmac_input[$i]) ^ ord($hmac_check[$i]); + } + + if ($diff !== 0) { return FALSE; } |