0

Guys I am developing an application in c# asp.net which deals with money. For that application password in the database should be securely saved.For that reason I did some research and came up with below two functions for encryption and decryption respectively from c#.So my question is whether I should go with these two functions or there are other secure ways to save password securely in my database.

 private string Encrypt(string clearText)
    {
        string EncryptionKey = "MAKV2SPBNI99212";
        byte[] clearBytes = Encoding.Unicode.GetBytes(clearText);
        using (Aes encryptor = Aes.Create())
        {
            Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
            encryptor.Key = pdb.GetBytes(32);
            encryptor.IV = pdb.GetBytes(16);
            using (System.IO.MemoryStream ms = new MemoryStream())
            {
                using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
                {
                    cs.Write(clearBytes, 0, clearBytes.Length);
                    cs.Close();
                }
                clearText = Convert.ToBase64String(ms.ToArray());
            }
        }
        return clearText;
    }

    private string Decrypt(string cipherText)
    {
        string EncryptionKey = "MAKV2SPBNI99212";
        byte[] cipherBytes = Convert.FromBase64String(cipherText);
        using (Aes encryptor = Aes.Create())
        {
            Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
            encryptor.Key = pdb.GetBytes(32);
            encryptor.IV = pdb.GetBytes(16);
            using (MemoryStream ms = new MemoryStream())
            {
                using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write))
                {
                    cs.Write(cipherBytes, 0, cipherBytes.Length);
                    cs.Close();
                }
                cipherText = Encoding.Unicode.GetString(ms.ToArray());
            }
        }
        return cipherText;
    }
killer
  • 592
  • 1
  • 9
  • 31
  • If you are dealing with real customers information (credit card, ss, etc), you really should use a commercial solution and not roll your own. – Mathemats Dec 11 '14 at 06:55
  • 1
    @Mathemats: The OP isn't rolling their own encryption - they're using existing crypo code, just wrapping it in helper methods. – Jon Skeet Dec 11 '14 at 06:57
  • 2
    The big problem here is that you've got your encryption key right there in the code. So anyone who is able to get access to that code can decrypt anything in your database - that's not a good position to be in. – Jon Skeet Dec 11 '14 at 06:57
  • any suggestions guys...that I should go with. – killer Dec 11 '14 at 07:03
  • 4
    Usually, the worst thing you can do is to store password(s) using **reversible** encryption. Are you absolutely sure you need it? Because if not, use standard approach, i.e. salted hashes. – Roger Wolf Dec 11 '14 at 10:09
  • Your site deals with money. Simply put, don't do this. You do NOT want to be able to decrypt your passwords, period. A randomly salted hash is the best approach. – Sean Lange Dec 11 '14 at 14:37

3 Answers3

0

In your actual implementation hardcoding your salt is not a good practice for various reasons, the most common reason could be malicious access to your code compromising all the data encrypted with such algorithm. Instead you should randomize your salt and save it somewhere, e.g. as part of your hash string or in data base for later retrieval.

There's a C# implementation of a salted password hashing algorithm in this article http://crackstation.net/hashing-security.htm. Note that the salt is randomly generated and saved as part of the hash string itself.

mgigirey
  • 1,027
  • 9
  • 13
0

Regarding your code, it is giving a warning using Code Analisys:

CA2202: Do not dispose objects multiple times

Because of the using nested

Here is an approach to it: CA2202: How to solve

If this matter interests you, can take a look at this: CA2202: Code review

Community
  • 1
  • 1
Juanito
  • 420
  • 1
  • 4
  • 18
-1

In general when you use cryptographic features in an app always consider using asymmetric algorithms instead of plain symmetric ones. You should consider using RSA key pairs based stuff instead of plain AES. Even better is to use a combination of them e.g: encrypt plain text using AES but then also encryt the AES key itself using RSA so that it becomes tamper proof.

But for passwords specifically you should consider using one way encryption like MD5 or SHA. This makes the password very secure. Why? since SHA or MD5 is one way hashing approach i.e: given a plain text you can derive its SHA or MD5 hash but not the other way round. There is no decrypt provisions here so even if your encrypted passwords get stolen no one can make any heads or tails of it and brute force would take years to break them down. You should do something like this:

  • When creating users, SHA their passwords and save the SHA string in DB.
  • when logging in, query the records based on username or email and save in a list.
  • calculate SHA hash for the password which user entered in the form.
  • match the calculated SHA hash against the value in password column for each record which you got back from DB.
  • if match found them user is authenticated else not.

This approach also protects you form injection attacks on SQL side. Only drawback of this approach is that no one cna recover the old password back. You cannot tell the user what his/her old password was. In case of 'forget password' kind of functionality you need to recreate a new password and use that.

Nazgul
  • 1,892
  • 1
  • 11
  • 15
  • 1
    I down voted you - you can google MD5 hashes, that's how weak they are. Hashes MUST be salted otherwise they are effectively worthless as a security mechanism. – slugster Dec 11 '14 at 07:07
  • I was giving am approach to follow. SHA is better than MD5 but my point was to provide an approach not a working example based answer. One was hashing for password stuff and asymmetric crypto pairs for other sensitive data like address, accounts etc. Though I don't agree to your down vote but I will accept it. – Nazgul Dec 11 '14 at 07:14
  • 2
    @slugster - Yes, MD5 is weak and should not be used. But salting does *not* improve the security of a (one) password. Salting is very important to make sure that if someone has cracked *one* password, he/she did not automatically crack *all* the passwords (in a DB for example) via rainbow tables. So salting is essential for the security of more than one password; but for the security of *one* password, the strength of the hashing algorithm is pivotal, since the salt (unique per password!) can even be public knowledge, without harming the security. – Corak Dec 11 '14 at 07:36
  • 1
    One more comment, both MD5 and SHA-* are not appropriate to hash passwords, because they are ways too fast ([8 Giga MD5 per second](http://hashcat.net/oclhashcat/#performance) with common hardware). Instead one should use a slow hash function with a cost factor, like BCrypt or PBKDF2. – martinstoeckli Dec 11 '14 at 12:00
  • You know you can improve your answer with the information given in the comments, so I can finally remove my downvote (and @slugster too). – Artjom B. Dec 11 '14 at 16:04