?
Solved

Encrypt Password using MD5CyptoServiceProvider Class

Posted on 2011-10-20
23
Medium Priority
?
424 Views
Last Modified: 2012-05-12
Hello Experts,

I would like to know if someone could help me with my code attached? I need help performing a one way encryption on my password using the salting+hash technique when a user creates a new account.

I'm also not sure what the field type(s) should be for the users_password and users_password_salt fields.

Thanks in advance!!!



I also
0
Comment
Question by:asp_net2
  • 9
  • 9
  • 2
20 Comments
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 37000634
0
 
LVL 4

Author Comment

by:asp_net2
ID: 37000778
Hi kaufmed,

I'm game for whatever you think is better to use then rather than MD5. I was not aware of that, hence just learning this sort of stuff.

Whatever you decide would you be willing to help me adjust my code to whatever you choose?

Thanks in advance!!!
0
 
LVL 4

Author Comment

by:asp_net2
ID: 37000993
Hi kaufmed,

Ok, I looked into the different Hash Function for .NET and found that SHA-512 is the best you can use. So I modified my code and was wondering if you would be willing to look over it and let me know if it looks good to you and if not what I should changed.

Thanks in advance!!!


protected void btn_NewUser_Click(object sender, EventArgs e)
    {
        using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["HealthCourses"].ConnectionString))
        {
            SqlCommand cmd = new SqlCommand();
            cmd.CommandText = "HealthCourses_InsertUsers";
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Connection = conn;

            cmd.Parameters.AddWithValue("@c_id", SqlDbType.Int).Value = ddlClient.SelectedItem.Value;
            cmd.Parameters.AddWithValue("@bldg_id", SqlDbType.Int).Value = ddlBldgLocation.SelectedItem.Value;
            cmd.Parameters.AddWithValue("@s_id", SqlDbType.Int).Value = ddlState.SelectedItem.Value;
            cmd.Parameters.AddWithValue("@users_flname", SqlDbType.VarChar).Value = txtName.Text;
            cmd.Parameters.AddWithValue("@users_street_address", SqlDbType.VarChar).Value = txtHomeAddress.Text;
            cmd.Parameters.AddWithValue("@users_city", SqlDbType.VarChar).Value = txtCity.Text;
            cmd.Parameters.AddWithValue("@users_zip", SqlDbType.VarChar).Value = txtZipCode.Text;
            cmd.Parameters.AddWithValue("@users_phone", SqlDbType.VarChar).Value = txtHomePhone.Text;
            cmd.Parameters.AddWithValue("@users_work_ext", SqlDbType.VarChar).Value = txtWorkExtension.Text;
            cmd.Parameters.AddWithValue("@users_email", SqlDbType.VarChar).Value = txtEmailAddress.Text;
            cmd.Parameters.AddWithValue("@users_username", SqlDbType.VarChar).Value = txtUserName.Text;

            //Encrypt the password
            SHA512CryptoServiceProvider SHA512Hash = new SHA512CryptoServiceProvider();

            byte[] hashedBytes = null;
            UTF8Encoding encoder = new UTF8Encoding();

            string guid = System.Guid.NewGuid().ToString(); //36 long characters
            hashedBytes = SHA512Hash.ComputeHash(encoder.GetBytes(txtPassword.Text + guid));

            cmd.Parameters.AddWithValue("@users_password", SqlDbType.VarChar).Value = hashedBytes;
            cmd.Parameters.AddWithValue("@users_password_salt", SqlDbType.VarChar).Value = guid;

            try
            {
                conn.Open();

                cmd.ExecuteNonQuery();

                Response.Redirect("newuser_success.aspx");
            }

            catch (Exception ex)
            {
                lblInsertError.Text = ex.Message.ToString();
            }

            finally
            {
                conn.Close();
            }
        }
    }

Open in new window

0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 37001241
I know you said that you wanted a one-way hash, and I believe you have it, but are you planning on comparing hashes at some later point? If so, the call to NewGuid is going to give you a completely different (1 in trillions chance of repetition, I believe; most likely a lower chance) salt value each time you call it. Since you appear to be salting your password value, you will never be able to compare an incoming password with the database version since the salt will be different each time.

Perhaps I misinterpret your intent, though.
0
 
