Matt
Matt

Reputation: 1241

C# Password Encryption

I found some code online that works fairly well for what I am trying to do. I need something that will encrypt a password, save it to a database, and retrieve with ease. The below code does almost everything I am looking for.

        string UserName = txtUser.Text;
        string password = txtPass.Text;

        string encrKey = "keyvalue";
        byte[] byteKey = { };
        byte[] IV = {25, 47, 60, 88, 99, 106, 125, 139};
        byteKey = Encoding.UTF8.GetBytes(encrKey.Substring(0, 8));
        DESCryptoServiceProvider des = new DESCryptoServiceProvider();
        byte[] inputArray = Encoding.UTF8.GetBytes(password);

        MemoryStream ms = new MemoryStream();
        CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(byteKey, IV), CryptoStreamMode.Write);
        cs.Write(inputArray, 0, inputArray.Length);
        cs.FlushFinalBlock();
        password = Convert.ToBase64String(ms.ToArray());

        SqlCommand cmd = new SqlCommand("INSERT INTO USers (UserName, Password) VALUES (@UserName, @Password)", myConnection);
        cmd.CommandType = CommandType.Text;

        cmd.Parameters.AddWithValue("@UserName", UserName);
        cmd.Parameters.AddWithValue("@Password", password);

        SqlDataReader rdr = cmd.ExecuteReader();

The issue that I am running into is the code errors out when the password is 8 characters or longer. I get this error:

System.Security.Cryptography.CryptographicException: Specified key is not a valid size for this algorithm. The error is generated on the Cryptostream line.

Do I need to use a different type for my keys?

Upvotes: 2

Views: 7492

Answers (5)

mrK
mrK

Reputation: 2290

Try this instead:

var hash = Encoding.ASCII.GetBytes(password);
var sha1 = new SHA1CryptoServiceProvider();
var sha1hash = sha1.ComputeHash(hash);
var hashedPassword = Encoding.ASCII.GetString(sha1hash);

Upvotes: 0

Dollar Money Woof Woof
Dollar Money Woof Woof

Reputation: 1058

i suggest u use bcrypt. the source code available at http://code.google.com/p/bcryptnet/ download and use it. but before using it. read the documentation and understand how it works and why bcrypt... it is important.

through my research for few weeks about password encryption. i finally found this bcrypt which best suit my need. ( i think it is the best suited for password, correct me if i am wrong)

it is a one way encryption. just like what few dope programmers said, hash it and compare but not decrypt.

hope this help you. if you find othre interesting things please let me know XD peace~~

anything i said wrong, correct me XD

Upvotes: 1

csharptest.net
csharptest.net

Reputation: 64248

If you need to actually reverse the encryption, just use the ProtectedData class: http://msdn.microsoft.com/en-us/library/system.security.cryptography.protecteddata.aspx

If others here are correct, use a salted hash as in the example class below. The following was taken from "Another example of how to store a salted password hash"

public sealed class PasswordHash
{
    const int SaltSize = 16, HashSize = 20, HashIter = 10000;
    readonly byte[] _salt, _hash;
    public PasswordHash(string password)
    {
        new RNGCryptoServiceProvider().GetBytes(_salt = new byte[SaltSize]);
        _hash = new Rfc2898DeriveBytes(password, _salt, HashIter).GetBytes(HashSize);
    }
    public PasswordHash(byte[] hashBytes)
    {
        Array.Copy(hashBytes, 0, _salt = new byte[SaltSize], 0, SaltSize);
        Array.Copy(hashBytes, SaltSize, _hash = new byte[HashSize], 0, HashSize);
    }
    public PasswordHash(byte[] salt, byte[] hash)
    {
        Array.Copy(salt, 0, _salt = new byte[SaltSize], 0, SaltSize);
        Array.Copy(hash, 0, _hash = new byte[HashSize], 0, HashSize);
    }
    public byte[] ToArray()
    {
        byte[] hashBytes = new byte[SaltSize + HashSize];
        Array.Copy(_salt, 0, hashBytes, 0, SaltSize);
        Array.Copy(_hash, 0, hashBytes, SaltSize, HashSize);
        return hashBytes;
    }
    public byte[] Salt { get { return (byte[])_salt.Clone(); } }
    public byte[] Hash { get { return (byte[])_hash.Clone(); } }
    public bool Verify(string password)
    {
        byte[] test = new Rfc2898DeriveBytes(password, _salt, HashIter).GetBytes(HashSize);
        for (int i = 0; i < HashSize; i++)
            if (test[i] != _hash[i])
                return false;
        return true;
    }
}

Upvotes: 2

mohammedn
mohammedn

Reputation: 2950

Hashing passwords is much better than encrypting. You store the hash of the password in the database and you don't care any more about the normal text password. When the user login, you fetch the normal text password, hash it and compare the two hashes (i.e. the one in the database, and the one you hashed from the user input) to authenticate. The clear benefit here is that you ensure no one - whatever the why he accessed the database - will know the original password (theoretically).

Upvotes: 1

Variant
Variant

Reputation: 17385

The common practice is not to encrypt a password in the database but to hash it.
When the user attempts to login, you take his typed password, hash it and compare to the hash stored in your db.

The industry standard hashing algorithm is SHA-1, which is readly available in .NET.

For even greater security you use a "Salt" in your hashing.

You can read more about it here: Salting Your Password: Best Practices?

Upvotes: 14

Related Questions