Hacker News new | past | comments | ask | show | jobs | submit login
Safari Password Generation (twitter.com/_inside)
164 points by tosh on Feb 3, 2018 | hide | past | favorite | 120 comments

I think putting in the effort and basically hard coding many popular solutions is an underutilized strategy in dealing with these sorts of things. Many times I see programmers try to come up with a general solutions which becomes a much more difficult sort of problem.

Hand-harvesting data is a perfectly legitimate solution, although it comes with a steep initial cost and an ongoing maintenance cost. However, this enables the data to be curated and validated.

For this, they wanted to accurately capture the exact rules each site uses, which makes sense to do out-of-band -- ahead of time, and validated by humans -- than to try to discover from the site dynamically, especially because the latter solution, in a world without sites making their own requirements available in a programmatically readable format, would have been complex and brittle.

In a program, this sort of data may be hard-coded directly in the code, or dynamically loaded from config files. That's largely an implementation detail.

> a world without sites making their own requirements available in a programmatically readable format

About that, is there a standardised way to do it?

Not well for arbitrary rules, but for simple syntactic rules at least, regular expressions in the `pattern` attribute of the <input type=password> will do it. Bonus points for using look-ahead assertions for more complex restrictions.

The following, for example, creates a password field that requires exactly six ASCII letters, including at least one uppercase and one lowercase letter, and forbidding having the same character twice in a row:

  <input type=password pattern="(?!.*(.)\1)(?=.*[a-z])(?=.*[A-Z])[A-Za-z]{6}">

If your stateless password rules are stronger than a backtracking RE engine, I have bad news for you.

Few password rules can’t be expressed in such a regular expression, but there are definitely some where doing is impractical or absurd. To take an example I’m familiar with, on FastMail and Topicbox we use Dropbox’s zxcvbn (a truly excellent library embodying a sound approach to password security), and flat-out deny passwords that are expected to take less than 10⁶ guesses, as too weak. I shudder to think how many megabytes long a regular expression to validate that would be, and how atrociously it would perform.

(Other rules may embed restrictions on use of names, dates, &c. associated with the account. Those may be painful to shoehorn into a regular expression, but doing so is probably generally not too impractical.)

Fortunately, the likes of zxcvbn are very password-generator-friendly, as they’re encouraging the sorts of strong passwords password generators like to make; so long as they also have similar accidentally-weak-generated-password protection, zxcvbn is unlikely to cause any trouble and can probably be ignored in defining a pattern for the generator to use. So long as the form uses setCustomValidity to do its complaining when pattern isn’t enough, and the browser’s password generator knows to look at that and try again, you’re good to go. (This is all hypothetical—I don’t believe any tools actually look at password field validation to see if they did the right thing.)

Isn't best practice to:

1) have a minimal password length 2) check all passwords against a set of known bad passwords

I don't see a decent way to do 2) based on a backtracking RE engine.

It’s a terrible approach, but it is easily feasible. Here’s a simplified pattern that forbids “password”, “123”, “1234”, “12345” and “123456”:


It's a perfect example of "doing things that don't scale", an immediate UX improvement and differentiator in the sea of password managers.

The problem is getting hardcoded values updated as websites change. This is where it’s useful to be Apple: if your website breaks 1Password then that’s 1Password’s problem; if your website breaks iPhones then that’s your problem.

It’s not exactly breaking them. You’d just have to adjust the pre filled values with something that fits the requirements of the site which is something most people are already used to anyway.

If you have ever used Safari's password generation feature, you know that is pretty much impossible.

> Many times I see programmers try to come up with a general solutions which becomes a much more difficult sort of problem.

Ouch, are you looking at me? I just chopped out a fragile "general case" implementation of something today and replaced it with something that robustly gets the job done for the small number of cases we have. I was the writer of that fragle cruft a couple of months ago.

Password restrictions are the worst.

Office365 doesn't support passwords > 16 characters in length. WTF.

Paypal passwords are 20 characters max.

Also Paypal doesn't support any form of secure OTP.

Also, Paypal forces security questions on the user.

In other news, my Hearthstone account has better security than my money.

You think that's bad. Virgin Media - a major ISP/Broadband supplier has these restrictions on is e-mail passwords (effectively the key to many kingdoms)

Be between 8 and 10 characters long (with no spaces)

Contain only numbers and letters (no characters like @*? etc).

Start with a letter.

Not contain 3 numbers in a row.

> Start with a letter.

