Security considerations for password generators

When I started writing my very own password generation extension I didn’t know much about the security aspects. In theory, any hash function should do in order to derive the password because hash functions cannot be reversed, right? Then I started reading and discovered that one is supposed to use PBKDF2. And not just that, you had to use a large number of iterations. But why?

Primary threat scenario: Giving away your master password

That’s the major threat with password generators: some website manages to deduce your master password from the password you used there. And once they have the master password they know all your other passwords as well. But how can this happen if hash functions cannot be reversed? Problem is, one can still guess your master password. They will try “password” as master password first — nope, this produces a different password for their site. Then they will try “password1” and get a match. Ok, now they know that your master password is most likely “password1” (it could still be something else but that’s quite unlikely).

Of course, a number of conditions have to be met for this scenario. First, a website where you have an account should be malicious — or simply leak its users database which isn’t too unlikely. Second, they need to know the algorithm you used to generate your password. However, in my case everybody knows now that I’m using Easy Passwords, no need to guess. And even for you it’s generally better if you don’t assume that they won’t figure out. And third, your master password has to be guessable within “finite” time. Problem is, if people start guessing passwords with GPUs most passwords fall way too quickly.

So, how does one address this issue? First, the master password clearly needs to be a strong one. But choosing the right hashing algorithm is also important. PBKDF2 makes guessing hard because it is computationally expensive — depending on the number of iterations generating a single password might take a second. A legitimate user won’t notice this delay, somebody who wants to test millions of guesses however will run out of time pretty quickly.

There are more algorithms, e.g. bcrypt and scrypt are even better. However, none of them found its way into Firefox so far. Since Easy Passwords is using the native (fast) PBKDF2 implementation in Firefox it can use a very high number of iterations without creating noticeable delays for the users. That makes guessing master passwords impractical on current hardware as long as the master password isn’t completely trivial.

To be precise, Easy Passwords is using PBKDF2-HMAC-SHA1 with 262,144 iterations. I can already hear some people exclaiming: “SHA1??? Old and busted!” Luckily, all the attacks against SHA1 and even MD5 are all about producing hash collisions which are completely irrelevant for password generation. Still, I would have preferred using SHA256, yet Firefox doesn’t support PBKDF2 with SHA256 yet. So it’s either SHA1 or a JavaScript-based implementation which will require a significantly reduced iteration count and result in a less secure solution.

Finally, it’s a good measure to use a random salt when hashing passwords — different salts would result in different generated passwords. A truly random salt would usually be unknown to potential attackers and make guessing master passwords impossible. However, that salt would also make recreating passwords on a different device complicated, one would need to back up the salt from the original device and transfer it to the new one. So for Easy Passwords I chose a compromise: the salt isn’t really random, instead the user-defined password name is used as salt. While an attacker will normally be able to guess the password’s name, it still makes his job significantly more complicated.

What about other password generators?

In order to check my assumptions I looked into what the other password generators were doing. I found more than twenty password generator extensions for Firefox, and most of them apparently didn’t think much about hashing functions. You have to keep in mind that none of them gained significant traction, most likely due to usability issues. The results outlined in the table below should be correct but I didn’t spend much time figuring out how these extensions work. For a few of them I noticed issues beyond their choice of a hashing algorithm, for others I might have missed these issues.

Extension User count Hashing algorithm Security
PasswordMaker 3056 SHA256/SHA1/MD4/MD5/RIPEMD160, optionally with HMAC Very weak
Password Hasher 2491 SHA1 Very weak
PwdHash 2325 HMAC+MD5 Very weak1
Hash Password Generator 291 Custom (same as Magic Password Generator) Very weak
Password Maker X 276 SHA256/SHA1/MD4/MD5/RIPEMD160, optionally with HMAC Very weak
masterpassword for Firefox 155 scrypt, cost parameter 32768, user-defined salt Medium2
uPassword 115 SHA1 Very weak
vPass Password Generator 88 TEA, 10 iterations Weak
Passwordgen For Firefox 1 77 SHA256 Very weak
Recall my password 64 SHA512 Very weak3
Phashword 57 SHA1 Very weak
Passera 52 SHA512 Very weak
My Password 51 MD5 Very weak
HashPass Firefox 48 MD5/SHA1/SHA256/SHA512 Very weak
UniPass 33 SHA256, 4,096 iterations Weak
RndPhrase 29 CubeHash Very weak
Domain Password Generator 29 SHA1 Very weak
PasswordProtect 28 SHA1, 10,000 iterations Weak
PswGen Toolbar v2.0 24 SHA512 Very weak
UniquePasswordBuilder Addon 13 scrypt, cost factor 1024 by default Strong4
Extrasafe 12 SHA3 Very weak
hash0 9 PBKDF2+HMAC+SHA256, 100,000 iterations, random salt Very strong5
MS Password Generator 9 SHA1 Very weak
Vault 9 PBKDF2+HMAC+SHA1, 8 iterations, fixed salt Weak
BPasswd2 8 bcrypt, 64 iterations by default, user-defined salt Weak6
Persistent "Magic" Password Generator 8 MurmurHash Very weak
BPasswd 7 bcrypt, 64 iterations Weak
CCTOO 4 scrypt, cost factor 16384, user-defined salt Very strong7
SecPassGen 2 PBKDF2+HMAC+SHA1, 10,000 iterations by default Weak8
Magic Password Generator ? Custom Very weak

