Index: src/wp-includes/class-wp-recovery-mode-key-service.php
===================================================================
--- src/wp-includes/class-wp-recovery-mode-key-service.php	(Revision 45282)
+++ src/wp-includes/class-wp-recovery-mode-key-service.php	(Arbeitskopie)
@@ -37,24 +37,15 @@
 	 *
 	 * @since 5.2.0
 	 *
-	 * @global PasswordHash $wp_hasher
-	 *
 	 * @param string $token A token generated by {@see generate_recovery_mode_token()}.
 	 * @return string $key Recovery mode key.
 	 */
 	public function generate_and_store_recovery_mode_key( $token ) {
 
-		global $wp_hasher;
-
 		$key = wp_generate_password( 22, false );
 
-		if ( empty( $wp_hasher ) ) {
-			require_once ABSPATH . WPINC . '/class-phpass.php';
-			$wp_hasher = new PasswordHash( 8, true );
-		}
+		$hashed = password_hash( $key, PASSWORD_BCRYPT );
 
-		$hashed = $wp_hasher->HashPassword( $key );
-
 		$records = $this->get_keys();
 
 		$records[ $token ] = array(
Index: src/wp-includes/pluggable.php
===================================================================
--- src/wp-includes/pluggable.php	(Revision 45282)
+++ src/wp-includes/pluggable.php	(Arbeitskopie)
@@ -1882,7 +1882,6 @@
 	 * @since 4.6.0 The `$notify` parameter accepts 'user' for sending notification only to the user created.
 	 *
 	 * @global wpdb         $wpdb      WordPress database object for queries.
-	 * @global PasswordHash $wp_hasher Portable PHP password hashing framework instance.
 	 *
 	 * @param int    $user_id    User ID.
 	 * @param null   $deprecated Not used (argument deprecated).
@@ -1899,7 +1898,7 @@
 			return;
 		}
 
-		global $wpdb, $wp_hasher;
+		global $wpdb;
 		$user = get_userdata( $user_id );
 
 		// The blogname option is escaped with esc_html on the way into the database in sanitize_option
@@ -1966,11 +1965,7 @@
 		do_action( 'retrieve_password_key', $user->user_login, $key );
 
 		// Now insert the key, hashed, into the DB.
-		if ( empty( $wp_hasher ) ) {
-			require_once ABSPATH . WPINC . '/class-phpass.php';
-			$wp_hasher = new PasswordHash( 8, true );
-		}
-		$hashed = time() . ':' . $wp_hasher->HashPassword( $key );
+		$hashed = time() . ':' . password_hash( $key, PASSWORD_BCRYPT );
 		$wpdb->update( $wpdb->users, array( 'user_activation_key' => $hashed ), array( 'user_login' => $user->user_login ) );
 
 		$switched_locale = switch_to_locale( get_user_locale( $user ) );
@@ -2271,21 +2266,11 @@
 	 *
 	 * @since 2.5.0
 	 *
-	 * @global PasswordHash $wp_hasher PHPass object
-	 *
 	 * @param string $password Plain text user password to hash
 	 * @return string The hash string of the password
 	 */
 	function wp_hash_password( $password ) {
-		global $wp_hasher;
-
-		if ( empty( $wp_hasher ) ) {
-			require_once( ABSPATH . WPINC . '/class-phpass.php' );
-			// By default, use the portable hash from phpass
-			$wp_hasher = new PasswordHash( 8, true );
-		}
-
-		return $wp_hasher->HashPassword( trim( $password ) );
+		return password_hash( trim( $password ), PASSWORD_BCRYPT );
 	}
 endif;
 
@@ -2294,7 +2279,7 @@
 	 * Checks the plaintext password against the encrypted Password.
 	 *
 	 * Maintains compatibility between old version and the new cookie authentication
-	 * protocol using PHPass library. The $hash parameter is the encrypted password
+	 * protocol using password_hash. The $hash parameter is the encrypted password
 	 * and the function compares the plain text password when encrypted similarly
 	 * against the already encrypted password to see if they match.
 	 *
@@ -2303,8 +2288,6 @@
 	 *
 	 * @since 2.5.0
 	 *
-	 * @global PasswordHash $wp_hasher PHPass object used for checking the password
-	 *  against the $hash + $password
 	 * @uses PasswordHash::CheckPassword
 	 *
 	 * @param string     $password Plaintext user's password
@@ -2313,41 +2296,35 @@
 	 * @return bool False, if the $password does not match the hashed password
 	 */
 	function wp_check_password( $password, $hash, $user_id = '' ) {
-		global $wp_hasher;
 
-		// If the hash is still md5...
-		if ( strlen( $hash ) <= 32 ) {
-			$check = hash_equals( $hash, md5( $password ) );
+		if ( password_needs_rehash( $hash, PASSWORD_BCRYPT ) ) {
+			if ( strlen( $hash ) <= 32 ) {
+				$check = hash_equals( $hash, md5( $password ) );
+			} else {
+				require_once( ABSPATH . WPINC . '/class-phpass.php' );
+				$wp_hasher = new PasswordHash( 8, true );
+				$check = $wp_hasher->CheckPassword( $password, $hash );
+			}
+
 			if ( $check && $user_id ) {
 				// Rehash using new hash.
 				wp_set_password( $password, $user_id );
 				$hash = wp_hash_password( $password );
 			}
-
-			/**
-			 * Filters whether the plaintext password matches the encrypted password.
-			 *
-			 * @since 2.5.0
-			 *
-			 * @param bool       $check    Whether the passwords match.
-			 * @param string     $password The plaintext password.
-			 * @param string     $hash     The hashed password.
-			 * @param string|int $user_id  User ID. Can be empty.
-			 */
-			return apply_filters( 'check_password', $check, $password, $hash, $user_id );
+		} else {
+			$check = password_verify( $password, $hash );
 		}
 
-		// If the stored hash is longer than an MD5, presume the
-		// new style phpass portable hash.
-		if ( empty( $wp_hasher ) ) {
-			require_once( ABSPATH . WPINC . '/class-phpass.php' );
-			// By default, use the portable hash from phpass
-			$wp_hasher = new PasswordHash( 8, true );
-		}
-
-		$check = $wp_hasher->CheckPassword( $password, $hash );
-
-		/** This filter is documented in wp-includes/pluggable.php */
+		/**
+		 * Filters whether the plaintext password matches the encrypted password.
+		 *
+		 * @since 2.5.0
+		 *
+		 * @param bool       $check    Whether the passwords match.
+		 * @param string     $password The plaintext password.
+		 * @param string     $hash     The hashed password.
+		 * @param string|int $user_id  User ID. Can be empty.
+		 */
 		return apply_filters( 'check_password', $check, $password, $hash, $user_id );
 	}
 endif;
Index: src/wp-includes/post-template.php
===================================================================
--- src/wp-includes/post-template.php	(Revision 45282)
+++ src/wp-includes/post-template.php	(Arbeitskopie)
@@ -866,14 +866,11 @@
 		return apply_filters( 'post_password_required', true, $post );
 	}
 
-	require_once ABSPATH . WPINC . '/class-phpass.php';
-	$hasher = new PasswordHash( 8, true );
-
 	$hash = wp_unslash( $_COOKIE[ 'wp-postpass_' . COOKIEHASH ] );
-	if ( 0 !== strpos( $hash, '$P$B' ) ) {
+	if ( 0 !== strpos( $hash, '$2y$' ) ) {
 		$required = true;
 	} else {
-		$required = ! $hasher->CheckPassword( $post->post_password, $hash );
+		$required = ! $password_verify( $post->post_password, $hash );
 	}
 
 	/**
Index: src/wp-includes/user.php
===================================================================
--- src/wp-includes/user.php	(Revision 45282)
+++ src/wp-includes/user.php	(Arbeitskopie)
@@ -2205,7 +2205,6 @@
  * @since 4.4.0
  *
  * @global wpdb         $wpdb      WordPress database abstraction object.
- * @global PasswordHash $wp_hasher Portable PHP password hashing framework.
  *
  * @param WP_User $user User to retrieve password reset key for.
  *
@@ -2212,7 +2211,7 @@
  * @return string|WP_Error Password reset key on success. WP_Error on error.
  */
 function get_password_reset_key( $user ) {
-	global $wpdb, $wp_hasher;
+	global $wpdb;
 
 	if ( ! ( $user instanceof WP_User ) ) {
 		return new WP_Error( 'invalidcombo', __( '<strong>ERROR</strong>: There is no account with that username or email address.' ) );
@@ -2274,11 +2273,7 @@
 	do_action( 'retrieve_password_key', $user->user_login, $key );
 
 	// Now insert the key, hashed, into the DB.
-	if ( empty( $wp_hasher ) ) {
-		require_once ABSPATH . WPINC . '/class-phpass.php';
-		$wp_hasher = new PasswordHash( 8, true );
-	}
-	$hashed    = time() . ':' . $wp_hasher->HashPassword( $key );
+	$hashed    = time() . ':' . password_hash( $key, PASSWORD_BCRYPT );
 	$key_saved = $wpdb->update( $wpdb->users, array( 'user_activation_key' => $hashed ), array( 'user_login' => $user->user_login ) );
 	if ( false === $key_saved ) {
 		return new WP_Error( 'no_password_key_update', __( 'Could not save password reset key to database.' ) );
@@ -2298,7 +2293,6 @@
  * @since 3.1.0
  *
  * @global wpdb         $wpdb      WordPress database object for queries.
- * @global PasswordHash $wp_hasher Portable PHP password hashing framework instance.
  *
  * @param string $key       Hash to validate sending user's password.
  * @param string $login     The user login.
@@ -2305,7 +2299,7 @@
  * @return WP_User|WP_Error WP_User object on success, WP_Error object for invalid or expired keys.
  */
 function check_password_reset_key( $key, $login ) {
-	global $wpdb, $wp_hasher;
+	global $wpdb;
 
 	$key = preg_replace( '/[^a-z0-9]/i', '', $key );
 
@@ -2322,11 +2316,6 @@
 		return new WP_Error( 'invalid_key', __( 'Invalid key.' ) );
 	}
 
-	if ( empty( $wp_hasher ) ) {
-		require_once ABSPATH . WPINC . '/class-phpass.php';
-		$wp_hasher = new PasswordHash( 8, true );
-	}
-
 	/**
 	 * Filters the expiration time of password reset keys.
 	 *
@@ -2348,7 +2337,7 @@
 		return new WP_Error( 'invalid_key', __( 'Invalid key.' ) );
 	}
 
-	$hash_is_correct = $wp_hasher->CheckPassword( $key, $pass_key );
+	$hash_is_correct = password_verify( $key, $pass_key );
 
 	if ( $hash_is_correct && $expiration_time && time() < $expiration_time ) {
 		return get_userdata( $row->ID );
@@ -3542,22 +3531,16 @@
  * @return string Confirmation key.
  */
 function wp_generate_user_request_key( $request_id ) {
-	global $wp_hasher;
 
 	// Generate something random for a confirmation key.
 	$key = wp_generate_password( 20, false );
 
 	// Return the key, hashed.
-	if ( empty( $wp_hasher ) ) {
-		require_once ABSPATH . WPINC . '/class-phpass.php';
-		$wp_hasher = new PasswordHash( 8, true );
-	}
-
 	wp_update_post(
 		array(
 			'ID'            => $request_id,
 			'post_status'   => 'request-pending',
-			'post_password' => $wp_hasher->HashPassword( $key ),
+			'post_password' => password_hash( $key, PASSWORD_BCRYPT ),
 		)
 	);
 
@@ -3574,7 +3557,6 @@
  * @return bool|WP_Error WP_Error on failure, true on success.
  */
 function wp_validate_user_request_key( $request_id, $key ) {
-	global $wp_hasher;
 
 	$request_id = absint( $request_id );
 	$request    = wp_get_user_request_data( $request_id );
@@ -3591,11 +3573,6 @@
 		return new WP_Error( 'missing_key', __( 'Missing confirm key.' ) );
 	}
 
-	if ( empty( $wp_hasher ) ) {
-		require_once ABSPATH . WPINC . '/class-phpass.php';
-		$wp_hasher = new PasswordHash( 8, true );
-	}
-
 	$key_request_time = $request->modified_timestamp;
 	$saved_key        = $request->confirm_key;
 
@@ -3617,7 +3594,7 @@
 	$expiration_duration = (int) apply_filters( 'user_request_key_expiration', DAY_IN_SECONDS );
 	$expiration_time     = $key_request_time + $expiration_duration;
 
-	if ( ! $wp_hasher->CheckPassword( $key, $saved_key ) ) {
+	if ( ! password_verify( $key, $saved_key ) ) {
 		return new WP_Error( 'invalid_key', __( 'Invalid key.' ) );
 	}
 
Index: src/wp-login.php
===================================================================
--- src/wp-login.php	(Revision 45282)
+++ src/wp-login.php	(Arbeitskopie)
@@ -508,9 +508,6 @@
 			exit();
 		}
 
-		require_once ABSPATH . WPINC . '/class-phpass.php';
-		$hasher = new PasswordHash( 8, true );
-
 		/**
 		 * Filters the life span of the post password cookie.
 		 *
@@ -528,7 +525,7 @@
 		} else {
 			$secure = false;
 		}
-		setcookie( 'wp-postpass_' . COOKIEHASH, $hasher->HashPassword( wp_unslash( $_POST['post_password'] ) ), $expire, COOKIEPATH, COOKIE_DOMAIN, $secure );
+		setcookie( 'wp-postpass_' . COOKIEHASH, password_hash( wp_unslash( $_POST['post_password'] ), PASSWORD_BCRYPT ), $expire, COOKIEPATH, COOKIE_DOMAIN, $secure );
 
 		wp_safe_redirect( wp_get_referer() );
 		exit();
Index: tests/phpunit/tests/auth.php
===================================================================
--- tests/phpunit/tests/auth.php	(Revision 45282)
+++ tests/phpunit/tests/auth.php	(Arbeitskopie)
@@ -8,7 +8,6 @@
 	protected $user;
 	protected static $_user;
 	protected static $user_id;
-	protected static $wp_hasher;
 
 	/**
 	 * action hook
@@ -23,9 +22,6 @@
 		);
 
 		self::$user_id = self::$_user->ID;
-
-		require_once( ABSPATH . WPINC . '/class-phpass.php' );
-		self::$wp_hasher = new PasswordHash( 8, true );
 	}
 
 	function setUp() {
@@ -184,7 +180,7 @@
 
 		wp_set_password( $limit, self::$user_id );
 		// phpass hashed password
-		$this->assertStringStartsWith( '$P$', $this->user->data->user_pass );
+		$this->assertStringStartsWith( '$2y$', $this->user->data->user_pass );
 
 		$user = wp_authenticate( $this->user->user_login, 'aaaaaaaa' );
 		// Wrong Password
@@ -236,7 +232,7 @@
 		$wpdb->update(
 			$wpdb->users,
 			array(
-				'user_activation_key' => strtotime( '-1 hour' ) . ':' . self::$wp_hasher->HashPassword( $key ),
+				'user_activation_key' => strtotime( '-1 hour' ) . ':' . password_hash( $key, PASSWORD_BCRYPT ),
 			),
 			array(
 				'ID' => $this->user->ID,
@@ -273,7 +269,7 @@
 		$wpdb->update(
 			$wpdb->users,
 			array(
-				'user_activation_key' => strtotime( '-48 hours' ) . ':' . self::$wp_hasher->HashPassword( $key ),
+				'user_activation_key' => strtotime( '-48 hours' ) . ':' . password_hash( $key, PASSWORD_BCRYPT ),
 			),
 			array(
 				'ID' => $this->user->ID,
@@ -310,7 +306,7 @@
 		$wpdb->update(
 			$wpdb->users,
 			array(
-				'user_activation_key' => self::$wp_hasher->HashPassword( $key ),
+				'user_activation_key' => password_hash( $key, PASSWORD_BCRYPT ),
 			),
 			array(
 				'ID' => $this->user->ID,
Index: tests/phpunit/tests/comment-submission.php
===================================================================
--- tests/phpunit/tests/comment-submission.php	(Revision 45282)
+++ tests/phpunit/tests/comment-submission.php	(Arbeitskopie)
@@ -175,9 +175,8 @@
 	public function test_submitting_comment_to_password_protected_post_succeeds() {
 
 		$password = 'password';
-		$hasher   = new PasswordHash( 8, true );
 
-		$_COOKIE[ 'wp-postpass_' . COOKIEHASH ] = $hasher->HashPassword( $password );
+		$_COOKIE[ 'wp-postpass_' . COOKIEHASH ] = password_hash( $password, PASSWORD_BCRYPT );
 
 		$post    = self::factory()->post->create_and_get(
 			array(
