I'm not really up to date with the most recent developments regarding hashing algorithms strengths; what is currently my best bet for storing passwords?
Also, how much more security do salting and key stretching offer me?
MD5 has been broken.
SHA-1 has significant weaknesses.
SHA-2 is considered adequate at the moment.
SHA-3 will shortly become a FIPS standard.
Best practice is to combine password hashing with random salting and key stretching, e.g. PBKDF2.
A good discussion on password salting, hashing, and stretching.
My implementation of password salting, hashing, and stretching in C#.
As for the extra security provided by hashing, that depends on how many hash iterations you use. As an example, say that you decide to use 2^14 hash iterations. This increases the password's entropy by 14 bits. According to Moore's Law, each extra bit of entropy provided by the hash means approximately 18 extra months to crack the password in the same time as today. So it will be 21 years (14 x 18 months) before the iterated hash can be cracked in the same time as the raw password can be cracked today.
The extra security provided by salting is twofold: it prevents the effective use of a rainbow table, and it makes it more time-consuming to crack a large list of passwords (but not a single password).
Check out this.
This question over at security.stackexchange is a good discussion of bcrypt vs. PBKDF2 - Do any security experts recommend bcrypt for password storage?
The key is that a hash function alone will not prevent a precomputation attack (e.g. rainbow table). And adding a salt won't protect you from a dictionary or a brute force attack. You are much better using bcrypt or PBKDF2 than building your own scheme with a hash algorithm.
Related
I would like to know which method to use to store passwords in database. I have implemented it using MD5 but according to some posts SHA1 is more secure. Is there any other method which is more secure?
Please help me finding out a best method to secure passwords.
Sure SHA1 is more secure that MD5, but for most purposes it is not secure enough.
You will probably find useful the video How NOT to Store Passwords by Computerphile - 9 minutes and 24 seconds long.
You must realize that there is much to cover when it comes to authentication and access control, so having a good hashing scheme is not enough.
On storing passwords.
As you already know, you don't store the password. In fact, when it comes to storing passwords, in general terms you want to store salted hashes of the passwords, using a modern algorithm optimized for this purpose. For the salt it is considered ok to store it alongside to the hash, for the salt value use a random value as long as possible.
Note: When generating random value for security purposes, use a cryptographic secure generator (such as a subclass of RandomNumberGenerator for .NET - example). This random number generator are designed to be hard to predict. While standard random number generator are meant to be repeatable (That is with System.Random all you need is the seed to generate all the values, and to guess the seed all you need is enough consecutive values generated with the same seed).
Also note: Most hashes are optimized to be fast to calculate, in that category falls both MD5 and SHA1. You should choose one that is not that fast, so that the attack will take a reasonable amount of time to compute the hashes when trying to crack your passwords.
One such algorithm is BCrypt - others include Scrypt and PBKDF2 - on using BCrypt from C# you will find the article Use BCrypt to Hash Your Passwords: Example for C# and SQL Server useful. If you can't resource to BCrypt or similar algorithm, you should atleast use a variant of SHA2 (SHA256, SHA512 and so on).
Addendum: You can use the class HMACSHA256 which is available in the BLC as a key derivation function, pass your salt as key. This is preferible to appending or prepending the salt (which could fall to Length extension attacks). That is, if you use HMAC, and your hash algorithm is vulerable to Length extension attacks (known or to be discovered), your system is till secure. MD5, SHA1 and SHA2 as suceptible to this kind of attack. SHA3 is not. Sadly SHA3 is not included in the BLC (no, it is not SHA384), you can get it from Multiformats.Hash or HashLib. I have to mention that SHA3 is also designed to be fast when implemented in hardware. And remember, for passwords an slow hash is better.
Addendum: Argon2
As it was pointed a year ago this answer should be updated to mention of Argon2. I did write the original answer before that existed.
At the time, I had not found an implementation for C# that I was willing to recommend. Since this answer was brought to my attention, I had another look, and that is no longer the case.
You can use Isopoh.Cryptography.Argon2 which has fully managed code (it is not a C# binding for a C++ implementation, but full C# code), works on all major platforms and there are Nugets available.
Notes:
Use Argon2Version.Nineteen. This is Argon2 v.1.3 (Nineteen = 0x13) which fixes known vulnerabilities.
Use Argon2Type.DataDependentAddressin (Argon2d), or use Argon2Type.DataIndependentAddressing (Argon2i) with TimeCost >= 10. Argon2d is in theory vulnerable to side channel attacks, as such it is not recommended for code that runs on client machines. Isopoh.Cryptography.Argon2 mitigates this by using OS calls to prevent sensitive memory to be moved to virtual memory/pagefile/swap and zero it as soon as possible. On the other hand Argon2i has a Time-memory tradeoff vulnerability, which allows to compute the hashes faster by using more memory. The paper Towards Practical Attacks on Argon2i and Balloon Hashing shows that you need 10 iterations/passes to make the exploit inefficient, even in Argon2 v.1.3.
Here are some recommended reading:
Speed Hashing
You're Probably Storing Passwords Incorrectly
Everything you ever wanted to know about building a secure password reset feature
The definitive guide to form based website authentication
OWASP's Password Storage Cheat Sheet
OWASP's Forgot Password Cheat Sheet
Also the video: Crypto is Back! - Google Tech Talk - August 5, 2009 - 54 minutes and 32 seconds long.
On recovering a password.
First off: don't. The point of the password recovery option is not to recover the password, but to recover access to the application. So... how do you recover access to the application?
I'm glad you ask. What you need is an alternative way to verify the identity of the user. This could be a second factor authentication (anything from security question to using a hardware key generator). Yet, what is often done is to resource on third party, such as mail.
So, you want to know if the user is the owner of the email (or cellphone, or whatever) the user has previouly claim to own. In order to do so you send a code (often refered as token or cookie) to that email (or whatever). This must be a random generated code with a cryptographic secure generator so that nobody else - except the owner of that email (or whatever) - will be able to know what that code is.
Now, if the user presents to your application that code, you are almost sure it is the right user.
Almost because: emails (or whatever) could has been stored in an unsecure location. To mitigate that, you want to put a time limit on your code (cookie or token). Also, if a code has been used, it should NOT work again. And for extra security you could resource to a CAPTCHA, to ensure this code doesn't come from a bot that just got lucky.
For more on this topic (this links are also presented above):
Everything you ever wanted to know about building a secure password reset feature
OWASP's Forgot Password Cheat Sheet
SHA1 has less vulnerabilities than MD5. It's a newer algorithm that utilizes more bits and requires more processing to "crack." You can view most of the mainstream hash algorithms and their known vulnerabilities here: http://en.wikipedia.org/wiki/Cryptographic_hash_function
As someone already commented, definitely make sure you add "salt" to your password hash to further obscure any possible pattern.
We are storing hashed passwords in a database table.
We prepend each password with a random salt value and hash using MD5CryptoServiceProvider.
Is this safe? I have heard MD5 was "broken".
If not, can you recommend an alternate hash method to use (specific .NET framework class)?
The security of a hash function mainly comes from the length of its output (message digest): a longer digest gives greater collision resistance. The birthday paradox tells us that on average you'd expect to find a collision from a work function of the square root of the digest size: in other words, given a 128-bit digest, an attacker would expect to hit paydirt after 2^64 trials.
MD5 has been frowned upon by the cryptographic community for some years now because it only has a 128-bit digest, and there are also some interesting cryptanalytic results which might effectively reduce its strength. SHA1 (160 bit digest) had been the preferred alternative, but even then it is starting to look like it was not long enough for a well-motivated adversary and there are also some interesting results in the research community. The SHA-2 family (output sizes from 224 to 512 bits) are the current preferred hash functions in widespread use. There is an active research competition organised by NIST to find a successor for SHA-2, but we won't have a new standard until 2012 or so.
Now, in the specific case of storing passwords, I note you are using a salt. This is the strongly recommended practice; without a salt you would be vulnerable to a rainbow table attack. I believe that this leaves you with only the brute force attack to consider; this is where keylength.com comes in. It brings together recommendations for key and digest sizes from across the cryptographic community and gives expected security timescales for various algorithms, considering current computing power and taking Moore's Law into account. Consider what sort of assets you are protecting and how long you need to a password to remain secure for (do you have an enforced password change policy, for example?) and that should pretty much answer the question of the digest size you need.
Of course, the best password storage in the world won't help you if your users use easy-to-guess passwords. Do you provide your users with tips for strong passwords? Have you considered a password strength meter or similar?
I think SHA256, SHA512 are more safe at this moment :)
See wiki
No, you shouldn't be using MD5. But you shouldn't be using a single round of any general purpose hash function, no matter how cryptographically secure it is, either! Not MD5, not SHA-1, not SHA-2, not SHA-3.
Why? Because general purpose hash functions are designed to be fast. And fast is exactly what you don't want in a password hash. Fast means that when the bad guys get your database, they can run a plain old dictionary attack against it in a reasonable amount of time.
What you need is slow. The simplest way to be slow is to iterate the fast hash function thousands of times - that's what the MD5 and SHA-1 based password scheme used to store passwords on UNIX-like systems do (it's not just one round of MD5 or SHA-1). Another way is to use a cryptographic primitive that is designed to be slow - that's what the "bcrypt" password scheme does.
This Matasano article, What You Need To Know About Secure Password Schemes, has some good reading on exactly this subject.
With a salt MD5 is much more secure than without, but you're better off using one of the SHA hashes such as SHA256Managed.
Storing hashed password is better since it hides the password from prying eyes of DBA's.
Also, yes, MD5 was broken, but is still used to this day. If you are concerned about MD5, rather use SHA-1 (MSDN link here). It's a hashing algorithm just like MD5 but stronger. You can have SHA-1 hashing of up to 512 bits.
Here's an example done on VB.NET (http://www.obviex.com/samples/hash.aspx).
Here's the US Department of Homeland Security stating why people should move away from MD5 (http://www.kb.cert.org/vuls/id/836068). Summary, it's "cryptograpically broken"
I'm working on an application and I need to store the users password, so I'm thinking I'll store it in the current-user class of the registry, but I also want to hash it for the obvious reason, and I've seen news items that state that SHA1 has been cracked, is there a better (uncracked) hashing algorithm available in the "standard" system or .net?
SHA1 is not encryption, it's a cryptographic hash function. And yes it has been broken, which means it's possible to generate collisions faster than a brute force method. The SHA2 family has not been broken.
But I would advise to use a custom seed per entry so that a rainbow table could not be used for trying out passwords. If you're using the SQL Membership provider the password format "Hashed" already uses a different seed for each user.
More information about seeding your hash can be found in the article What You Need To Know About Secure Password Schemes by Thomas Ptacek.
As you say in your comment, SHA1 is a hash algorithm, not encryption. It is a one-way function that, even if it is broken, does not allow the password to be retrieved.
If you want stronger hash functions that are already in .NET, look at the SHA2 family - SHA256, SHA384, SHA512. (SHA224 also exists, but isn't implemented in the System.Security.Cryptography namespace.)
The collision attacks on SHA1 are not practically exploitable yet, but you are right to be looking ahead. NIST is currently running a selection process for SHA3 in the light of these attacks, but this is a few years from completion and commercial acceptance. SHA2 on the other hand is an existing family of algorithms that are standardised by NIST and are not subject to the attacks that have been successful against MD5 and SHA1.
What you need to do is salt your passwords. Here is some actual sample code in C# that uses SHA1 and salting.
The problem with SHA1 "being cracked" is all basic possible combinations have been pre-calculated, however salting makes your password nonbasic (it is still vulnerable to a brute force if it is weak or easily guessable but it kills rainbow tables)
Hash algorithms have been showing some signs of weakness as of late, which is why NIST has offered up a hashing contest much like they had an encryption contest which crowned Rijndael as the new AES.
I personally like what MD6 has to offer, as it is being spearheaded by Ron Rivest, who has been in the cryptography space for over three decades. MD6 has been withdrawn, so I suggest some of the stronger candidates in Round 2 in my humble opinion are Keccak, Blue Midnight Wish, and Fugue.
From there, definitely use good practices such as salting.
Yes you can use SHA512, just remember how long the actual hash is. You can always add extra security by salting the hash results as well.
SHA512("The quick brown fox jumps over the lazy dog") =
07e547d9 586f6a73 f73fbac0 435ed769 51218fb7 d0c8d788 a309d785 436bbb64
2e93a252 a954f239 12547d1e 8a3b5ed6 e1bfd709 7821233f a0538f3d b854fee6
If you want to look into other Hashing algorythms, here's a short list.
5 days too late but you could try this highly secure encryption function:
uint64_t highly_secure_encrypt(char* password) {
sleep(1);
return 0;
}
No way you're getting the passwords back from that.
Now, onto serious matters. If you don't already know the answer to your question you shouldn't be designing security systems.
If you're storing the password in the current-user section of the registry then the only people who can access it (under normal circumstances) are the user and the administrator. I'd trust (somewhat) the current-user section of the registry and use the standard password hashing mechanisms that the OS provides.
Jeff Atwood's "Rainbow Hash Cracking" describes hashes and password storage at a good beginner detail, and Thomas Ptacek's "Enough With the Rainbow Tables: What You Need to Know About Secure Password Schemes" goes on to tell you why you should not try and do it yourself usually.
Choosing a good hash function is less than 1% of the battle. If an attacker can run you hash function millions of times a second then (s)he can test millions of combinations a second. What you need is a slow, tunable secure hash. That's not something that is easy to come by and SHA*, MD5, etc are designed to be bloody fast since they're meant to be used over files and chunks of files usually, where speed is king.
I'd recommend reading up more, since the answers are out there and very easy to find.
The company I work for has taken on a support contract for a large order processing system. As part of the initial system audit I noticed that the passwords stored in the database were actually the hashcode of the password.
Essentially:
string pwd = "some pasword";
string securePwd = pwd.GetHashCode();
My question is, how secure or otherwise is this?
I'm not comfortable with it, but I don't know enough about how GetHashCode works. I would prefer to use something like an MD5 hash, but if I'm wasting my time then I won't bother.
You should use a salted, cryptographically strong hash, such as SHA256Managed.
Jeff Attwood has a few good posts on this topic:
Rainbow Hash Cracking
You're Probably Storing Passwords Incorrectly
It's not just insecure, but also subject to change:
http://netrsc.blogspot.com/2008/08/gethashcode-differs-on-systems.html
The value returned by GetHashValue for a given input has changed in the past.
There's no guarantee it will even be the same between different executions of the app.
GetHashCode returns a 32 bit integer as the hash value. Considering the birthday paradox, it's not a long enough hash value due to the relatively high probability of collisions, even if it were explicitly designed to be collision resistant, which is not.
You should go for SHA256 or another cryptographically secure hash function designed to handle such a task.
To store passwords, just using a simple hash function is not enough. You should add some random "salt" per user and iterate enough times so that it would be computationally expensive to brute force. Therefore, you should use something like bcrypt, scrypt, PBKDF2, with a large number of iterations.
I'd recommend using BCrypt instead. As others have already said using GetHashCode for passwords isn't a good idea.
GetHashCode was definitely not designed to be used in this way as the implementation does not guarantee different hash returns for different objects. This means that potentially multiple passwords could produce the same hash. It also isn't guaranteed to return the same hash value on different versions of the .NET framework meaning that an upgrade could potentially produce a different hash for the same string, rendering your passwords unusable to you.
It is recommended that you use a salted hash or even MD5 at a push. You can easily switch it to something within the Security.Cryptography namespace.
As others have said, GetHashCode isn't designed for what you're trying to do. There is a really excellent article on how to handle user passwords securely.
To summarise the article, you need to use either a relatively slow adaptive hashing scheme such as bcrypt, or alternatively the Stanford Secure Remote Password Protocol. I would suggest the former. And of course you should also use a salt.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 6 years ago.
Improve this question
I have read that when hashing a password, many programmers recommend using the BCrypt algorithm.
I am programming in C# and is wondering if anyone knows of a good implementation for BCrypt? I found this page, but I don't really know if it is bogus or not.
What should I be aware of when choosing a password hashing scheme? Is BCrypt a 'good' implementation?
First, some terms that are important:
Hashing - The act of taking a string and producing a sequence of characters that cannot be reverted to the original string.
Symmetric Encryption - (Usually just referred to as 'encryption') - The act of taking a string and producing a sequence of characters that can be decrypted to the original string through the use of the same encryption key that encrypted it.
Rainbow Table - a lookup table that contains all variations of characters hashed in a specific hashing algorithm.
Salt - a known random string appended to the original string before it is hashed.
For the .NET Framework, Bcrypt does not yet have a verified reference implementation. This is important because there's no way to know if there are serious flaws in an existing implementation. You can get an implementation of BCrypt for .NET here. I don't know enough about cryptography to say whether it's a good or bad implementation. Cryptography is a very deep field. Do not attempt to build your own encryption algorithm. Seriously.
If you are going to implement your own password security (sigh), then you need to do several things:
Use a relatively secure hash algorithm.
Salt each password before it's hashed.
Use a unique and long salt for each password, and store the salt with the password.
Require strong passwords.
Unfortunately, even if you do all this, a determined hacker still could potentially figure out the passwords, it would just take him a really long time. That's your chief enemy: Time.
The bcrypt algorithm works because it takes five orders of magnitude longer to hash a password than MD5; (and still much longer than AES or SHA-512). It forces the hacker to spend a lot more time to create a rainbow table to lookup your passwords, making it far less likely that your passwords will be in jeopardy of being hacked.
If you're salting and hashing your passwords, and each salt is different, then a potential hacker would have to create a rainbow table for each variation of salt, just to have a rainbow table for one salted+hashed password. That means if you have 1 million users, a hacker has to generate 1 million rainbow tables. If you're using the same salt for every user, then the hacker only has to generate 1 rainbow table to successfully hack your system.
If you're not salting your passwords, then all an attacker has to do is to pull up an existing Rainbow table for every implementation out there (AES, SHA-512, MD5) and just see if one matches the hash. This has already been done, an attacker does not need to calculate these Rainbow tables themselves.
Even with all this, you've got to be using good security practices. If they can successfully use another attack vector (XSS, SQL Injection, CSRF, et. al.) on your site, good password security doesn't matter. That sounds like a controversial statement, but think about it: If I can get all your user information through a SQL injection attack, or I can get your users to give me their cookies through XSS, then it doesn't matter how good your password security is.
Other resources:
Jeff Atwood: .NET Encryption Simplified (great for an overview of hashing)
Jeff Atwood: I just logged in as you
Jeff Atwood: You're probably storing passwords incorrectly
Jeff Atwood: Speed Hashing
Note: Please recommend other good resources. I've must have read a dozen articles by dozens of authors, but few write as plainly on the subject as Jeff does. Please edit in articles as you find them.
You must not use BCrypt in .NET. You must use PBKDF2 as is with the built in .NET framework implementation. It is the only freely available cryptographically verified implementation in .NET along with being the algorithm recommended by NIST.
StackId previously used BCrypt and moved to PBKDF2 for this very reason:
For those curious, we’re hashing passwords with PBKDF2. Relavent code
is here (
http://code.google.com/p/stackid/source/browse/OpenIdProvider/Current.cs#1135
), through a few layers of indirection. In an earlier iteration, we
were using BCrypt; but moved to PBKDF2 as it is built into the .NET
framework, whereas BCrypt would require us to verify an implementation
(no small undertaking).
Kevin Montrose, May 27 2011
(Updated link on GitHub)
Edit: The meaning of verified in cryptographic terms seems to not be readily understood, a verified implementation means it's been cryptographically proven to be implemented without error. The cost of this can easily reach $20,000 or higher. I recall this when I was doing research on OpenSSL and read where they stated they haven't completed the entire verification process but if you need fully verified that they can point you down the right path for it and mentioned costs associated. Certain government requirements include mandates for verified encryption algorithms.
The bcrypt implementations in .NET have not been verified. Using an unverified encryption implementation you can't be absolutely certain that there is not either intentional malicious faults in it such as allowing a backdoor into what is encrypted or unintentional implementation faults that result in cryptographically insecure data.
2014 edit: For anyone that questioned the imperativeness of using verified cryptopgraphical algorithims look at the devastation that was wrought by the heartbleed hack exploited in OpenSSL. That is the cost of using an unverified implementation. It's secure.... until you find out that any person can just read the entire memory contents of your server.
The author of the change which introduced Heartbleed, Robin Seggelmann, stated that he "missed validating a variable containing a length" and denied any intention to submit a flawed implementation. Following Heartbleed's disclosure, Seggelmann suggested focusing on the second aspect, stating that OpenSSL is not reviewed by enough people.
This is the definition of an unverified implementation. Even the smallest defect can result in crippling the entire security.
2015 edit: Removed recommendation based language and replaced with absolutes. Embedded original Kevin Montrose comment for posterity.