diff --git includes/common.inc includes/common.inc index 8026209..51131a1 100644 --- includes/common.inc +++ includes/common.inc @@ -4209,14 +4209,15 @@ function drupal_random_bytes($count) { // If /dev/urandom is not available or returns no bytes, this loop will // generate a good set of pseudo-random bytes on any system. // Note that it may be important that our $random_state is passed - // through md5() prior to being rolled into $output, that the two md5() + // through hash() prior to being rolled into $output, that the two hash() // invocations are different, and that the extra input into the first one - // the microtime() - is prepended rather than appended. This is to avoid // directly leaking $random_state via the $output stream, which could // allow for trivial prediction of further "random" numbers. while (strlen($output) < $count) { - $random_state = md5(microtime() . mt_rand() . $random_state); - $output .= md5(mt_rand() . $random_state, TRUE); + $random_state = hash('sha256', microtime() . mt_rand() . $random_state); + // Re-hash and truncate from 32 to 20 bytes. + $output .= substr(hash('sha256', mt_rand() . $random_state, TRUE), 0, 20); } return substr($output, 0, $count); } @@ -4242,7 +4243,7 @@ function drupal_get_hash_salt() { */ function drupal_get_private_key() { if (!($key = variable_get('drupal_private_key', 0))) { - $key = md5(drupal_random_bytes(64)); + $key = hash('sha256', drupal_random_bytes(64)); variable_set('drupal_private_key', $key); } return $key; @@ -4255,10 +4256,25 @@ function drupal_get_private_key() { * An additional value to base the token on. */ function drupal_get_token($value = '') { - $private_key = drupal_get_private_key(); - // A single md5() is vulnerable to length-extension attacks, so use it twice. - // @todo: add md5 and sha1 hmac functions to core. - return md5(drupal_get_hash_salt() . md5(session_id() . $value . $private_key)); + return drupal_hmac_base64(session_id() . $value, drupal_get_private_key() . drupal_get_hash_salt()); +} + +/** + * Calculate a base-64 encoded, URL-safe sha-256 hmac. + * + * @param $data + * String data. + * @param $key + * A secret string key. + * + * @return + * A base-64 encoded sha-256 hmac, with + replaced with -, / with _ and + * any = padding characters removed. + */ +function drupal_hmac_base64($data, $key) { + $hmac = base64_encode(hash_hmac('sha256', $data, $key, TRUE)); + // Modify the hmac so it's safe to use in URLs. + return strtr($hmac, array('+' => '-', '/' => '_', '=' => '')); } /** diff --git includes/session.inc includes/session.inc index 438d47d..d59c9e0 100644 --- includes/session.inc +++ includes/session.inc @@ -206,7 +206,7 @@ function drupal_session_initialize() { // processes (like drupal_get_token()) needs to know the future // session ID in advance. $user = drupal_anonymous_user(); - session_id(md5(uniqid('', TRUE))); + session_id(hash('sha256', drupal_random_bytes(64))); } } diff --git modules/update/update.fetch.inc modules/update/update.fetch.inc index 7944828..9db4d1c 100644 --- modules/update/update.fetch.inc +++ modules/update/update.fetch.inc @@ -137,7 +137,7 @@ function _update_process_fetch_task($project) { $success = FALSE; $available = array(); - $site_key = md5($base_url . drupal_get_private_key()); + $site_key = drupal_hmac_base64($base_url, drupal_get_private_key()); $url = _update_build_fetch_url($project, $site_key); $fetch_url_base = _update_get_fetch_url_base($project); $project_name = $project['name']; diff --git modules/user/user.module modules/user/user.module index 51e4db5..30f45d4 100644 --- modules/user/user.module +++ modules/user/user.module @@ -2079,8 +2079,7 @@ function user_cancel_url($account) { } function user_pass_rehash($password, $timestamp, $login) { - // A single md5() is vulnerable to length-extension attacks, so use it twice. - return md5(drupal_get_hash_salt() . md5($timestamp . $password . $login)); + return drupal_hmac_base64($timestamp . $login, drupal_get_hash_salt() . $password); } /**