9 ms·
Handmade Rails Authentication
- tptacek 16y agoauto_hash is an inferior password hash; use bcrypt or scrypt instead.
- KevinMS 16y agoI don't really understand your phrasing, "auto_hash is an inferior password hash", its a rails plugin that uses SHA2 (256). If you mean "auto_hash" uses an inferior password hash, could somebody please point me to some info on why it shouldn't be a good enough option for almost all websites? I really don't want to go imposing an obscure hashing algorithm on users of the plugin, especially with hashing algorithms that deliberately impose a speed penalty for extra security. I'm not interesting in changing the world of password hashing with my trivial rails plugin by using anything other than the most secure of the common hashing algorithms, SHA2. I'm also under the impression that SHA2 is now the most widely recommended security hash.
- tptacek 16y agoThere's no such thing as a "security hash". You mean to say "secure hash function". The term "security" refers to the integrity of the hash itself; SHA256 is "secure" against attempts to cause collisions (and several other attacks). None of that has anything to do with the security that SHA256 provides to your application. SHA256 knows how to take care of itself. It doesn't know a damn thing about passwords. SHA256 isn't a secure password hash. You already know that, because you're not just using SHA256; you're also adding a random salt to it. That's because if you didn't do that, attackers could just aim a precomputed dictionary at your database rows and smite it. So your hash isn't SHA256; it's a construction called "salted SHA256" (or "SHA256 with a nonce"). Nonced SHA256 still sucks, though, because SHA256 is lightning fast. Attackers can't throw precomputed dictionaries at your password hash, because you randomized them. But they can take each hash in turn and run a large dictionary against each hash. This is a brute force attack, but it's not a brute force against the 256 bits of the hash; it's an attack against the (low) entropy of the passwords themselves. This is how all password cracking got done in the '90s, which was a bit of a golden age for password cracking. It's how John the Ripper (the most famous password cracker) works. John the Ripper is extraordinarily fast against Unix password hashes, which are slower (by a lot) than SHA256. Incremental crackers tear through naked SHA256 hashes like a knife through butter. That you don't know any of this --- and I say this respectfully --- tells me that maybe you should be using someone else's password hashing library instead of reinventing your own. But you're welcome anyways for the quick and dirty lesson in password hashing.
- generalk 16y agoThe deal with bcrypt is that you can increase the number of work units, so that bcrypt gets slower and slower as you like. That defeats the ability to very quickly iterate over a dictionary, because it simply takes too long to do effectively. (Please correct any of this if I'm wrong. IANACryptographer.)
- seiji 16y agoShort version (you almost got around to it, but didn't explicitly state it :)) -- Don't use straight hash functions because they are made to be fast. Even if you salt/nonce them, you can generate private rainbow tables quickly. Use a password hiding method that's slow to compute (slow being "this operation isn't implemented in hardware or optimized assembly") which is what bcrypt or scrypt provides. Differences in speed/effort are mentioned at http://www.tarsnap.com/scrypt.html http://www.tarsnap.com/scrypt.html -- scrypt enc is approximately 100 billion times more than the cost of cracking the same password on a file encrypted by openssl enc
- lonestar 16y agoActually, slow in this case does not at all mean "this operation isn't implemented in hardware or optimized assembly". The slowness of an algorithm like bcrypt is a tunable property of the key expansion algorithm. A step in this process will be repeated 2^n times, where n can be configured by the user. If a password function was only slow because it wasn't implemented in assembly on your server, an attacker would obviously just go implement it in assembly for his brute-force crack.
- tptacek 16y agoActually, the major contribution in Colin's scrypt work is to find primitives that don't admit as well to hardware acceleration; his hypothesis is that one of bcrypt's weaknesses is that even though it's very slow in software, it might be possible to massively accelerate it with FPGAs.
- KevinMS 16y agoYou sure are reading a lot into what I said, and coming off as pretty arrogant trying to correct me. So because I haven't yet offered other hashing algorithm options yet, since this plugin is about a week old and nobody has used it, and nobody has requested options, I have no right to be offering this solution for public use and scrutiny? Looks like authlogic uses sha512 by default and clearance and devise use SHA1 by default. If these are their defaults, as you would say, I say this respectfully, maybe those guys should be using somebody else's password hashing library. Also, could I not continue using SHA2 256, and add an option to specify the number of hashing repetitions, which would increase the time to compute, as well as frustrate dictionary attacks?
- hopeless 16y agoPersonally, I feel authentication is one area where it's best to have "many eyes". Sure, rolling your own is easy enough but have you really thought of every edge case, every security exploit? It is also one area where most applications are extremely similar and there's (not usually) any business advantage gained by rolling your own. Still, always good to see how others approach authentication code (personally, I use Clearance).
- ichverstehe 16y agoThis is one of my pet peeves. I can implement some basic authentication in something like 25 lines of code. AuthLogic: 2500 LOC. Devise: 2200 LOC. Clearance: 690. And yet, both times I tried to use AuthLogic, it actually didn't work for my case–login and password in different tables–without some weird hacks, at least not back then. My own custom authentication code can do that by simply modifying an existing LOC, and I know what is going on. There's no way I am going to ever feel comfortable with e.g. AuthLogic's code, simple because I can't justify spending time getting comfortable with it, when I can write it myself in 15 minutes. It's the same issue I have with RSpec, actually. Too much code.
- tptacek 16y agoI actually kind of agree. Rails Auth isn't a hard problem. As long as you're not rolling your own password hash and you're not rolling your own session store, I'm comfortable saying "authentication code in Rails is just glue; do the simplest thing that can work". Now, authorization is a radically different story; unfortunately, though, there's no good Rails solution for getting "off-the-shelf" access control and permissioning, so you may be kind of stuck anyways. (Pet peeve of mine? Mixing up authorization and authentication.)
- epochwolf 16y ago> (Pet peeve of mine? Mixing up authorization and authentication.) For anyone that's confused: Authentication: Is the user who they are they are? Authorization: Is the user allowed to do this?
- pkulak 16y agoWhat, no salt?
- KevinMS 16y agoIts one of the things that is the "auto" in "auto_hash".