A potential common excuse may be, "No one will remember a secure password in excess of 16 characters, we are trying to minimize support volume", but this is not a "reasonable" excuse.
Right, as the OP said, there is no reasonable excuse to limit character intake to less than multiple hundreds. I agree that some limit is sensible just to ensure someone doesn't insert War and Peace (or base64-encoded binaries or whatever) as their password.
I won't say 20MB passwords wouldn't pose any practical problems, but the hashing itself isn't really an issue. A simple bcrypt test on my laptop (w/work factor 12) gave me these numbers:
1KB: 0.279 secs
1MB: 0.277
10MB: 0.293
100MB: 0.473
1000MB: 2.169
Getting the 1GB string allocated in Python locked my system up for longer than the 20 loops over bcrypt did. :)
I should probably find a machine with a little more RAM to test 10GB...
Purely in the spirit of "because I can", I fired up a 244GB EC2 instance:
1MB -- 0.310421895981 seconds
10MB -- 0.317299044132
100MB -- 0.409169948101
1GB -- 1.3299703002
10GB -- 10.8254830956
100GB -- 133.936514747
I noticed during the 100GB loop that the process oscillated between 100GB and 200GB, making me suspect that the 100GB string is actually being copied somewhere, which is inefficient and surely has a significant effect on the timings at larger string sizes. As such, I didn't go for a 200GB string.
And just 'cause most of us don't see 200GB python processes every day:
The primary problem here would be a DoS attack against a web server that accepted that much data in a submission form.
edit: also, merely saying "bcrypt" isn't quite sufficient; we'd have to know what work factor you were testing with. bcrypt with a work factor of 2 is vastly different in performance from bcrypt with a work factor of 12.
> we'd have to know what work factor you were testing with
Parentheses are not made to be ignored.
But I don't think it matters, which is why it was a parenthetical. The point is the relative differences between different sized strings, not the absolute timings.
Isn't the password length check done locally on the machine (with javascript or similar)? If so, an attacker could easily ignore that check and send as much data as he want.
The check on that should (and, AFAIK, is) done server-side, with the server closing the connection after a certain amount of data or time.
Doesn't most of bcrypt's work come from rehashing its output? So it only has to touch the 1GB input once, right?
Edit: after reading https://en.wikipedia.org/wiki/Bcrypt#Algorithm, it looks like bcryt's make-work loop does refer to the key in each iteration. I can't tell on a cursory reading whether access to the original key can be memoized, though hashing the large input once before passing it into bcrypt would have the same effect.
now enter the first 72 characters of that password in the bcrypt verification function and it'll still say it's correct. bcrypt is a valid technical reason to limit passwords to 72 characters.
You could really support an arbitrary password size by locally hashing the password to a length at least as long as the one you store in the database to preserve entropy, then send the fixed length hash as the user's "password", and hash it again on the server using something slower, like PBKDF2 with a few thousand rounds.
this doesn't add extra security - the first hash becomes a substitute password. A cracker could modify their steam account to take said hash as input and sent it directly over the wire.
It doesn't remove any security, either. If you perform a hash on the server that sends an arbitrary input size to a fixed number of bits, the attacker needs only to try O(2^n) different inputs where n is the number of bits of that hash. By using a hash with at least n bits as a substitute password, there's no less security. It does mitigate the DoS vector, however.
It does add something: users can use any password they want. Any unicode string. You just UTF-8 encode then locally hash into a constant size. This alleviates the issue mentioned in the grandparent that supporting arbitrary length passwords introduces a DoS vector, especially when a slow hash is used on the server.
arbitrary length passwords simply aren't necessary though, and are unlikely to be used - if you were to cap passwords at, say, 128 characters, who would run into that limit?
I'm not arguing that if this functionality were already present in an app that you should remove it; however if it's not there already there's very little value it could add that would justify any development time. That's just my opinion though.
The only reasonable restriction is in overall POST body length. I recall an exploit once on node.js where unreasonably large POST requests could DDOS a server with minimal effort.
Only the support issue, but then I'd have thought that people using really long passwords as normally the ones who'll make an effort to remember / store them. They mention "Encrypted passwords", which would vary the amount of storage required in their database and also make the passwords retrievable if the attacker had gained access to the key / algorithm etc...
I'd had preferred if they used a one way hash instead, obviously with a secure hash algorithm, uniquely salted and rehashed multiple times. All passwords would then be the same length when stored and users wouldn't have to have such a low maximum limit.
None that wouldn't be better handled with a warning of "excessive password complexity, we're not sure you'll remember this". Even truncating all password entries (create/change and auth) and simply taking the used subset would be better than blocking me from using my intended password.
Hmmm... if your password was
password30jf0sd09jga09ja0i9sdfasi09djf0-sdj9faspiodjf
and they only used the first 8 characters, you'd think you had a strong password, but would really have a very weak password. Hashing then truncating as discussed above would be much safer.
Really no reason to truncate after hashing. The output size of any cryptographic hash function should be more than small enough to send down the wire and hash again properly.
Really though, just reject passwords over a few KB. Nobody will ever notice that limit except for people trying to fuck with you.