That is a requirement in a ton of places. Try creating an Oracle database user, and have the password start with a number. To be fair it's documented that it won't work, but Oracle won't stop you from doing it, so you end up with an unusable account.

This shouldn't be an issue. You should always be storing a hash of the password, making the content of the password irrelevant. The hash might start with a number, but then you can just make a versioning scheme for the hash which is identified by the first character being a letter. I don't understand how this is still a common issue.

Every password hashing library I've worked with has output starting with a $. It's use a deliminator to separate the id, strength, salt, and hash (sometimes the last two are not separated).

So for example, a bcrypt output might look like: $2a$12$2zuYZPvIlfC.L84k0oWZR.8yGd62dPkhoyg4aEC6TzGl7aASTw5F.

You think that's bad? Banc Sabadell, a bank in Spain, requires the users of online banking to have a 4 digit number as their password. Although, they also have 2 factor for doing things involving moving money.

But still...

I've been locked out of my Hearthstone account for the last few weeks because I lost my 2fa authenticator and they've refused to remove it due to my driver's license being expired.

BTW, Battle.net Authenticators look nonstandard at first glance, but they are actually 8-digit TOTP. I wrote a Python library and command line utility which can create new Battle.net authenticators as well as generate codes and QR URIs:


See the README for usage :)

This should help you to have a backup next time you get locked out!

This just saved my ass. I only play Diablo 3 occasionally, but Blizzard doesn't offer their client on Windows Phone, which would have been great to know prior to switching over from Android. Fortunately I didn't have the same issues getting it taken off of my account as the parent comment , but I was stuck using SMS as a 2FA after that, which is no beuno. I just used your python script, imported the 'secret' into Microsoft Authenticator via the generated QR code, and now it is working just as if I was using one of their auth dongle doohickies. Fantastic, thank you sir/madam!

Glad it helped!

I actually did use a system like this previously, but somehow the site just stopped accepting the codes from my TOTP app one day. I restored the official blizzard authenticator app from a backup but that wasn't working any longer either.

Sounds like time shift to be honest.

I vaguely recall checking the clock but it's possible. I've since deleted the backups anyway.

> This should help you to have a backup next time you get locked out!

The official authenticator also displays a backup code which it tells you to keep a copy of somewhere safe...

Sounds like it's working at intended then? I imagine your reaction to losing everything in your account would amount to much more then a minor annoyance.

That makes sense for WoW or Diablo. Hearthstone doesn't have any trading system, so there would be nothing to steal.

It's all the same account.

I think has something to do with older Outlook clients and how they pass credentials.

You can bypass the limit with ADFS.

Up until about 2010, Amex Corporate Card website required passwords at minimum 6, but not more than 8, with minimum one upper/one lower/one number each, and zero anything else (aka no punctuation or non-basic ascii letter).

serious question: what's the issue? 16 characters alphanumeric = 95 bits of entropy, which is enough for most purposes.

95bits of entropy for a computer, but for an actual user?

Humans are bad at remembering most things. The more entropy there is, the more difficult it tends to be for us to remember.

The way for increasing password entropy, whilst lowering the human bound, tends to be by utilising things humans find easy to remember, but computers find difficult to randomly/brute-force solve.

That usually requires a longer password.

You can sort-of bypass the human memory problem by using password managers, but they have their own set of problems (mostly usability), and assuming people actually use them is an assumption too far in most cases.

With password generation, nothing really. If you want to choose the password yourself, it limits your options (for no good reason for the user).

Yes - for instance it makes the Correct Horse Battery Stapler passphrase strategy[1] difficult to apply, because now you can only pick words up to ~4 letters long.

[1]: https://xkcd.com/936/

Right. Human-memorable passwords have low entropy density, likely less than 2 bits per character. 32 bits of entropy doesn't sound very appealing.

A long passphrase can be easier to remember than a 5h0rt 5tr1ng. On the mental side, it can take more internal *pointers to remember the latter than the former.

A common reason to limit the length of a password — and doubly so to a power of 2 — is that they’re being stored or passed around as plaintext

I use a password manager with auto-generated password length "turned up to 11" (64 characters). It probably doesn't matter, but I am decreasing the secruity of my password because of their limitation.

It's a restriction without any reason other than decreasing security. (Unless they plan to store plaintext passwords, which should be prohibited by law.)

