diff --git includes/bootstrap.inc includes/bootstrap.inc
index 203b052..e4aaaa8 100644
--- includes/bootstrap.inc
+++ includes/bootstrap.inc
@@ -1709,6 +1709,46 @@ function drupal_block_denied($ip) {
 }
 
 /**
+ * Returns a string of highly randomized bytes (over the full 8-bit range).
+ *
+ * This function is better than simply calling mt_rand() or any other built-in
+ * PHP function because it can return a long string of bytes (compared to < 4
+ * bytes normally from mt_rand()) and uses the best available pseudo-random source.
+ *
+ * @param $count
+ *   The number of characters (bytes) to return in the string.
+ */
+function drupal_random_bytes($count)  {
+  // $random_state does not use drupal_static as it stores random bytes.
+  static $random_state;
+  // We initialize with the somewhat random PHP process ID on the first call.
+  if (empty($random_state)) {
+    $random_state = getmypid();
+  }
+  $output = '';
+  // /dev/urandom is available on many *nix systems and is considered the best
+  // commonly available pseudo-random source.
+  if ($fh = @fopen('/dev/urandom', 'rb')) {
+    $output = fread($fh, $count);
+    fclose($fh);
+  }
+  // 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 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 = 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);
+}
+
+/**
  * Generates a default anonymous $user object.
  *
  * @return Object - the user object.
diff --git includes/common.inc includes/common.inc
index 8026209..f596541 100644
--- includes/common.inc
+++ includes/common.inc
@@ -4183,45 +4183,6 @@ function drupal_json_output($var = NULL) {
 }
 
 /**
- * Returns a string of highly randomized bytes (over the full 8-bit range).
- *
- * This function is better than simply calling mt_rand() or any other built-in
- * PHP function because it can return a long string of bytes (compared to < 4
- * bytes normally from mt_rand()) and uses the best available pseudo-random source.
- *
- * @param $count
- *   The number of characters (bytes) to return in the string.
- */
-function drupal_random_bytes($count)  {
-  // $random_state does not use drupal_static as it stores random bytes.
-  static $random_state;
-  // We initialize with the somewhat random PHP process ID on the first call.
-  if (empty($random_state)) {
-    $random_state = getmypid();
-  }
-  $output = '';
-  // /dev/urandom is available on many *nix systems and is considered the best
-  // commonly available pseudo-random source.
-  if ($fh = @fopen('/dev/urandom', 'rb')) {
-    $output = fread($fh, $count);
-    fclose($fh);
-  }
-  // 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()
-  // 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);
-  }
-  return substr($output, 0, $count);
-}
-
-/**
  * Get a salt useful for hardening against SQL injection.
  *
  * @return
@@ -4242,7 +4203,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 +4216,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);
 }
 
 /**
