diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index e62c07d..ceae38f 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -2025,7 +2025,7 @@ function drupal_generate_test_ua($prefix) {
     else {
       // Generate and save a new hash salt for a test run.
       // Consumed by drupal_valid_test_ua() before settings.php is loaded.
-      $private_key = Crypt::randomStringHashed(55);
+      $private_key = Crypt::randomBytesBase64(55);
       file_put_contents($key_file, $private_key);
     }
     // The file properties add more entropy not easily accessible to others.
diff --git a/core/includes/common.inc b/core/includes/common.inc
index 92f21ef..277ccc1 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -1,5 +1,6 @@
 <?php
 
+use Drupal\Component\Utility\Crypt;
 use Drupal\Component\Utility\Json;
 use Drupal\Component\Utility\Number;
 use Drupal\Component\Utility\Settings;
@@ -3100,6 +3101,10 @@ function _drupal_bootstrap_code() {
 
   // Make sure all stream wrappers are registered.
   file_get_stream_wrappers();
+  // Ensure mt_rand is reseeded, to prevent random values from one page load
+  // being exploited to predict random values in subsequent page loads.
+  $seed = unpack("L", Crypt::randomBytes(4));
+  mt_srand($seed[1]);
 
   // Set the allowed protocols once we have the config available.
   $allowed_protocols = \Drupal::config('system.filter')->get('protocols');
@@ -4199,7 +4204,7 @@ function drupal_pre_render_render_cache_placeholder($element) {
   if (!is_array($context)) {
     throw new Exception(t('#context must be an array.'));
   }
-  $token = \Drupal\Component\Utility\Crypt::randomStringHashed(55);
+  $token = \Drupal\Component\Utility\Crypt::randomBytesBase64(55);
 
   // Generate placeholder markup and store #post_render_cache callback.
   $element['#markup'] = drupal_render_cache_generate_placeholder($callback, $context, $token);
diff --git a/core/includes/file.inc b/core/includes/file.inc
index 83e6dc9..4a05589 100644
--- a/core/includes/file.inc
+++ b/core/includes/file.inc
@@ -6,7 +6,7 @@
  */
 
 use Drupal\Core\StreamWrapper\LocalStream;
-use Drupal\Component\PhpStorage\MTimeProtectedFastFileStorage;
+use Drupal\Component\PhpStorage\FileStorage;
 use Drupal\Component\Utility\String;
 use Drupal\Core\StreamWrapper\PublicStream;
 
@@ -579,17 +579,16 @@ function file_ensure_htaccess() {
 /**
  * Creates a .htaccess file in the given directory.
  *
- * @param $directory
+ * @param string $directory
  *   The directory.
- * @param $private
- *   FALSE indicates that $directory should be an open and public directory.
- *   The default is TRUE which indicates a private and protected directory.
- *
- * @return bool
- *   TRUE if the .htaccess file could be created or existed already, FALSE
- *   otherwise.
- */
-function file_save_htaccess($directory, $private = TRUE) {
+ * @param bool $private
+ *   (Optional) FALSE indicates that $directory should be a web-accessible
+ *   directory. Defaults to TRUE which indicates a private directory.
+ * @param bool $force_overwrite
+ *   (Optional) Set to TRUE to attempt to overwrite the existing .htaccess file
+ *   if one is already present. Defaults to FALSE.
+ */
+function file_save_htaccess($directory, $private = TRUE, $force_overwrite = FALSE) {
   if (file_uri_scheme($directory)) {
     $htaccess_path = file_stream_wrapper_uri_normalize($directory . '/.htaccess');
   }
@@ -598,19 +597,11 @@ function file_save_htaccess($directory, $private = TRUE) {
     $htaccess_path = $directory . '/.htaccess';
   }
 
-  if (file_exists($htaccess_path)) {
+  if (file_exists($htaccess_path) && !$force_overwrite) {
     // Short circuit if the .htaccess file already exists.
     return TRUE;
   }
-
-  if ($private) {
-    // Private .htaccess file.
-    $htaccess_lines = MTimeProtectedFastFileStorage::HTACCESS;
-  }
-  else {
-    // Public .htaccess file.
-    $htaccess_lines = "SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006\nOptions None\nOptions +FollowSymLinks";
-  }
+  $htaccess_lines = file_htaccess_lines($private);
 
   // Write the .htaccess file.
   if (file_exists($directory) && is_writable($directory) && file_put_contents($htaccess_path, $htaccess_lines)) {
@@ -624,6 +615,23 @@ function file_save_htaccess($directory, $private = TRUE) {
 }
 
 /**
+ * Returns the standard .htaccess lines that Drupal writes to file directories.
+ *
+ * @param bool $private
+ *   (Optional) Set to FALSE to return the .htaccess lines for a web-accessible
+ *   public directory. The default is TRUE, which returns the .htaccess lines
+ *   for a private directory that should not be web-accessible.
+ *
+ * @return string
+ *   The desired contents of the .htaccess file.
+ *
+ * @see file_create_htaccess()
+ */
+function file_htaccess_lines($private = TRUE) {
+  return FileStorage::htaccessLines($private);
+}
+
+/**
  * Determines whether the URI has a valid scheme for file API operations.
  *
  * There must be a scheme and it must be a Drupal-provided scheme like
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index 928694d..c6db0cd 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -1256,7 +1256,7 @@ function install_settings_form_submit($form, &$form_state) {
     'required' => TRUE,
   );
   $settings['settings']['hash_salt'] = (object) array(
-    'value'    => Crypt::randomStringHashed(55),
+    'value'    => Crypt::randomBytesBase64(55),
     'required' => TRUE,
   );
   // Remember the profile which was used.
diff --git a/core/includes/install.inc b/core/includes/install.inc
index d7a7573..d1d23d5 100644
--- a/core/includes/install.inc
+++ b/core/includes/install.inc
@@ -457,7 +457,7 @@ function drupal_install_config_directories() {
   // Add a randomized config directory name to settings.php, unless it was
   // manually defined in the existing already.
   if (empty($config_directories)) {
-    $config_directories_hash = Crypt::randomStringHashed(55);
+    $config_directories_hash = Crypt::randomBytesBase64(55);
     $settings['config_directories'] = array(
       CONFIG_ACTIVE_DIRECTORY => (object) array(
         'value' => conf_path() . '/files/config_' . $config_directories_hash . '/active',
diff --git a/core/includes/session.inc b/core/includes/session.inc
index fd2b1ec..cb11801 100644
--- a/core/includes/session.inc
+++ b/core/includes/session.inc
@@ -267,10 +267,10 @@ function drupal_session_initialize() {
     // Less random sessions (which are much faster to generate) are used for
     // anonymous users than are generated in drupal_session_regenerate() when
     // a user becomes authenticated.
-    session_id(Crypt::hashBase64(uniqid(mt_rand(), TRUE)));
+    session_id(Crypt::randomBytesBase64());
     if ($is_https && settings()->get('mixed_mode_sessions', FALSE)) {
       $insecure_session_name = substr(session_name(), 1);
-      $session_id = Crypt::hashBase64(uniqid(mt_rand(), TRUE));
+      $session_id = Crypt::randomBytesBase64();
       $cookies->set($insecure_session_name, $session_id);
     }
   }
@@ -369,7 +369,7 @@ function drupal_session_regenerate() {
       $old_insecure_session_id = $cookies->get($insecure_session_name);
     }
     $params = session_get_cookie_params();
-    $session_id = Crypt::hashBase64(uniqid(mt_rand(), TRUE) . Crypt::randomBytes(55));
+    $session_id = Crypt::randomBytesBase64();
     // If a session cookie lifetime is set, the session will expire
     // $params['lifetime'] seconds from the current request. If it is not set,
     // it will expire when the browser is closed.
@@ -381,7 +381,7 @@ function drupal_session_regenerate() {
   if (drupal_session_started()) {
     $old_session_id = session_id();
   }
-  session_id(Crypt::hashBase64(uniqid(mt_rand(), TRUE) . Crypt::randomBytes(55)));
+  session_id(Crypt::randomBytesBase64());
 
   if (isset($old_session_id)) {
     $params = session_get_cookie_params();
diff --git a/core/lib/Drupal/Component/PhpStorage/FileStorage.php b/core/lib/Drupal/Component/PhpStorage/FileStorage.php
index e6b4f0f..9309d00 100644
--- a/core/lib/Drupal/Component/PhpStorage/FileStorage.php
+++ b/core/lib/Drupal/Component/PhpStorage/FileStorage.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Definition of Drupal\Component\PhpStorage\FileStorage.
+ * Contains \Drupal\Component\PhpStorage\FileStorage.
  */
 
 namespace Drupal\Component\PhpStorage;
@@ -53,11 +53,83 @@ public function load($name) {
    */
   public function save($name, $code) {
     $path = $this->getFullPath($name);
-    $this->ensureDirectory(dirname($path));
+    $directory = dirname($path);
+    if ($this->ensureDirectory($directory)) {
+      $htaccess_path =  $directory . '/.htaccess';
+      if (!file_exists($htaccess_path) && file_put_contents($htaccess_path, static::htaccessLines())) {
+        @chmod($htaccess_path, 0444);
+      }
+    }
     return (bool) file_put_contents($path, $code);
   }
 
   /**
+   * Returns the standard .htaccess lines that Drupal writes to file directories.
+   *
+   * This code is located here so this component can be stand-alone, but it is
+   * also called by file_htaccess_lines().
+   *
+   * @param bool $private
+   *   (Optional) Set to FALSE to return the .htaccess lines for an open and
+   *   public directory. The default is TRUE, which returns the .htaccess lines
+   *   for a private and protected directory.
+   *
+   * @return string
+   *   The desired contents of the .htaccess file.
+   */
+  public static function htaccessLines($private = TRUE) {
+    $lines = <<<EOF
+# Turn off all options we don't need.
+Options None
+Options +FollowSymLinks
+
+# Set the catch-all handler to prevent scripts from being executed.
+SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006
+<Files *>
+  # Override the handler again if we're run later in the evaluation list.
+  SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003
+</Files>
+
+# If we know how to do it safely, disable the PHP engine entirely.
+<IfModule mod_php5.c>
+  php_flag engine off
+</IfModule>
+EOF;
+
+    if ($private) {
+      $lines = "Deny from all\n\n" . $lines;
+    }
+
+    return $lines;
+  }
+
+  /**
+   * Ensures the =directory exists, has the right permissions, and a .htaccess.
+   *
+   * For compatibility with open_basedir, the requested directory is created
+   * using a recursion logic that is based on the relative directory path/tree:
+   * It works from the end of the path recursively back towards the root
+   * directory, until an existing parent directory is found. From there, the
+   * subdirectories are created.
+   *
+   * @param string $directory
+   *   The directory path.
+   * @param int $mode
+   *   The mode, permissions, the directory should have.
+   *
+   * @return bool
+   *   TRUE if the directory exists or has been created, FALSE otherwise.
+   */
+  protected function ensureDirectory($directory, $mode = 0777) {
+    if ($this->createDirectory($directory, $mode)) {
+      $htaccess_path =  $directory . '/.htaccess';
+      if (!file_exists($htaccess_path) && file_put_contents($htaccess_path, static::htaccessLines())) {
+        @chmod($htaccess_path, 0444);
+      }
+    }
+  }
+
+  /**
    * Ensures the requested directory exists and has the right permissions.
    *
    * For compatibility with open_basedir, the requested directory is created
@@ -76,7 +148,7 @@ public function save($name, $code) {
    * @return bool
    *   TRUE if the directory exists or has been created, FALSE otherwise.
    */
-  protected function ensureDirectory($directory, $mode = 0777, $is_backwards_recursive = FALSE) {
+  protected function createDirectory($directory, $mode = 0777, $is_backwards_recursive = FALSE) {
     // If the directory exists already, there's nothing to do.
     if (is_dir($directory)) {
       return TRUE;
@@ -97,7 +169,7 @@ protected function ensureDirectory($directory, $mode = 0777, $is_backwards_recur
     // until an existing directory is hit, and from there, recursively create
     // the sub-directories. Only if that recursion succeeds, create the final,
     // originally requested subdirectory.
-    return $this->ensureDirectory($parent, $mode, TRUE) && mkdir($directory) && chmod($directory, $mode);
+    return $this->createDirectory($parent, $mode, TRUE) && mkdir($directory) && chmod($directory, $mode);
   }
 
   /**
diff --git a/core/lib/Drupal/Component/PhpStorage/MTimeProtectedFastFileStorage.php b/core/lib/Drupal/Component/PhpStorage/MTimeProtectedFastFileStorage.php
index 25429bb..3e660a0 100644
--- a/core/lib/Drupal/Component/PhpStorage/MTimeProtectedFastFileStorage.php
+++ b/core/lib/Drupal/Component/PhpStorage/MTimeProtectedFastFileStorage.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Definition of Drupal\Component\PhpStorage\MTimeProtectedFastFileStorage.
+ * Contains \Drupal\Component\PhpStorage\MTimeProtectedFastFileStorage.
  */
 
 namespace Drupal\Component\PhpStorage;
@@ -40,13 +40,6 @@
 class MTimeProtectedFastFileStorage extends FileStorage {
 
   /**
-   * The .htaccess code to make a directory private.
-   *
-   * Disabling Options Indexes is particularly important.
-   */
-  const HTACCESS="SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006\nDeny from all\nOptions None\nOptions +FollowSymLinks";
-
-  /**
    * The secret used in the HMAC.
    *
    * @var string
@@ -74,10 +67,6 @@ public function __construct(array $configuration) {
    */
   public function save($name, $data) {
     $this->ensureDirectory($this->directory);
-    $htaccess_path =  $this->directory . '/.htaccess';
-    if (!file_exists($htaccess_path) && file_put_contents($htaccess_path, self::HTACCESS)) {
-      @chmod($htaccess_path, 0444);
-    }
 
     // Write the file out to a temporary location. Prepend with a '.' to keep it
     // hidden from listings and web servers.
diff --git a/core/lib/Drupal/Component/Utility/Crypt.php b/core/lib/Drupal/Component/Utility/Crypt.php
index ea008bd..e2378e4 100644
--- a/core/lib/Drupal/Component/Utility/Crypt.php
+++ b/core/lib/Drupal/Component/Utility/Crypt.php
@@ -27,30 +27,29 @@ class Crypt {
    *   A randomly generated string.
    */
   public static function randomBytes($count) {
-    static $random_state, $bytes;
-    // Initialize on the first call. The contents of $_SERVER includes a mix of
-    // user-specific and system information that varies a little with each page.
-    // Further initialize with the somewhat random PHP process ID.
-    if (!isset($random_state)) {
-      $random_state = print_r($_SERVER, TRUE) . getmypid();
-      $bytes = '';
-    }
-    if (strlen($bytes) < $count) {
-      // /dev/urandom is available on many *nix systems and is considered the
-      // best commonly available pseudo-random source.
-      if ($fh = @fopen('/dev/urandom', 'rb')) {
+    // $random_state does not use drupal_static as it stores random bytes.
+    static $random_state, $bytes, $has_openssl;
+
+    $missing_bytes = $count - strlen($bytes);
+
+    if ($missing_bytes > 0) {
+      // openssl_random_pseudo_bytes() will find entropy in a system-dependent
+      // way.
+      if (function_exists('openssl_random_pseudo_bytes')) {
+        $bytes .= openssl_random_pseudo_bytes($missing_bytes);
+      }
+
+      // Else, read directly from /dev/urandom, which is available on many *nix
+      // systems and is considered cryptographically secure.
+      elseif ($fh = @fopen('/dev/urandom', 'rb')) {
         // PHP only performs buffered reads, so in reality it will always read
         // at least 4096 bytes. Thus, it costs nothing extra to read and store
         // that much so as to speed any additional invocations.
-        $bytes .= fread($fh, max(4096, $count));
+        $bytes .= fread($fh, max(4096, $missing_bytes));
         fclose($fh);
       }
-      // openssl_random_pseudo_bytes() will find entropy in a system-dependent
-      // way.
-      elseif (function_exists('openssl_random_pseudo_bytes')) {
-        $bytes .= openssl_random_pseudo_bytes($count - strlen($bytes));
-      }
-      // If /dev/urandom is not available or returns no bytes, this loop will
+
+      // If we couldn't get enough entropy, this simple hash-based PRNG 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()
@@ -58,9 +57,22 @@ public static function randomBytes($count) {
       // 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($bytes) < $count) {
-        $random_state = hash('sha256', microtime() . mt_rand() . $random_state);
-        $bytes .= hash('sha256', mt_rand() . $random_state, TRUE);
+      if (strlen($bytes) < $count) {
+        // Initialize on the first call. The contents of $_SERVER includes a mix of
+        // user-specific and system information that varies a little with each page.
+        if (!isset($random_state)) {
+          $random_state = print_r($_SERVER, TRUE);
+          if (function_exists('getmypid')) {
+            // Further initialize with the somewhat random PHP process ID.
+            $random_state .= getmypid();
+          }
+          $bytes = '';
+        }
+
+        do {
+          $random_state = hash('sha256', microtime() . mt_rand() . $random_state);
+          $bytes .= hash('sha256', mt_rand() . $random_state, TRUE);
+        } while (strlen($bytes) < $count);
       }
     }
     $output = substr($bytes, 0, $count);
@@ -111,20 +123,18 @@ public static function hashBase64($data) {
   }
 
   /**
-   * Generates a random, base-64 encoded, URL-safe, sha-256 hashed string.
+   * Returns a URL-safe, base64 encoded string of highly randomized bytes (over the full 8-bit range).
    *
-   * @param int $count
-   *   The number of characters (bytes) of the string to be hashed.
+   * @param $byte_count
+   *   The number of random bytes to fetch and base64 encode.
    *
    * @return string
-   *   A base-64 encoded sha-256 hash, with + replaced with -, / with _ and
-   *   any = padding characters removed.
+   *   The base64 encoded result will have a length of up to 4 * $byte_count.
    *
    * @see \Drupal\Component\Utility\Crypt::randomBytes()
-   * @see \Drupal\Component\Utility\Crypt::hashBase64()
    */
-  public static function randomStringHashed($count) {
-    return static::hashBase64(static::randomBytes($count));
+  public static function randomBytesBase64($count = 32) {
+    return strtr(base64_encode(static::randomBytes($count)), array('+' => '-', '/' => '_', '=' => ''));
   }
 
 }
diff --git a/core/lib/Drupal/Core/Form/FormBuilder.php b/core/lib/Drupal/Core/Form/FormBuilder.php
index 8e8a82a..49692d9 100644
--- a/core/lib/Drupal/Core/Form/FormBuilder.php
+++ b/core/lib/Drupal/Core/Form/FormBuilder.php
@@ -329,7 +329,7 @@ public function rebuildForm($form_id, &$form_state, $old_form = NULL) {
       $form['#build_id'] = $old_form['#build_id'];
     }
     else {
-      $form['#build_id'] = 'form-' . Crypt::hashBase64(uniqid(mt_rand(), TRUE) . mt_rand());
+      $form['#build_id'] = 'form-' . Crypt::randomBytesBase64();
     }
 
     // #action defaults to request_uri(), but in case of Ajax and other partial
@@ -672,7 +672,7 @@ public function prepareForm($form_id, &$form, &$form_state) {
     // @see self::buildForm()
     // @see self::rebuildForm()
     if (!isset($form['#build_id'])) {
-      $form['#build_id'] = 'form-' . Crypt::hashBase64(uniqid(mt_rand(), TRUE) . mt_rand());
+      $form['#build_id'] = 'form-' . Crypt::randomBytesBase64();
     }
     $form['form_build_id'] = array(
       '#type' => 'hidden',
diff --git a/core/lib/Drupal/Core/PrivateKey.php b/core/lib/Drupal/Core/PrivateKey.php
index 762a664..f41adeb 100644
--- a/core/lib/Drupal/Core/PrivateKey.php
+++ b/core/lib/Drupal/Core/PrivateKey.php
@@ -64,7 +64,7 @@ public function set($key) {
    *   The private key.
    */
   protected function create() {
-    return Crypt::randomStringHashed(55);
+    return Crypt::randomBytesBase64(55);
   }
 
 }
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/DirectoryTest.php b/core/modules/system/lib/Drupal/system/Tests/File/DirectoryTest.php
index 8c5634e..d17db20 100644
--- a/core/modules/system/lib/Drupal/system/Tests/File/DirectoryTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/File/DirectoryTest.php
@@ -99,7 +99,7 @@ function testFileCheckDirectoryHandling() {
     $this->assertTrue(is_file(file_default_scheme() . '://.htaccess'), 'Successfully re-created the .htaccess file in the files directory.', 'File');
     // Verify contents of .htaccess file.
     $file = file_get_contents(file_default_scheme() . '://.htaccess');
-    $this->assertEqual($file, "SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006\nOptions None\nOptions +FollowSymLinks", 'The .htaccess file contains the proper content.', 'File');
+    $this->assertEqual($file, file_htaccess_lines(FALSE), 'The .htaccess file contains the proper content.', 'File');
   }
 
   /**
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/HtaccessUnitTest.php b/core/modules/system/lib/Drupal/system/Tests/File/HtaccessUnitTest.php
index 5f4b656..4bc7f92 100644
--- a/core/modules/system/lib/Drupal/system/Tests/File/HtaccessUnitTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/File/HtaccessUnitTest.php
@@ -43,7 +43,10 @@ function testHtaccessSave() {
     mkdir($public, 0777, TRUE);
     $this->assertTrue(file_save_htaccess($public, FALSE));
     $content = file_get_contents($public . '/.htaccess');
-    $this->assertIdentical($content, "SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006\nOptions None\nOptions +FollowSymLinks");
+    $this->assertTrue(strpos($content, "SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006") !== FALSE);
+    $this->assertTrue(strpos($content, "Options None") !== FALSE);
+    $this->assertTrue(strpos($content, "Options +FollowSymLinks") !== FALSE);
+    $this->assertTrue(strpos($content, "SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003") !== FALSE);
     $this->assertFilePermissions($public . '/.htaccess', 0444);
 
     $this->assertTrue(file_save_htaccess($public, FALSE));
@@ -52,7 +55,11 @@ function testHtaccessSave() {
     mkdir($private, 0777, TRUE);
     $this->assertTrue(file_save_htaccess($private));
     $content = file_get_contents($private . '/.htaccess');
-    $this->assertIdentical($content, "SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006\nDeny from all\nOptions None\nOptions +FollowSymLinks");
+    $this->assertTrue(strpos($content, "SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006") !== FALSE);
+    $this->assertTrue(strpos($content, "Deny from all") !== FALSE);
+    $this->assertTrue(strpos($content, "Options None") !== FALSE);
+    $this->assertTrue(strpos($content, "Options +FollowSymLinks") !== FALSE);
+    $this->assertTrue(strpos($content, "SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003") !== FALSE);
     $this->assertFilePermissions($private . '/.htaccess', 0444);
 
     $this->assertTrue(file_save_htaccess($private));
@@ -61,7 +68,11 @@ function testHtaccessSave() {
     mkdir($stream, 0777, TRUE);
     $this->assertTrue(file_save_htaccess($stream));
     $content = file_get_contents($stream . '/.htaccess');
-    $this->assertIdentical($content, "SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006\nDeny from all\nOptions None\nOptions +FollowSymLinks");
+    $this->assertTrue(strpos($content,"SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006") !== FALSE);
+    $this->assertTrue(strpos($content,"Deny from all") !== FALSE);
+    $this->assertTrue(strpos($content,"Options None") !== FALSE);
+    $this->assertTrue(strpos($content,"Options +FollowSymLinks") !== FALSE);
+    $this->assertTrue(strpos($content, "SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003") !== FALSE);
     $this->assertFilePermissions($stream . '/.htaccess', 0444);
 
     $this->assertTrue(file_save_htaccess($stream));
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index 5e32a6b..ea60d48 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -264,6 +264,39 @@ function system_requirements($phase) {
     $requirements['settings.php']['title'] = t('Configuration files');
   }
 
+  // Test the contents of the .htaccess files.
+  if ($phase == 'runtime') {
+    // Try to write the .htaccess files first, to prevent false alarms in case
+    // (for example) the /tmp directory was wiped.
+    file_ensure_htaccess();
+    $htaccess_files['public://.htaccess'] = array(
+      'title' => t('Public files directory'),
+      'directory' => drupal_realpath('public://'),
+    );
+    if (\Drupal::config('system.file')->get('path.private')) {
+      $htaccess_files['private://.htaccess'] = array(
+        'title' => t('Private files directory'),
+        'directory' => drupal_realpath('private://'),
+      );
+    }
+    $htaccess_files['temporary://.htaccess'] = array(
+      'title' => t('Temporary files directory'),
+      'directory' => drupal_realpath('temporary://'),
+    );
+    foreach ($htaccess_files as $htaccess_file => $info) {
+      // Check for the string which was added to the recommended .htaccess file
+      // in the latest security update.
+      if (!file_exists($htaccess_file) || !($contents = @file_get_contents($htaccess_file)) || strpos($contents, 'Drupal_Security_Do_Not_Remove_See_SA_2013_003') === FALSE) {
+        $requirements[$htaccess_file] = array(
+          'title' => $info['title'],
+          'value' => t('Not fully protected'),
+          'severity' => REQUIREMENT_ERROR,
+          'description' => t('See <a href="@url">@url</a> for information about the recommended .htaccess file which should be added to the %directory directory to help protect against arbitrary code execution.', array('@url' => 'http://drupal.org/SA-CORE-2013-003', '%directory' => $info['directory'])),
+        );
+      }
+    }
+  }
+
   // Report cron status.
   if ($phase == 'runtime') {
     $cron_config = \Drupal::config('system.cron');
@@ -560,7 +593,7 @@ function system_install() {
     ->save();
 
   // Populate the cron key state variable.
-  $cron_key = Crypt::randomStringHashed(55);
+  $cron_key = Crypt::randomBytesBase64(55);
   \Drupal::state()->set('system.cron_key', $cron_key);
 
   // Populate the site UUID.
diff --git a/core/modules/user/tests/Drupal/user/Tests/PermissionsHashTest.php b/core/modules/user/tests/Drupal/user/Tests/PermissionsHashTest.php
index 422abd1..453bcfb 100644
--- a/core/modules/user/tests/Drupal/user/Tests/PermissionsHashTest.php
+++ b/core/modules/user/tests/Drupal/user/Tests/PermissionsHashTest.php
@@ -112,7 +112,7 @@ protected function setUp() {
       ->will($this->returnValue($roles_1_updated));
 
     // Mocked private key + cache services.
-    $random = Crypt::randomStringHashed(55);
+    $random = Crypt::randomBytesBase64(55);
     $this->private_key = $this->getMockBuilder('Drupal\Core\PrivateKey')
       ->disableOriginalConstructor()
       ->setMethods(array('get'))
@@ -202,7 +202,7 @@ function drupal_get_hash_salt() {
       static $salt;
 
       if (!isset($salt)) {
-        $salt = Drupal\Component\Utility\Crypt::randomStringHashed(55);
+        $salt = Drupal\Component\Utility\Crypt::randomBytesBase64(55);
       }
 
       return $salt;
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index bd8e6ee..a59c088 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -365,10 +365,14 @@ function user_password($length = 10) {
 
   // Loop the number of times specified by $length.
   for ($i = 0; $i < $length; $i++) {
+    do {
+      // Find a secure random number within the range needed.
+      $index = ord(Crypt::randomBytes(1));
+    } while ($index > $len);
 
     // Each iteration, pick a random character from the
     // allowable string and append it to the password:
-    $pass .= $allowable_characters[mt_rand(0, $len)];
+    $pass .= $allowable_characters[$index];
   }
 
   return $pass;
diff --git a/core/modules/user/user.pages.inc b/core/modules/user/user.pages.inc
index e093781..22d221a 100644
--- a/core/modules/user/user.pages.inc
+++ b/core/modules/user/user.pages.inc
@@ -62,7 +62,7 @@ function user_pass_reset($form, &$form_state, $uid, $timestamp, $hashed_pass, $a
           watchdog('user', 'User %name used one-time login link at time %timestamp.', array('%name' => $account->getUsername(), '%timestamp' => $timestamp));
           drupal_set_message(t('You have just used your one-time login link. It is no longer necessary to use this link to log in. Please change your password.'));
           // Let the user's password be changed without the current password check.
-          $token = Crypt::randomStringHashed(55);
+          $token = Crypt::randomBytesBase64(55);
           $_SESSION['pass_reset_' . $user->id()] = $token;
           return new RedirectResponse(url('user/' . $user->id() . '/edit', array(
             'query' => array('pass-reset-token' => $token),
diff --git a/core/tests/Drupal/Tests/Component/PhpStorage/MTimeProtectedFileStorageTest.php b/core/tests/Drupal/Tests/Component/PhpStorage/MTimeProtectedFileStorageTest.php
index 214b1a7..49cc53a 100644
--- a/core/tests/Drupal/Tests/Component/PhpStorage/MTimeProtectedFileStorageTest.php
+++ b/core/tests/Drupal/Tests/Component/PhpStorage/MTimeProtectedFileStorageTest.php
@@ -80,7 +80,7 @@ function testSecurity() {
 
     // Ensure the root directory for the bin has a .htaccess file denying web
     // access.
-    $this->assertSame(file_get_contents($expected_root_directory . '/.htaccess'), "SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006\nDeny from all\nOptions None\nOptions +FollowSymLinks");
+    $this->assertSame(file_get_contents($expected_root_directory . '/.htaccess'), call_user_func(array($this->storageClass, 'htaccessLines')));
 
     // Ensure that if the file is replaced with an untrusted one (due to another
     // script's file upload vulnerability), it does not get loaded. Since mtime
diff --git a/core/tests/Drupal/Tests/Core/Access/CsrfTokenGeneratorTest.php b/core/tests/Drupal/Tests/Core/Access/CsrfTokenGeneratorTest.php
index 3a6d75c..766d641 100644
--- a/core/tests/Drupal/Tests/Core/Access/CsrfTokenGeneratorTest.php
+++ b/core/tests/Drupal/Tests/Core/Access/CsrfTokenGeneratorTest.php
@@ -37,7 +37,7 @@ public static function getInfo() {
    */
   function setUp() {
     parent::setUp();
-    $this->key = Crypt::randomStringHashed(55);
+    $this->key = Crypt::randomBytesBase64(55);
 
     $private_key = $this->getMockBuilder('Drupal\Core\PrivateKey')
       ->disableOriginalConstructor()
diff --git a/core/tests/Drupal/Tests/Core/PrivateKeyTest.php b/core/tests/Drupal/Tests/Core/PrivateKeyTest.php
index 9f864f8..02ac1e6 100644
--- a/core/tests/Drupal/Tests/Core/PrivateKeyTest.php
+++ b/core/tests/Drupal/Tests/Core/PrivateKeyTest.php
@@ -50,7 +50,7 @@ public static function getInfo() {
    */
   public function setUp() {
     parent::setUp();
-    $this->key = Crypt::randomStringHashed(55);
+    $this->key = Crypt::randomBytesBase64(55);
 
     $this->state = $this->getMock('Drupal\Core\KeyValueStore\StateInterface');
 
