Avishka Dambawinna
Avishka Dambawinna

Reputation: 1215

How to Store and retrieve Salt from and into a database?

I have managed to write a set of methods to get password, add salt to it, and store salt and hashed password in a database. But when I try to retrieve and print the salt it prints System.byte[] instead of salt string. I think there's a problem with return types of methods. Here are my methods,

class HashSalt
    {

        private readonly int num_of_iterations;

        // --- constructor to initialize num_of_iterations
        public HashSalt(int numOfIterations)
        {
            num_of_iterations = numOfIterations;
        }

        // --- Generate Salt ---
        public string  generateSalt()
        {
            var salt = new byte[32];

            var randomProvider = new RNGCryptoServiceProvider();
            randomProvider.GetBytes(salt);

            return Convert.ToBase64String(salt);        // returns salt as a string
        }

        // --- converts salt string into byte[]
        public byte[] saltToByte(string salt)
        {
            var byteSalt = Convert.FromBase64String(salt);
            return byteSalt;
        }

        // --- Generate hash of(pass+salt) ---
        public string generateHash(string password, byte[] salt)
        {

            var rfc2898 = new Rfc2898DeriveBytes(password, salt, num_of_iterations);

            var Password = rfc2898.GetBytes(32);    // gives 32 byte encoded password

            return Convert.ToBase64String(Password);    // returns hash
        }
    }

Database structure enter image description here

Code used to save into database

DbHandler db = new DbHandler();
                MySqlCommand cmd = new MySqlCommand("INSERT INTO `student`(`indexno`,`firstname`,`lastname`,`address`,`gender`,`dob`,`email`,`faculty`,`mobile`,`password`,`salt`)VALUES(@index, @firstname, @lastname, @address, @gender, @dob, @email, @faculty, @mobile, @password, @salt);", db.getConnection());


                var salt = hashSalt.generateSalt();  // generates random salt type string
                var byteSalt = hashSalt.saltToByte(salt);   // gets byte[] from salt string

                cmd.Parameters.Add("@index", MySqlDbType.VarChar).Value = txtindex.Text;
                cmd.Parameters.Add("@firstname", MySqlDbType.VarChar).Value = txtfname.Text;
                cmd.Parameters.Add("@lastname", MySqlDbType.VarChar).Value = txtlname.Text;
                cmd.Parameters.Add("@address", MySqlDbType.VarChar).Value = txtaddress.Text;
                cmd.Parameters.Add("@gender", MySqlDbType.VarChar).Value = getGender();
                cmd.Parameters.Add("@dob", MySqlDbType.Date).Value = dateDob.Value.Date;
                cmd.Parameters.Add("@email", MySqlDbType.VarChar).Value = txtemail.Text;
                cmd.Parameters.Add("@faculty", MySqlDbType.VarChar).Value = cmbfaculty.GetItemText(cmbfaculty.SelectedItem);
                cmd.Parameters.Add("@mobile", MySqlDbType.VarChar).Value = txtmobile.Text;
                cmd.Parameters.Add("@password", MySqlDbType.VarChar).Value = hashSalt.generateHash(txtpassword.Text, byteSalt); // get (password+salt) hashed from db 
                cmd.Parameters.Add("@salt", MySqlDbType.VarBinary).Value = salt;

                db.openConnection();    // open connection
                // execute query
                if (cmd.ExecuteNonQuery() == 1)
                {
                    MessageBox.Show("Record added!", "Success!", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                else
                {
                    MessageBox.Show("Failed!, please retry", "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                db.openConnection();    // close connection

Hoping to solve this issue.

Upvotes: 0

Views: 655

Answers (2)

Christopher
Christopher

Reputation: 9804

But when I try to retrieve and print the salt it prints System.byte[] instead of salt string. Hoping to solve this issue.

If not given a String, WriteLine and most similar code will take a object and call ToString() on it.

The default implementation of ToString() returns the class name as a string - System.byte[] in your case - which can then be printed. Classes need to override ToString() if they want something a bit more useful for debugging. String for example does, returning itself or a copy of itself (I think the former, but I would have to look into the code).

There is no automatic that will try to iterate over arrays or other collections either. It will only automatically print the class name. If you want the contents of a collection printed, you have to iterate over it manually - and potentially recursively - adding proper separator and annotation chars. A simple foreach should do for this case. However I am not sure how you want to convert each byte into a string or char here. Usually you would print one byte as a 2 digit hexadecimal value.

Upvotes: 1

Avishka Dambawinna
Avishka Dambawinna

Reputation: 1215

Found it, the problem is with the datatype of the salt column in the database, it set to varBinary but return type of the method generateSalt() is string and that string is send to store into the database. So all I had to do is change the datatype of salt column in the database to varchar.

Upvotes: 0

Related Questions