diff --git a/core/composer.json b/core/composer.json
index c975dc9..067f70c 100644
--- a/core/composer.json
+++ b/core/composer.json
@@ -31,7 +31,8 @@
     "behat/mink": "~1.6",
     "behat/mink-goutte-driver": "~1.1",
     "fabpot/goutte": "^2.0.3",
-    "masterminds/html5": "~2.1"
+    "masterminds/html5": "~2.1",
+    "ircmaxell/password-compat": "~1.0"
   },
   "autoload": {
     "psr-4": {
diff --git a/core/composer.lock b/core/composer.lock
index 0c90697..25db4e0 100644
--- a/core/composer.lock
+++ b/core/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
         "This file is @generated automatically"
     ],
-    "hash": "377cea36943eae1762c885ef742bc320",
+    "hash": "a1f5c8c7e6843c8fdde4e03c7a383ecb",
     "packages": [
         {
             "name": "behat/mink",
@@ -940,6 +940,48 @@
             "time": "2014-10-12 19:18:40"
         },
         {
+            "name": "ircmaxell/password-compat",
+            "version": "v1.0.4",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/ircmaxell/password_compat.git",
+                "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/ircmaxell/password_compat/zipball/5c5cde8822a69545767f7c7f3058cb15ff84614c",
+                "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c",
+                "shasum": ""
+            },
+            "require-dev": {
+                "phpunit/phpunit": "4.*"
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "lib/password.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Anthony Ferrara",
+                    "email": "ircmaxell@php.net",
+                    "homepage": "http://blog.ircmaxell.com"
+                }
+            ],
+            "description": "A compatibility library for the proposed simplified password hashing algorithm: https://wiki.php.net/rfc/password_hash",
+            "homepage": "https://github.com/ircmaxell/password_compat",
+            "keywords": [
+                "hashing",
+                "password"
+            ],
+            "time": "2014-11-20 16:49:30"
+        },
+        {
             "name": "masterminds/html5",
             "version": "2.1.0",
             "source": {
diff --git a/core/core.services.yml b/core/core.services.yml
index 2b81197..2b240ee 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -658,13 +658,14 @@ services:
     arguments: ['@router', '@router.no_access_checks', '@current_user', '@path_processor_manager']
 
 # The argument to the hashing service defined in services.yml, to the
-# constructor of PhpassHashedPassword is the log2 number of iterations for
-# password stretching.
+# constructor of Password is the 'cost' option of password_hash().
 # @todo increase by 1 every Drupal version in order to counteract increases in
-# the speed and power of computers available to crack the hashes. The current
-# password hashing method was introduced in Drupal 7 with a log2 count of 15.
+# the speed and power of computers available to crack the hashes.
   password:
-    class: Drupal\Core\Password\PhpassHashedPassword
+    class: Drupal\Core\Password\Password
+    arguments: [16, '@drupal7_password']
+  drupal7_password:
+    class: Drupal\Core\Password\Drupal7Password
     arguments: [16]
   accept_header_matcher:
     class: Drupal\Core\Routing\AcceptHeaderMatcher
diff --git a/core/lib/Drupal/Core/Password/Drupal7Password.php b/core/lib/Drupal/Core/Password/Drupal7Password.php
new file mode 100644
index 0000000..5e46807
--- /dev/null
+++ b/core/lib/Drupal/Core/Password/Drupal7Password.php
@@ -0,0 +1,239 @@
+<?php
+
+/**
+ * @file
+ * Contains of \Drupal\Core\Password\Drupal7Password.
+ */
+
+namespace Drupal\Core\Password;
+
+use Drupal\Component\Utility\Crypt;
+use Drupal\user\UserInterface;
+
+/**
+ * Secure password hashing functions used in Drupal 7 and used for migrated
+ * password rehashing.
+ */
+class Drupal7Password implements PasswordInterface {
+  /**
+   * The minimum allowed log2 number of iterations for password stretching.
+   */
+  const MIN_HASH_COUNT = 7;
+
+  /**
+   * The maximum allowed log2 number of iterations for password stretching.
+   */
+  const MAX_HASH_COUNT = 30;
+
+  /**
+   * The expected (and maximum) number of characters in a hashed password.
+   */
+  const HASH_LENGTH = 55;
+
+  /**
+   * Returns a string for mapping an int to the corresponding base 64 character.
+   *
+   * @var string
+   */
+  static protected $ITOA64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
+
+  /**
+   * Specifies the number of times the hashing function will be applied when
+   * generating new password hashes. The number of times is calculated by
+   * raising 2 to the power of the given value.
+   *
+   * @var int
+   */
+  protected $countLog2;
+
+  /**
+   * Constructs a new phpass password hashing instance.
+   *
+   * @param int $countLog2
+   *   Password stretching iteration count. Specifies the number of times the
+   *   hashing function will be applied when generating new password hashes.
+   *   The number of times is calculated by raising 2 to the power of the given
+   *   value.
+   */
+  function __construct($countLog2) {
+    // Ensure that $countLog2 is within set bounds.
+    $this->countLog2 = $this->enforceLog2Boundaries($countLog2);
+  }
+
+  /**
+   * Encodes bytes into printable base 64 using the *nix standard from crypt().
+   *
+   * @param string $input
+   *   The string containing bytes to encode.
+   * @param int $count
+   *   The number of characters (bytes) to encode.
+   *
+   * @return string
+   *   Encoded string
+   */
+  protected function base64Encode($input, $count) {
+    $output = '';
+    $i = 0;
+    do {
+      $value = ord($input[$i++]);
+      $output .= static::$ITOA64[$value & 0x3f];
+      if ($i < $count) {
+        $value |= ord($input[$i]) << 8;
+      }
+      $output .= static::$ITOA64[($value >> 6) & 0x3f];
+      if ($i++ >= $count) {
+        break;
+      }
+      if ($i < $count) {
+        $value |= ord($input[$i]) << 16;
+      }
+      $output .= static::$ITOA64[($value >> 12) & 0x3f];
+      if ($i++ >= $count) {
+        break;
+      }
+      $output .= static::$ITOA64[($value >> 18) & 0x3f];
+    } while ($i < $count);
+
+    return $output;
+  }
+
+  /**
+   * Generates a random base 64-encoded salt prefixed with settings for the hash.
+   *
+   * Proper use of salts may defeat a number of attacks, including:
+   *  - The ability to try candidate passwords against multiple hashes at once.
+   *  - The ability to use pre-hashed lists of candidate passwords.
+   *  - The ability to determine whether two users have the same (or different)
+   *    password without actually having to guess one of the passwords.
+   *
+   * @return string
+   *   A 12 character string containing the iteration count and a random salt.
+   */
+  protected function generateSalt() {
+    $output = '$S$';
+    // We encode the final log2 iteration count in base 64.
+    $output .= static::$ITOA64[$this->countLog2];
+    // 6 bytes is the standard salt for a portable phpass hash.
+    $output .= $this->base64Encode(Crypt::randomBytes(6), 6);
+    return $output;
+  }
+
+  /**
+   * Ensures that $count_log2 is within set bounds.
+   *
+   * @param int $count_log2
+   *   Integer that determines the number of iterations used in the hashing
+   *   process. A larger value is more secure, but takes more time to complete.
+   *
+   * @return int
+   *   Integer within set bounds that is closest to $count_log2.
+   */
+  protected function enforceLog2Boundaries($count_log2) {
+    if ($count_log2 < static::MIN_HASH_COUNT) {
+      return static::MIN_HASH_COUNT;
+    }
+    elseif ($count_log2 > static::MAX_HASH_COUNT) {
+      return static::MAX_HASH_COUNT;
+    }
+
+    return (int) $count_log2;
+  }
+
+  /**
+   * Hashes a password using a secure stretched hash.
+   *
+   * By using a salt and repeated hashing the password is "stretched". Its
+   * security is increased because it becomes much more computationally costly
+   * for an attacker to try to break the hash by brute-force computation of the
+   * hashes of a large number of plain-text words or strings to find a match.
+   *
+   * @param string $algo
+   *   The string name of a hashing algorithm usable by hash(), like 'sha256'.
+   * @param string $password
+   *   Plain-text password up to 512 bytes (128 to 512 UTF-8 characters) to
+   *   hash.
+   * @param string $setting
+   *   An existing hash or the output of $this->generateSalt().  Must be
+   *   at least 12 characters (the settings and salt).
+   *
+   * @return string
+   *   A string containing the hashed password (and salt) or FALSE on failure.
+   *   The return string will be truncated at HASH_LENGTH characters max.
+   */
+  protected function crypt($algo, $password, $setting) {
+    // Prevent DoS attacks by refusing to hash large passwords.
+    if (strlen($password) > 512) {
+      return FALSE;
+    }
+
+    // The first 12 characters of an existing hash are its setting string.
+    $setting = substr($setting, 0, 12);
+
+    if ($setting[0] != '$' || $setting[2] != '$') {
+      return FALSE;
+    }
+    $count_log2 = $this->getCountLog2($setting);
+    // Stored hashes may have been crypted with any iteration count. However we
+    // do not allow applying the algorithm for unreasonable low and high values
+    // respectively.
+    if ($count_log2 != $this->enforceLog2Boundaries($count_log2)) {
+      return FALSE;
+    }
+    $salt = substr($setting, 4, 8);
+    // Hashes must have an 8 character salt.
+    if (strlen($salt) != 8) {
+      return FALSE;
+    }
+
+    // Convert the base 2 logarithm into an integer.
+    $count = 1 << $count_log2;
+
+    // We rely on the hash() function being available in PHP 5.2+.
+    $hash = hash($algo, $salt . $password, TRUE);
+    do {
+      $hash = hash($algo, $hash . $password, TRUE);
+    } while (--$count);
+
+    $len = strlen($hash);
+    $output =  $setting . $this->base64Encode($hash, $len);
+    // $this->base64Encode() of a 16 byte MD5 will always be 22 characters.
+    // $this->base64Encode() of a 64 byte sha512 will always be 86 characters.
+    $expected = 12 + ceil((8 * $len) / 6);
+    return (strlen($output) == $expected) ? substr($output, 0, static::HASH_LENGTH) : FALSE;
+  }
+
+  /**
+   * Parses the log2 iteration count from a stored hash or setting string.
+   *
+   * @param string $setting
+   *   An existing hash or the output of $this->generateSalt().  Must be
+   *   at least 12 characters (the settings and salt).
+   *
+   * @return int
+   */
+  protected function getCountLog2($setting) {
+    return strpos(static::$ITOA64, $setting[3]);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function hash($password) {
+    return $this->crypt('sha512', $password, $this->generateSalt());
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function check($password, UserInterface $account) {
+    // Not used.
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function userNeedsNewHash(UserInterface $account) {
+    // Not used.
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Password/Password.php b/core/lib/Drupal/Core/Password/Password.php
new file mode 100644
index 0000000..1be8d2b
--- /dev/null
+++ b/core/lib/Drupal/Core/Password/Password.php
@@ -0,0 +1,91 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Password\Password.
+ */
+
+namespace Drupal\Core\Password;
+
+use Drupal\user\UserInterface;
+
+/**
+ * Secure password hashing functions based on PHP (>=5.5.0) password hashing
+ * functions.
+ */
+class Password implements PasswordInterface {
+
+  /**
+   * The algorithmic cost that should be used.
+   *
+   * @var int
+   */
+  protected $cost;
+
+  /**
+   * The Drupal 7 password hashing service.
+   *
+   * @var \Drupal\Core\Password\PasswordInterface
+   */
+  protected $drupal7Password;
+
+  /**
+   * Constructs a new password hashing instance.
+   *
+   * @param int $cost
+   *   The algorithmic cost that should be used.
+   * @param \Drupal\Core\Password\PasswordInterface
+   *   The Drupal7 password hashing service.
+   */
+  function __construct($cost, PasswordInterface $drupal7_password) {
+    $this->cost = $cost;
+    $this->drupal7Password = $drupal7_password;
+
+    // Assure PHP 5.4 backward compatibility.
+    // @todo To be removed along with the 'ircmaxell/password-compat' library
+    //   when Drupal will require PHP >= 5.5.
+    if (version_compare(PHP_VERSION, '5.5.0', '>=')) {
+      // @todo Is there a standard API to include such files?
+      require_once 'core/vendor/ircmaxell/password-compat/lib/password.php';
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function hash($password) {
+    return password_hash($password, PASSWORD_DEFAULT, ['cost' => $this->cost]);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function check($password, UserInterface $account) {
+    if (substr($account->getPassword(), 0, 2) == 'U$') {
+      // This may be an updated password from user_update_7000(). Such hashes
+      // have 'U' added as the first character and need an extra md5() (see the
+      // Drupal 7 documentation).
+      $stored_hash = substr($account->getPassword(), 1);
+      $password = md5($password);
+    }
+    elseif (substr($account->getPassword(), 0, 3) == 'D7$') {
+      $stored_hash = substr($account->getPassword(), 2);
+      $password = $this->drupal7Password->hash($password);
+    }
+    else {
+      $stored_hash = $account->getPassword();
+    }
+
+    // Is this is a Drupal 8 password?
+    return password_verify($password, $stored_hash);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function userNeedsNewHash(UserInterface $account) {
+    $info = password_get_info($account->getPassword());
+    return (bool) $info['algo'];
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Password/PhpassHashedPassword.php b/core/lib/Drupal/Core/Password/PhpassHashedPassword.php
deleted file mode 100644
index 17cafdd..0000000
--- a/core/lib/Drupal/Core/Password/PhpassHashedPassword.php
+++ /dev/null
@@ -1,268 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\Core\Password\PhpassHashedPassword
- */
-
-namespace Drupal\Core\Password;
-
-use Drupal\Component\Utility\Crypt;
-use Drupal\user\UserInterface;
-
-/**
- * Secure password hashing functions based on the Portable PHP password
- * hashing framework.
- *
- * @see http://www.openwall.com/phpass/
- */
-class PhpassHashedPassword implements PasswordInterface {
-  /**
-   * The minimum allowed log2 number of iterations for password stretching.
-   */
-  const MIN_HASH_COUNT = 7;
-
-  /**
-   * The maximum allowed log2 number of iterations for password stretching.
-   */
-  const MAX_HASH_COUNT = 30;
-
-  /**
-   * The expected (and maximum) number of characters in a hashed password.
-   */
-  const HASH_LENGTH = 55;
-
-  /**
-   * Returns a string for mapping an int to the corresponding base 64 character.
-   */
-  static $ITOA64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
-
-  /**
-   * Specifies the number of times the hashing function will be applied when
-   * generating new password hashes. The number of times is calculated by
-   * raising 2 to the power of the given value.
-   */
-  protected $countLog2;
-
-  /**
-   * Constructs a new phpass password hashing instance.
-   *
-   * @param int $countLog2
-   *   Password stretching iteration count. Specifies the number of times the
-   *   hashing function will be applied when generating new password hashes.
-   *   The number of times is calculated by raising 2 to the power of the given
-   *   value.
-   */
-  function __construct($countLog2) {
-    // Ensure that $countLog2 is within set bounds.
-    $this->countLog2 = $this->enforceLog2Boundaries($countLog2);
-  }
-
-  /**
-   * Encodes bytes into printable base 64 using the *nix standard from crypt().
-   *
-   * @param String $input
-   *   The string containing bytes to encode.
-   * @param Integer $count
-   *   The number of characters (bytes) to encode.
-   *
-   * @return String
-   *   Encoded string
-   */
-  protected function base64Encode($input, $count) {
-    $output = '';
-    $i = 0;
-    do {
-      $value = ord($input[$i++]);
-      $output .= static::$ITOA64[$value & 0x3f];
-      if ($i < $count) {
-        $value |= ord($input[$i]) << 8;
-      }
-      $output .= static::$ITOA64[($value >> 6) & 0x3f];
-      if ($i++ >= $count) {
-        break;
-      }
-      if ($i < $count) {
-        $value |= ord($input[$i]) << 16;
-      }
-      $output .= static::$ITOA64[($value >> 12) & 0x3f];
-      if ($i++ >= $count) {
-        break;
-      }
-      $output .= static::$ITOA64[($value >> 18) & 0x3f];
-    } while ($i < $count);
-
-    return $output;
-  }
-
-  /**
-   * Generates a random base 64-encoded salt prefixed with settings for the hash.
-   *
-   * Proper use of salts may defeat a number of attacks, including:
-   *  - The ability to try candidate passwords against multiple hashes at once.
-   *  - The ability to use pre-hashed lists of candidate passwords.
-   *  - The ability to determine whether two users have the same (or different)
-   *    password without actually having to guess one of the passwords.
-   *
-   * @return String
-   *   A 12 character string containing the iteration count and a random salt.
-   */
-  protected function generateSalt() {
-    $output = '$S$';
-    // We encode the final log2 iteration count in base 64.
-    $output .= static::$ITOA64[$this->countLog2];
-    // 6 bytes is the standard salt for a portable phpass hash.
-    $output .= $this->base64Encode(Crypt::randomBytes(6), 6);
-    return $output;
-  }
-
-  /**
-   * Ensures that $count_log2 is within set bounds.
-   *
-   * @param Integer $count_log2
-   *   Integer that determines the number of iterations used in the hashing
-   *   process. A larger value is more secure, but takes more time to complete.
-   *
-   * @return Integer
-   *   Integer within set bounds that is closest to $count_log2.
-   */
-  protected function enforceLog2Boundaries($count_log2) {
-    if ($count_log2 < static::MIN_HASH_COUNT) {
-      return static::MIN_HASH_COUNT;
-    }
-    elseif ($count_log2 > static::MAX_HASH_COUNT) {
-      return static::MAX_HASH_COUNT;
-    }
-
-    return (int) $count_log2;
-  }
-
-  /**
-   * Hash a password using a secure stretched hash.
-   *
-   * By using a salt and repeated hashing the password is "stretched". Its
-   * security is increased because it becomes much more computationally costly
-   * for an attacker to try to break the hash by brute-force computation of the
-   * hashes of a large number of plain-text words or strings to find a match.
-   *
-   * @param String $algo
-   *   The string name of a hashing algorithm usable by hash(), like 'sha256'.
-   * @param String $password
-   *   Plain-text password up to 512 bytes (128 to 512 UTF-8 characters) to
-   *   hash.
-   * @param String $setting
-   *   An existing hash or the output of $this->generateSalt().  Must be
-   *   at least 12 characters (the settings and salt).
-   *
-   * @return String
-   *   A string containing the hashed password (and salt) or FALSE on failure.
-   *   The return string will be truncated at HASH_LENGTH characters max.
-   */
-  protected function crypt($algo, $password, $setting) {
-    // Prevent DoS attacks by refusing to hash large passwords.
-    if (strlen($password) > 512) {
-      return FALSE;
-    }
-
-    // The first 12 characters of an existing hash are its setting string.
-    $setting = substr($setting, 0, 12);
-
-    if ($setting[0] != '$' || $setting[2] != '$') {
-      return FALSE;
-    }
-    $count_log2 = $this->getCountLog2($setting);
-    // Stored hashes may have been crypted with any iteration count. However we
-    // do not allow applying the algorithm for unreasonable low and high values
-    // respectively.
-    if ($count_log2 != $this->enforceLog2Boundaries($count_log2)) {
-      return FALSE;
-    }
-    $salt = substr($setting, 4, 8);
-    // Hashes must have an 8 character salt.
-    if (strlen($salt) != 8) {
-      return FALSE;
-    }
-
-    // Convert the base 2 logarithm into an integer.
-    $count = 1 << $count_log2;
-
-    // We rely on the hash() function being available in PHP 5.2+.
-    $hash = hash($algo, $salt . $password, TRUE);
-    do {
-      $hash = hash($algo, $hash . $password, TRUE);
-    } while (--$count);
-
-    $len = strlen($hash);
-    $output =  $setting . $this->base64Encode($hash, $len);
-    // $this->base64Encode() of a 16 byte MD5 will always be 22 characters.
-    // $this->base64Encode() of a 64 byte sha512 will always be 86 characters.
-    $expected = 12 + ceil((8 * $len) / 6);
-    return (strlen($output) == $expected) ? substr($output, 0, static::HASH_LENGTH) : FALSE;
-  }
-
-  /**
-   * Parse the log2 iteration count from a stored hash or setting string.
-   *
-   * @param String $setting
-   *   An existing hash or the output of $this->generateSalt().  Must be
-   *   at least 12 characters (the settings and salt).
-   */
-  public function getCountLog2($setting) {
-    return strpos(static::$ITOA64, $setting[3]);
-  }
-
-  /**
-   * Implements Drupal\Core\Password\PasswordInterface::hash().
-   */
-  public function hash($password) {
-    return $this->crypt('sha512', $password, $this->generateSalt());
-  }
-
-  /**
-   * Implements Drupal\Core\Password\PasswordInterface::checkPassword().
-   */
-  public function check($password, UserInterface $account) {
-    if (substr($account->getPassword(), 0, 2) == 'U$') {
-      // This may be an updated password from user_update_7000(). Such hashes
-      // have 'U' added as the first character and need an extra md5() (see the
-      // Drupal 7 documentation).
-      $stored_hash = substr($account->getPassword(), 1);
-      $password = md5($password);
-    }
-    else {
-      $stored_hash = $account->getPassword();
-    }
-
-    $type = substr($stored_hash, 0, 3);
-    switch ($type) {
-      case '$S$':
-        // A normal Drupal 7 password using sha512.
-        $hash = $this->crypt('sha512', $password, $stored_hash);
-        break;
-      case '$H$':
-        // phpBB3 uses "$H$" for the same thing as "$P$".
-      case '$P$':
-        // A phpass password generated using md5.  This is an
-        // imported password or from an earlier Drupal version.
-        $hash = $this->crypt('md5', $password, $stored_hash);
-        break;
-      default:
-        return FALSE;
-    }
-    return ($hash && $stored_hash == $hash);
-  }
-
-  /**
-   * Implements Drupal\Core\Password\PasswordInterface::userNeedsNewHash().
-   */
-  public function userNeedsNewHash(UserInterface $account) {
-    // Check whether this was an updated password.
-    if ((substr($account->getPassword(), 0, 3) != '$S$') || (strlen($account->getPassword()) != static::HASH_LENGTH)) {
-      return TRUE;
-    }
-    // Ensure that $count_log2 is within set bounds.
-    $count_log2 = $this->enforceLog2Boundaries($this->countLog2);
-    // Check whether the iteration count used differs from the standard number.
-    return ($this->getCountLog2($account->getPassword()) !== $count_log2);
-  }
-}
diff --git a/core/modules/migrate/src/MigratePassword.php b/core/modules/migrate/src/MigratePassword.php
index ba42e8a..796c7f1 100644
--- a/core/modules/migrate/src/MigratePassword.php
+++ b/core/modules/migrate/src/MigratePassword.php
@@ -59,10 +59,22 @@ public function userNeedsNewHash(UserInterface $account) {
   public function hash($password) {
     $hash = $this->originalPassword->hash($password);
 
-    // Allow prefixing only if the service was asked to prefix. Check also if
-    // the $password pattern is conforming to a MD5 result.
-    if ($this->enabled && preg_match('/^[0-9a-f]{32}$/', $password)) {
-      $hash = 'U' . $hash;
+    // Allow prefixing only if the service was asked to prefix.
+    if ($this->enabled) {
+      // If the $password pattern is conforming to a MD5 result this is most
+      // likely a Drupal 6 hashed password.
+      if (preg_match('/^[0-9a-f]{32}$/', $password)) {
+        $hash = 'U' . $hash;
+      }
+      // @todo Is this enough? Maybe we should pass and test somehow the current
+      // migration source to detect a Drupal 7 source. This can be done by
+      // injecting the current migration when enabling prefixing in
+      // Drupal\migrate\Plugin\migrate\destination\EntityUser. In that case
+      // ::enableMd5Prefixing() needs to be renamed. Or pass the migration into
+      // constructor? How?
+      if (substr($password, 0, 3) == '$S$') {
+        $hash = 'D7' . $hash;
+      }
     }
 
     return $hash;
diff --git a/core/modules/user/src/UserAuth.php b/core/modules/user/src/UserAuth.php
index 625b444..c1bf679 100644
--- a/core/modules/user/src/UserAuth.php
+++ b/core/modules/user/src/UserAuth.php
@@ -8,7 +8,6 @@
 namespace Drupal\user;
 
 use Drupal\Core\Entity\EntityManagerInterface;
-use Drupal\Core\Entity\EntityStorageInterface;
 use Drupal\Core\Password\PasswordInterface;
 
 /**
diff --git a/core/vendor/composer/autoload_files.php b/core/vendor/composer/autoload_files.php
index 853f9a0..d257539 100644
--- a/core/vendor/composer/autoload_files.php
+++ b/core/vendor/composer/autoload_files.php
@@ -7,5 +7,6 @@
 
 return array(
     $vendorDir . '/react/promise/src/functions_include.php',
+    $vendorDir . '/ircmaxell/password-compat/lib/password.php',
     $baseDir . '/lib/Drupal.php',
 );
diff --git a/core/vendor/composer/installed.json b/core/vendor/composer/installed.json
index 314ce82..5481bc3 100644
--- a/core/vendor/composer/installed.json
+++ b/core/vendor/composer/installed.json
@@ -3133,5 +3133,49 @@
             "serializer",
             "xml"
         ]
+    },
+    {
+        "name": "ircmaxell/password-compat",
+        "version": "v1.0.4",
+        "version_normalized": "1.0.4.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/ircmaxell/password_compat.git",
+            "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/ircmaxell/password_compat/zipball/5c5cde8822a69545767f7c7f3058cb15ff84614c",
+            "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c",
+            "shasum": ""
+        },
+        "require-dev": {
+            "phpunit/phpunit": "4.*"
+        },
+        "time": "2014-11-20 16:49:30",
+        "type": "library",
+        "installation-source": "dist",
+        "autoload": {
+            "files": [
+                "lib/password.php"
+            ]
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Anthony Ferrara",
+                "email": "ircmaxell@php.net",
+                "homepage": "http://blog.ircmaxell.com"
+            }
+        ],
+        "description": "A compatibility library for the proposed simplified password hashing algorithm: https://wiki.php.net/rfc/password_hash",
+        "homepage": "https://github.com/ircmaxell/password_compat",
+        "keywords": [
+            "hashing",
+            "password"
+        ]
     }
 ]
diff --git a/core/vendor/ircmaxell/password-compat/LICENSE.md b/core/vendor/ircmaxell/password-compat/LICENSE.md
new file mode 100644
index 0000000..1efc565
--- /dev/null
+++ b/core/vendor/ircmaxell/password-compat/LICENSE.md
@@ -0,0 +1,7 @@
+Copyright (c) 2012 Anthony Ferrara
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/core/vendor/ircmaxell/password-compat/composer.json b/core/vendor/ircmaxell/password-compat/composer.json
new file mode 100644
index 0000000..822fd1f
--- /dev/null
+++ b/core/vendor/ircmaxell/password-compat/composer.json
@@ -0,0 +1,20 @@
+{
+    "name": "ircmaxell/password-compat",
+    "description": "A compatibility library for the proposed simplified password hashing algorithm: https://wiki.php.net/rfc/password_hash",
+    "keywords": ["password", "hashing"],
+    "homepage": "https://github.com/ircmaxell/password_compat",
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "Anthony Ferrara",
+            "email": "ircmaxell@php.net",
+            "homepage": "http://blog.ircmaxell.com"
+        }
+    ],
+    "require-dev": {
+        "phpunit/phpunit": "4.*"
+    },
+    "autoload": {
+        "files": ["lib/password.php"]
+    }
+}
diff --git a/core/vendor/ircmaxell/password-compat/lib/password.php b/core/vendor/ircmaxell/password-compat/lib/password.php
new file mode 100644
index 0000000..cc6896c
--- /dev/null
+++ b/core/vendor/ircmaxell/password-compat/lib/password.php
@@ -0,0 +1,314 @@
+<?php
+/**
+ * A Compatibility library with PHP 5.5's simplified password hashing API.
+ *
+ * @author Anthony Ferrara <ircmaxell@php.net>
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @copyright 2012 The Authors
+ */
+
+namespace {
+
+    if (!defined('PASSWORD_BCRYPT')) {
+        /**
+         * PHPUnit Process isolation caches constants, but not function declarations.
+         * So we need to check if the constants are defined separately from 
+         * the functions to enable supporting process isolation in userland
+         * code.
+         */
+        define('PASSWORD_BCRYPT', 1);
+        define('PASSWORD_DEFAULT', PASSWORD_BCRYPT);
+        define('PASSWORD_BCRYPT_DEFAULT_COST', 10);
+    }
+
+    if (!function_exists('password_hash')) {
+
+        /**
+         * Hash the password using the specified algorithm
+         *
+         * @param string $password The password to hash
+         * @param int    $algo     The algorithm to use (Defined by PASSWORD_* constants)
+         * @param array  $options  The options for the algorithm to use
+         *
+         * @return string|false The hashed password, or false on error.
+         */
+        function password_hash($password, $algo, array $options = array()) {
+            if (!function_exists('crypt')) {
+                trigger_error("Crypt must be loaded for password_hash to function", E_USER_WARNING);
+                return null;
+            }
+            if (is_null($password) || is_int($password)) {
+                $password = (string) $password;
+            }
+            if (!is_string($password)) {
+                trigger_error("password_hash(): Password must be a string", E_USER_WARNING);
+                return null;
+            }
+            if (!is_int($algo)) {
+                trigger_error("password_hash() expects parameter 2 to be long, " . gettype($algo) . " given", E_USER_WARNING);
+                return null;
+            }
+            $resultLength = 0;
+            switch ($algo) {
+                case PASSWORD_BCRYPT:
+                    $cost = PASSWORD_BCRYPT_DEFAULT_COST;
+                    if (isset($options['cost'])) {
+                        $cost = $options['cost'];
+                        if ($cost < 4 || $cost > 31) {
+                            trigger_error(sprintf("password_hash(): Invalid bcrypt cost parameter specified: %d", $cost), E_USER_WARNING);
+                            return null;
+                        }
+                    }
+                    // The length of salt to generate
+                    $raw_salt_len = 16;
+                    // The length required in the final serialization
+                    $required_salt_len = 22;
+                    $hash_format = sprintf("$2y$%02d$", $cost);
+                    // The expected length of the final crypt() output
+                    $resultLength = 60;
+                    break;
+                default:
+                    trigger_error(sprintf("password_hash(): Unknown password hashing algorithm: %s", $algo), E_USER_WARNING);
+                    return null;
+            }
+            $salt_requires_encoding = false;
+            if (isset($options['salt'])) {
+                switch (gettype($options['salt'])) {
+                    case 'NULL':
+                    case 'boolean':
+                    case 'integer':
+                    case 'double':
+                    case 'string':
+                        $salt = (string) $options['salt'];
+                        break;
+                    case 'object':
+                        if (method_exists($options['salt'], '__tostring')) {
+                            $salt = (string) $options['salt'];
+                            break;
+                        }
+                    case 'array':
+                    case 'resource':
+                    default:
+                        trigger_error('password_hash(): Non-string salt parameter supplied', E_USER_WARNING);
+                        return null;
+                }
+                if (PasswordCompat\binary\_strlen($salt) < $required_salt_len) {
+                    trigger_error(sprintf("password_hash(): Provided salt is too short: %d expecting %d", PasswordCompat\binary\_strlen($salt), $required_salt_len), E_USER_WARNING);
+                    return null;
+                } elseif (0 == preg_match('#^[a-zA-Z0-9./]+$#D', $salt)) {
+                    $salt_requires_encoding = true;
+                }
+            } else {
+                $buffer = '';
+                $buffer_valid = false;
+                if (function_exists('mcrypt_create_iv') && !defined('PHALANGER')) {
+                    $buffer = mcrypt_create_iv($raw_salt_len, MCRYPT_DEV_URANDOM);
+                    if ($buffer) {
+                        $buffer_valid = true;
+                    }
+                }
+                if (!$buffer_valid && function_exists('openssl_random_pseudo_bytes')) {
+                    $buffer = openssl_random_pseudo_bytes($raw_salt_len);
+                    if ($buffer) {
+                        $buffer_valid = true;
+                    }
+                }
+                if (!$buffer_valid && @is_readable('/dev/urandom')) {
+                    $f = fopen('/dev/urandom', 'r');
+                    $read = PasswordCompat\binary\_strlen($buffer);
+                    while ($read < $raw_salt_len) {
+                        $buffer .= fread($f, $raw_salt_len - $read);
+                        $read = PasswordCompat\binary\_strlen($buffer);
+                    }
+                    fclose($f);
+                    if ($read >= $raw_salt_len) {
+                        $buffer_valid = true;
+                    }
+                }
+                if (!$buffer_valid || PasswordCompat\binary\_strlen($buffer) < $raw_salt_len) {
+                    $bl = PasswordCompat\binary\_strlen($buffer);
+                    for ($i = 0; $i < $raw_salt_len; $i++) {
+                        if ($i < $bl) {
+                            $buffer[$i] = $buffer[$i] ^ chr(mt_rand(0, 255));
+                        } else {
+                            $buffer .= chr(mt_rand(0, 255));
+                        }
+                    }
+                }
+                $salt = $buffer;
+                $salt_requires_encoding = true;
+            }
+            if ($salt_requires_encoding) {
+                // encode string with the Base64 variant used by crypt
+                $base64_digits =
+                    'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+                $bcrypt64_digits =
+                    './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
+
+                $base64_string = base64_encode($salt);
+                $salt = strtr(rtrim($base64_string, '='), $base64_digits, $bcrypt64_digits);
+            }
+            $salt = PasswordCompat\binary\_substr($salt, 0, $required_salt_len);
+
+            $hash = $hash_format . $salt;
+
+            $ret = crypt($password, $hash);
+
+            if (!is_string($ret) || PasswordCompat\binary\_strlen($ret) != $resultLength) {
+                return false;
+            }
+
+            return $ret;
+        }
+
+        /**
+         * Get information about the password hash. Returns an array of the information
+         * that was used to generate the password hash.
+         *
+         * array(
+         *    'algo' => 1,
+         *    'algoName' => 'bcrypt',
+         *    'options' => array(
+         *        'cost' => PASSWORD_BCRYPT_DEFAULT_COST,
+         *    ),
+         * )
+         *
+         * @param string $hash The password hash to extract info from
+         *
+         * @return array The array of information about the hash.
+         */
+        function password_get_info($hash) {
+            $return = array(
+                'algo' => 0,
+                'algoName' => 'unknown',
+                'options' => array(),
+            );
+            if (PasswordCompat\binary\_substr($hash, 0, 4) == '$2y$' && PasswordCompat\binary\_strlen($hash) == 60) {
+                $return['algo'] = PASSWORD_BCRYPT;
+                $return['algoName'] = 'bcrypt';
+                list($cost) = sscanf($hash, "$2y$%d$");
+                $return['options']['cost'] = $cost;
+            }
+            return $return;
+        }
+
+        /**
+         * Determine if the password hash needs to be rehashed according to the options provided
+         *
+         * If the answer is true, after validating the password using password_verify, rehash it.
+         *
+         * @param string $hash    The hash to test
+         * @param int    $algo    The algorithm used for new password hashes
+         * @param array  $options The options array passed to password_hash
+         *
+         * @return boolean True if the password needs to be rehashed.
+         */
+        function password_needs_rehash($hash, $algo, array $options = array()) {
+            $info = password_get_info($hash);
+            if ($info['algo'] != $algo) {
+                return true;
+            }
+            switch ($algo) {
+                case PASSWORD_BCRYPT:
+                    $cost = isset($options['cost']) ? $options['cost'] : PASSWORD_BCRYPT_DEFAULT_COST;
+                    if ($cost != $info['options']['cost']) {
+                        return true;
+                    }
+                    break;
+            }
+            return false;
+        }
+
+        /**
+         * Verify a password against a hash using a timing attack resistant approach
+         *
+         * @param string $password The password to verify
+         * @param string $hash     The hash to verify against
+         *
+         * @return boolean If the password matches the hash
+         */
+        function password_verify($password, $hash) {
+            if (!function_exists('crypt')) {
+                trigger_error("Crypt must be loaded for password_verify to function", E_USER_WARNING);
+                return false;
+            }
+            $ret = crypt($password, $hash);
+            if (!is_string($ret) || PasswordCompat\binary\_strlen($ret) != PasswordCompat\binary\_strlen($hash) || PasswordCompat\binary\_strlen($ret) <= 13) {
+                return false;
+            }
+
+            $status = 0;
+            for ($i = 0; $i < PasswordCompat\binary\_strlen($ret); $i++) {
+                $status |= (ord($ret[$i]) ^ ord($hash[$i]));
+            }
+
+            return $status === 0;
+        }
+    }
+
+}
+
+namespace PasswordCompat\binary {
+
+    if (!function_exists('PasswordCompat\\binary\\_strlen')) {
+
+        /**
+         * Count the number of bytes in a string
+         *
+         * We cannot simply use strlen() for this, because it might be overwritten by the mbstring extension.
+         * In this case, strlen() will count the number of *characters* based on the internal encoding. A
+         * sequence of bytes might be regarded as a single multibyte character.
+         *
+         * @param string $binary_string The input string
+         *
+         * @internal
+         * @return int The number of bytes
+         */
+        function _strlen($binary_string) {
+            if (function_exists('mb_strlen')) {
+                return mb_strlen($binary_string, '8bit');
+            }
+            return strlen($binary_string);
+        }
+
+        /**
+         * Get a substring based on byte limits
+         *
+         * @see _strlen()
+         *
+         * @param string $binary_string The input string
+         * @param int    $start
+         * @param int    $length
+         *
+         * @internal
+         * @return string The substring
+         */
+        function _substr($binary_string, $start, $length) {
+            if (function_exists('mb_substr')) {
+                return mb_substr($binary_string, $start, $length, '8bit');
+            }
+            return substr($binary_string, $start, $length);
+        }
+
+        /**
+         * Check if current PHP version is compatible with the library
+         *
+         * @return boolean the check result
+         */
+        function check() {
+            static $pass = NULL;
+
+            if (is_null($pass)) {
+                if (function_exists('crypt')) {
+                    $hash = '$2y$04$usesomesillystringfore7hnbRJHxXVLeakoG8K30oukPsA.ztMG';
+                    $test = crypt("password", $hash);
+                    $pass = $test == $hash;
+                } else {
+                    $pass = false;
+                }
+            }
+            return $pass;
+        }
+
+    }
+}
\ No newline at end of file
diff --git a/core/vendor/ircmaxell/password-compat/version-test.php b/core/vendor/ircmaxell/password-compat/version-test.php
new file mode 100644
index 0000000..96f60ca
--- /dev/null
+++ b/core/vendor/ircmaxell/password-compat/version-test.php
@@ -0,0 +1,6 @@
+<?php
+
+require "lib/password.php";
+
+echo "Test for functionality of compat library: " . (PasswordCompat\binary\check() ? "Pass" : "Fail");
+echo "\n";
\ No newline at end of file
