2016-06-19 197 views
0

我试图在数据库中存储哈希密码。这里是我的代码:Bcrypt验证密码

string passwords = textBox2.Text; 
string salt = BCrypt.Net.BCrypt.GenerateSalt(12); 
string hashPwd = BCrypt.Net.BCrypt.HashPassword(passwords, salt); 
     try 
     { 
      SQLiteCommand command = new SQLiteCommand(); 
      connection.Open(); 
      command.Connection = connection; 
      command.CommandText = ((@"INSERT INTO acc (UserName, Pass) VALUES ('" + textBox1.Text + "','" + hashPwd+ "');")); 
      command.ExecuteNonQuery(); 
      connection.Close(); 
     } 
     catch (Exception ex) 
     { 
      MessageBox.Show("Error:" + ex.ToString()); 
      return; 
     } 

登录/验证码

  try 
      { 

      SQLiteDataAdapter sqlad = new SQLiteDataAdapter("SELECT COUNT(*) From acc WHERE Username = '" + textBox1.Text + "' AND Pass = '" + textBox2.Text + "' ", connection); 
      DataTable dt = new DataTable(); 
      sqlad.Fill(dt);` 
      string userid = dt.Rows[0]["UserName"].ToString(); 
      string password = dt.Rows[0]["Pass"].ToString(); 
      bool flag = BCrypt.Net.BCrypt.Verify(textBox2.Text, password); 

      if (userid == textBox1.Text && flag == true) 
      { 
       Form2 frm = new Form2(); 
       frm.Show(); 
      } 
      else 
      { 
       MessageBox.Show("Invalid UserId or password"); 
      } 
      } 
      catch (Exception ex) 
      { 
      MessageBox.Show(ex.ToString()); 
      return; 
      } 

我无法验证密码,我得到的错误,你能帮助我吗?还有一个问题,我应该在数据库中储存盐吗?

+2

为什么在你的SELECT语句,你有'并通过= ' “+ textBox2.Text +”''?数据库中的密码是散列的,大概'textBox2.Text'包含纯文本,所以这找不到任何东西。您还要返回计数,而不是“用户名”和“通过”列,因此这些将不在结果集中。最后,可能想要阅读SQL注入。 – steve16351

+0

如何将用户输入的密码与数据库中的哈希值进行比较? –

+0

@LuisVito看看[这篇文章](https://crackstation.net/hashing-security.htm),尤其是[本节](https://crackstation.net/hashing-security.htm#properhashing) 。相关步骤在此处列出。请考虑阅读完整的文章;这是一个很好的:-) – khlr

回答

2

有几个与你的代码的问题:

1 SQL注入

无论您的插入和验证码块容易受到SQL注入,因为它们允许你的文本从用户直接拿输入到执行的SQL字符串中,它们可以用来破坏登录检查或破坏数据库的漏洞。不要这样做!

2.您从数据库中选择的散列密码不会选择哈希密码..或任何感兴趣的东西。

想想你有什么在这里:

SQLiteDataAdapter sqlad = new SQLiteDataAdapter(@" 
    SELECT 
     COUNT(*) 
    From 
     acc 
    WHERE 
     Username = '" + textBox1.Text + "' 
     AND 
     Pass = '" + textBox2.Text + "' ", connection); 

所以,让我们说我给我的用户名是“史蒂夫”,密码为“你好”,这得到了散列以“ab123cdef”,并插入到你的acc表:

UserName Pass 
Steve  ab123cdef 

当我带着原来正确的用户名和密码来验证这一点,你的SELECT语句说:“给我行的数量与用户名‘史蒂夫’,并通过‘你好’”,这将适时归零。

您的代码应该在这里抛出异常:

string userid = dt.Rows[0]["UserName"].ToString(); 

由于结果集不包含用户名作为输出。

这是一个基本的小例子,它使用您选择的库来展示如何成功插入和验证密码。

关于如何处理盐,函数HashPassword已将salt加入密码哈希中,因此如果存储此输出,则存储salt。您在验证中使用的验证功能将处理并为您检查。

static void CreateUser(string username, string password) 
{ 
    if (UserExists(username)) 
     throw new InvalidOperationException("User already exists"); 

    string salt = BCrypt.Net.BCrypt.GenerateSalt(12); 
    // if you look at the hashed password, notice that it's prepended with the salt generated above 
    string hashedPassword = BCrypt.Net.BCrypt.HashPassword(password, salt); 

    using (SQLiteConnection connection = new SQLiteConnection(connectionString)) 
    { 
     connection.Open(); 
     SQLiteCommand insertCommand = new SQLiteCommand(connection); 
     insertCommand.CommandText = @"INSERT INTO acc (UserName, Pass) VALUES (@username, @hashedPass);"; 
     // use parameterised queries to mitigate sql injection 
     insertCommand.Parameters.Add(new SQLiteParameter("@username", username)); 
     insertCommand.Parameters.Add(new SQLiteParameter("@hashedPass", hashedPassword)); 
     insertCommand.ExecuteNonQuery(); 
    } 
} 

要验证一个给定的用户名/密码,我们需要从数据库返回的是哈希函数来验证对我们已经给出什么样的输出。

static bool Verify(string username, string password) 
{ 
    using (SQLiteConnection connection = new SQLiteConnection(connectionString)) 
    { 
     connection.Open(); 

     SQLiteCommand checkUserCommand = new SQLiteCommand(connection) 
     { 
      CommandText = @"SELECT Pass FROM acc WHERE UserName = @username;" 
     }; 

     checkUserCommand.Parameters.Add(new SQLiteParameter("@username", username)); 
     var hashedPassword = (string)checkUserCommand.ExecuteScalar();     
     return BCrypt.Net.BCrypt.Verify(password, hashedPassword);     
    } 
} 

用法会是这样的..

if (!UserExists(username)) 
{ 
    CreateUser(username, password); 
    Console.WriteLine("User {0} created", username); 
} 
else 
{ 
    bool loginOk = Verify(username, password); 
    Console.WriteLine("Login ok?: {0}", loginOk); 
} 
+0

非常感谢。我会阅读有关注射。 –