Gmail password first character is case insensitive on mobile device
support.google.com
support.google.com
Facebook actually accepts three forms of your password:
* Your original password.
* Your original password with the first letter capitalized. This is only for mobile devices, which sometimes capitalize the first character of a word.
* Your original password with the case reversed, for those with a caps lock key on.
[0]: https://www.zdnet.com/article/facebook-passwords-are-not-cas...
A related question: when a password system tells me I need to change my password, and it has to differ by 3 letters from my previous password, is that system storing my password text rather than the hash of the password? Is that safe?
So if i typed "Password" on mobile. The client would first send the request as "Password". If that succeeds, then no worries. If it fails, then the client could send a second request by reversing the case of the first letter. In this case, it would send a second request for "password".
At most, it is 2 login requests per password. Many other commenters here are incorrectly stating that 3 requests would be necessary, but this is untrue. A letter can only have 2 possible cases (uppercase or lowercase). So the client sends the originally typed one, and if that fails, then it flips the case of that first letter. That is the only alternative. There is not a third option.
A well-built login form would restrict users after 3-5 login attempts anyway and require a password-reset process. So that is 6-10 client requests to the backend (n * 2). That shouldn't be hitting any sort of rate limit.
To implement, choice of storing three hashes or computing n * hashes where n < 1, the probability of getting a match before having to try another.
Maybe these generous assumptions about someone’s pseudo code are unwarranted?
Didn't I write that this shouldn't be done via the clause? I haven't edited my comment either so it should still be there and I see it is.
> the pseudo sql doesn’t select anything
It should select the hash(es) and bring them back to the app for comparison.
> The name of the original is “pass” but since it wouldn’t make sense to compare a plaintext string to a hash another logical assumption is that “pass” is a hash.
It doesn't matter whether it's a password or a hash, the form of the SQL statement is going to cause trouble and should be the other way round.
> Maybe these generous assumptions about someone’s pseudo code are unwarranted?
Perhaps you meant to reply to someone else?
Agreed 100%. Calculating three hashes and sending them to sql for comparison—maybe index lookup—seems backward to me.
Which means you are performing 3 hashes, two of which are likely unnecessary and sending all of them to sql for evaluation.
Pseudo code is supposed to strip away details that might distract from fundamentals, yet your pseudo code and subsequent replies suggest that your understanding is contrary to the actual fundamentals of checking a password securely. Start with limiting the set by choosing by user, never by hash.
Jeremy Evans goes over many of the fundamentals[1], including why restriction of the selection is important, and why restriction of access to hashes (i.e. not sending them from the initial machine) are important. In his own framework (Rodauth) he doesn’t even allow selects of the hashes to be returned to app, let alone used as part of the where clause. Note the clause in each of the functions he defines (12:53 and 14:05).
It’s not the select that’s the problem, it’s the clause, so your explanation also seems to imply that misunderstanding on your part is real.
The same password won't hash to the same thing without the same salt so you can't compare them like that.
(If you could, then you would notice multiple users with the same hashes, i.e. the same passwords).
To verify a hash you need to retrieve the user's salt (typically stored with the hash the algorithm in a single string) then re-hash with the same salt.
Given the forum I too would have believed that to a reasonable assumption, but this thread shows it may not have been.
Back of the envelope: 2 million logins per second would mean about 170 billion logins per day. With 7 billion people on the planet, that'd mean about 25 logins per day from each man, woman and child.
HeLLo, heLLo, hEllO, HEllO all normalize to heLLo
Going further to avoid collisions that could happen between words like massen and maßen when upper cased the rule of thumb was to convert ß to SZ when that happened, so getting the correct upper case would have also required a full German dictionary.
TL;DR: Upper/Lower case conversion is complex, avoid it if possible.
> Case Mapping Rule: There is no case mapping rule (because mapping uppercase and titlecase code points to their lowercase equivalents would lead to false accepts and thus to reduced security).
EDIT: Oh right, salts.
Salting is more about making it non-obvious which passwords map to which hashes so you can’t easily build tables of hashes for common passwords.
Sending the password to the server in “plain text” is fine over https, it’s a secure channel. Hashing isn’t meant to hide the password on the wire, it’s to prevent anyone with access to the database from learning what the passwords are.
I feel like if the client always hash passwords as soon as it is typed (the javascript never sees the unhashed password), no one would notice. (except some with crazy password rules that would disallow a hash-looking password)
SRP is one such system: https://en.m.wikipedia.org/wiki/Secure_Remote_Password_proto...
This often isn't considered worth the accessibility and maintenance costs of requiring the user to compute a hash (the threat model isn't exactly hugely concerning, especially to service providers, and is mostly obviated by transport encryption anyway) or the risk that somebody's going to come along and ask why we're hashing twice and rip out the server hash (very bad), but calling that "no benefits" is more or less lies-to-children.
What I'm more worried about is the system that some Polish banks use, called masked passwords over here. With this system, you're only required to enter certain characters of your password, but the set of required characters changes at each login. This exists to make key loggers much less effective. There's apparently some hashing going on (something to do with curves and polynomials), but I couldn't find more details when I last looked.
If someone steals a hash for characters 1-4 they'll be able to brute force it. Only 10000x the cost of a single login. And then if you have the hash for characters 2-5...
Then, suddenly, they got back to a normal login and password (I think I had the choice IIRC) but then I left the country.
Poland is a beautiful country, I lived in Krakow for a few years and it was A-WE-SOME.
“ Gmail doesn't recognize periods as characters in addresses -- we just ignore them. For example, you could tell people your address was hikingfan@gmail.com, hiking.fan@gmail.com or hi.kin.g.fan@gmail.com. (We understand that there has been some confusion about this in the past, but to settle it once and for all, you can indeed receive mail at all the variations with dots.)”
https://gmail.googleblog.com/2008/03/2-hidden-ways-to-get-mo...
No it wouldn't. The problem is that people believe they have addresses they don't. They don't have firstmlast@gmail.com any more than they have firt.m.last@gmail.com.
I have a surname@ address, and I receive similar mails all the time. People just simply assume they have my email address. No dots involved.
Most mobile keyboards automatically capitalize the first character by default.
With the ephemeral nature of password characters upon entry; it would be easy to miss the capitalization, annoying users.
This one small trick probably prevents millions of people from becoming frustrated with Google every single day.
And I'll bet it only works one way.
If your password was "ABCD", then by my logic "aBCD" should work.
But if your password was "abcd", then "Abcd" should not work.
[0] https://developer.mozilla.org/en-US/docs/Web/HTML/Global_att...
Also.. not sure what safari/iOS did in their early years with keyboard password entry capitalization... but if they did auto capitalize... since Apple is so good at saving profile info across new installs/os updates... I imagine there would be a large portion of old apple users with perma-capitalized passwords out there as well.
Did I get anything wrong?
1: https://pics.me.me/caps-lock-cruise-control-for-cool-image-5...
https://news.ycombinator.com/item?id=21862160
There's a much more evil prank than that:
A user was having a really bizarre problem: They could log in when they were sitting down in a seat in front of the keyboard, but when they were standing in front of the keyboard, their password didn't work! The problem happened every time, so they called for support, who finally figured it out after watching them demonstrate the problem many times:
It turned out that some joker had rearranged the numbers keys on the keyboard, so they were ordered "0123456789" instead of "1234567890". And the user's password had a digit in it. When the user was sitting down comfortably in front of the keyboard, they looked at the screen while they touch-typed their password, and were able to log in. But when they were standing in front of the computer, they looked at the keyboard and pressed the numbers they saw, which were wrong!
Many go to the effort of having an error message pop up that says "no dashes or parentheses allowed." So they went to the effort of writing special case code to notice and handle this ... by giving instructions to the person, instead of the computer.
In fact, on my phone, when I type in just the digits, my phone inserts the parens and dashes. Presumably, users consider this easier to read, and dare I say, more canonical.
So, many applications can't handle phone number input in the exact form they display it to the user.
So you don't actually want the input box to strip dashes, right? It sounds like you want more sites to accept dashes.
This works for a lot of other things that people format wildly like Canadian postal codes (which are A1A 1A1 format but many places require presence or absence of a space), credit cards (strip the spaces) and so many other fields.
I agree it should work for any phone number I've ever encountered, but just why
The "best" solution is to separate country code into a different field or input. Then have everything other than the country code (generally called a "subscriber number") added to another input.
Then on the backend you would essentially strip out all the non-numeric characters from the subscriber number and combine the country code and stripped "subscriber number" into an E.164 format number and store that in the database.
(Source) I have spent a decade dealing with phone numbers in databases and web forms. This is the "best" way to handle it, and even it isn't bulletproof, but it works 99.8% of the time. The best way to handle the other 0.2% of cases is to make a descriptive error message that explains to the user how you are expecting them to input their number (ie. No extensions, etc).
Here is the E.164 standard: https://www.itu.int/rec/T-REC-E.164/
Validation with onblur or submission is great, but changing my input makes me angry.
You'll probably need to do more than just strip dashes, though. You also need to strip spaces and parenthesis but keep other characters such as + and ~. Many prebuilt phone number input boxes have trouble with even normal American phone numbers, let alone foreign phone number systems. Even if you're only targeting American customers, you'll probably need to support the phone number format for a visiting foreigner as well.
With something as complex as phone numbers I'd just stick to using standard form validation code (like in the HTML standard) to warn users of explicitly invalid input like letters or most special characters and storing phone numbers as a 20 character random text strings for all other purposes. Phone numbers are like time zones, you'd think they're easy to deal with but they're surprisingly finicky to get right.
If there's no current operation, Python has no way of knowing for sure if you intended to exit, or if you intended to interrupt an operation, but the operation finished before you pressed the key combo.
Python's behavior here is good UX. A key combo that does two different things depending on the current state of the program, and the program's state is changing right in front of you... that would suck.
A lot of technical folk who rely on this immediately notice when some shell doesn't do this (exiting instead of breaking of the current input line). I have this with Hbase's hbase shell. I've dropped out of that by accident dozens of times because Ctrl + C interrupts the whole shell.
>>> exit
Use exit() or Ctrl-Z plus Return to exitI'd love to find (never looked...) a python3 repl where `print`, `dir`, `help` all behave like python2's `print`, since they're debug/lookup tools. It's rather often I'll open a terminal and want to check one of those things, and... typing () characters just adds significant effort (for lack of better description).
I always found Ruby's optional parenthesis to be annoying in stored code, but I gotta admit it's nice on the REPL.
Python functions are invoked with parenthesis, while typing a name without parenthesis retrieves the content of a variable. The Python CLI helpfully sets the "exit" variable to that string so that you don't get a confusing NameError when you make this mistake.
Besides, you usually have a more convenient exit available with Ctrl-D anyway.
Note that this isn't specific to the REPL. Running `print(exit)` in a Python script will print the same message.
$ bc -l
bc 1.07.1
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006, 2008, 2012-2017 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
exit
0
quit
Gets me everytime.Some applications use -h and some --help. Many support both. So unless we get all software to agree on one standard here, expecting your user to remember which one it was is actually bad UX in my book. Best is to just support both, so people don't have to think about how to get the help.
Displaying a notice when some option changed makes totally sense tho, but -h/--help is not that kind of issue.
Personally, I pretty passionate about NOT changing data that my tools receive. It takes a specific, documented situation for me to say "you give me X, and I make it Y". I am more comfortable with "your address, X, has been standardized to Y. Do you accept?".
So JavaScript to intercept keypresses or postprocess the string is risky at best and often poorly implemented.
If it was in HTML it could be reliable, and have a unified behaviour when text is pasted in.
For phone numbers there is a "tel" input, so the undesirable behaviour your experiencing may be in spite or because of it.
I have experienced this so many times over my life with so many different hardware/software configurations, and I have to assume others have as well. It hasn’t happened in years but could explain why the “fix” described in the parent post was implemented.
The German letter ß gets uppercased to SS instead of ẞ by most libraries in a neutral/generic culture. ẞ on the other hand gets lowercased to ß.
This happens because there wasn't an official ẞ in German until recently but the uppercasing/lowercasing standard was already written for ß.
it seems i just can't type korean to password fields
As far as I know, there's nothing preventing a password field from containing any valid unicode string. The problem may be IME support or servers stuck in ASCII, but the textbox itself will just work.
Even good websites that will accept any valid password string will sometimes cut off the last part of a long password because their hashing algorithm throws that data away. Bcrypt, for example, supports a maximum input length between 50 and 72 bytes, depending on the library you use to hash your passwords. That's bytes, not characters!
More primitive systems used to have problems with non-alfanumerical passwords and once those algorithms have been unleashed upon the unsuspecting public, you need to support them in your login flow for years to come.
So I guess that could also be "bad," but not incompetent "bad" or Michael Jackson "bad."
So while we’d love to make it utf8, it is just too much work to justify doing over other things.
What you don't normally want to do is normalize passwords before hashing and then only store the hash of the normalized string, because that's fragile to changes in your normalization algorithm, e.g. updating your Unicode data tables.
> only costs a single bit
What if the password includes İ. The swapcase would be i. And the again its swapcase would be İ. And swapcase of I is ı. And swapcase of ı is I. Right? Well, it should depend on what language you use. Or should it?
Also I think this was in Github; they ask uppercase and I enter Ğ and Github doesn't recognize it as uppercase letter.
I wonder how many passwords have the first letter uppercase because that's easy to remember.
And then a trailing "!" because it's the first one you see.
Not that I would ever do that.
- At least one upper case
- At least one lower case
- At least one number, but not as the first character and no two numbers in a row
- No special characters
- Maximum characters: 8
There was a minimum too but I can’t recall what it was. Hopefully 7 for maximum security.
My randomly generated password from my password manager got a “medium” on their strength scale.
The worst of these also had a 20 character password limit (at least it wasn't 8!), along with several of these nonsense requirements that limit repeated characters. I couldn't manage to generate a password they would accept. Eventually I realized that not only did they allow only certain specific special characters, but their password length validation was wrong and would only accept 19 characters because they were testing for <= 20.
So "Pasword1234#" was "strong" password, but "ha_ivrkbs(i5HzJzee%Ii3jsk#7jaot" was considered weak - note "ee" in the middle of string.
No idea how maby bits of entropy it removes but it's absurd.
Yahoo seems to be big on this these days. I had an old Yahoo account that I don't use much, but every time I try to log in, they seem to change around exactly what pseudo-2FA they want. Now they won't even let me try to type my password. Good grief, guess I'll just write off that account.
Then one day stopped doing truncating … but only in some boxes, not others.
This is especially true for sites that provide email accounts for users on sites like yahoo which are the 2FA for many other sites a user has accounts on. Gaining access to a yahoo user's email account could allow someone to reset all their passwords on any 3rd account they used that email address for when they signed up.
Turns out if you try to log in from new device from new location (I guess your account is tied to IP from which it was created), just password alone isn't enough to log in. And there's no alternative way to prove that account actually belongs to me.
I understand that most services try to provide you with good security, but I hate it when everything is overcomplicated and everyone tells me what to do. No, I don't want to give you my phone number. Yes, I know I won't be able to recover my password, I don't need that. Yes, I actually want my password to be this long. No, I don't want you to block login attempts from new locations. Believe it or not, people do travel and want to log in from more than 1 city. It's none of your business if I want to give my password to my friend and let him login, just stop this please. Let me choose whatever password I want without any backup emails, phone numbers, and let everyone who knows the password log in. Is it too much to ask?
Why is it even allowed to let users create accounts without providing a phone number, but then not letting those same users to log in because their accounts are not tied to any phone number? How does it make any sense?
Pretty sure this is a detail documented somewhere public-facing
Bank of America, internally, required you to have two passwords, a Windows and a UNIX password. The UNIX password was only 8 characters due to , you guessed it, mainframes. I don't know if this was ever resolved.
Actually I realise GP is equally ambiguous. But I read that as (and my own assumption would be) frontend retries with the variation, backend verifies against the same only one stored.
I've also found that for email fields you need to be careful to normalize the input (trim, casing) as safari had a habit of autocorrecting the first character to be a capital
I find apps that don’t trim the whitespace for the email field so annoying in terms of UX. I usually use a Text Replacement shortcut to fill in my emails (e.g. “gml” fills in my GMail address, “cld” my iCloud address etc.) and that always inserts a space after the email and I have to manually fiddle with the cursor to delete it.
Why is that relevant? The standard technically allows for case sensitivity but nobody does it
It's technically true that the part before the domain can be case sensitive, but as nobody does this the gain in UX from people not having to know the exact casing used during sign-up is worth it to me.
Normal password code would be
if (doHash(password+salt) == storedHash) {
failedLogins = 0;
return 1;
}
failedLogins++;
return 0;
This would presumably be if (doHash(password+salt) == storedHash) {
failedLogins = 0;
return 1;
}
if (doHash(swapFirstLetterIfClientIsMobile(password)+salt) == storedHash) {
failedLogins = 0;
return 1;
}
failedLogins++;
return 0;
So while the password is 'stored' in the server side heap, it's no different to normal password 'storage'If the hash is done in the client it's the same, just the client sends two attempts rather than one.
Edit: not a good idea.
> Looks like the app is clever enough to try changing the case of the first letter if the first attempt fails.
Still, looks like a compromise between usability and security/reduced password entropy.
So now you have to create 2 flows, those before the new policy and those that were set after the normalization.
https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpubli...
If you're actually using a 'strong enough' hash to prevent easy cracking if your hashed password database is leaked then you're doubling the server load which can be quite substantial in some cases.
And obviously this is server side
In that case this solution would have the disadvantage that it wouldn’t be platform specific.
You may try 2 versions of first letter, but do they go as far as bruteforce removing all the % character combinations from the password, unless they did remove them all?
Iirc it had a cool demo, but was never used in production.
This doesn't scale well with password length.
PS. You can see this for yourself, just leave a negative review for Staples Canada on google and your account will be attacked from somewhere inside Vietnam via windows phone.
Then there's the fact that many banking sites (BofA, IIRC) only used the first 8 char of your password anyway.
Does this also mean they probably store passwords in clear text? Because there's no way to normalize the numeric passwords back to letters and symbols.
They can generate the phone password on the client side and send both passwords to be salted, hashed, and stored separately.
That much seems OK.
But the salted+hashed phone password is incredibly weak. It can be brute forced readily unless it is very long.
From the brute forced phone password, the regular password can be brute forced as well, since the digits of the phone password tremendously constrain the characters of the regular password.
It's very much like the Hollywood hacking where the hackers progressively lock digits of your password and eventually discover the whole thing.
It got me thinking - imagine wanting to let users log in with a single character typo in their password, could you do this without storing hashes of all edit distance 1 passwords?
Notation: "||" means string concatenation.
Let password P = P1 || P2, where len(P1) + len(P2) = len(P) and |len(P1) - len(P2)| <= 1.
Let H1 = hash(P1), H2 = hash(P2), where hash() is a cryptographic hash function that produces at least as many bits as the longest allowed password and satisfies whatever slowness and memory use requirements that you have for a password hash.
To store a password, store P ⊕ H1 and P ⊕ H2.
To check a password candidate C received at login, let C = C1 || C2 using the same splitting rule as used for P above, and compute C ⊕ hash(C1) and C ⊕ hash(C2).
A login is successful if either P ⊕ H1 or P ⊕ H2 is within edit distance 1 of either C ⊕ hash(C1) or C ⊕ hash(C2).
(I've omitted salt from the above for simplicity. Replace the hash with a salted hash if you want salt).
What if.. in the RARE case, a hacker guessed wrong, but was helped by google to get into your account?