--- a/wp/wp-includes/class-wp-application-passwords.php Fri Sep 05 18:40:08 2025 +0200
+++ b/wp/wp-includes/class-wp-application-passwords.php Fri Sep 05 18:52:52 2025 +0200
@@ -60,6 +60,7 @@
*
* @since 5.6.0
* @since 5.7.0 Returns WP_Error if application name already exists.
+ * @since 6.8.0 The hashed password value now uses wp_fast_hash() instead of phpass.
*
* @param int $user_id User ID.
* @param array $args {
@@ -71,7 +72,7 @@
* @return array|WP_Error {
* Application password details, or a WP_Error instance if an error occurs.
*
- * @type string $0 The unhashed generated application password.
+ * @type string $0 The generated application password in plain text.
* @type array $1 {
* The details about the created password.
*
@@ -94,12 +95,8 @@
return new WP_Error( 'application_password_empty_name', __( 'An application name is required to create an application password.' ), array( 'status' => 400 ) );
}
- if ( self::application_name_exists_for_user( $user_id, $args['name'] ) ) {
- return new WP_Error( 'application_password_duplicate_name', __( 'Each application name should be unique.' ), array( 'status' => 409 ) );
- }
-
$new_password = wp_generate_password( static::PW_LENGTH, false );
- $hashed_password = wp_hash_password( $new_password );
+ $hashed_password = self::hash_password( $new_password );
$new_item = array(
'uuid' => wp_generate_uuid4(),
@@ -128,6 +125,7 @@
* Fires when an application password is created.
*
* @since 5.6.0
+ * @since 6.8.0 The hashed password value now uses wp_fast_hash() instead of phpass.
*
* @param int $user_id The user ID.
* @param array $new_item {
@@ -141,7 +139,7 @@
* @type null $last_used Null.
* @type null $last_ip Null.
* }
- * @param string $new_password The unhashed generated application password.
+ * @param string $new_password The generated application password in plain text.
* @param array $args {
* Arguments used to create the application password.
*
@@ -161,7 +159,7 @@
*
* @param int $user_id User ID.
* @return array {
- * The list of app passwords.
+ * The list of application passwords.
*
* @type array ...$0 {
* @type string $uuid The unique identifier for the application password.
@@ -204,7 +202,17 @@
*
* @param int $user_id User ID.
* @param string $uuid The password's UUID.
- * @return array|null The application password if found, null otherwise.
+ * @return array|null {
+ * The application password if found, null otherwise.
+ *
+ * @type string $uuid The unique identifier for the application password.
+ * @type string $app_id A UUID provided by the application to uniquely identify it.
+ * @type string $name The name of the application password.
+ * @type string $password A one-way hash of the password.
+ * @type int $created Unix timestamp of when the password was created.
+ * @type int|null $last_used The Unix timestamp of the GMT date the application password was last used.
+ * @type string|null $last_ip The IP address the application password was last used by.
+ * }
*/
public static function get_user_application_password( $user_id, $uuid ) {
$passwords = static::get_user_application_passwords( $user_id );
@@ -243,10 +251,21 @@
* Updates an application password.
*
* @since 5.6.0
+ * @since 6.8.0 The actual password should now be hashed using wp_fast_hash().
*
* @param int $user_id User ID.
* @param string $uuid The password's UUID.
- * @param array $update Information about the application password to update.
+ * @param array $update {
+ * Information about the application password to update.
+ *
+ * @type string $uuid The unique identifier for the application password.
+ * @type string $app_id A UUID provided by the application to uniquely identify it.
+ * @type string $name The name of the application password.
+ * @type string $password A one-way hash of the password.
+ * @type int $created Unix timestamp of when the password was created.
+ * @type int|null $last_used The Unix timestamp of the GMT date the application password was last used.
+ * @type string|null $last_ip The IP address the application password was last used by.
+ * }
* @return true|WP_Error True if successful, otherwise a WP_Error instance is returned on error.
*/
public static function update_application_password( $user_id, $uuid, $update = array() ) {
@@ -280,9 +299,21 @@
* Fires when an application password is updated.
*
* @since 5.6.0
+ * @since 6.8.0 The password is now hashed using wp_fast_hash() instead of phpass.
+ * Existing passwords may still be hashed using phpass.
*
* @param int $user_id The user ID.
- * @param array $item The updated app password details.
+ * @param array $item {
+ * The updated application password details.
+ *
+ * @type string $uuid The unique identifier for the application password.
+ * @type string $app_id A UUID provided by the application to uniquely identify it.
+ * @type string $name The name of the application password.
+ * @type string $password A one-way hash of the password.
+ * @type int $created Unix timestamp of when the password was created.
+ * @type int|null $last_used The Unix timestamp of the GMT date the application password was last used.
+ * @type string|null $last_ip The IP address the application password was last used by.
+ * }
* @param array $update The information to update.
*/
do_action( 'wp_update_application_password', $user_id, $item, $update );
@@ -404,9 +435,22 @@
* @since 5.6.0
*
* @param int $user_id User ID.
- * @param array $passwords Application passwords.
+ * @param array $passwords {
+ * The list of application passwords.
*
- * @return bool
+ * @type array ...$0 {
+ * @type string $uuid The unique identifier for the application password.
+ * @type string $app_id A UUID provided by the application to uniquely identify it.
+ * @type string $name The name of the application password.
+ * @type string $password A one-way hash of the password.
+ * @type int $created Unix timestamp of when the password was created.
+ * @type int|null $last_used The Unix timestamp of the GMT date the application password was last used.
+ * @type string|null $last_ip The IP address the application password was last used by.
+ * }
+ * }
+ * @return int|bool User meta ID if the key didn't exist (ie. this is the first time that an application password
+ * has been saved for the user), true on successful update, false on failure or if the value passed
+ * is the same as the one that is already in the database.
*/
protected static function set_user_application_passwords( $user_id, $passwords ) {
return update_user_meta( $user_id, static::USERMETA_KEY_APPLICATION_PASSWORDS, $passwords );
@@ -420,9 +464,52 @@
* @param string $raw_password The raw application password.
* @return string The chunked password.
*/
- public static function chunk_password( $raw_password ) {
+ public static function chunk_password(
+ #[\SensitiveParameter]
+ $raw_password
+ ) {
$raw_password = preg_replace( '/[^a-z\d]/i', '', $raw_password );
return trim( chunk_split( $raw_password, 4, ' ' ) );
}
+
+ /**
+ * Hashes a plaintext application password.
+ *
+ * @since 6.8.0
+ *
+ * @param string $password Plaintext password.
+ * @return string Hashed password.
+ */
+ public static function hash_password(
+ #[\SensitiveParameter]
+ string $password
+ ): string {
+ return wp_fast_hash( $password );
+ }
+
+ /**
+ * Checks a plaintext application password against a hashed password.
+ *
+ * @since 6.8.0
+ *
+ * @param string $password Plaintext password.
+ * @param string $hash Hash of the password to check against.
+ * @return bool Whether the password matches the hashed password.
+ */
+ public static function check_password(
+ #[\SensitiveParameter]
+ string $password,
+ string $hash
+ ): bool {
+ if ( ! str_starts_with( $hash, '$generic$' ) ) {
+ /*
+ * If the hash doesn't start with `$generic$`, it is a hash created with `wp_hash_password()`.
+ * This is the case for application passwords created before 6.8.0.
+ */
+ return wp_check_password( $password, $hash );
+ }
+
+ return wp_verify_fast_hash( $password, $hash );
+ }
}