26 ms·
Salted Password Hashing – Doing it Right
- kijin 13y agoQuestion: Is there any reason to prefer bcrypt over pbkdf2, or vice versa? I can see that scrypt has an obvious advantage over both, since it is memory-intensive unlike the others. But when comparing bcrypt with pbkdf2, I can't seem to find any reason to prefer one over the other. bcrypt is everyone's darling at the moment, but why so little love for pbkdf2? PHP 5.5, for example, bundles a very convenient password_hash() function that defaults to bcrypt, whereas hash_pbkdf2(), which is also new to PHP 5.5, won't even generate a salt for you. Is pbkdf2 broken in some way, or do people simply not trust it because it's just a bunch of iterations of sha256? On the other hand, has anyone discovered a weakness in bcrypt and/or the underlying blowfish algorithm? On my computer, pbkdf2 with 20,000 rounds of sha256 takes about as much time as bcrypt with a cost factor of 10.
- TillE 13y agobcrypt has a fixed output size, which makes it less than perfect for generating encryption keys from passwords. That's the primary function of PBKDF2, while bcrypt is mostly used for simply comparing hashes. You could also feed the output of bcrypt into PBKDF2, but as far as I'm aware, nobody is recommending against straight PBKDF2/SHA256 for key derivation.
- tptacek 13y agoYes, all other things being equal, you should prefer bcrypt, which forces more effort onto attackers than PBKDF2 given similar parameters. The reality is, bcrypt, scrypt, PBKDF2: throw a dart at them and you'll be fine no matter which you hit.
- mistercow 13y agoThe long and short of it is that PBKDF2's assumptions are better vetted, but bcrypt is stronger if its assumptions are correct.
- tptacek 13y agoExactly what do you mean by this?
- mistercow 13y agoThat PBKDF2 has been more extensively studied, but it has lower memory requirements. So the chances of a surprising vulnerability being found in bcrypt are higher, but failing that, it is the better option.
- tptacek 13y agoIn what way has PBKDF2 been more extensively studied? It's the product of a standards effort, not academic research. bcrypt was introduced in a refereed Usenix paper. I'm not suggesting bcrypt is particularly rigorous either, but I'm unclear on what "study" you're referring to for PBKDF2. I'm also unclear on which "assumptions" you believed bcrypt depended. Could you be a little more specific, please?
- mistercow 13y agoI'm just going by what I've read elsewhere, and I don't have citations on hand. I'm not a security expert, I just try to listen to security experts. So if you say bcrypt is as well vetted as PBKDF2, I'm going to defer to your judgment and update accordingly.
- rdl 13y agoWhat's maybe more relevant is that PBKDF2 is explicitly called out by name as the Proper Thing in various standards, so it's less work to use it in environments where people care about those standards.
- yeukhon 13y agoThis is what I use to justify my need. http://security.stackexchange.com/a/33684/9897 http://security.stackexchange.com/a/33684/9897 As I said in another post, use adaptive hash function (bcrypt, scrypt or pbkdf2). And if you do it with limited computing power, my preference is to use PBKDF2 over bcrypt (scrypt is of course out of question).
- dspillett 13y agoDo you know where that table came from originally? I'd be interested to read a fuller report so if/when I resent those figures to anyone else I can answer any pertenant questions that come up.
- Huppie 13y agoThat table can be found in the paper "Stronger Key Derivation via Sequential Memory-Hard Functions"[0] by Colin Percival[1]. This is the paper that introduces explains and introduced scrypt. The costs are based on what was considered 'modern hardware' in 2009. [0]: https://www.tarsnap.com/scrypt/scrypt.pdf https://www.tarsnap.com/scrypt/scrypt.pdf [1]: https://news.ycombinator.com/user?id=cperciva https://news.ycombinator.com/user?id=cperciva
- drakaal 13y agoThis isn't "Doing it right". A. Your Salt should ALWAYS include a feature you have to store anyway about the user that would be unique to your service. Use multiple if you need to. This applies no matter what Hash mechanism you use. Also include a calculated value that isn't stored. Example: UserName + PassWord + User ID + CreationDate + <Numerals from a Base64 encode of the users first and last name> Don't put all of this in the same database, so that a Data Breach won't give an attacker all the data they need. No Rainbows for that combination. If a user changes their user name update their hash. This is why in good services you have to provide your password when changing your username even when you are logged in. B. To Validate the User Name: Step 1 is always "Check that the password meets your password Criteria. If you have a requirement that passwords are 6-24 characters, contain 1 upper, one lower, and one digit, then make sure the password has those before you do anything else. No database lookups for bad passwords. No running bcrypt on a 4 megabyte section of post data. This is how you keep Denial of service attacks from crushing your service. C. MD5 and Sha1 are only bad because there are rainbows for them, and because you can calculate every possible combination of values for a user/pass quickly if you know a single user/pass in the system you can calculate the salt methodology if you have access to the source code as well. I won't tell you to use either of these, but if you lose your source code, and two databases worth of data so they have user, pass, and user data, you did something else horribly wrong, or it was an inside job and nothing would have saved you. (bcrypt is expensive if you have millions of users a day logging in and not any more secure if you did the other things above.)
- sk5t 13y agoIMHO this is all unsound advice. No sane system follows the "store the data in multiple places" design; you'd need to pull it all back together to validate the password anyway, and a breach is extremely likely to compromise a system that can do exactly that. Similarly, creating a salt from a calculation rather than, say, taking 128 random bits, is not going to help, nor is depending on the secrecy of the source code ever a prudent choice. It will certainly produce less entropy than the latter, will not produce a different salt across password changes, and is just very, very hacky.
- 13y ago
- squigs25 13y agoIt's always shocking to me how many people just assume that a login/password system should store everything in plain text. This was a pretty good explanation of the right way to hash. One problem though with this guide, some experts think it makes sense to add some extra computation to make it a little bit more difficult to compute the hash, for example creating a hash loop which rehashes 10,000 times or something similar. In the past, I've found the following php tutorial really well written, and comprehensive: http://forums.devshed.com/php-faqs-and-stickies-167/how-to-program-a-basic-but-secure-login-system-using-891201.html http://forums.devshed.com/php-faqs-and-stickies-167/how-to-p...
- Kenji 13y agoI remember the incident when the League of Legends server got hacked and the attackers got all the passwords in plaintext. After that my google account almost got hijacked because I reused passwords - lesson learned :D (To be honest, I didn't expect one of the largest online games to have such incompetent programmers) This guide is a must for everyone who handles user passwords.
- hcarvalhoalves 13y agoThat has happened to me as well, when Dropbox leaked passwords (they claimed only emails leaked... bullshit). I reseted the Dropbox password right away, but someone had access to my Steam account with the same password and purchased a game. I was able to get a refund, but my password probably got into some forum, every other week or so someone attempts to login into my Steam account (Steam now requires a token sent by email to login from a different computer). Lesson learned, never reuse passwords.
- balls187 13y agoThat's what key derivation functions, and hashing algorithms like bcrypt do, they have a #rounds, or a cost factor which adds a non-trivial amount of computation time. Fast enough that it doesn't impact "human time" but slow enough that "computer time" is impacted.
- wprl 13y agoPassword hashing with salt was one of the things I first implemented when switching to Node.js 3 years ago. It's an essential part of local password storage.
- Spittie 13y agoQuestion: that article suggest to hash passwords client side too. This has any security advantages? The only one that I can think of is that an eventual MITM can't sniff your password, and then try to reuse it with other sites (as he only has an hash specific for a site, and not your password). Is that all? "If you are worried about the computational burden, but still want to use key stretching in a web application, consider running the key stretching algorithm in the user's browser with JavaScript." make it sounds like I can use a lighter hash-solution server-side if I use key stretching client-side (at least to me, non native here so probably I'm just reading that wrong).
- san86 13y agoIMO Hashing on the client side is a terrible idea. There is now no way for the application to check the complexity of the password on the server side. Relying on client side controls to do the same is almost useless.
- thirsteh 13y agoWhy do you think it's useless? Not transmitting the password in plain text is clearly a win, and you can do whatever checks you need on the client side just as easily. (If a user wants to fool whatever checks you have, they can do that whether or not you have server-side checks--it happens all the time.)
- Xylakant 13y agoIt's fairly useless: If an attacker can sniff your connection he can just submit the encrypted password he sniffed to the server. The only win you have is that the attacker can't see the password itself, a potential bonus when people reuse passwords. However, if you can sniff the connection you can probably alter it and inject javascript that submits the clear-text password to the attacker.
- thirsteh 13y agoWe are just talking about scrambling the password. You would still be using e.g. SSL/TLS or TLS-SRP for the transport. There's nothing "useless" about it.
- ancarda 13y ago>Always display a generic message like "Invalid username or password." This prevents attackers from enumerating valid usernames without knowing their passwords. If you have a password recovery page, couldn't attackers use that to test usernames?
- axaxs 13y agoNot really. If you mean actual password recovery, then I'd consider the site broken anyhow. If you mean password reset - any site worth its salt in security displays the same message regardless. Usually something like "If the account was found, an email will be sent shortly." I ran into one recently that simply said "An email has been sent" regardless of what was entered, which threw me off a bit as I was entering the wrong email address for that site and wondering why I wasn't getting their email....
- gibybo 13y agoHow about a registration page instead? Are you going to not tell the user whether the registration worked or not? I've never seen a site that does that. I've seen tons of sites that tell you "invalid username or password" but will happily tell you if the username is registered if you try to register it. It adds no security and just inconveniences users.
- fabulist 13y agoRespectfully, just because hackers can drive a truck through your app doesn't mean they should get to fly a plane, too. Its also easier for your users if you put a CAPTCHA in you registration form rather than your login form. This can mitigate large-scale fishing for usernames. Granted, that hacker who is going after a single poor soul who uses your service won't even feel the speedbump. But s/he is the toughest adversary, and the least common.
- HeyImAlex 13y agoOr just trying to register an account? Are you just going to say "that registration may or may not have worked, check your email". I think you should just accept that usernames are public unless your specific instance really needs to hide them.
- M4v3R 13y agoSRP [1] is a very nice alternative for storing password hashes in the database. As an added bonus, it prevents MITM attacks which steal user passwords before they reach your servers. Meteor [2] JS framework successfully uses SRP for authentication. [1] http://srp.stanford.edu http://srp.stanford.edu [2] http://docs.meteor.com/#meteor_loginwithpassword http://docs.meteor.com/#meteor_loginwithpassword
- tptacek 13y agoBrowsers don't support SRP, which means that if you want to use it, you'll need to deliver it via Javascript. SRP is particularly tricky to get right; a substantial fraction of the SRP implementations we've looked at have bugs that cough up authentication bypass. SRP verifiers are easier to crack than bcrypt hashes (though harder than trivial salted hashes). And finally, it's not much of a win; you get the same or better protections simply by running your login over HTTPS.
- zAy0LfpBZLC8mAC 13y agoWould you mind expanding on that a bit? I mean, what kind of authenticsation bypasses you found? I am using SRP (for non-web stuff) and it would be good to know/to check whether I am affected by those problems.
- rikacomet 13y agoNo Perl example? Sob :(
- pjscott 13y agoDry your tears! A Perl example can be found in the synopsis of this fine POD file: http://search.cpan.org/~gray/Crypt-Scrypt-0.05/lib/Crypt/Scrypt.pm http://search.cpan.org/~gray/Crypt-Scrypt-0.05/lib/Crypt/Scr...
- djao 13y agoThe part about having to use HMAC for keyed hashing is (hopefully) going to be obsolete soon. SHA-3 is explicitly designed to be safe under the H(key+message) usage.
- kellros 13y agoPretty good article, I especially like the idea behind doing linear time comparison using XOR. Although, the XOR comparison implementation seems flawed as it will only compare min(supplied password length, existing password length); which would allow the attacker to identify the existing password length by providing a sufficiently long password. Instead the existing password should be padded to the length of the supplied password in order to hide the length of the existing password. My issue with the XOR comparison implementation is irrelevant as password hashing should use stretching (ex. PBKDF2, BCrypt, SCrypt) which means the hash of the supplied password and that of the existing password would be the same length. The implementation of the PBKDF2 is also flawed. Iterations: The recommended PBKDF2 iterations has long surpassed 10,000 (it's closer to 100,00 now). See here: http://security.stackexchange.com/questions/3959/recommended-of-iterations-when-using-pkbdf2-sha256 http://security.stackexchange.com/questions/3959/recommended... The rule of them is that given a sufficient length salt, the number of iterations should take about 8ms on the hardware it is running on. Salt Size: The recommended salt size is 128-bits/16 bytes (not 24). See here: http://security.stackexchange.com/questions/17994/with-pbkdf2-what-is-an-optimal-hash-size-in-bytes-what-about-the-size-of-the-s http://security.stackexchange.com/questions/17994/with-pbkdf... That stackexchange question also recommends using SHA512 as it requires 64-bit arithmetic operations which GPU's are supposidly not great at. I believe I read stackoverflow and most big websites store about 24 bytes of the hash. The salt is generally prefixed to the hash and that is stored (ex. salt size 16 bytes + password hash 24 bytes = 40 bytes). If I wanted to version a stored password, I'd simply use the first byte as an indexer to select a password hashing function instead of prefixing the hash with the number of iterations which seems non-portable. Even if you do everything right concerning the hashing of passwords, account security extends beyond passwords - such as alternative methods of authenticating (forgot password, secret questions, authentication tokens). OWASP is a great authority in regards to this: https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet
- tptacek 13y agoConstant-time comparisons of password hashes are a regular feature of password hashing discussions, mostly because timing attacks are one of the few crypto attacks that developers can get their heads around immediately. But they're practically irrelevant to password hashing†. It does not matter if you use a constant time comparison for your password hashes; to see why, try to design the actual timing attack on the password hash compare (if you've never done this before, start by demonstrating to yourself that you can design a timing attack against an HMAC comparison). The OWASP site's password storage guidance is particularly bad, and I recommend that developers avoid that page altogether. The page began as a litany of very bad advice (reversible encryption, salted hashes), and when it was pointed out that secure password hashes like scrypt were the right answer, the authors decided instead to "teach the controversy". OWASP is very political, and not managed by computer scientists. † The post we're commenting on inaccurately says that the hypothetical timing attack it describes has been done before, but links to Boneh's TLS timing attack paper. My guess is that the password hash attack the author was considering has never been tried; among other things, it stipulates a password hash oracle for the attacker.
- atmosx 13y agoNice reading, bookmarked.
- stephen_g 13y agoThat's a lot of code in the PHP example! To use bcrypt you can just do this: password_hash($password, PASSWORD_BCRYPT) From version 5.5 that is, but you can get a compatibility library for older versions.
- jamesmoss 13y agoThis is bang on. PHP devs need to stop rolling their own hashing methods. The compatibility library to use for PHP <5.5 is Antony Ferrara's password_compat: https://github.com/ircmaxell/password_compat https://github.com/ircmaxell/password_compat.
- RyanZAG 13y agoAgree - same applies for the other languages at the bottom of the page. He should remove those code samples and just link to the bcrypt function/library for each language.
- junto 13y agoDisagree. Windows .net devs shouldn't use Bcrypt. The .net bcrypt port hasn't been verified for .net, so they should be using pbkdf2 instead, as per the article. The most recent version of the ASP.net Membership provider offers this hashing algorithm as a built in option. http://stackoverflow.com/questions/481160/is-bcrypt-a-good-hashing-algorithm-to-use-in-c-where-can-i-find-it/4435888#4435888 http://stackoverflow.com/questions/481160/is-bcrypt-a-good-h...
- selimthegrim 13y agoI assume this is that .NET library function Rfc2898DeriveBytes?
- cmircea 13y agoHas the BCrypt code for all other languages been formally verified?
- roryokane 13y ago
- LukeB_UK 13y agoSeems to be down, here's the google cached version: http://webcache.googleusercontent.com/search?q=cache:S76Yg0P_ArEJ:https://crackstation.net/hashing-security.htm+&cd=1&hl=en&ct=clnk&gl=uk&client=ms-android-google http://webcache.googleusercontent.com/search?q=cache:S76Yg0P...
- leotsem 13y ago...or you can consider going password-less: https://news.ycombinator.com/item?id=7283650 https://news.ycombinator.com/item?id=7283650
- fundon 13y agoNode.js password hash module, node version >= 0.11.11. https://github.com/fundon/pbkdf2 https://github.com/fundon/pbkdf2
- JoshGlazebrook 13y agoNot many people are going to be running the unstable branch of node in production.
- pixelcort 13y agoHow is this better than the built-in pbkdf2 in node? http://nodejs.org/api/crypto.html#crypto_crypto_pbkdf2_password_salt_iterations_keylen_callback http://nodejs.org/api/crypto.html#crypto_crypto_pbkdf2_passw...
- fundon 13y agoNode.js stable version(0.10.x) can not change algorithm. http://nodejs.org/api/crypto.html#crypto_crypto_pbkdf2_password_salt_iterations_keylen_callback http://nodejs.org/api/crypto.html#crypto_crypto_pbkdf2_passw...
- ishener 13y agosite down. yet again a static html file is served from a private server.
- nopar8 13y agoExcuse my ignorance, can you please elaborate. What's the alternative?
- borplk 13y agoHe is probably suggesting that it should be served from large CDNs so it wont go down
- PavlovsCat 13y agohn could do that on behalf of the sites it links: http://www.coralcdn.org http://www.coralcdn.org
- yeukhon 13y agoWhich cryptographically strong hashing algorithm to use? It depends on situation. I think adaptive one ( PBKDF2, bcrypt, and scrypt) should be used all the time. PBKDF2 if you want to hash on devices with limited computing power, bcrypt and scrypt on standard servers. Other one like SHA256, SHA512 are supposedly for fast, cryptographically strong hashing. At least that's how I view it. > If you have special security needs, enforce a minimum length of 12 characters and require at least two letters, two digits, and two symbols. I hate when passwords require certain patterns. See http://i.imgur.com/hvyziAx.png http://i.imgur.com/hvyziAx.png from USCIS. And I think there is one point missing: limit the max number of characters for the password. As shown in Django's password DoDS attack, don't allow long password takes up 1MB.
- huxley 13y agoDjango reverted the password limit change: "In Django 1.5.5, we’ve reverted this change and instead improved the speed of our PBKDF2 algorithm by not rehashing the key on every iteration." Incidentally Bcrypt does have a 56 byte limit which I understood to be a Blowfish limitation (you can use longer bcrypt passwords by doing a SHA256 pass first) edit: typo
- borando 13y agoIncidentally Bcrypt does have a 56 byte limit This is incorrect; bcrypt has a 72-character limit. Try this in python: import bcrypt, sys salt = "$2a$10$2TmO7iAhRfimvNwvpBn.7e" print bcrypt.hashpw(sys.argv[1], salt) Nearly identical 56 and 57-char inputs produce different hashes: $ python pass.py 12345678901234567890123456789012345678901234567890123456 $2a$10$2TmO7iAhRfimvNwvpBn.7e701F3mp2Z7fpuY/4lu6vUUkrlMEmMou $ python pass.py 123456789012345678901234567890123456789012345678901234567 $2a$10$2TmO7iAhRfimvNwvpBn.7ejJV9jpN0Ahp2RmNAdUGaRxRZndRAs9y Nearly identical 72 and 73-char inputs produce identical hashes: $ python pass.py 123456789012345678901234567890123456789012345678901234567890123456789012 $2a$10$2TmO7iAhRfimvNwvpBn.7e9w2f6/fKQ2QBu1eaIXp4A1WheruxtGK $ python pass.py 1234567890123456789012345678901234567890123456789012345678901234567890123 $2a$10$2TmO7iAhRfimvNwvpBn.7e9w2f6/fKQ2QBu1eaIXp4A1WheruxtGK you can use longer bcrypt passwords by doing a SHA256 pass True, but: Beware! Imagine you're doing bcrypt in C, and the first sha256 output byte is a 0-byte. bcrypt() sees the NUL / empty password and produces a hash trivially breakable by anyone aware of this issue. :-) So I'd recommend doing Base64 on the sha256 hash, if you're using C and you want such long passwords with bcrypt. But plain bcrypt will give the best results. Hopefully the above illustrates the general wisdom of avoiding DIY crypto of any kind. edit: code formatting
- chrisfarms 13y agoJust had a quick port of his example to Go. https://bitbucket.org/pkg/passwd/src/27f970fbcc05c0c6c2586000dd083f606bd0a9e2?at=master https://bitbucket.org/pkg/passwd/src/27f970fbcc05c0c6c258600... Anyone fancy taking a look to see if I understood correctly? EDIT: Specifically, should the PBKDF2 "key", not be used for something (like HMAC) rather than being used as the hash itself?
- Jabbles 13y agoUse bcrypt. http://godoc.org/code.google.com/p/go.crypto/bcrypt http://godoc.org/code.google.com/p/go.crypto/bcrypt
- sillysaurus3 13y ago1,000 rounds of PBKDF2 is less secure than just using scrypt, and probably less secure than just using bcrypt. But the code looks correct as written. It seems like a red flag that it took more than 50 lines of code to do this simple thing, though. EDIT: Specifically, should the PBKDF2 "key", not be used for something (like HMAC) rather than being used as the hash itself? Using the output of 1,000 rounds of PBKDF2 as an input to HMAC wouldn't get you any extra security.
- elithrar 13y agoAlternatively, Go's bcrypt implementation has a very simple API: hash, err := bcrypt.GenerateFromPassword([]byte(password), 10) err := CompareHashAndPassword(hash, []byte(password)) There's also a Cost(hash) function that you can leverage to re-hash passwords with a higher cost.
- deleted 13y ago[deleted]
- bradleyjg 13y agoThe java version instantiates a new SecureRandom instance every time it creates a new salt. While I don't think this hurts the randomness of the salt, it's an unnecessary performance hit.
- Ironlink 13y agoAs far as I know, that behavior is best practice. An instance of SecureRandom does not automatically receive new entropy over time. If you desperately need to keep using that same instance, you have to keep seeding it.
- bradleyjg 13y agoYou can use a SecureRandom implementation that uses the underlying entropy pool for every call, or you can use an ordinary implementation of SecureRandom and call getSeed(numBits) instead of next(numBits), or as you mentioned, you can call random.setSeed(random.getSeed(NUM_BITS) every once in a while. Finally, if you are on linux the default SecureRandom provider will mix urandom with the prng output on every call to nextBytes, so there's no need to reseed at all. Anyway you look at it, there's no good reason to instantiate use a fresh SecureRandom instance every call.
- fabulist 13y agoAs this is a tutorial, the snippet will likely be copy-pasted into production code running on God knows what OS by someone who can't imagine why there could be a problem with seeding from the system clock. Using a fresh instance allows the code to be portable, noob-friendly, and concise, which are important traits for its context.
- Gonzih 13y agoI have question. Is salting solution like hash_function(salt_hardcoded_in_app + password_string + user_unique_salt) bad? Does adding hardcoded salt reduces security of app? Why? Thanks for any info on that.
- deleted 13y ago[deleted]
- drakaal 13y agoI just added a comment basically saying the same thing. But you should use data that you would have that an attacker would not. First and Last Name as stored in your system, User ID (like 128912) and User Creation date are good choices. These should be in a separate database from the hashes.
- rolux 13y ago> But you should use data that you would have that an attacker would not. First and Last Name as stored in your system, User ID (like 128912) and User Creation date are good choices. These two statements contradict each other.
- rdl 13y agoMaking the password comparison depend subtly on other fields seems like a bad idea from a maintainability perspective. Lots of reasons to update name, etc., which might not happen anywhere near the password code, and might be done automatically.
- drakaal 13y agoIf the fact that a field might change some where else in your code is a "maintainability" issue, you have bigger issues and shouldn't be doing anything with passwords. Private User Data should not be changed by many things. That is "PRIVATE" and therefore should be under tighter control than the rest of your data.
- 13y ago
- mastermindxxx 13y agonice article. password hashing - doing it right && cracking it right http://www.linuxx.eu/2014/01/how-to-hash-and-crack-unix-passwords-in.html http://www.linuxx.eu/2014/01/how-to-hash-and-crack-unix-pass...
- rlpb 13y agoThis article looks great for anybody who wants to know the details. But "doing it right" is much simpler, and doesn't really need an article: "Use an accepted key derivation function, such as PBKDF2, bcrypt or scrypt". All the work described is encapsulated into the concept of a key derivation function. Telling people to go into the details is like telling people how to do encryption by describing how to implement AES and Twofish. Don't go there. Find a library that implements a key derivation function, and use it. PBKDF2, bcrypt and scrypt are all fine.
- thirsteh 13y agoYou might want to add "with a high number of iterations or work factor," at least. PBKDF2-HMAC-SHA-256 is just as useless as 2xSHA-256 if you just do one iteration.
- rlpb 13y agoYes - this is reasonable. I'd generalise this to: "Use an accepted key derivation function, such as PBKDF2, bcrypt or scrypt, with accepted parameters". What is "accepted" changes over time, of course.
- anonymoushn 13y agoIndeed. This article is much longer than the docs for some bcrypt library in $LANGUAGE.
- anaphor 13y agoThere is some use in this article though, because it gives some good examples of terrible crypto. Oddly enough the "combine different hash functions!" meme isn't just limited to amateurs: "An Secure Hash Algorithim (SHA) hash of the received challenge string, the peer challenge string, the session identifier, and the MD4-hashed version of the user's password." http://technet.microsoft.com/en-us/library/cc957983.aspx http://technet.microsoft.com/en-us/library/cc957983.aspx
- kibibu 13y ago
- sopooneo 13y agoIf an attacker already has access to your user's table (as is implied by most of the situations in this article), then they probably have your whole database. What else is there to lose? Why would an attacker bother to use any method to match passwords to hashes? Don't they already have everything they could want?
- Kenji 13y agoNo, they do not. Maybe an important person's password hash gets leaked and they want to extract the password to check other sites for reuse to get into other systems. Now you say reuse is dumb, and I agree, yet a lot of people do it because they're lazy. This is just an additional stepping stone to make a malicious hacker's life harder.
- gamblor956 13y agoThey have everything they could want from your site, but presumably your site isn't a financial institution. The goal of most hackers is to crack relatively insecure or low-value databases in order to leverage the results for hacking user accounts in better-protected or higher-value databases.
- kumar303 13y agoThere are many things wrong with this article. You can't hash secrets like this because hash functions are iterative. You should be using HMAC. Here's a good explanation http://benlog.com/2008/06/19/dont-hash-secrets/ http://benlog.com/2008/06/19/dont-hash-secrets/
- Xylakant 13y agoThe article you're referencing speaks about extension attacks. The attack allows you to extend a plaintext and calculate the appropriate hash if you know the original hash and the last parts of the original plaintext. These properties do not apply to password. You could extend the original password and calculate the appropriate hash in theory, but that doesn't help the attacker since the password hash is known and in the database. As a matter of fact, the article you reference even says so: " “Don’t Hash Secrets” is not always entirely necessary. In the password example, you can hash a password as long as you salt it correctly". Using a HMAC may be useful since you can add an extra secret that's only known to a separate server or a HSM. The original article describes that in the section titled "Impossible-to-crack Hashes: Keyed Hashes and Password Hashing Hardware".
- jchendy 13y agoFor anybody who doesn't need this much detail, there's a great intro to this topic in the Web Dev course on Udacity: https://www.udacity.com/course/viewer#!/c-cs253/l-48666069/m-48673622 https://www.udacity.com/course/viewer#!/c-cs253/l-48666069/m...
- techdfuture 13y agoThis is just awesome article, I have been using MD5 encryption in all my web applications, but never thought of having salted password hashing
- jmnicolas 13y agoThis is a great article though I knew most of what is said. I'd like to find the same thing for encrypting all the data of users in a DB.
- Myrmornis 13y agoVery helpful and well written article.