diff options
author | nashe <thomas@chauchefoin.fr> | 2017-12-18 22:59:42 +0100 |
---|---|---|
committer | nashe <thomas@chauchefoin.fr> | 2017-12-18 22:59:42 +0100 |
commit | 0979b67e1baf88d7534d39c9744801a54d487b7f (patch) | |
tree | d05a7ceee24d1c1aefc64e724e5e4daec1bf7f36 /app | |
parent | f8a64e98db4bcc406196a33eb869d0bcff3a4058 (diff) | |
download | planet-0979b67e1baf88d7534d39c9744801a54d487b7f.tar planet-0979b67e1baf88d7534d39c9744801a54d487b7f.tar.gz planet-0979b67e1baf88d7534d39c9744801a54d487b7f.tar.bz2 planet-0979b67e1baf88d7534d39c9744801a54d487b7f.tar.xz planet-0979b67e1baf88d7534d39c9744801a54d487b7f.zip |
Add hash_equals polyfill and related tests
Diffstat (limited to 'app')
-rw-r--r-- | app/helpers.php | 52 |
1 files changed, 51 insertions, 1 deletions
diff --git a/app/helpers.php b/app/helpers.php index 3bce65f..8765fc6 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -1,6 +1,24 @@ <?php /** + * Register polyfills for old PHP versions. + * + * This way, the real function will only be called if it + * is available, and we won't force the use of our own + * implementation. + */ +function register_polyfills() +{ + if (!function_exists('hash_equals')) { + function hash_equals($known_string, $user_string) { + call_user_func_array('_hash_equals', func_get_args()); + } + } +} + +register_polyfills(); + +/** * Path to the _custom_ directory. * * @param string $file Append this filename to the returned path. @@ -72,4 +90,36 @@ function removeCustomFiles() unlink($path); } } -}
\ No newline at end of file +} + +/** + * Compare two strings in a constant-time manner. + * + * It returns `true` if both strings are exactly the same + * (same size and same value). + * + * @param string $known_string + * @param string $user_string + * @return bool + */ +function _hash_equals($known_string = '', $user_string = '') +{ + // In our case, it's not problematic if `$known_string`'s + // size leaks, we will only compare password hashes and + // CSRF tokens—their size is already somehow public. + if (!is_string($known_string) || !is_string($user_string) + || strlen($known_string) !== strlen($user_string)) { + return false; + } + + $ret = 0; + + // Do not stop the comparison when a difference is found, + // always completely compare them. + for ($i = 0; $i < strlen($known_string); $i++) { + $ret |= (ord($known_string[$i]) ^ ord($user_string[$i])); + } + + return !$ret; +} + |