1 The very weak hash function isn’t even the worst issue with PwdHash. It also requires you to enter the master password into a field on the web page. The half-hearted attempts to prevent the website from stealing that password are easily circumvented.

2 Security rating for masterpassword downgraded because (assuming that I understand the approach correctly) scrypt isn’t being applied correctly. The initial scrypt hash calculation only depends on the username and master password. The resulting key is combined with the site name via SHA-256 hashing then. This means that a website only needs to break the SHA-256 hashing and deduce the intermediate key — as long as the username doesn’t change this key can be used to generate passwords for other websites. This makes breaking scrypt unnecessary, security rating is still “medium” however because the intermediate key shouldn’t be as guessable as the master password itself.

3 Recall my password is quite remarkable as it manages to sent the user to the author’s website in order to generate a password for no good reason (unless the author is actually interested in stealing some of the passwords of course). Not only is it completely unnecessary, the website also has an obvious XSS vulnerability.

4 Security rating for UniquePasswordBuilder downgraded because of low default cost factor which it mistakenly labels as “rounds.” Users can select cost factor 16384 manually which is very recommendable.

5 hash0 actually went as far as paying for a security audit. Most of the conclusions just reinforced what I already came up with by myself, others were new (e.g. the pointer to window.crypto.getRandomValues() which I didn’t know before).

6 BPasswd2 allows changing the number of iterations, anything up to 2100 goes (the Sun will die sooner than this calculation completes). However, the default is merely 26 iterations which is a weak protection, and the extension neither indicates that changing the default is required nor does it give useful hints towards choosing a better value.

7 The security rating for CCTOO only applies when it is used with a password, not drawn gestures. From the look of it, the latter won’t have enough entropy and can be guess despite the good hashing function.

8 Security rating for SecPassGen downgraded because the master password is stored in Firefox preferences as clear text.

Additional threats: Shoulder surfing & Co.

Websites aren’t the only threat however, one classic being somebody looking over your shoulder and noting your password. Easy Passwords addresses this by never showing your passwords: it’s either filling in automatically or copying to clipboard so that you can paste it into the password field yourself. In both scenarios the password never become visible.

And what if you leave your computer unattended? Easy Password remembers your master password once it has been entered, this is an important usability feature. The security concerns are addressed by “forgetting” the master password again after a given time, 10 minutes by default. And, of course, the master password is never saved to disk.

Usability vs. security: Validating master password

There is one more usability feature in Easy Password with the potential to compromise security. When you mistype your master password Easy Passwords will notify you about it. That’s important because otherwise wrong passwords will get generated and you won’t know why. But how does one validate the master password without storing it?

My initial idea was storing a SHA hash of the master password. Then I realized that it opens the primary threat scenario again: somebody who can get their hands on this SHA hash (e.g. by walking past your computer when it is unattended) can use it to guess your master password. Only store a few characters of the SHA hash? Better but it will still allow an attacker who has both this SHA hash and a generated password to throw away a large number of guesses without having to spend time on calculating the expensive PBKDF2 hash. Wait, why treat this hash differently from other passwords at all?

And that’s the solution I went with. When the master password is set initially it is used to generate a new password with a random salt, using the usual PBKDF2 algorithm. Then this salt and the first two characters of the password are stored. The two characters are sufficient to recognize typos in most cases. They are not sufficient to guess the master password however. And they won’t even provide a shortcut when guessing based on a known generated password — checking the master password hash is just as expensive as checking the generated password itself.

Encrypting legacy passwords

One requirement for Easy Passwords was dealing with “legacy passwords,” meaning existing passwords that cannot be changed for some reason. Instead of generating, these passwords would have to be stored securely. Luckily, there is a very straightforward solution: the PBKDF2 algorithm can be used to generate an encryption key. The password is then encrypted with AES-256.