LVL 4

Author Comment

by:asp_net2
ID: 37001535
I'm not sure what you mean. I was under the impression that it is recommended that you HASH your password in it's own field in the DB and then add the SALT value to the password in another field in the DB.

So once again I thought I needed to use SHA512 to encrypt/hash the password in Field A but then I also thought I have to create a SALT value in Field B. So that when the users try to login you compane Field A and Field B and if true authenticate.

Perhaps I'm missing something or doing something more than what is needed.

0
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 37001639
I was under the impression that it is recommended that you HASH your password in it's own field in the DB and then add the SALT value to the password in another field in the DB.
That is correct, to my knowledge. But think about this:  why would one want to hash a password? When a user uses your page or your form to enter his password, does he enter the hash or does he enter the password? You hash a password so that intruders don't get the actual passwords of your users. When you accept a user's password via data entry, you hash the incoming data using the same method (and same salt!) that you used when you inserted it into the database. If you were not hashing, and an intruder got the clear-text passwords from your database, then he could simply log into your application or web site using normal credentials. If you hash your passwords, then having the hash does an intruder no good because you be running the text received via data entry through your hash algorithm again and comparing that hash to the hash that is stored in the database. If an intruder submits the hashed value, then your comparison is then the hash on the database to the hash of the hash of the password, which for all intents and purposes will never be the same.

The fact that you call NewGuid without keeping track of that generated GUID means that when you hash the incoming text from the user, you will never be using the same salt. Different salt == different hash.
0
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 37001678
Disregard my last comment regarding the GUID. I missed the line in your code where you are storing that value. The very last statement holds true, though.
0
 
LVL 4

Author Comment

by:asp_net2
ID: 37002030
Hi kaufmed,

Ok, I'm confused now. Is the reasons that you HASH and SALT using two different fields to begin with is to compare the two fields when a user attempts to login? Please take a look at my attached .txt file it contains all code and stored procedures used. Everytihng works fine, but I just want someone else to make sure that the coding i'm using for HASHING is correct. It just seems very easy and not much involved to HASH a password and I'm worried that I"m leaving something out.

 EE.txt
0
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 37002203
Please feel free to hold out for responses from those who are more security-proficient as I cannot safely claim to be. I am expressing what I understand hash and salt to be used for.

A salt is just some value that you append (or prepend or insert) into the value you want to encrypt. You do this because without it, it is a tad easier to brute-force the guessing of passwords. This can be accomplished using rainbow tables, among other things. When you add a salt, it causes a value that would ordinarily hash to some arbitrary value to hash to some other arbitrary value.

Here's a real example using your selected algorithm.

using System;
using System.Security.Cryptography;
using System.Text;

namespace _27406871
{
    class Program
    {
        static void Main(string[] args)
        {
            string toHash = "Hello World";
            SHA512CryptoServiceProvider hasher = new SHA512CryptoServiceProvider();
            Encoding encoding = System.Text.UTF8Encoding.UTF8;
            byte[] unsaltedBytes = encoding.GetBytes(toHash);
            byte[] saltedBytes = encoding.GetBytes(toHash + "some_arbitrary_value");
            byte[] saltedBytes2 = encoding.GetBytes(toHash + "some_other_arbitrary_value");

            byte[] unsaltedHash = hasher.ComputeHash(unsaltedBytes);
            byte[] saltedHash = hasher.ComputeHash(saltedBytes);
            byte[] saltedHash2 = hasher.ComputeHash(saltedBytes2);

            string unsaltedHashString = encoding.GetString(unsaltedHash);
            string saltedHashString = encoding.GetString(saltedHash);
            string saltedHashString2 = encoding.GetString(saltedHash2);

            Console.WriteLine("Unsalted Hash:");
            Console.WriteLine(unsaltedHashString);
            Console.WriteLine("\nSalted Hash:");
            Console.WriteLine(saltedHashString);
            Console.WriteLine("\nSalted Hash 2:");
            Console.WriteLine(saltedHashString2);
            Console.ReadKey();
        }
    }
}

Open in new window


If you ran the above, you would see three different outputs. This is what the salt gives you. If an intruder tried to brute force passwords against your encryption, they wouldn't work because of the addition of salt.

