从 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 需要做更多的工作,但从上到下将其分解:

  1. data1 存储在 utfD1 中作为 UTF-8 字节数组 -> byte[] utfD1 = new System.Text.UTF8Encoding(false).GetBytes(data1);
  2. utfD1写入流encryptencryptionStream是CryptoStream的底层流)-> encrypt.Write(utfD1, 0, utfD1.Length);
  3. 写入encryptionStream int edata1字节数组-> byte[] edata1 = encryptionStream.ToArray();
  4. edata1写入decryptionStreamBacking(因为它是decrypt的底层流)-> decrypt.Write(edata1, 0, edata1.Length);
  5. decryptionStreamBacking 解码 UTF-8 字节数组并将其存储在 data2 ->
  6. 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);
                        }
                    }
                }