diff --git src/wp-admin/includes/user.php src/wp-admin/includes/user.php
index 8304314..d023239 100644
--- src/wp-admin/includes/user.php
+++ src/wp-admin/includes/user.php
@@ -20,7 +20,7 @@ function add_user() {
 /**
  * Edit user settings based on contents of $_POST
  *
- * Used on user-edit.php and profile.php to manage and process user options, passwords etc.
+ * Used on user-edit.php, user-new.php, and profile.php to manage and process user options, passwords etc.
  *
  * @since 2.0.0
  *
@@ -39,9 +39,6 @@ function edit_user( $user_id = 0 ) {
 		$update = false;
 	}
 
-	if ( !$update && isset( $_POST['user_login'] ) )
-		$user->user_login = sanitize_user($_POST['user_login'], true);
-
 	$pass1 = $pass2 = '';
 	if ( isset( $_POST['pass1'] ) )
 		$pass1 = $_POST['pass1'];
@@ -104,9 +101,16 @@ function edit_user( $user_id = 0 ) {
 
 	$errors = new WP_Error();
 
-	/* checking that username has been typed */
-	if ( $user->user_login == '' )
-		$errors->add( 'user_login', __( '<strong>ERROR</strong>: Please enter a username.' ) );
+	/* Validate the user_login when not updating the user */
+	if ( ! $update ) {
+		$user_login = '';
+
+		if ( isset( $_POST['user_login'] ) ) {
+			$user_login = $_POST['user_login'];
+		}
+
+		$user->user_login = wp_validate_user_login( $user_login, $errors );
+	}
 
 	/* checking the password has been typed twice */
 	/**
@@ -143,12 +147,6 @@ function edit_user( $user_id = 0 ) {
 	if ( !empty( $pass1 ) )
 		$user->user_pass = $pass1;
 
-	if ( !$update && isset( $_POST['user_login'] ) && !validate_username( $_POST['user_login'] ) )
-		$errors->add( 'user_login', __( '<strong>ERROR</strong>: This username is invalid because it uses illegal characters. Please enter a valid username.' ));
-
-	if ( !$update && username_exists( $user->user_login ) )
-		$errors->add( 'user_login', __( '<strong>ERROR</strong>: This username is already registered. Please choose another one.' ));
-
 	/* checking e-mail address */
 	if ( empty( $user->user_email ) ) {
 		$errors->add( 'empty_email', __( '<strong>ERROR</strong>: Please enter an e-mail address.' ), array( 'form-field' => 'email' ) );
diff --git src/wp-includes/ms-functions.php src/wp-includes/ms-functions.php
index 487d840..55580e1 100644
--- src/wp-includes/ms-functions.php
+++ src/wp-includes/ms-functions.php
@@ -458,55 +458,27 @@ function is_email_address_unsafe( $user_email ) {
  *
  * @global wpdb $wpdb
  *
- * @param string $user_name  The login name provided by the user.
+ * @param string $user_login The login name provided by the user.
  * @param string $user_email The email provided by the user.
  * @return array Contains username, email, and error messages.
  */
-function wpmu_validate_user_signup($user_name, $user_email) {
+function wpmu_validate_user_signup( $user_login, $user_email ) {
 	global $wpdb;
 
 	$errors = new WP_Error();
+	$orig_userlogin = $user_login;
 
-	$orig_username = $user_name;
-	$user_name = preg_replace( '/\s+/', '', sanitize_user( $user_name, true ) );
-
-	if ( $user_name != $orig_username || preg_match( '/[^a-z0-9]/', $user_name ) ) {
-		$errors->add( 'user_name', __( 'Only lowercase letters (a-z) and numbers are allowed.' ) );
-		$user_name = $orig_username;
-	}
+	$user_login = wp_validate_user_login( $user_login, $errors );
 
 	$user_email = sanitize_email( $user_email );
 
-	if ( empty( $user_name ) )
-	   	$errors->add('user_name', __( 'Please enter a username.' ) );
-
-	$illegal_names = get_site_option( 'illegal_names' );
-	if ( ! is_array( $illegal_names ) ) {
-		$illegal_names = array(  'www', 'web', 'root', 'admin', 'main', 'invite', 'administrator' );
-		add_site_option( 'illegal_names', $illegal_names );
-	}
-	if ( in_array( $user_name, $illegal_names ) )
-		$errors->add('user_name',  __( 'That username is not allowed.' ) );
-
-	if ( is_email_address_unsafe( $user_email ) )
+	if ( is_email_address_unsafe( $user_email ) ) {
 		$errors->add('user_email',  __('You cannot use that email address to signup. We are having problems with them blocking some of our email. Please use another email provider.'));
-
-	if ( strlen( $user_name ) < 4 )
-		$errors->add('user_name',  __( 'Username must be at least 4 characters.' ) );
-
-	if ( strlen( $user_name ) > 60 ) {
-		$errors->add( 'user_name', __( 'Username may not be longer than 60 characters.' ) );
 	}
 
-	if ( strpos( $user_name, '_' ) !== false )
-		$errors->add( 'user_name', __( 'Sorry, usernames may not contain the character &#8220;_&#8221;!' ) );
-
-	// all numeric?
-	if ( preg_match( '/^[0-9]*$/', $user_name ) )
-		$errors->add('user_name', __('Sorry, usernames must have letters too!'));
-
-	if ( !is_email( $user_email ) )
+	if ( ! is_email( $user_email ) ) {
 		$errors->add('user_email', __( 'Please enter a valid email address.' ) );
+	}
 
 	$limited_email_domains = get_site_option( 'limited_email_domains' );
 	if ( is_array( $limited_email_domains ) && ! empty( $limited_email_domains ) ) {
@@ -516,38 +488,37 @@ function wpmu_validate_user_signup($user_name, $user_email) {
 		}
 	}
 
-	// Check if the username has been used already.
-	if ( username_exists($user_name) )
-		$errors->add( 'user_name', __( 'Sorry, that username already exists!' ) );
-
 	// Check if the email address has been used already.
-	if ( email_exists($user_email) )
+	if ( email_exists( $user_email ) ) {
 		$errors->add( 'user_email', __( 'Sorry, that email address is already used!' ) );
+	}
 
 	// Has someone already signed up for this username?
-	$signup = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->signups WHERE user_login = %s", $user_name) );
+	$signup = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->signups WHERE user_login = %s", $user_login ) );
 	if ( $signup != null ) {
 		$registered_at =  mysql2date('U', $signup->registered);
 		$now = current_time( 'timestamp', true );
 		$diff = $now - $registered_at;
 		// If registered more than two days ago, cancel registration and let this signup go through.
-		if ( $diff > 2 * DAY_IN_SECONDS )
-			$wpdb->delete( $wpdb->signups, array( 'user_login' => $user_name ) );
-		else
+		if ( $diff > 2 * DAY_IN_SECONDS ) {
+			$wpdb->delete( $wpdb->signups, array( 'user_login' => $user_login ) );
+		} else {
 			$errors->add('user_name', __('That username is currently reserved but may be available in a couple of days.'));
+		}
 	}
 
-	$signup = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->signups WHERE user_email = %s", $user_email) );
+	$signup = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->signups WHERE user_email = %s", $user_email ) );
 	if ( $signup != null ) {
 		$diff = current_time( 'timestamp', true ) - mysql2date('U', $signup->registered);
 		// If registered more than two days ago, cancel registration and let this signup go through.
-		if ( $diff > 2 * DAY_IN_SECONDS )
+		if ( $diff > 2 * DAY_IN_SECONDS ) {
 			$wpdb->delete( $wpdb->signups, array( 'user_email' => $user_email ) );
-		else
+		} else {
 			$errors->add('user_email', __('That email address has already been used. Please check your inbox for an activation email. It will become available in a couple of days if you do nothing.'));
+		}
 	}
 
-	$result = array('user_name' => $user_name, 'orig_username' => $orig_username, 'user_email' => $user_email, 'errors' => $errors);
+	$result = array( 'user_name' => $user_login, 'orig_username' => $orig_userlogin, 'user_email' => $user_email, 'errors' => $errors );
 
 	/**
 	 * Filter the validated user registration details.
diff --git src/wp-includes/user.php src/wp-includes/user.php
index 1c8a5b3..916e075 100644
--- src/wp-includes/user.php
+++ src/wp-includes/user.php
@@ -1803,6 +1803,89 @@ function validate_username( $username ) {
 }
 
 /**
+ * Validate a provided user_login
+ *
+ * user_login requirements:
+ *     - minimum of 4 characters
+ *     - maximum of 60 characters
+ *     - only contains (case-insensitive) characters: a-z 0-9 _ . - @
+ *     - no whitespace
+ *     - not on blacklist of illegal names
+ *     - contains at least one letter
+ *     - must be unique
+ *     - not pending signup already
+ *
+ * @since TBD
+ *
+ * @param string $user_login The user_login value to be be validated.
+ *
+ * @return array Contains user_login, original_user_login, and any generated errors
+ */
+function wp_validate_user_login( $user_login = '', $errors = null ) {
+	$original_user_login = $user_login;
+
+	if ( ! is_wp_error( $errors ) ) {
+		$errors = new WP_Error();
+	}
+
+	// User login cannot be empty
+	if ( empty( $user_login ) ) {
+		$errors->add( 'user_name', __( 'Please enter a username.' ) );
+	}
+
+	// User login must be at least 4 characters
+	if ( strlen( $user_login ) < 4 ) {
+		$errors->add( 'user_name',  __( 'Username must be at least 4 characters.' ) );
+	}
+
+	// User login must be less than 60 characters
+	if ( strlen( $user_login ) > 60 ) {
+		$errors->add( 'user_name', __( 'Username may not be longer than 60 characters.' ) );
+	}
+
+	// Strip any whitespace and then match against case insensitive characters a-z 0-9 _ . - @
+	$user_login = preg_replace( '/\s+/', '', sanitize_user( $user_login, true ) );
+
+	// If the previous operation generated a different value, the username is invalid
+	if ( $user_login !== $original_user_login ) {
+		$errors->add( 'user_name', __( '<strong>ERROR</strong>: This username is invalid because it uses illegal characters. Please enter a valid username.' ) );
+	}
+
+	// Check the user_login against an array of illegal names
+	$illegal_names = get_site_option( 'illegal_names' );
+	if ( false == is_array( $illegal_names ) ) {
+		$illegal_names = array(  'www', 'web', 'root', 'admin', 'main', 'invite', 'administrator' );
+		add_site_option( 'illegal_names', $illegal_names );
+	}
+
+	if ( true === in_array( $user_login, $illegal_names ) ) {
+		$errors->add( 'user_name',  __( 'That username is not allowed.' ) );
+	}
+
+	// User login must have at least one letter
+	if ( preg_match( '/^[0-9]*$/', $user_login ) ) {
+		$errors->add( 'user_name', __( 'Sorry, usernames must have letters too!' ) );
+	}
+
+	// Check if the username has been used already.
+	if ( username_exists( $user_login ) ) {
+		$errors->add( 'user_name', __( 'Sorry, that username already exists!' ) );
+	}
+
+	/**
+	 * Filter a user's login after it has been validated for creation.
+	 *
+	 * @since TBD
+	 *
+	 * @param string   $user_login          The user's login.
+	 * @param string   $original_user_login The original user login.
+	 * @param WP_Error $errors              User's feedback error messages.
+	 * }
+	 */
+	return apply_filters_ref_array( 'wp_validate_user_login', array( $user_login, $original_user_login, &$errors ) );
+}
+
+/**
  * Insert a user into the database.
  *
  * Most of the `$userdata` array fields have filters associated with the values. Exceptions are
@@ -2542,7 +2625,6 @@ function reset_password( $user, $new_pass ) {
 function register_new_user( $user_login, $user_email ) {
 	$errors = new WP_Error();
 
-	$sanitized_user_login = sanitize_user( $user_login );
 	/**
 	 * Filter the email address of a user being registered.
 	 *
@@ -2552,15 +2634,8 @@ function register_new_user( $user_login, $user_email ) {
 	 */
 	$user_email = apply_filters( 'user_registration_email', $user_email );
 
-	// Check the username
-	if ( $sanitized_user_login == '' ) {
-		$errors->add( 'empty_username', __( '<strong>ERROR</strong>: Please enter a username.' ) );
-	} elseif ( ! validate_username( $user_login ) ) {
-		$errors->add( 'invalid_username', __( '<strong>ERROR</strong>: This username is invalid because it uses illegal characters. Please enter a valid username.' ) );
-		$sanitized_user_login = '';
-	} elseif ( username_exists( $sanitized_user_login ) ) {
-		$errors->add( 'username_exists', __( '<strong>ERROR</strong>: This username is already registered. Please choose another one.' ) );
-	}
+	// Validate the username
+	$sanitized_user_login = wp_validate_user_login( $user_login, $errors );
 
 	// Check the e-mail address
 	if ( $user_email == '' ) {
diff --git src/wp-signup.php src/wp-signup.php
index 3373f8e..72d7393 100644
--- src/wp-signup.php
+++ src/wp-signup.php
@@ -89,7 +89,10 @@ do_action( 'before_signup_form' );
  */
 function show_blog_form( $blogname = '', $blog_title = '', $errors = '' ) {
 	$current_site = get_current_site();
+
 	// Blog name
+	$blogname = preg_replace( '|[_.\-@]|i', '', $blogname );
+
 	if ( !is_subdomain_install() )
 		echo '<label for="blogname">' . __('Site Name:') . '</label>';
 	else
diff --git tests/phpunit/tests/multisite/wpmuValidateUserSignup.php tests/phpunit/tests/multisite/wpmuValidateUserSignup.php
index a368288..c69ec97 100644
--- tests/phpunit/tests/multisite/wpmuValidateUserSignup.php
+++ tests/phpunit/tests/multisite/wpmuValidateUserSignup.php
@@ -9,8 +9,8 @@ class Tests_Multisite_WpmuValidateUserSignup extends WP_UnitTestCase {
 	/**
 	 * @dataProvider data_user_name
 	 */
-	public function test_user_name( $user_name, $error_message ) {
-		$v = wpmu_validate_user_signup( $user_name, 'foo@example.com' );
+	public function test_user_name( $user_login, $error_message ) {
+		$v = wpmu_validate_user_signup( $user_login, 'foo@example.com' );
 		$this->assertContains( 'user_name', $v['errors']->get_error_codes(), $error_message );
 	}
 
@@ -18,7 +18,6 @@ class Tests_Multisite_WpmuValidateUserSignup extends WP_UnitTestCase {
 		return array(
 			array( 'contains spaces', 'User names with spaces are not allowed.' ),
 			array( 'ContainsCaps', 'User names with capital letters are not allowed.'  ),
-			array( 'contains_underscores', 'User names with underscores are not allowed.'  ),
 			array( 'contains%^*()junk', 'User names with non-alphanumeric characters are not allowed.'  ),
 			array( '', 'Empty user names are not allowed.'  ),
 			array( 'foo', 'User names of 3 characters are not allowed.'  ),