Adding salt to a value before encryption gives you a different value than not having salt does. If you didn't use salt, then there would be nothing more you had to do when you compared your two values (the hashed DB value and the incoming user-supplied text, which you would run through your hashing algorithm). However, if you use salt, then you must keep that salt in order to be able to compare the test coming from your user at a later date.

Let's assume you are doing this for a login screen. As you saw above, if you hashed your original value using a salt, then you would get a particular value. Let's pretend you stored this value to the database. You user knows absolutely nothing about the salt--this is something for you (your computer) alone. The user will enter his password to log in to your site. When he clicks the submit button, his browser sends this password (clear text) to your site. Your site will attempt to hash the password. Now, if you hash the password with no salt, then you will get some arbitrary value, and this value will not match the value stored in your database, even if it is the correct password. You must hash the incoming password using the same salt that you used when you inserted the original hashed password into the database. The reason you store both values is simple:

You store the hash for comparison.
You store the salt to hash the password the user submitted via his browser.

If you hash the incoming password using the salt you stored in the database, then the resulting value should be the same as what you stored in the hash field when you originally inserted it into the database (provided the user entered the correct password and you didn't change your hashing algorithm or the salt).
0
 
LVL 4

Author Comment

by:asp_net2
ID: 37002558
Confused by all that. Im not sure what I'm missing. Do I need to use salt if I'm hashing using sha512? If so do I or should I include the hash and salt into the same database field rather than having two fields in my database?
0
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 37002633
Do I need to use salt if I'm hashing using sha512?
I don't see how it would hurt.

If so do I or should I include the hash and salt into the same database field rather than having two fields in my database?
No. Keep it separate because you will need the hash again.
0
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 37002640
No. Keep it separate because you will need the hash again.
Sorry. I meant to say, "No. Keep it separate because you will need the salt again."
0
 
LVL 4

Author Comment

by:asp_net2
ID: 37002911
Ok, so is there something wrong with my code in the way that I'm storing the hash/salt values?

is there something wrong with how I authenticate using my attached login code?

I just want to make sure my code is good. If you are not 100% sure then how can I get more input on this post?
0
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 37002955
If you are not 100% sure then how can I get more input on this post?
"Request Attention" for this question and ask that an expert alert be sent out.
untitled.PNG
0
 
LVL 4

Author Comment

by:asp_net2
ID: 37003176
Hi kaufmed,

Please do not take that personal. I just want to make sure that I'm handling everything properly. If not then I would like someone to tell me what I need to change in my code. Hopefully it does not take a long time to get a response :(
0
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 37003225
Please do not take that personal.
Not at all. That's why I made a point of telling you that I am not a security expert  = )

Besides, it vicariously gives me a chance to confirm whether or not I know what I'm talking about  ; )
0
 
LVL 14

Expert Comment

by:Dustin Hopkins
ID: 37021795
You would want to add salt to the password then hash it and store the resulting hash along with the salt in your database. That way the next time the user inputs their password you add the salt from the database, hash it. Then compare the hash results with those stored in the database. You always want to hash with salt, so the cracker would have to generate new rainbow tables for each entry based off of the salt.(Much more time consuming and expensive)

Below I use two functions, one to create a random salt which I hash and encode to base 64. Then the other function takes the typed password and salt and returns a hashed value. These could be modified for database use or however you need. You would want to store in a varchar(max) datatype since it is base64 text encoded.

Hope this helps,
Dustin
using System.Security.Cryptography;
public class PassEnc
{
	public static string SHA512_CreateSalt()
	{
		object minSize = 64;
		object maxSize = 128;
		Random rndom = new Random();
		Int32 saltsize = rndom.Next(minSize, maxSize);
		RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
		byte[] saltBytes = new byte[saltsize];
		rng.GetNonZeroBytes(saltBytes);
		SHA512Managed sha = new SHA512Managed();
		ASCIIEncoding ae = new ASCIIEncoding();
		byte[] Hash = sha.ComputeHash(saltBytes);
		return Convert.ToBase64String(Hash);
	}
	public static string SHA512_Encrypt(string Txt, string salt)
	{
		// Convert plain text into a byte array.
		byte[] plainTextBytes = Encoding.UTF8.GetBytes(Txt);
		// Convert salt into a byte array from Base64
		byte[] saltbytes = Convert.FromBase64String(salt);
		// Allocate array, which will hold plain text and salt.
		byte[] plainTextWithSaltBytes = new byte[plainTextBytes.Length + (saltbytes.Length - 1) + 1];
		// Copy plain text bytes into resulting array.
		for (int i = 0; i <= plainTextBytes.Length - 1; i++) {
			plainTextWithSaltBytes(i) = plainTextBytes(i);
		}
		// Append salt bytes to the resulting array.
		for (int i = 0; i <= saltbytes.Length - 1; i++) {
			plainTextWithSaltBytes(plainTextBytes.Length + i) = saltbytes(i);
		}
		//Define cryptographic algorithm
		SHA512Managed sha = new SHA512Managed();
		//Define and fill hash
		byte[] Hash = sha.ComputeHash(plainTextWithSaltBytes);
		//Return hash as Base64
		return Convert.ToBase64String(Hash);

	}
}

Open in new window

0
 
LVL 4

Author Comment

by:asp_net2
ID: 37022075
Hi Dustin,

Ok, first of all let me thank you for choosing to help out with this post. It means alot to me and is a big part before I can finish my project not to mention the most important part which is signing up users but protecting their data.

Please forgive me if I repeat what you mentioned but I'm not as knowledable when it comes to this stuff but I have been trying very hard to learn it. I really want to learn this stuff and it's very important to my job, but I most importantly I really want to understand what it means and not just copy/paste.

I looked at the .NET Class Library and what I got from that was the following below. Please keep in mind you and kaufmed are both saying the same thing in regards to using Salt + Hash and I just want someone to look over my code to make sure I did it correctly and if not to tell me what it is that I need to fix and why.

I'm going to attach my current code that "Inserts data" which as you will see I'm trying to Salt + Hash the Password and I'm storing the Password into a field called "users_password" and then storing the Password Salt into a field called "users_password_salt". I'm not sure if I'm doing this correctly but please see my attached code for creating a new user and then logging that user in against his/her credentials.

Note: All of the code that I just attached works perfectly fine and I have no errors/problems at all I just want to make sure that I'm Salting and Hashing the Password correctlyl and storing it in the Database properly.

Database Field Names / Field Types:

users_password  varchar(50)
users_password_salt  varchar(50)



Thanks in advance!!!
CREATE USER CODE:

protected void btn_NewUser_Click(object sender, EventArgs e)
    {
        using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["HealthCourses"].ConnectionString))
        {
            SqlCommand cmd = new SqlCommand();
            cmd.CommandText = "HealthCourses_InsertUsers";
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Connection = conn;

            cmd.Parameters.AddWithValue("@c_id", SqlDbType.Int).Value = ddlClient.SelectedItem.Value;
            cmd.Parameters.AddWithValue("@bldg_id", SqlDbType.Int).Value = ddlBldgLocation.SelectedItem.Value;
            cmd.Parameters.AddWithValue("@s_id", SqlDbType.Int).Value = ddlState.SelectedItem.Value;
            cmd.Parameters.AddWithValue("@users_flname", SqlDbType.VarChar).Value = txtName.Text;
            cmd.Parameters.AddWithValue("@users_street_address", SqlDbType.VarChar).Value = txtHomeAddress.Text;
            cmd.Parameters.AddWithValue("@users_city", SqlDbType.VarChar).Value = txtCity.Text;
            cmd.Parameters.AddWithValue("@users_zip", SqlDbType.VarChar).Value = txtZipCode.Text;
            cmd.Parameters.AddWithValue("@users_phone", SqlDbType.VarChar).Value = txtHomePhone.Text;
            cmd.Parameters.AddWithValue("@users_work_ext", SqlDbType.VarChar).Value = txtWorkExtension.Text;
            cmd.Parameters.AddWithValue("@users_email", SqlDbType.VarChar).Value = txtEmailAddress.Text;
            cmd.Parameters.AddWithValue("@users_username", SqlDbType.VarChar).Value = txtUserName.Text;

            //Create instance of SHA512CryptoServiceProvider
            SHA512CryptoServiceProvider SHA512Hash = new SHA512CryptoServiceProvider();

            byte[] hashedBytes = null;
            UTF8Encoding encoder = new UTF8Encoding();

            string guid = System.Guid.NewGuid().ToString(); //36 long characters
            hashedBytes = SHA512Hash.ComputeHash(encoder.GetBytes(txtPassword.Text + guid));

            cmd.Parameters.AddWithValue("@users_password", SqlDbType.VarChar).Value = hashedBytes;
            cmd.Parameters.AddWithValue("@users_password_salt", SqlDbType.VarChar).Value = guid;

            try
            {
                conn.Open();

                cmd.ExecuteNonQuery();

                Response.Redirect("newuser_success.aspx");
            }

            catch (Exception ex)
            {
                lblInsertError.Text = ex.Message.ToString();
            }

            finally
            {
                conn.Close();
            }
        }
    }





