从 SQL 服务器数据库检索条目的 C# HASH 算法逻辑
C# HASH Algorithm logic for retrieved entry from SQL Server database
我一直在努力解决这个问题的逻辑,以及如何使用 HASH 算法来检查从 SQL 服务器数据库中检索到的条目是否与用户输入的条目相匹配。
下面的代码确实有效,我无法理解的是从 SQL 服务器数据库检索的字段应该放在代码中的什么位置,以及它如何与输入的条目相匹配用户。
下面的代码确实包含用于保存修改后的 HASH 条目的代码。
SQL 服务器数据库中的条目保存为 Varbinary
'0xD94C0F10760D83BC35C0786C674B5F8F'
如有任何帮助,我们将不胜感激。
string[] passwordargs = new string[] { "turkey", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
//If no file name is specified, write usage text.
if (passwordargs.Length == 0)
{
Console.WriteLine(usageText);
}
else
{
string pwd1 = passwordargs[0];
// Create a byte array to hold the random value.
byte[] salt1 = new byte[8];
using (RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider())
{
// Fill the array with a random value.
rngCsp.GetBytes(salt1);
}
//data1 can be a string or contents of a file.
string data1 = "Some test data";
//The default iteration count is 1000 so the two methods use the same iteration count.
int myIterations = 1000;
try
{
Rfc2898DeriveBytes k1 = new Rfc2898DeriveBytes(pwd1, salt1, myIterations);
Rfc2898DeriveBytes k2 = new Rfc2898DeriveBytes(pwd1, salt1);
// Encrypt the data.
Aes encAlg = Aes.Create();
encAlg.Key = k1.GetBytes(16);
MemoryStream encryptionStream = new MemoryStream();
CryptoStream encrypt = new CryptoStream(encryptionStream, encAlg.CreateEncryptor(), CryptoStreamMode.Write);
byte[] utfD1 = new System.Text.UTF8Encoding(false).GetBytes(data1);
encrypt.Write(utfD1, 0, utfD1.Length);
encrypt.FlushFinalBlock();
encrypt.Close();
byte[] edata1 = encryptionStream.ToArray();
string encryptString = Convert.ToBase64String(edata1.ToArray());
string queryStmt = "UPDATE [dbo].[Staff] SET [MEMWORD] = (@Content) WHERE STAFF_ID=7";
using (SqlConnection _con = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["AppDb"].ConnectionString))
using (SqlCommand _cmd = new SqlCommand(queryStmt, _con))
{
SqlParameter param = _cmd.Parameters.Add("@Content", SqlDbType.VarBinary);
param.Value = edata1;
_con.Open();
_cmd.ExecuteNonQuery();
_con.Close();
}
k1.Reset();
// Try to decrypt, thus showing it can be round-tripped.
Aes decAlg = Aes.Create();
decAlg.Key = k2.GetBytes(16);
decAlg.IV = encAlg.IV;
MemoryStream decryptionStreamBacking = new MemoryStream();
CryptoStream decrypt = new CryptoStream(decryptionStreamBacking, decAlg.CreateDecryptor(), CryptoStreamMode.Write);
decrypt.Write(edata1, 0, edata1.Length);
decrypt.Flush();
decrypt.Close();
k2.Reset();
string data2 = new UTF8Encoding(false).GetString(decryptionStreamBacking.ToArray());
if (!data1.Equals(data2))
{
Console.WriteLine("Error: The two values are not equal.");
}
else
{
Console.WriteLine("The two values are equal.");
Console.WriteLine("k1 iterations: {0}", k1.IterationCount);
Console.WriteLine("k2 iterations: {0}", k2.IterationCount);
}
}
catch (Exception e)
{
Console.WriteLine("Error: {0}", e);
string error = e.ToString();
}
}
你的意思是
The code below does work ...
if (!data1.Equals(data2))
在你期望的时候是相等的?
根据我的理解,你设置了 data1 = "Some test data"
并且在我们到达终点之前不会改变。
而 data2
需要做更多的工作,但从上到下将其分解:
- 将
data1
存储在 utfD1
中作为 UTF-8 字节数组 -> byte[] utfD1 = new System.Text.UTF8Encoding(false).GetBytes(data1);
- 将
utfD1
写入流encrypt
(encryptionStream
是CryptoStream的底层流)-> encrypt.Write(utfD1, 0, utfD1.Length);
- 写入
encryptionStream
int edata1
字节数组-> byte[] edata1 = encryptionStream.ToArray();
- 将
edata1
写入decryptionStreamBacking
(因为它是decrypt
的底层流)-> decrypt.Write(edata1, 0, edata1.Length);
decryptionStreamBacking
解码 UTF-8 字节数组并将其存储在 data2
->
string data2 = new UTF8Encoding(false).GetString(decryptionStreamBacking.ToArray());
所以对我来说,string data2 = data1
看起来像是一种奇特的说法,而且数据库是只写方案。您只更新了数据库中的一个值,但没有从中读取任何内容。
感谢您的所有帮助和建议,我们现在已经得到了工作代码。
我们不得不改变
byte[] salt1 = new byte[8];
到
byte[] salt1 = new byte[]{0, 1, 2, 3, 4, 5, 6, 7};
否则 salt1 每次都会不同,这将创建不同的加密,不允许输入的密码与数据库中保存的内容配对。
谢谢大家的意见。
byte[] returned_Data;
string[] passwordargs = new string[] { "turkey", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
//If no file name is specified, write usage text.
if (passwordargs.Length == 0)
{
Console.WriteLine(usageText);
}
else
{
string pwd1 = passwordargs[0];
byte[] salt1 = new byte[]{0,1 ,2, 3,4, 5,6, 7};
using (RNGCryptoServiceProvider rngCsp = new
RNGCryptoServiceProvider())
{
// Fill the array with a random value.
rngCsp.GetBytes(salt1);
}
//data1 can be a string or contents of a file.
string data1 = "Some test data";
//The default iteration count is 1000 so the two methods use the same iteration count.
int myIterations = 1000;
try
{
Rfc2898DeriveBytes k1 = new Rfc2898DeriveBytes(pwd1, salt1,myIterations);
Rfc2898DeriveBytes k2 = new Rfc2898DeriveBytes(pwd1, salt1);
// Encrypt the data.
Aes encAlg = Aes.Create();
encAlg.Key = k1.GetBytes(16);
MemoryStream encryptionStream = new MemoryStream();
CryptoStream encrypt = new CryptoStream(encryptionStream,
encAlg.CreateEncryptor(), CryptoStreamMode.Write);
byte[] utfD1 = new System.Text.UTF8Encoding(false).GetBytes(
data1);
encrypt.Write(utfD1, 0, utfD1.Length);
encrypt.FlushFinalBlock();
encrypt.Close();
byte[] edata1 = encryptionStream.ToArray();
string queryStmt = "UPDATE [dbo].[Staff] SET [PASSWORD] = (@Content) WHERE STAFF_ID=7";
using (SqlConnection _con = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["Conn"].ConnectionString))
using (SqlCommand _cmd = new SqlCommand(queryStmt, _con))
{
SqlParameter param = _cmd.Parameters.Add("@Content", SqlDbType.VarBinary);
param.Value = edata1;
_con.Open();
_cmd.ExecuteNonQuery();
_con.Close();
}
using (SqlConnection sqlconnection = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["Conn"].ConnectionString))
{
sqlconnection.Open();
string selectQuery = string.Format(@"Select [PASSWORD] From [dbo].[Staff] Where STAFF_ID={0}", 7);
SqlCommand selectCommand = new SqlCommand(selectQuery, sqlconnection);
SqlDataReader reader = selectCommand.ExecuteReader();
if (reader.Read())
{
returned_Data = (byte[])reader[0];
string strData = Encoding.UTF8.GetString(returned_Data);
Console.WriteLine(strData);
if(!edata1.SequenceEqual(returned_Data))
{
Console.WriteLine("Error: The two values are not equal.");
}
else
{
Console.WriteLine("The two values are equal.");
Console.WriteLine("k1 iterations: {0}", k1.IterationCount);
Console.WriteLine("k2 iterations: {0}", k2.IterationCount);
}
}
}
我一直在努力解决这个问题的逻辑,以及如何使用 HASH 算法来检查从 SQL 服务器数据库中检索到的条目是否与用户输入的条目相匹配。
下面的代码确实有效,我无法理解的是从 SQL 服务器数据库检索的字段应该放在代码中的什么位置,以及它如何与输入的条目相匹配用户。
下面的代码确实包含用于保存修改后的 HASH 条目的代码。
SQL 服务器数据库中的条目保存为 Varbinary
'0xD94C0F10760D83BC35C0786C674B5F8F'
如有任何帮助,我们将不胜感激。
string[] passwordargs = new string[] { "turkey", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
//If no file name is specified, write usage text.
if (passwordargs.Length == 0)
{
Console.WriteLine(usageText);
}
else
{
string pwd1 = passwordargs[0];
// Create a byte array to hold the random value.
byte[] salt1 = new byte[8];
using (RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider())
{
// Fill the array with a random value.
rngCsp.GetBytes(salt1);
}
//data1 can be a string or contents of a file.
string data1 = "Some test data";
//The default iteration count is 1000 so the two methods use the same iteration count.
int myIterations = 1000;
try
{
Rfc2898DeriveBytes k1 = new Rfc2898DeriveBytes(pwd1, salt1, myIterations);
Rfc2898DeriveBytes k2 = new Rfc2898DeriveBytes(pwd1, salt1);
// Encrypt the data.
Aes encAlg = Aes.Create();
encAlg.Key = k1.GetBytes(16);
MemoryStream encryptionStream = new MemoryStream();
CryptoStream encrypt = new CryptoStream(encryptionStream, encAlg.CreateEncryptor(), CryptoStreamMode.Write);
byte[] utfD1 = new System.Text.UTF8Encoding(false).GetBytes(data1);
encrypt.Write(utfD1, 0, utfD1.Length);
encrypt.FlushFinalBlock();
encrypt.Close();
byte[] edata1 = encryptionStream.ToArray();
string encryptString = Convert.ToBase64String(edata1.ToArray());
string queryStmt = "UPDATE [dbo].[Staff] SET [MEMWORD] = (@Content) WHERE STAFF_ID=7";
using (SqlConnection _con = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["AppDb"].ConnectionString))
using (SqlCommand _cmd = new SqlCommand(queryStmt, _con))
{
SqlParameter param = _cmd.Parameters.Add("@Content", SqlDbType.VarBinary);
param.Value = edata1;
_con.Open();
_cmd.ExecuteNonQuery();
_con.Close();
}
k1.Reset();
// Try to decrypt, thus showing it can be round-tripped.
Aes decAlg = Aes.Create();
decAlg.Key = k2.GetBytes(16);
decAlg.IV = encAlg.IV;
MemoryStream decryptionStreamBacking = new MemoryStream();
CryptoStream decrypt = new CryptoStream(decryptionStreamBacking, decAlg.CreateDecryptor(), CryptoStreamMode.Write);
decrypt.Write(edata1, 0, edata1.Length);
decrypt.Flush();
decrypt.Close();
k2.Reset();
string data2 = new UTF8Encoding(false).GetString(decryptionStreamBacking.ToArray());
if (!data1.Equals(data2))
{
Console.WriteLine("Error: The two values are not equal.");
}
else
{
Console.WriteLine("The two values are equal.");
Console.WriteLine("k1 iterations: {0}", k1.IterationCount);
Console.WriteLine("k2 iterations: {0}", k2.IterationCount);
}
}
catch (Exception e)
{
Console.WriteLine("Error: {0}", e);
string error = e.ToString();
}
}
你的意思是
The code below does work ...
if (!data1.Equals(data2))
在你期望的时候是相等的?
根据我的理解,你设置了 data1 = "Some test data"
并且在我们到达终点之前不会改变。
而 data2
需要做更多的工作,但从上到下将其分解:
- 将
data1
存储在utfD1
中作为 UTF-8 字节数组 ->byte[] utfD1 = new System.Text.UTF8Encoding(false).GetBytes(data1);
- 将
utfD1
写入流encrypt
(encryptionStream
是CryptoStream的底层流)->encrypt.Write(utfD1, 0, utfD1.Length);
- 写入
encryptionStream
intedata1
字节数组->byte[] edata1 = encryptionStream.ToArray();
- 将
edata1
写入decryptionStreamBacking
(因为它是decrypt
的底层流)->decrypt.Write(edata1, 0, edata1.Length);
decryptionStreamBacking
解码 UTF-8 字节数组并将其存储在data2
->string data2 = new UTF8Encoding(false).GetString(decryptionStreamBacking.ToArray());
所以对我来说,string data2 = data1
看起来像是一种奇特的说法,而且数据库是只写方案。您只更新了数据库中的一个值,但没有从中读取任何内容。
感谢您的所有帮助和建议,我们现在已经得到了工作代码。
我们不得不改变 byte[] salt1 = new byte[8]; 到 byte[] salt1 = new byte[]{0, 1, 2, 3, 4, 5, 6, 7};
否则 salt1 每次都会不同,这将创建不同的加密,不允许输入的密码与数据库中保存的内容配对。
谢谢大家的意见。
byte[] returned_Data;
string[] passwordargs = new string[] { "turkey", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
//If no file name is specified, write usage text.
if (passwordargs.Length == 0)
{
Console.WriteLine(usageText);
}
else
{
string pwd1 = passwordargs[0];
byte[] salt1 = new byte[]{0,1 ,2, 3,4, 5,6, 7};
using (RNGCryptoServiceProvider rngCsp = new
RNGCryptoServiceProvider())
{
// Fill the array with a random value.
rngCsp.GetBytes(salt1);
}
//data1 can be a string or contents of a file.
string data1 = "Some test data";
//The default iteration count is 1000 so the two methods use the same iteration count.
int myIterations = 1000;
try
{
Rfc2898DeriveBytes k1 = new Rfc2898DeriveBytes(pwd1, salt1,myIterations);
Rfc2898DeriveBytes k2 = new Rfc2898DeriveBytes(pwd1, salt1);
// Encrypt the data.
Aes encAlg = Aes.Create();
encAlg.Key = k1.GetBytes(16);
MemoryStream encryptionStream = new MemoryStream();
CryptoStream encrypt = new CryptoStream(encryptionStream,
encAlg.CreateEncryptor(), CryptoStreamMode.Write);
byte[] utfD1 = new System.Text.UTF8Encoding(false).GetBytes(
data1);
encrypt.Write(utfD1, 0, utfD1.Length);
encrypt.FlushFinalBlock();
encrypt.Close();
byte[] edata1 = encryptionStream.ToArray();
string queryStmt = "UPDATE [dbo].[Staff] SET [PASSWORD] = (@Content) WHERE STAFF_ID=7";
using (SqlConnection _con = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["Conn"].ConnectionString))
using (SqlCommand _cmd = new SqlCommand(queryStmt, _con))
{
SqlParameter param = _cmd.Parameters.Add("@Content", SqlDbType.VarBinary);
param.Value = edata1;
_con.Open();
_cmd.ExecuteNonQuery();
_con.Close();
}
using (SqlConnection sqlconnection = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["Conn"].ConnectionString))
{
sqlconnection.Open();
string selectQuery = string.Format(@"Select [PASSWORD] From [dbo].[Staff] Where STAFF_ID={0}", 7);
SqlCommand selectCommand = new SqlCommand(selectQuery, sqlconnection);
SqlDataReader reader = selectCommand.ExecuteReader();
if (reader.Read())
{
returned_Data = (byte[])reader[0];
string strData = Encoding.UTF8.GetString(returned_Data);
Console.WriteLine(strData);
if(!edata1.SequenceEqual(returned_Data))
{
Console.WriteLine("Error: The two values are not equal.");
}
else
{
Console.WriteLine("The two values are equal.");
Console.WriteLine("k1 iterations: {0}", k1.IterationCount);
Console.WriteLine("k2 iterations: {0}", k2.IterationCount);
}
}
}