Salting and Hashing Using PBKDF2

I am trying to learn cryptography with storing passwords in a database using hashing and salting, so I decided to make a login system trying to implement this system.

My database consists of

  • UserID int PK
  • Varchar Username (250)
  • Salt varbinary (64)
  • Password varbinary (64)
  • Regdate datetime
  • Email varchar (250)

I use PBKDF2 , but it looks like this is not a hash / salting method, what if it is not?

If so, am I doing it right?

My keys

private const int SALT_SIZE = 64; private const int KEY_SIZE = 64; 

Insert data into a database

 public static void RegisterMe(string _username, string _password, string _email) { using (var cn = new SqlConnection(User.strcon)) { string _sqlins = @" INSERT INTO [User] ([Username],[Salt],[Password],[RegDate], [Email]) VALUES (@Username, @Salt, @Password, CURRENT_TIMESTAMP, @Email)"; var cmd = new SqlCommand(_sqlins, cn); cn.Open(); using (var deriveBytes = new Rfc2898DeriveBytes(_password, SALT_SIZE)) { byte[] salt = deriveBytes.Salt; byte[] key = deriveBytes.GetBytes(KEY_SIZE); // save salt and key to database cmd.Parameters.AddWithValue("@Username", _username); cmd.Parameters.AddWithValue("@Password", key); cmd.Parameters.AddWithValue("@Salt", salt); cmd.Parameters.AddWithValue("@Email", _email); } cmd.ExecuteNonQuery(); } } 

User Validation

 public bool IsValid(string _email, string _password) { using (var cn = new SqlConnection(strcon)) { byte[] salt = { }, key = { }; string _sql = @" SELECT SALT, [Password], UserID FROM [User] WHERE [Email] = @email"; SqlCommand cmd = new SqlCommand(_sql, cn); cmd.Parameters.AddWithValue("@email", _email); cn.Open(); SqlDataReader reader = cmd.ExecuteReader(); if (reader.Read()) { salt = reader.GetSqlBytes(0).Value; key = reader.GetSqlBytes(1).Value; reader.Dispose(); cmd.Dispose(); using (var deriveBytes = new Rfc2898DeriveBytes(_password, salt)) { byte[] newKey = deriveBytes.GetBytes(KEY_SIZE); // derive a 20-byte key return newKey.SequenceEqual(key); } } else { reader.Dispose(); cmd.Dispose(); return false; } } } 

My system works, it sets the data to the database in bytes, and if the user enters the correct password, it returns true. But is that right? Is it even hashing / salting?

+3
source share
1 answer

You basically go in the right direction, but I will point out some things to think about:

  • The default number of iterations of the PBKDF2 method may not be enough, and you may not want to leave the default value. I would recommend specifying the number of iterations of at least 10K.

  • On the other hand, the key size and salt size are calculated in bytes by this implementation. 64 bytes is too much. Storing both of 16 bytes should be enough. It is not recommended to use more than 20 bytes than the maximum size of the underlying hash function / HMAC. Switching to this will give an advantage to the attacker (this, according to many, is a design error in PBKDF2). Of course, you can set the varbinary size to a higher value to allow future updates.

  • It is recommended that you save the protocol number with a salt and hashed password. This allows you to update the circuit later and at each input, when the user is available to reset his password.

  • Insignificant point; MSDN does not indicate when salt is generated. I would check the randomness of the salt (check if it is different every time), and just ask the salt after calling getBytes to make sure the salt is really random, even if its implementation changes. Otherwise, create it yourself using a cryptographically secure random number generator.

+8
source

Source: https://habr.com/ru/post/892631/


All Articles