如何在数据库中存储和检索 Salt?
How to Store and retrieve Salt from and into a database?
我已经设法编写了一组方法来获取密码,向其添加盐,并将盐和散列密码存储在数据库中。
但是当我尝试检索并打印盐时,它会打印 System.byte[]
而不是盐字符串。我认为 return 类型的方法存在问题。这是我的方法,
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
}
}
数据库结构
用于保存到数据库中的代码
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
希望能解决这个问题。
But when I try to retrieve and print the salt it prints System.byte[] instead of salt string. Hoping to solve this issue.
如果没有给定字符串,WriteLine 和大多数类似的代码将获取一个对象并对其调用 ToString()
。
ToString()
returns 的默认实现 class 名称作为字符串 - System.byte[]
在您的情况下 - 然后可以打印。 类 需要覆盖 ToString()
如果他们想要一些对调试更有用的东西。例如,字符串会返回自身或自身的副本(我认为是前者,但我必须查看代码)。
也没有自动尝试遍历数组或其他集合。它只会自动打印 class 名称。如果你想打印一个集合的内容,你必须手动迭代它 - 并且可能递归地 - 添加适当的分隔符和注释字符。一个简单的 foreach 应该适用于这种情况。但是我不确定你想在这里如何将每个字节转换成字符串或字符。通常您会将一个字节打印为 2 位十六进制值。
找到了,问题出在数据库中盐列的数据类型,它设置为 varBinary 但 return 方法 generateSalt()
的类型是 string 并且该字符串被发送以存储到数据库中。所以我所要做的就是将数据库中 salt 列的数据类型 更改为 varchar.
我已经设法编写了一组方法来获取密码,向其添加盐,并将盐和散列密码存储在数据库中。
但是当我尝试检索并打印盐时,它会打印 System.byte[]
而不是盐字符串。我认为 return 类型的方法存在问题。这是我的方法,
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
}
}
数据库结构
用于保存到数据库中的代码
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
希望能解决这个问题。
But when I try to retrieve and print the salt it prints System.byte[] instead of salt string. Hoping to solve this issue.
如果没有给定字符串,WriteLine 和大多数类似的代码将获取一个对象并对其调用 ToString()
。
ToString()
returns 的默认实现 class 名称作为字符串 - System.byte[]
在您的情况下 - 然后可以打印。 类 需要覆盖 ToString()
如果他们想要一些对调试更有用的东西。例如,字符串会返回自身或自身的副本(我认为是前者,但我必须查看代码)。
也没有自动尝试遍历数组或其他集合。它只会自动打印 class 名称。如果你想打印一个集合的内容,你必须手动迭代它 - 并且可能递归地 - 添加适当的分隔符和注释字符。一个简单的 foreach 应该适用于这种情况。但是我不确定你想在这里如何将每个字节转换成字符串或字符。通常您会将一个字节打印为 2 位十六进制值。
找到了,问题出在数据库中盐列的数据类型,它设置为 varBinary 但 return 方法 generateSalt()
的类型是 string 并且该字符串被发送以存储到数据库中。所以我所要做的就是将数据库中 salt 列的数据类型 更改为 varchar.