42

Everyone knows that if they have a system that requires a password to log in, they should be storing a hashed & salted copy of the required password, rather than the password in plaintext.

What I started to wonder today is why the don't they also store the user ID in a similar hashed & salted password?

To me this would seem logical because I can't see any drawbacks, and if the db was compromised, the attackers would need to "crack" the password and the username hash before they could compromise that account. It would also mean that if usernames were hashed and salted email addresses, they would be more protected from being sold on to SPAMmers.

14
  • 2
    Because you would need to likely store the salt? What happens when you forget your username and/or password that would be horrible useability. There is a reason this isn't done.
    – Ramhound
    Commented Dec 13, 2012 at 12:29
  • 30
    Usernames are not for authentication, merely for identification. Treating them with any kind of secure protocol in mind is asking for trouble - it's just as important to identify what does not need to be kept private as it is to identify what does. A clear distinction is important.
    – lynks
    Commented Dec 13, 2012 at 14:22
  • 10
    "everyone knows that if they have a system that requires a password to log in, they should be storing a hashed & salted copy of the required password, rather than the password in plaintext." no, they don't. None of that is obvious to someone who is new to security. Even the difference between encryption and hashing is beyond what some people can understand.
    – zzzzBov
    Commented Dec 13, 2012 at 16:37
  • 1
    @zzzzBov OK, perhaps I meant "everyone who understands security"
    – Grezzo
    Commented Dec 13, 2012 at 17:19
  • 2
    @lynks but wouldn't it be nice if when a database was compromised, they didn't get all the email addresses of the users. Not only can they SPAM these addresses, they can also target them with site specific phishing attacks
    – Grezzo
    Commented Dec 13, 2012 at 22:54

9 Answers 9

41

While what Terry is saying is true, sometimes login systems actually hash the username (but without salt). They have you pick a login name and a display name. The login name is stored hashed (without salt because you need to be able to look it up) and the password is salted. The display name is different from your login name (because this should be kept secret as well) and is shown where needed.

Even when an attacker sees your name, he will be unable to attach it to your login name. While I say it can be salted, there is actually no need to this. The most important part is just to keep it secret. If the database gets compromised, stuff like your email address or name will still be there for the attacker to use if he wants to stage new attacks on your other accounts.

15
  • 5
    Yeah, I've seen this done. It's more of an obscurity mechanism really, because if the password is hashed strongly then it shouldn't be necessary at all.
    – Polynomial
    Commented Dec 13, 2012 at 14:46
  • 1
    @Polynomial It may not be necessarry, but if login names were something like email addresses, it could be a good way of trying to hide a users email address if the database were to get dumped, no?
    – Grezzo
    Commented Dec 13, 2012 at 17:32
  • 2
    mmm good point, you can hash the email too if you don't plan to send any emails to your users. Password resets by email could still be done I guess. Commented Dec 13, 2012 at 19:45
  • 1
    @LucasKauffman I guess that's a good point, it helps to be able to email your users. That certainly would certainly mean hashing it before storing could not be done!
    – Grezzo
    Commented Dec 13, 2012 at 23:00
  • 4
    @Grezzo: Actually, you could still email users after hashing their email address. Just request that they provide their email address when requesting a password reset or other request, hash that email against their stored hash to confirm their identity, and then send the password reset or reply to the email address they just gave you. Since you don't have their email stored, you can only send them email with their cooperation, but unless you plan on spamming them with sales offers, I don't see that as a bad thing. Commented Nov 4, 2016 at 10:46
73

You see that thing up there where it displays your username? They can't do that if the username is stored hashed now can they?

One word, usability.

16
  • 28
    The snark is strong in this one ;)
    – Polynomial
    Commented Dec 13, 2012 at 14:44
  • 76
    Welcome, 21840c1a3e3db69e01445c8782a99f9b.
    – Thomas
    Commented Dec 13, 2012 at 16:29
  • 7
    But they could if you had a login name and a displayed name, like you do in facebook and many other services. In fact don't we log in to stack exchange using an email address, but a Nickname is displayed
    – Grezzo
    Commented Dec 13, 2012 at 17:28
  • 19
    Actually you could. After a successful login store the unhashed username in the session.
    – Freiheit
    Commented Dec 13, 2012 at 18:00
  • 3
    Well it was posited that if the username were an e-mail address, dumping the DB would provide someone with a long list of valid e-mail addresses. It follows that the username in that case would be sensitive.
    – KeithS
    Commented Dec 14, 2012 at 4:08
15

Generally usernames are not considered secure, they are identity, not authentication. It's good to not reveal what usernames are valid, but would be worse if you happened to have a collision. You could still work around this by looking at all matching usernames for a password hash that matches, but that's kind of messy.

Realistically, if you otherwise have good password security and limits on login attempts, a complete list of usernames offers little practical value to an attacker. It's main benefit would be phishing, but if your official correspondence has any information in it, then that information can't be hashed and they'd get it if they compromised your DB anyway.

Also, usability like Terry said. It's far easier to find your account if they can see usernames. You don't gain enough by trying to secure an identifier to justify it in most contexts.

4
  • Looking up by password have a one problem - what to do if they are the same (also - how to do reset)? If you prohibit such situation then you effectively disclose password. Commented Dec 13, 2012 at 15:34
  • @MaciejPiechotka - Yeah, if you have a double collision, that is also a problem, though the chances of a double collision are pretty remarkably small. Also, if you did prevent a double collision, you wouldn't be disclosing the username it corresponded to, so you'd still have a pretty hard time making use of the information, but it is still a valid observation that it would be telling them that some user has a password which would resolve with their password, but the chances of an attacker managing to hit that case are pretty (cryptographically secure) remote. Commented Dec 13, 2012 at 15:39
  • 2
    FWIW if there was a collision, the second user would be met with a "that username already exists" message upon attempting to register.
    – panofsteel
    Commented Mar 3, 2016 at 20:39
  • @MaciejPiechotka That's why you look up the identifier first. It follows that if the identifier is present, only one password (hash) should be associated with it. If one were looking up the hash of a login identifier and using a timing attack safe way of doing the comparison, how could this hurt? Commented Feb 1, 2017 at 13:20
7

While others have well pointed out that there are few (if any) advantages, I would take issue with your claim that there aren't any drawbacks. If you store just the hashed username, then searching for the username is easy. If you store a salted, hashed username then searching becomes a bit more problematic.

Let's assume that if we build some SQL table containing usernames and (hashed) passwords and tell the SQL server to index the username column that it will do some sort of binary search or some other magic. We could have a table that looks like:

Username  |  Password
test      |  j9lnvqjAuhNJs

(This is the old-school unix crypt(3) hash just for simplicity and brevity.)

If you store your usernames in plaintext, retrieving the (hashed) password for a user is a simple SQL call. Let's say you want to validate the credentials for a user who typed in the username test:

SELECT password FROM users WHERE username='test`;

Simple enough. Now if we were to store the usernames in the same format as the passwords, our table ends up looking like this:

Username       |  Password
M1CAtvzDdJDGU  |  j9lnvqjAuhNJs

Now when a user types in their username of test, how do you validate the password? A binary search is useless here, since you don't even know the salt you used to store the username. Instead, you need to iterate over each username in the database, crypting the given username with the salt for that username and comparing it to the stored (hashed) username to see if it matches. Youch!

Assume that you took some good precautions and used a nice slow hash like bcrypt instead of good old Unix crypt? Double youch!

As you can imagine, there are some serious drawbacks to storing a salted hashed username instead of just plaintext.