LOGIN CODE:

protected void btn_ProgramInfoSignIn_Click(object sender, EventArgs e)
    {
        //Retrieve the guid from db
        string guid = String.Empty;

        using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["HealthCourses"].ConnectionString))
        {
            SqlCommand cmd = new SqlCommand();
            cmd.CommandText = "HealthCourses_LoginPassSalt";
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Connection = conn;

            cmd.Parameters.AddWithValue("@users_username", SqlDbType.VarChar).Value = txtUserName.Text;

            DataTable dtGuid = new DataTable();

            SqlDataAdapter adp = new SqlDataAdapter();
            adp.SelectCommand = cmd;
            adp.Fill(dtGuid);

            if (dtGuid != null && dtGuid.Rows.Count > 0)
            {
                guid = dtGuid.Rows[0]["users_password_salt"].ToString();

                SqlCommand cmdClientLogin = new SqlCommand();
                cmdClientLogin.CommandText = "HealthCourses_Login";
                cmdClientLogin.CommandType = CommandType.StoredProcedure;
                cmdClientLogin.Connection = conn;

                //Create instance of SHA512CryptoServiceProvider
                SHA512CryptoServiceProvider SHA512Hash = new SHA512CryptoServiceProvider();
                byte[] hashedBytes = null;
                UTF8Encoding encoder = new UTF8Encoding();
                hashedBytes = SHA512Hash.ComputeHash(encoder.GetBytes(txtPassword.Text + guid));

                cmdClientLogin.Parameters.AddWithValue("@users_username", SqlDbType.VarChar).Value = txtUserName.Text;
                cmdClientLogin.Parameters.AddWithValue("@users_password", SqlDbType.VarChar).Value = hashedBytes;

                conn.Open();

                SqlDataReader rdr = cmdClientLogin.ExecuteReader();

                if (rdr.HasRows && rdr.Read())
                {
                    rdr.Close();
                    conn.Close();
                    Session["UserNameSessionID"] = txtUserName.Text;
                    FormsAuthentication.RedirectFromLoginPage(txtPassword.Text, false);
                }
            }

            else
            {
                lblSignInError.Text = "Invalid Credentials!";
            }
        }
    }