Someday maybe the web will catch up with: “Memorized secrets SHALL be at least 8 characters in length if chosen by the subscriber. Memorized secrets chosen randomly by the CSP or verifier SHALL be at least 6 characters in length and MAY be entirely numeric. […] No other complexity requirements for memorized secrets SHOULD be imposed.” — Memorized Secret Authenticators, NIST Special Publication 800-63B: Digital Identity Guidelines Authentication and Lifecycle Management https://pages.nist.gov/sp800-63b.html

> Memorized secrets chosen randomly by the CSP or verifier SHALL be at least 6 characters in length and MAY be entirely numeric.

Is that really secure? I mean, 6 numbers is not exactly a very strong secret.

It's fine if you can invalidate the secret after some finite number of tries and block a particular actor from attacking many accounts. And there's no leaking cross sites if someone obtains and breaks the salted hash db.

It is for something like a CAC PIN.

I think the Web could come up with a robots.txt-like standard where all the requirements for passwords, usernames, maybe even form field names etc. would be published in a parseable form.

The "pattern" attribute on an <input> can do that using regex.

This looks to me like something you could (literally) throw up on Github as a JSON file, so that it's easily updated by people and usable to other applications.

Wouldn't it make more sense to have this information in the website's manifest? This way we don't have to wait for a manual update and it doesn't have to be limited to Safari

It would make sense, sure. Good luck getting every bank/utility/store/etc to update the system they set up ten years ago and haven’t updated since to broadcast that information. You’ll probably have to get a law passed.

Until then, this way works.

If you know what you’re doing, you shouldn’t put a maximum on the length or character set of passwords, and you should accept any password that has some reasonable amount of entropy rather than putting in arbitrary restrictions like “must have 1 number and 1 symbol”. This is for the sake of users who want to supply their own passwords, but as a side effect, it means Safari’s default password generation algorithm should work fine.

If you don’t know what you’re doing, you probably wouldn’t know how to put information in a manifest anyway…

Well, yes, but standards are kinda hard to incite.

Sounds like we need a standard for setting standards to make this easier!

Consider a site that still enforces rules like: 8-12 characters, ASCII only, at least one lowecase, uppercase and number.

Does that seem like the kind of site that will take action to help users with password managers? Personally, I wouldn't expect that kind of site to be quite up-to-date with the newest security practices.

Great. As long they attempt to keep these rules up-to-date.

Recently, saw strange thing -- I was allowed to have password with lengths between 16 and 128 characters, but my password manager 1Password supports only... 60 or 64 characters. Oh well, wish that this would be a problem, not other way around. Still kills me that my health records are behind 12 characters password, and my bank think 16 character password is enough.

My favorite was some newsletter (I can’t remember the website) that allowed me to log in using my foo+bar@gmail.com email address, but the unsubscribe form backend didn’t accept the “plus” character, thus I could never unsubscribe.

I have several 100+ character passwords stored in 1Password.

Yes, 1Password supports long passwords, but it's password generator can generate only 64 character long. (I'm not talking about word-based passwords).

Ah yes, agree there. What I do is generate twice and combine together, annoying, but works.

I wish my bank allowed 16 character passwords!

I wish my bank would stop asking me for individual characters from my password - make auto-fill all but impossible AFAICT.

HSBC used(?) to do this. It was a reason I closed account there.

Is there a way (for a non-MacOS user) to have a look at this database? I seem to remember that there was a website that collected password requirements, but i can't find it.

I don't know if this is a complete list, but a search returned this page: https://codegists.com/snippet/xml/wbsautofillquirksplist_saa...

What is the desired requirements for passwords these days then? No passwords just a magic link or some open but difficult to hack standard (12+ characters?).

I’ve always liked the idea of using a predefined sentence structure and having lots of choices to increase entropy, e.g. The magic butterfly flapped faithfully. Article adjective noun verb adverb. No one does this of course.

In Topicbox, we use emailed codes/magic links by default, but you can set a password and use that if you prefer (and if you want 2FA, you must use a password). We then use zxcvbn for password strength detection, denying weak passwords (those where it is estimated to take less than 10⁶ attempts to guess). I believe this is working well for us.

In FastMail, it’s much the same but without emailed codes as an option, because it is your email account that you’re trying to log in to.

I think we support almost arbitrary lengths and arbitrary Unicode in both now. (And note that due to how the fancier password hashing algorithms like bcrypt work, supporting beyond ~72 characters without loss of entropy actually tends to take deliberate design; and if you get it wrong, it can be a DoS vector—Django had such a problem a few years back, where you could feed it a 1MB password and keep it occupied hashing it for ages.)

