Please tell me I am missing something. There is no salt. The hashing algorithm is hence vulnerable to a simple dictionary attack. It does not matter if you do a gigazillion rounds. Someone can still pre-calculate a list of common passwords and then test that list against each and every user.
Correct, there is no salt. A dictionary attack will uncover common passwords. It's crucial to pick a strong secret key. That's the price you pay for using a stateless password manager.
However, the gigazillion rounds are not for nothing. That is the defense against brute force attacks, which could otherwise crack passwords even if they are random.
and the best part is you can't change your password in case some website becomes compromised and the hash is leaked. (without changing the secret key and as the result changing all passwords on all websites).
The #1 benefit of a purely stateless password manager is that there is no password database, so your password database cannot be compromised.
The drawback, as others have mentioned, is that it's difficult to use strong salts without keeping some sort of database. Changing passwords also becomes a big hassle.
But what about a compromise? Keep a database, but only store the salts in the database. Generate the passwords on the fly using the master password and the domain-specific salt. Now you can have your cake and eat it too! If anyone steals your database, all they have is a bunch of salts. You probably won't even have to keep it encrypted.
Keeping a database will also let you add some of the following features, which I consider essential to any modern password manager:
- Remember the username for each website. Some websites ask for my email address, others ask for a simple handle, and I shouldn't have to remember which is which.
- Manage more than one account for the same domain, each with a different username.
- Change the password for only one website, without changing the master password, and without having to use a silly suffix. Just change the salt for that website. (This is one reason why it's a bad idea to use the username as the salt. The salt should be random and easily changeable.)
- Remember password restrictions for each website. If your bank limits passwords to 12 characters, you can store this setting in the database and automatically truncate the hash to the desired length. If your school doesn't allow special characters in the password, also remember this setting and skip non-alphanumeric characters from the auto-generated hash.
Until now, most of the features I listed above have only been possible with password databases. But if you think about it, there's no reason not to go the hybrid route.
I pretty much wrote hash0 (https://github.com/dannysu/hash0) for most reasons you listed. Would love more auditing if you're interested to take a look.
There are many of this type of hash function based generators, but pretty much all use fast hash functions. The no salt thing also makes me uneasy.
From another Ask HN[0], I learned about bpasswd[1] which does bcrypt and allows the cost (iterations) to be configured. That looks pretty cool.
For me, I chose to go with a hybrid approach and wrote hash0[2] for my less important passwords (important ones live in KeePass). Hash0 does 100,000 iterations of PBKDF2 with salt from CSPRNG unique for each site. It stores the encrypted metadata (just the salt, length, symbol/no symbol, etc) at a location of your choosing (I just store it in my Google App Engine).
Would love to get more eyes on it and get feedback (See services.js for generation logic).
Benefits of hybrid are that:
- Allows me to use random salt
- Allows me to easily change password for individual sites (thanks for random salt)
- Allows me to store website's preferred password length and whether to use symbols or not
- Allows me to create mappings (so say www.twitter.com and account.twitter.com can use the same password)
- Allows me to store notes along with the metadata (e.g. what username I used)
- salt. To avoid rainbow table attacks. One could use the login/email as salt
- key strengthening function. Instead of repeating naively SHA-256 a few times, use PBDKF2 or even better, something which is also memory hard like scrypt.
Finally. What happens when the password requires to have upper case, symbols, x number of digits, min or max number of characters... If you think about it, some websites have conflicting requirements.
A salt is random bits added to a password. Hashpass prefers to be stateless, so it just asks the user to pick a strong password (possibly by adding random bits like a salt). It puts more trust in the user, which obviously comes at a price.
Re key strengthening: Agreed, but only salt-less schemes will work in this stateless model. Unfortunately they are few.
> Finally. What happens when the password requires to have upper case, symbols, x number of digits, min or max number of characters... If you think about it, some websites have conflicting requirements.
Addressed this in the article: "Some websites have certain requirements on passwords, e.g., at least one number and one capital letter. A simple way to meet such requirements is to append something like A9! to the generated password (and remember you did that)."
>Finally. What happens when the password requires to have upper case, symbols, x number of digits, min or max number of characters... If you think about it, some websites have conflicting requirements.
It would be great if there was a site ran by a widely-trusted body (EFF for example) that tracks the various password requirements and limitations of websites. That way password managers, such as this one, can query that authoritative database for the idiosyncratic password rules for each domain and generate a password of the maximum allowable length and with the largest possible alphabet.
Ok, the idea in general isn't good because most people won't use a good password and also because now there's a single point of failure if someone sees your password.
However, it might be okay if one can provide their own hashing function. Like a JS function that takes the domain and secret key as parameters.
This is a technique that's been in use for about a decade (in GenPass and SuperGenpass). There are, in fact, flaws in an all JavaScript bookmarklet solution, as the site you're visiting can snoop your JavaScript data structures and could readily figure out your master password. This is resolved by use of a Google extension that does not share a JavaScript interpreter with the page you're visiting; and it's reportedly been fixed in the bookmarklet version of SuperGenPass though I haven't read it to see how it is resolved.
But, your suggestion of a JS function that take the domain and secret key is how the GenPass and SuperGenPass bookmarklets have worked for years (and the flaw in that method has only been fixed this year, I think).
Yes, you should not use this unless you are willing to memorize a strong secret key. There are warnings in the article, but perhaps it could have used a few more.
This is one of those "only use it if you know what you're doing" things.
I've been using SuperGenPass for this for years. There is a Chrome extension that is safe (from website snooping of your key) and a browser bookmarklet that is not safe. But, I just use the mobile browser version in another tab and copy paste since I choose to use Firefox. It's a little less convenient, but not inconvenient enough that I've spent time trying to figure out how to make a safe extension for Firefox.
So, what's different about this from the SuperGenPass session Chrome plugin?
> SuperGenPass uses a one-way hash algorithm (base-64 MD5) to generate passwords. Specifically, it concatenates the master password and the domain name of the Web site (masterpassword:domain.com), hashes the result at least ten times (and until it satisfies the generated password requirements), and cuts the result to the desired length.
Yikes! MD5 is known to be broken, and 10 rounds of hashing is no defense against brute force attacks. Hashpass uses SHA-256 (not broken) and does 2^16 rounds of hashing.
It's an interesting idea, but is it really usable? If you ever need to change the master key, you'll have to update all the websites you are using, and you won't even know on which websites you used the password manager with since there is no database. I just don't see how I could ever want this. Or is it assumed that master keys never need to be changed?
It's true that changing the master key is a pain, but you don't have to do it for every website at once. Though it might be hard during the transition to remember which sites have the updated key.
Not having a database certainly has its downsides.
Re usability: I've been using it for a couple days now, and I find it pretty tolerable. It's nice to not have to memorize a new password when I sign up for something. I did change my master key once; it took about 5 minutes to update all my passwords. If you only do that once every few months or once a year, it's not so bad.
Use slower / heavier hash -- PBKDF2 or better. For lulz use something like Darkcoin Cryptocurrency 'X11' Proof of Work function - multiple rounds of 11 different hashes.
Or more. (X13, X15 and X17 all exist as PoW functions in CryptoCurrencies today).
A <$1000 bitcoin (SHA-256) mining ASIC appliance is likely to be doing 1TH/s. Makes 2^16 rounds look kinda weak.
This is not a new technique. In addition to the Stanford paper, there are several other implementations mentioned in these comments. It's a compromise, not a mistake. It is better to memorize one strong password than a dozen weak ones.
This isn't custom crypto. It's a well-known hash function that serves as a filter, transforming the passwords you would otherwise enter directly into a website's login form. It is no less secure than typing in passwords by hand.
[+] [-] a1a|11 years ago|reply
[+] [-] stepstep|11 years ago|reply
However, the gigazillion rounds are not for nothing. That is the defense against brute force attacks, which could otherwise crack passwords even if they are random.
[+] [-] epimenov|11 years ago|reply
[+] [-] thomasfromcdnjs|11 years ago|reply
[+] [-] unknown|11 years ago|reply
[deleted]
[+] [-] kijin|11 years ago|reply
The #1 benefit of a purely stateless password manager is that there is no password database, so your password database cannot be compromised.
The drawback, as others have mentioned, is that it's difficult to use strong salts without keeping some sort of database. Changing passwords also becomes a big hassle.
But what about a compromise? Keep a database, but only store the salts in the database. Generate the passwords on the fly using the master password and the domain-specific salt. Now you can have your cake and eat it too! If anyone steals your database, all they have is a bunch of salts. You probably won't even have to keep it encrypted.
Keeping a database will also let you add some of the following features, which I consider essential to any modern password manager:
- Remember the username for each website. Some websites ask for my email address, others ask for a simple handle, and I shouldn't have to remember which is which.
- Manage more than one account for the same domain, each with a different username.
- Change the password for only one website, without changing the master password, and without having to use a silly suffix. Just change the salt for that website. (This is one reason why it's a bad idea to use the username as the salt. The salt should be random and easily changeable.)
- Remember password restrictions for each website. If your bank limits passwords to 12 characters, you can store this setting in the database and automatically truncate the hash to the desired length. If your school doesn't allow special characters in the password, also remember this setting and skip non-alphanumeric characters from the auto-generated hash.
Until now, most of the features I listed above have only been possible with password databases. But if you think about it, there's no reason not to go the hybrid route.
[+] [-] dannysu|11 years ago|reply
[+] [-] anton_gogolev|11 years ago|reply
[+] [-] unknown|11 years ago|reply
[deleted]
[+] [-] dannysu|11 years ago|reply
From another Ask HN[0], I learned about bpasswd[1] which does bcrypt and allows the cost (iterations) to be configured. That looks pretty cool.
For me, I chose to go with a hybrid approach and wrote hash0[2] for my less important passwords (important ones live in KeePass). Hash0 does 100,000 iterations of PBKDF2 with salt from CSPRNG unique for each site. It stores the encrypted metadata (just the salt, length, symbol/no symbol, etc) at a location of your choosing (I just store it in my Google App Engine).
Would love to get more eyes on it and get feedback (See services.js for generation logic).
Benefits of hybrid are that:
[0]: https://news.ycombinator.com/item?id=8753534[1]: http://www.alexhornung.com/code/bpasswd/
[2]: https://github.com/dannysu/hash0
[+] [-] jackjeff|11 years ago|reply
- salt. To avoid rainbow table attacks. One could use the login/email as salt
- key strengthening function. Instead of repeating naively SHA-256 a few times, use PBDKF2 or even better, something which is also memory hard like scrypt.
Finally. What happens when the password requires to have upper case, symbols, x number of digits, min or max number of characters... If you think about it, some websites have conflicting requirements.
[+] [-] stepstep|11 years ago|reply
Re key strengthening: Agreed, but only salt-less schemes will work in this stateless model. Unfortunately they are few.
> Finally. What happens when the password requires to have upper case, symbols, x number of digits, min or max number of characters... If you think about it, some websites have conflicting requirements.
Addressed this in the article: "Some websites have certain requirements on passwords, e.g., at least one number and one capital letter. A simple way to meet such requirements is to append something like A9! to the generated password (and remember you did that)."
[+] [-] desdiv|11 years ago|reply
It would be great if there was a site ran by a widely-trusted body (EFF for example) that tracks the various password requirements and limitations of websites. That way password managers, such as this one, can query that authoritative database for the idiosyncratic password rules for each domain and generate a password of the maximum allowable length and with the largest possible alphabet.
[+] [-] lqdc13|11 years ago|reply
However, it might be okay if one can provide their own hashing function. Like a JS function that takes the domain and secret key as parameters.
[+] [-] SwellJoe|11 years ago|reply
But, your suggestion of a JS function that take the domain and secret key is how the GenPass and SuperGenPass bookmarklets have worked for years (and the flaw in that method has only been fixed this year, I think).
[+] [-] kennywinker|11 years ago|reply
[+] [-] stepstep|11 years ago|reply
This is one of those "only use it if you know what you're doing" things.
[+] [-] prohor|11 years ago|reply
Firefox: https://addons.mozilla.org/pl/firefox/addon/password-hasher/
Chrome: https://chrome.google.com/webstore/detail/pawhash/adgekjfphh...
[+] [-] SwellJoe|11 years ago|reply
So, what's different about this from the SuperGenPass session Chrome plugin?
[+] [-] stepstep|11 years ago|reply
> SuperGenPass uses a one-way hash algorithm (base-64 MD5) to generate passwords. Specifically, it concatenates the master password and the domain name of the Web site (masterpassword:domain.com), hashes the result at least ten times (and until it satisfies the generated password requirements), and cuts the result to the desired length.
Yikes! MD5 is known to be broken, and 10 rounds of hashing is no defense against brute force attacks. Hashpass uses SHA-256 (not broken) and does 2^16 rounds of hashing.
[+] [-] laurent123456|11 years ago|reply
[+] [-] stepstep|11 years ago|reply
Not having a database certainly has its downsides.
Re usability: I've been using it for a couple days now, and I find it pretty tolerable. It's nice to not have to memorize a new password when I sign up for something. I did change my master key once; it took about 5 minutes to update all my passwords. If you only do that once every few months or once a year, it's not so bad.
[+] [-] MiWDesktopHack|11 years ago|reply
A <$1000 bitcoin (SHA-256) mining ASIC appliance is likely to be doing 1TH/s. Makes 2^16 rounds look kinda weak.
[+] [-] unknown|11 years ago|reply
[deleted]
[+] [-] unknown|11 years ago|reply
[deleted]
[+] [-] dchest|11 years ago|reply
[+] [-] unknown|11 years ago|reply
[deleted]
[+] [-] moe|11 years ago|reply
Do not use this, it's a textbook example of how to not do it.
[+] [-] stepstep|11 years ago|reply
This is not a new technique. In addition to the Stanford paper, there are several other implementations mentioned in these comments. It's a compromise, not a mistake. It is better to memorize one strong password than a dozen weak ones.
This isn't custom crypto. It's a well-known hash function that serves as a filter, transforming the passwords you would otherwise enter directly into a website's login form. It is no less secure than typing in passwords by hand.
[+] [-] sekasi|11 years ago|reply
[+] [-] hrvbr|11 years ago|reply
[+] [-] rnbrady|11 years ago|reply
[+] [-] dsego|11 years ago|reply