Open in new window

0
 
LVL 4

Author Comment

by:asp_net2
ID: 37030388
@dusion:

Are you still able to assist?
0
 
LVL 14

Accepted Solution

by:
Dustin Hopkins earned 2000 total points
ID: 37050109
Sorry for the delay, Your code looks fine, I would change your sql datatype for the hash to varchar(max) or varchar(8000). Also if you plan to use a WHERE statement against the encrypted or salt values, you will want to change them to a case-sensitive collation.

Hope this helps,
Dustin
0

Featured Post

NEW Veeam Agent for Microsoft Windows

Backup and recover physical and cloud-based servers and workstations, as well as endpoint devices that belong to remote users. Avoid downtime and data loss quickly and easily for Windows-based physical or public cloud-based workloads!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article will inform Clients about common and important expectations from the freelancers (Experts) who are looking at your Gig.
Without even knowing it, most of us are using web applications on a daily basis.  In fact, Gmail and Yahoo email, Twitter, Facebook, and eBay are used by most of us daily—and they are web applications. We generally confuse these web applications to…
The viewer will learn how to create a basic form using some HTML5 and PHP for later processing. Set up your basic HTML file. Open your form tag and set the method and action attributes.: (CODE) Set up your first few inputs one for the name and …
Loops Section Overview
Suggested Courses

850 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question