I have wondered before how secure a single astral plane Unicode code point would be as a password. I haven’t investigated the question at all.

This is excellent advice and zxcvbn [1] looks awesome.

[1] https://github.com/dropbox/zxcvbn

This probably isn't mostly about password generation rules, but rather about how to fill the forms, e.g. what's the user name field named, etc. (Otherwise why would it be called "AutofillQuirks" and not "PasswordRequirements"?)

Overall the file does appear to contain various autofill quirks, but the expanded dictionary in the screenshot is literally named “PasswordGenerationRequirements”. It’s definitely about password generation rules.

Good point, but in the photo, the expanded dictionary property in the property list is “PasswordGenerationRequirements,” so it’s most likely all of the above.

The most disturbing thing about iCloud Keychain is that you can get access to all of your stored passwords just by unlocking a device linked to your Apple ID. Not just the ability to log in with them, the actual plaintext.

Urm, if you have the ability to log in with a password to a website, you require the plain text password. Keychain also prompts for your user password before allowing plaintext access, not just the fact you're logged in.

Not sure what else is expected in this case, you'd get the same behavior from most other password managers.

Keychain doesn't prompt for your user password on iOS. Just your unlock code. That's what bothers me.

But iOS won’t reveal the plaintext password from the keychain to the user (it will only autocomplete forms).

It will if you go to settings->accounts and passwords.

you still get a password or touch if prompt before showing the passwords.

I assume RGS1811 was worried about someone using your finger for TouchID or face for FaceID, involuntarily. I also worry about that, especially if you get knocked out or black out or something, but I think the solution is to not have important login info in the keychain at all, such as access to money (bank apps), email, or other uses that can be used to verify your identity or steal from you.

If that is a legitimate concern, then don't use Touch ID or Face ID. By using those a person is intentionally choosing convenience over security. By even saving passwords in an account-shared fashion (be it Keychain, LastPass, or 1Password), you're giving up some security for convenience.

The latest iOS versions have also included a "five clicks on the power button" emergency option, which disables both TouchID and FaceID. It's not perfect, but if you're going into a questionable situation, it's a good way to avoid being coerced into using those to unlock your phone.

What made me concerned was the discovery that, on an old iPad mini I rarely use (without touch id / face id), entering the standard four digit unlock code is enough to get access to the full list of logins/passwords stored by iCloud Keychain. I would like to have to at least re-enter my apple ID to get at this full list.

Don’t use a basic unlock code then. I use an XKCD style passcode to unlock mine.

This isn't unique to Apple: Google has adopted the same policy.

It's not clear what the best solution is here, or if the best way to have the conversation about it follows hyperbole like "the most disturbing thing".

I think password managers are on the whole a good thing because people are using more (stronger) passwords.

I also think the password manager could (at least on trusted hardware like an iPhone) provide some protection from the attacks you're alluding to, such as a tarpit that slows access to the password database, but they certainly won't offer any protection on a desktop machine without specialised hardware and it might be difficult to get right -- difficult enough that new security vulnerabilities are introduced instead.

What exactly do you propose?

I think Firefox's solution is a little better. You can set a master password which is used to encrypt the password database. To unlock you have to enter the password. You can browse without unlocking.

Both the iPhone and Google Chrome ask for authentication before showing the passwords.

Firefox works similarly: Once you unlock it, you see all the passwords. On an iPhone or Google Chrome, you have to click each password you want to see.

Fortunately, Chrome for Linux and Chrome OS don't ask. Both OSes trust users to control access at the session level.

You need a second factor (physical access to a device already in the circle) to add a device to the iCloud Keychain.

Edit: I see you are worried about devices already linked

I don't believe this is entirely accurate – a further auth prompt is always required before revealing plain-text passwords.

apple.com: PasswordGenerationDisallowed


Makes sense if you consider that the keychain is typically backed up to iCloud, under your Apple ID. So if you generate your Apple ID password through Safari and then lose your device, you’re going to have a chicken and egg problem…

Your Apple ID password is effectively your master password for your keychain. The whole point of a master password is for it to be stored in the brain of the end user.

They probably turned it off after an increase in support requests when people inevitably at one point don't have the "wallet" around. Of course they don't care for other sites support load enough to look at their 50 entries long list of special cases and think "are we doing this wrong".

Alternate link if Twitter is blocked behind your corp firewall, etc: https://archive.is/Uzssa

I like Hacker News' policy of "it's up to you to be in the know and generate your password securely".

