0

I have never encrypted a password before, and this is what I came up with to do it, with the aid of this article. The article didn't include salt, so I had to figure it out myself:

        UTF8Encoding encoder = new UTF8Encoding();
        byte[] salt = new byte[8];
        new Random().NextBytes(salt);
        byte[] encodedPassword = encoder.GetBytes(txtPassword.Text);
        byte[] saltedPassword = new byte[8 + encodedPassword.Length];
        System.Buffer.BlockCopy(salt, 0, saltedPassword, 0, 8);
        System.Buffer.BlockCopy(encodedPassword, 0, saltedPassword, 8, encodedPassword.Length);
        byte[] encryptedPassword = new MD5CryptoServiceProvider().ComputeHash(saltedPassword);
        byte[] saltedEncryptedPassword = new byte[8 + encryptedPassword.Length];
        System.Buffer.BlockCopy(salt, 0, saltedEncryptedPassword, 0, 8);
        System.Buffer.BlockCopy(encryptedPassword, 0, saltedEncryptedPassword, 8, encryptedPassword.Length);

with saltedEncryptedPassword being stored in the database. As you probably notice, I had some trouble concatenating the byte arrays together where the salt was involved. Have I done this right, or is there a better way? Thanks.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
MarioDS
  • 12,895
  • 15
  • 65
  • 121
  • 7
    There is no good way to encrypt passwords using MD5. You should **hash** passwords using scrypt or PBKDF2. – SLaks May 06 '12 at 15:09
  • 2
    There is no way to *encrypt* passwords using MD5. It's a one-way hash function, not an encryption algorithm. – dtb May 06 '12 at 15:15
  • It's hard to keep up with the changes here. As more computing horsepower becomes available, it is easier to crack some of the weaker approaches. While MD5 was adequate in the past, there are newer approaches that require even more computing power to break. – DOK May 06 '12 at 15:15
  • 4
    Apart from the obviously wrong choice of MD5 over PBKDF2, bcrypt or scrypt, your salting method sucks too. Use a crypto PRNG for your salt, not the current time. – CodesInChaos May 06 '12 at 15:17
  • And just to repeat SLaks point: Single iteration SHA-2 is just as wrong as MD5, so I've downvoted all answers which recommend that. – CodesInChaos May 06 '12 at 15:18
  • http://www.codinghorror.com/blog/2012/04/speed-hashing.html . If you look at the SimpleMembershipProvider shipped with WebMatrix you should get an idea how to implement a secure way. – Andreas May 06 '12 at 15:19
  • Choices that are computationally expensive are wrong as well, if it's the server that has to perform the computation. The client should perform the expensive computation, and the server should be able to verify the client's request without spending too many resources on it. – dtb May 06 '12 at 15:20
  • @dtb That's certainly nice, but at least for websites there are two problems 1) It requires javascript 2) Even with javascript, fast hashing implementations aren't widely deployed yet. – CodesInChaos May 06 '12 at 15:23
  • @all: Read http://chargen.matasano.com/chargen/2007/9/7/enough-with-the-rainbow-tables-what-you-need-to-know-about-s.html – SLaks May 06 '12 at 15:30

4 Answers4

6

Password hashes should be slow, not fast.
The faster the hash, the faster an attacker can run through a password dictionary.

Therefore, you should never use general-purpose hashes like SHA for passwords.

Instead, use proven slow techniques like scrypt or PBKDF2.

dtb
  • 213,145
  • 36
  • 401
  • 431
SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • Thanks. (I'm not sure why I waited so long to answer) – SLaks May 06 '12 at 15:30
  • Can you point me to a website that explains how to implement it correctly? I know google will provide me with multiple, I just trust you to pick the right one :) – MarioDS May 06 '12 at 15:31
  • [This](http://stackoverflow.com/a/5278644/34397) ought to be good, although I can't guarantee it. Or PBKDF with http://msdn.microsoft.com/en-us/library/yx129kfs.aspx I would probably say to start with 10K iterations, and decrease it if that's too slow. – SLaks May 06 '12 at 15:33
  • It's for a dummy school project and not for real-life use. I just want to get the concept right, so I'll use fewer iterations. thanks for the help! I want to use the standard library, so I'll find out how to do it. Will I need to UTF8-encode the password string? – MarioDS May 06 '12 at 15:36
  • The ctor will do that for you. – SLaks May 06 '12 at 15:37
0

I would store only the salt value and the hash (not the saltedencryptedPassword) in separate columns in the database and regenerate the hash with the typed in password. You find a similar answer here Hash and salt passwords in C#.1`

I sometimes just us a GUID as a salt value and add it to the password before hashing.

MD5 is not safe any longer (hacked in 2004 by the Chinese), you can use SHA256 or SHA512 instead of. EDIT: However these algorithmes are pretty fast in calculation and therefore easier to hack. @SLaks suggests to use scrypt or PBKDF2, because they are much harder to calculate. There is a built-in implementation of PBKDF2 in .NET under Rfc2898DeriveBytes.

Another point: I would not create a new Random() object every time. If you call this within short period time the same sequence of random numbers will be generated every time, because the seed value is time based.

Community
  • 1
  • 1
slfan
  • 8,950
  • 115
  • 65
  • 78
  • Huh? You need to store the hash too. Also, don't use SHA for passwords. – SLaks May 06 '12 at 15:14
  • Of course the hash too, but not the saltedEncryptedPassword. What should you use as a Hash algorithm in your opinion? MD5 is not safe, SHA256 is 20 times slower, but safe and RIPEMD160 is too slow. Regarding to the C# in a Nutshell, SHA256 is the way to go. – slfan May 06 '12 at 15:21
  • @slfan RIPEMD160 is too fast, not too slow. Password hashing should be deliberately slow. – CodesInChaos May 06 '12 at 15:24
  • "MD5 is not safe any longer (hacked in 2004 by the Chinese)," So far the best pre-image attack against MD5 is still around 2^120. The cryptoanalysis you mention is mainly about collisions, and those are completely irrelevant to password hashing. – CodesInChaos May 06 '12 at 15:27
  • @CodeInChaos: good point, but there are only 4 hash algorithms in .NET and RIPEMD160 is slow and slightly above SHA1 in security. The only way to make it slower is to rehash, but that's also not considered to be good. – slfan May 06 '12 at 15:28
  • @slfan: Iterative hashing is good, not bad. See http://en.wikipedia.org/wiki/PBKDF2 (which ships in .Net) – SLaks May 06 '12 at 15:30
  • There is a built in implementation of PBKDF2 with HMAC-SHA-1, namely [Rfc2898DeriveBytes](http://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes.aspx). It is an iterative hashing scheme. – CodesInChaos May 06 '12 at 15:30
-1

No, it's no good. MD5 is no good anymore. It collides with itself and not to be trusted. You should use SHA256.

public string getSHA256(string input)
{
    try
    {
        return BitConverter.ToString(SHA256Managed.Create().ComputeHash(Encoding.Default.GetBytes(input))).Replace(“-”, “”).ToLower();
    }
    catch (Exception e)
    {
        return string.Empty;
    }
}
Stan
  • 25,744
  • 53
  • 164
  • 242
  • 6
    No, no, no. Use salt. SHA is too fast. Don't swallow exceptions. – SLaks May 06 '12 at 15:12
  • @SLaks +1, Never swollow exceptions, and furthermore never catch `System.Exception`. – David Anderson May 06 '12 at 15:15
  • What about "Too Fast"? I'm no expert, can you please explain why it is a problem? In this particular example I needed to return empty string if something went wrong for some reason, don't remember why though... :) – Stan May 06 '12 at 15:17
  • 2
    @Qmal: SHA has been optimized to run extremely fast. That means an attacker can try millions of passwords per second in a brute force attack. That's not good. – SLaks May 06 '12 at 15:18
-1

I always use SHA2-512 for the hashing of my passwords. In my opinion passwords should never be encrypted, but always hashed (no way to trace back to the original password).

But please no longer use MD5, which is easily translated back in a password nowadays.

Wim Haanstra
  • 5,918
  • 5
  • 41
  • 57
  • SHA should not be used for passwords. – SLaks May 06 '12 at 15:16
  • 1
    There are no efficient pre-image attacks against MD5. You'd attack a password hashed with MD5 just the same way you'd attack a passwored hashed with SHA-512: by guessing the password – CodesInChaos May 06 '12 at 15:58