My understanding is that AES-encrypted data currently cannot be decrypted without knowing the encryption key. And the encryption key is derived using the same algorithm as Easy Passwords uses for generating passwords, so the security of stored passwords is identical to that of generated ones. The only drawback of such legacy passwords currently seems to be a more complicated backup approach, also moving the password from one device to another is no longer trivial.

Phishing & Co.

Password generators will generally protect you nicely against phishing: a phishing website can look exactly like the original, a password generator will still produce a different password for it. But what about malicious scripts injected into a legitimate site? These will still be able to steal your password. On the bright side, they will only compromise your password for a single website.

Question is, how do malicious scripts get to run there in the first place? One option are XSS vulnerabilities, not much can be done about those. But there are also plenty of websites showing password fields on pages that are transmitted unencrypted (plain HTTP, not HTTPS). These can then be manipulated by an attacker who is in the same network as you. The idea is that Easy Passwords could warn in such cases in future. It should be possible to disable this warning for websites that absolutely don’t support HTTPS, but for others it will hopefully be helpful. Oh, and did I recommend using Enforce Encryption extension already?

Finally, there is the worst-case scenario: your computer could be infected with a keylogger. This is really bad because it could intercept your master password. Then again, it could also intercept all the individual passwords as you log into the respective websites, it will merely take a bit longer. I think that there is only one effective solution here: just don’t get infected.

Other threats?

There are probably more threats to consider that I didn’t think of. It might also be that I made a mistake in my conclusions somewhere. So feel free to post your own thoughts in the comments.

Comments

  • aaa

    What about lastpass.com built-in generator?

    Wladimir Palant

    That’s an entirely different beast. If I understand it correctly, it won’t derive a password from some master password but rather generate a random one and store it in the password manager. So as long as the passwords are stored securely this should be safe. The point of password generators listed here is that passwords don’t need to be stored at all.

  • Omega

    Is this new password manager using the tried and true XUL addon system or the up and coming WebExtensions API?

    Wladimir Palant

    Neither, it’s using the Add-on SDK. WebExtensions definitely weren’t ready to be used back when I started, and I doubt that they are ready now. I’ll have to look into migrating eventually however, and be it for the sake of supporting Chrome as well. Either way, Add-on SDK will stay supported for a while.

  • egrooclus

    Interesting project. It needs versatility of original PasswordMaker to be fully usable IMO (which was strangely omitted in your comparison while having more users than others).
    https://addons.mozilla.org/en-US/firefox/addon/passwordmaker/

    Your crypto + their customizability – that sounds like a DEAL :)))

    Wladimir Palant

    Yes, I somehow overlooked this one. It’s not like there is a single category listing all password generators on AMO. There you go – added it to the top of the list. The crypto appears to be identical to Password Maker X, meaning: large choice of algorithms, all of them offering pseudo-security. It also allows storing your master password on disk which you shouldn’t do – the master password is encrypted and the encryption key is stored right next to it, yet another piece of pseudo-security.

    What’s exactly the deal with customizability? I only looked at the screenshots but it seems that Eric implemented all the same concepts, merely in a somewhat less convenient way (state of the art was quite a bit different ten years ago when his extension was written). There is plenty of password tweaking options but I don’t see why anybody would use them. My goal with Easy Passwords was making passwords require as few configuration parameters as possible, while still being compatible with pretty much every website out there. Which exact features are missing?

  • egrooclus

    Yeah simplicity is nice goal to have but the reality is that users have different needs = they use something in different ways than others. There is no one solution that fits all.
    This is why I prefer versatility|customizability|optionality.

    You said “There is plenty of password tweaking options but I don’t see why anybody would use them”. I’ll add an example:

    As you wrote, security that this extension provides is partially based on strong masterpass provided. But memorizing even one strong password is beyond abilities of MANY non-tech savvy users! (and retyping it every 10 minutes as memory clears itself).

    What those users needs is to translate weak password i.e. ‘dog’ into strong one. I don’t know if your crypto with weak masterpass is better than weak crypto with strong masterpass but it’s certainly not secure. This is where “plenty of password tweaking options” come in place.

    In passwordmaker there are many ways to “obfuscate” provided masterpass (username, modifier,custom character set, prefix,suffix, l33t language level).

    Providing all of those is probably unnecessary but I’ll vote for add “custom password modifier” option which work like this:

    default (as it is now): crypto(‘masterspass’) => crypto(‘dog’)
    enchanced: crypto(‘masterpass+modifier’) => crypto(‘dog+custom_string’)

    So in reality user master pass is ‘dog+custom_string’ but she has to type only ‘dog’. The modifier has to be saved along password names and site options.

    Of course this solution is less secure if someone has access to your computer (but then she could just install keylogger and it’s all over) but is way more secure than using ‘dog’ as masterpass and dealing with malicious website or stolen databases.

    Other users who don’t need this option may ignore it (nothing changes to them). This is what versatility|customizability|optionality is about.

    Few other things:

    Ability to fill usernames (automatically or user can choose the appropriate field by himself)
    Fill only if field is empty (useful when changing passwords)
    One time option (password is generated and filled to current website without storing anything in memory)
    Typing masterpass twice to validate (avoiding typos)

    BTW: You wrote “two characters are sufficient to recognize typos in most cases”. If I understand this correctly I think that two characters are NOT sufficient to recognize typos especially when strong masterpass is provided. Therefore “running it twice” is better option to validate password.

    Above all thank you for incredible work you do!

    Wladimir Palant

    I wonder whether “memorizing even one strong password is beyond abilities” applies to you or merely somebody you’ve heard about. If it is the latter then I’d consider it a rumor. The problem is usually not memorizing a single strong password, it’s memorizing a strong password you don’t use regularly – and with Easy Passwords you are using it regularly. No matter how it is implemented, allowing weak master passwords is a security issue that I’d rather not implement. For now, “many non-tech savvy users” aren’t my problem because these will never install my extension in the first place.

    Filling in usernames is planned, this feature is far from trivial however. The approach for filling in passwords changed already – if you focus a specific password field only this field will be filled out (should do for password changes). One time option seems pointless to me, maybe you could explain under which circumstances this is needed (adult websites?). Having to type master password twice increases the annoyance factor significantly but doesn’t really help much (e.g. consider Caps Lock being stuck, an unusual keyboard layout or simply remembering the password incorrectly, both passwords will be identical and still wrong).

    I think you misunderstood the thing about “two characters” – Easy Passwords doesn’t validate the first two characters of your password, it rather validates the first two characters of a generated password. So chances of you mistyping the master password and Easy Passwords not detecting it are rather small, 1 in 6724 to be precise. The chances of you making the same mistake twice should be considerably higher.

  • egrooclus

    Maybe we came from different environments then. For me it’s not a rumor – it’s ubiquitous. As “non-tech savvy users” I mean those whose passwords are regularly in top 10000 common passwords leaked – let’s say ‘Jane1967’ or something. I thought that password hashers would be good solution for them. They don’t need to be in 1% passwords security elite ~20% is enough. Also some people need it only once a week or less – far from regular.

    You already allow choosing anything as masterpass even ‘aaaaaa’ and it can’t be different since it’s up to the user. Allowing password modifier in any case would IMPROVE security (with weak masterpass and strong).

    You are right that those users I mentioned won’t install your extension and I wouldn’t advice them to do it (for now) but is it your goal to develop another excellent password security solution which nobody uses?

    In any case I appreciate your work. Maybe I wanted too much. Good luck!

    Wladimir Palant

    Improving master password security is on the list of issues to be resolved – while I’m not going to forbid choosing “aaaaaa” as password, there should be a good indicator explaining that this isn’t good as your password.

    The extension targets experienced users for now – simply because that’s the only group where I can hope that they understand the concept and install it. Whether it is even possible to make a compelling argument towards installing a password generator for non-tech savvy users is questionable. But that’s something I can worry about once the usability issues are out of the way (meaning: security indicators, user names, platform support, sync etc.).

  • Dale

    Will there be a facility to optionally export a backup of passwords for known sites? (I understand the risk) Perhaps as an encrypted 7z of a key3.db and logins.json so in an emergency it could be quickly recovered without using easy password gen. From my understanding I think that will not be necessary, yet I am scared of losing access for some as yet unknown reason and having to use “forgot password” on every website that is not legacy!

    Wladimir Palant

    There is already the possibility to back up all data, from the “All Passwords” page. It’s not a file format that will be usable without Easy Passwords, which is why I created https://github.com/palant/easypasswords/issues/11 – if the passwords are displayed then you can print the page or save it and encrypt by whatever means you like.

  • PizzaGuy

    Can LessPass using PBKDF2 with 100,000 interactions be considered secure? If possible, could you add it to the comparison list?

    Wladimir Palant

    This article is eight years old. I’m not updating it with all the extensions which came out afterwards.

    No, things change over time as hardware improves, and PBKDF2 with 100,000 is no longer considered sufficient. Current OWASP recommendation for PBKDF2-HMAC-SHA256 is at least 600,000 iterations: https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#pbkdf2

    There is also a newer article on the topic (about LastPass, but it applies to any password manager): LastPass breach: The significance of these password iterations