(I mean HN doesn't impose any restrictions, as I remember it.)

The HN audience is mostly not completely incompetent in password matters.

But by and large, people have been trained into terrible habits concerning passwords, and they have no idea how to make a halfway decent password. I tend to think a good baseline for most sites is to use zxcvbn and reject passwords with score 0 (which means, guessing is expected to take less than 1,000 attempts). That way you’re not being particularly onerous, but you are at least blocking useless passwords.

Still, there’s a space in some services for allowing no password. NewsBlur allows a zero-character password, for example, and that’s fine. I’d much prefer a thing to allow no password if possible, deny useless passwords and allow anything else (with hints about weaknesses), than have rules about character classes and mandatory inclusions.

This. Imposing no restrictions is generally the best option for most websites, which should focus on things like rate limiting, secure hashing, and 2FA before getting user-hostile wrt passwords.

I wonder who has the best-maintained list of these password requirements for popular websites. Probably some group that does black-hat brute forcing of passwords.

I wonder how many sites reject random A-Z, a-z, 0-9, and -.

In my experience, the number of websites doing this has gone down significantly. Of the passwords I have, only around 2-3% are "specialty" passwords generated through Keychain Access rather than Safari.

Interesting, but there are only 48 sites in this list, which is really tiny. Perhaps they will continue to expand it in the future.

All this time I thought they were using an amazing heuristic to infer password requirements from the page

Does Apple maintain this and update it when the websites change their requirements?

I always thought curation creates value

Can someone post the .plist?

Under 10.12.6 running Safari 11.0.3 (12604., no file named WBSAutoFillQuirks.plist exists anywhere on the file system. The closest named file I found is WBSPasswordGenerationRequirementsByDomain.plist which is found under /System/Library/StagedFrameworks/Safari/SafariShared.framework/Versions/A/Resources/

I've posted its contents here - https://pastebin.com/iPY6gLSC

There's a separately named WBSFormAutoFillKeywords.plist.

Here you go: https://gist.github.com/saagarjha/719af0a83b51bae7955d844a46...

It's located at /System/Library/PrivateFrameworks/SafariShared.framework/Resources/WBSAutoFillQuirks.plist on the iOS base system image.

Unfortunately, Safari itself is closed source, only WebKit is open. :(

Googling the filename of course returns no results.

I am VERY curious how 1Password were confident they'd be able to get anywhere with getting a copy of this. I have no info suggesting they'd have a problem with it, of course, and time will tell if it works out.

The plist is probably just stored within the Safari bundle, and 1password could look there at runtime.

It doesn't even have to be done at runtime. All they need to do is extract it from an iOS install image.

Oh! Of course. Awesome.

Why would 1Password need a copy of this? They just need to implement a similar feature for their own Safari extension.

Saving time..

This is coming from the same company that doesn't allow you to put a space in your AppleID password? The irony is thick.

I have spaces in my AppleID password. Four of them in fact.

From https://support.apple.com/en-us/HT201355

Learn more about passwords and your Apple ID When you create a new password, keep the following in mind:

Your new Apple ID password must contain at least eight characters, a number, an uppercase letter, and a lowercase letter. You can't use spaces, the same character three times in a row, your Apple ID, or a password you've used in the last year. Learn more about password requirements and how to keep your Apple ID secure.

FaceTime is not available in all countries or regions.

Published Date: Oct 20, 2017

A reader's exercise: Can you determine how many bits of apparent entropy in his password rrdharan has disclosed in this post?

If you presume rrdharan generated his password as a string of random alphanumeric characters and round that to there being 64 of those, he revealed $32 / n pick 4$ bits of entropy. Where $n pick 4$ is the number of combinations of length 4 drawn from n.

That only works if you presume his password was generated as a string of random bits though. If the password was generated as a dice-ware password [1] with 5 characters this reveals roughly 2 bits of entropy. For we know he doesn't use -, _ or nothing as his word-separator. Those 2 bits aren't included in the calculation that states his diceware password has about 65 bits of entropy though. (5 words from a list of 8000) 65 bits feels like plenty to me.

[1] http://world.std.com/~reinhold/diceware.html

For a clever intern, or at least one who knows a little python, it probably wasn't that bad. Or maybe I am missing something.

How does knowing a little python help here? Most of this seems like manual scutwork - going to each site and finding and reading the stupid password rules.

Possibly even testing them, because I've used sites that rejected passwords that met all the requirements.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact