Hacker News new | ask | show | jobs
by obiterdictum 4829 days ago
Because the developer is storing passwords in plaintext, and he wants to save database space.

This seem far fetched, not sure what thought process would lead anyone to come to this conclusion. Even if you have a million users, you have ~8MB worth of passwords. I'd imagine even developers who are not competent in cryptography realise that.

3 comments

If you allow truly unlimited-length passwords, malicious users can set gigabyte-long passwords. Whether you hash them or just store them, that's a DoS waiting to happen with every login.

So, there actually is a reasonable limit for the length of passwords, email addresses, and most other user-editable fields that end up either being hashed, or shoved through to the database. That limit is just probably somewhere around 100KB to 1MB, not "eight". ;)

More importantly, that limit is an infrastructure concern, not a business-domain concern; it's best enforced by something like nginx spitting out a 400, not the model-validation logic in your app server.

While this is true, hashes use a set number of characters. For example, SHA-256 hashes can be stored in 32-character hex strings. In that sense, there's no point in allowing for a variable length field for password hashes.
It's not only dealing with password length. You could DoS the server by tying up all threads in processing the upload. Uploading 4GB isn't instantaneous.
For the application code to complain about password length then the 4gb upload has to have already occurred.

Protecting against a DoS attack this way is done in the webserver, which doesn't care about individual fields. Sure this means there's an implicit password length limit, but not in any application-level sense.

I'm not arguing with that. I wholly agree with you that a client should not be able to upload 4 GB for the password field. I think I misread your first point as if it dealt with server-side storage.
That's why the client should perform the hash and only submit the result.
No; this is effectively the same as doing no hashing at all. If your database gets stolen, people can replay the "hashed" passwords from it to the server, without having to hash them themselves.
I didn't mean to imply that you'd just store the hash the client comes up with. That's idiotic, of course. Not everyone uses SSL, even though they should, and it's not always secure, and even with the use of SSL, it seems that there would be a potential length attack that could be employed to effectively guess a user's password length. So in all cases, IMO, it makes more sense to be receiving a fixed-length thing that is fairly insensitive to attack in itself. So perhaps a user has 2 salts associated with their account, per password: an auth salt and a storage salt. Then an auth looks something like this:

    hash(saltFromServer + hash(password))
And then the server would do

    hash(user.salt + clientHash)
I'm not sure, but this seems reasonable to me.
Couldn't you solve that by hashing it again on the sever?
Some developers love that kind of micro optimizations. Even smart ones. I've had my varchar(256) columns changed to a more modest varchar(30) because I was "wasting space." Those people dont like being wrong either so there's no point arguing it either and instead concentrate on the bigger issues.
I've seen that, but once the internal format is actually explained, varchar(256) generally survives.

For those who don't know, for varchar(1) through varchar(256) the internal database representation in sensible databases is one byte to say how long the varchar is, followed by the actual data. There is therefore absolutely no difference between the representation of varchar(30) and varchar(256) - it is just an arbitrary restriction on what data is allowed to fit in there. But databases that support varchar(257) need 2 bytes in front for it.

I believe in InnoDB the way text and varchar(X) is stored is exactly the same. They both only use as much space as the data they are storing requires. However if you pass a 101 character string to a varchar(100) it will be truncated. I'd guess that is useful in some cases, but in reality you probably want to do the truncation in your application so you have more control over it.
Truncation is the failure mode which MySQL describes as a feature.

Don't use MySQL.

Thanks for the explanation, didn't know that.

Is this true in most modern DBs? (I'm thinking MySQL and Postgres particularly).

Close enough in PostgreSQL. String columns larger than 256 actually use 4 bytes to indicate the length, but on the other hand, large strings are automatically compressed, so they may use less space than 4 + length.

http://www.postgresql.org/docs/9.2/static/datatype-character...

I recently discovered its a similar case for numbers in Oracle, which slightly surprised me.
I would think that the kind of developer that considers it acceptable to store passwords in plaintext could easily be the kind of developer that would make arbitrary decisions based on feelings rather calculating the actual likely storage a longer limit would result in to make an informed decision...