diff options
author | Andrey Andreev <narf@devilix.net> | 2014-02-06 01:38:27 +0100 |
---|---|---|
committer | Andrey Andreev <narf@devilix.net> | 2014-02-06 01:38:27 +0100 |
commit | 7c5544817de29222aa2d79ac7445122d57ad62c6 (patch) | |
tree | dd7ae9b077aa3318dabdb5beff4233ff171f29e9 | |
parent | 8d33a9a4a8ac924678ae5bba6387ca7fce206f4b (diff) |
CI_Encryption: Time-attack-safe HMAC verification
-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; } |