6
  • but if you don't salt it, or use a site wide salt for the username you could use the same select command, but instead of searching for the plaintext username, you could search for the hash of it. Or am I missing something?
    – Grezzo
    Commented Dec 13, 2012 at 17:25
  • 1
    If you use a site-wide salt, you might as well not salt at all. crypto.stackexchange.com/questions/1855/… Commented Dec 13, 2012 at 17:29
  • 4
    That's not true. It is true that with a site specific salt they could attack all hashes at the same time using brute force, but without a salt attackers could use an unsalted rainbow table which would be much less effort. And after all, isn't security about making it too much effort to attack, not really about making it impossible?
    – Grezzo
    Commented Dec 13, 2012 at 17:35
  • If you assume that my email address exists in some rainbow table of unsalted bcrypts somewhere, then yes, you're right. Commented Dec 13, 2012 at 17:39
  • That's a fair point I suppose. I doubt my email address is in any rainbow tables as it's quite a number of characters. I guess that's probably true of most peoples including yours. Having said that, there must be tons of email addresses that are [a-zA-z0-9]{8}@hotmail.com. That wouldn't require a huge rainbow table, though I have no idea (and doubt) if anyone has ever made one like that
    – Grezzo
    Commented Dec 13, 2012 at 23:10
4

If you hashed and salted the username, how would the system know that new accounts had a unique username, without iterating through all existing records and hashing the new username with every single existing salt?

1
  • 1
    Perhaps by using a site wide salt (or pepper as I think that's known)
    – Grezzo
    Commented Dec 14, 2012 at 9:29
3

I think the most likely reason is that hashing the usernames along with the password doesn't actually give any extra protection.

We encourage users to create difficult and complex passwords, making them harder to crack. Any database of hashed usernames could be cracked in minutes with a basic dictionary... unless you require your usernames to have at least 6 alphanumeric characters ;)

1
  • 2
    It would give a very small amount of extra protection, but admittedly not much. It could give the benefit though that it obscures users usernames, which are likely to be email addresses which could be used for targeted phishing attacks.
    – Grezzo
    Commented Dec 13, 2012 at 23:13
3

Your idea is noble and the question interesting. Now, I believe you either did not think of usability at all while bringing up the question or you missed the point of hashing (or maybe you just misspelled 'encryption').

Hashing is irreversible, unless you have supercomputers to brute force things or rainbow tables to try search for hashes. Hence the usability would go downhill if you were to hash the usernames/emails used for logins. If, however one were to 'encrypt' the same using a predefined key in the program (the one which check for the username) itself, then it might be a bit secure. However, once again - an encryption key stored directly in a program is just as good as no key at all. These are the prime reasons usernames are not hashed or encrypted.

3
  • 1
    I definitely meant hashing it, not encrypting it. If we also have a displayed name, there there is no usability sacrifice is there?
    – Grezzo
    Commented Dec 13, 2012 at 17:30
  • @Grezzo - If you have a display name stored separately, the majority of people are going to make their display name closely resemble their username. If you generate their username, then it reduces usability. Commented Dec 14, 2012 at 14:18
  • Let us continue this discussion in chat. Commented Feb 1, 2017 at 18:14
1

This idea falls in line with two tactics: 1) Security by obscurity , 2) Extra mitigation of timing attacks (if you use a timing safe comparison function). You cannot use a unique salt to do this effectively, but it is a good idea. This would allow one to separate the table that holds login information from the one that hold "person" information. Two tables then, person (could hold plain text email addresses) and user (could hold a hashed username {site wide salted} and a hashed and uniquely salted password). Looking up the user by hashed username is not a problem.

1

I think this is an excellent idea. As expressed by Anthony Rutledge; this can provide security through obscurity/obfuscation and if using a key derivation function, such as PBKDF2, there is, I presume, increased difficulty, in orders of magnitude, for a would-be attacker attempting to compromise a stolen database.

For example, an offline-brute force attack attempted on a stolen database would require finding hash collisions for both username and password, notwithstanding the fact that the salting of the username in the method, as I mentioned above, would render any identified username collisions moot.

This means that attackers would need to commandeer your machine and also identify and understand your source code, since the salt wouldn't exist anywhere within your database. It adds multiple layers of additional defense, without adding much - if any - significant increase in computational load for the web application.

In regards to issues with hashing: the username can be salted with a proprietary server-side hash, based on the actual username/email.

That would mean the salt is known, albeit programmatically. And the script that calculates and returns the salt can reside on the machine in an out-of-band fashion, relative to the web service - such that any method for generating the salt could be inaccessible from any web-facing entry points.

0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .