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.
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 want to generate a hash code for a file. Using C# I would do something like this then store the value in a database.
byte[] b = File.ReadAllBytes(#"C:\image.jpg");
string hash = ComputeHash(b);
Now, if i use say a Java program that implements the same hashing alogorithm (Md5), can i expect the hash values to be the equal to the value generated in C#? What if i execute the java program from different environments, Windows, Linux or Mac?
Hash values are not globally unique. But that is not what you are really asking.
What you really want to know is whether a hashing algorithm (such as MD5) will produce the same hash value for identical files on different operating system platforms. The answer to that is "yes" ... provided that files are byte-for-byte identical.
In the case of an binary format that should be the case. In the case of text files, transcoding between different character encodings, or changing line termination sequences will make the files different at the byte level and result in different MD5 hash values.
Havh values generated from the same input and with the same algorithm are defined to be equal. 1+1=2, regardless of the programming language I program this in.
Otherwise the internet would not work at all, you know.
My suggestion would be to use a common/accepted hashing algorithm like MD5 to achieve the same hash values.
If the Hashing algorithm and the input are same, the hash value generated would be same irrespective of language or environment.
The hashing algorithm takes the full/part of the key and manipulates it to generate the value which is why it would be same in all languages.
I wish I could comment on this but I don't have enough reputation to do that.
While I don't know for what purpose you want to use a hash algorithm, I'd like to say that some collisions have been found for MD5 so it might be less "secure" (well, we probably can't say "broken" since those collisions are hard to compute). The same remark applies to the SHA-1 algorithm.
More information here: http://www.mathstat.dal.ca/~selinger/md5collision/
So if you want to use a hash algorithm for security purposes, you might take a look at SHA-256 or SHA-512 which are stronger for now.
Otherwise you can probably keep going with MD5.
My two cents.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I generate a hashcode from a byte array in c#
In C#, I need to create a Hash of an image to ensure it is unique in storage.
I can easily convert it to a byte array, but unsure how to proceed from there.
Are there any classes in the .NET framework that can assist me, or is anyone aware of some efficient algorithms to create such a unique hash?
There's plenty of hashsum providers in .NET which create cryptographic hashes - which satisifies your condition that they are unique (for most purposes collision-proof). They are all extremely fast and the hashing definitely won't be the bottleneck in your app unless you're doing it a trillion times over.
Personally I like SHA1:
public static string GetHashSHA1(this byte[] data)
{
using (var sha1 = new System.Security.Cryptography.SHA1CryptoServiceProvider())
{
return string.Concat(sha1.ComputeHash(data).Select(x => x.ToString("X2")));
}
}
Even when people say one method might be slower than another, it's all in relative terms. A program dealing with images definitely won't notice the microsecond process of generating a hashsum.
And regarding collisions, for most purposes this is also irrelevant. Even "obsolete" methods like MD5 are still highly useful in most situations. Only recommend not using it when the security of your system relies on preventing collisions.
The part of Rex M's answer about using SHA1 to generate a hash is a good one (MD5 is also a popular option). zvolkov's suggestion about not constantly creating new crypto providers is also a good one (as is the suggestion about using CRC if speed is more important than virtually-guaranteed uniqueness.
However, do not use Encoding.UTF8.GetString() to convert a byte[] into a string (unless of course you know from context that it is valid UTF8). For one, it will reject invalid surogates. A method guaranteed to always give you a valid string from a byte[] is Convert.ToBase64String().
Creating new instance of SHA1CryptoServiceProvider every time you need to compute a hash is NOT fast at all. Using the same instance is pretty fast.
Still I'd rather do one of the many CRC algorithms instead of a cryptographic hash as hash functions designed for cryptography don't work too well for very small hash sizes (32 bit) which is what you want for your GetHash() override (assuming that's what you want).
Check this link out for one example of computing CRC in C#: http://sanity-free.org/134/standard_crc_16_in_csharp.html
P.S. the reason you want your hash to be small (16 or 32 bit) is so you can compare them FAST (that was the whole point of having hashes, remember?). Having hash represented by a 256-bit long value encoded as string is pretty insane in terms of performance.
You can use any of the standard hashing algorithms, but hashing can't technically guarantee uniqueness. Hashing is designed to be a relatively fast and/or small token to be able to see if one piece of data likely is the same as the other. It's fully possible for entirely different sets of data to produce the same hash, though being able to produce these algorithmically is very hard.
All of that aside, for checking likely identity, MD5 is fairly fast. SHA is more reliable (MD5 has been hacked, so shouldn't be use for security), but it's also slower.
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.