试图将密码存储到数据库

时间:2009-02-25 09:32:23

标签: c# .net database linq-to-sql

我正在测试哈希和盐密码。 好吧,我可以向数据库添加哈希和盐密码,但我坚持从数据库存储密码。 我有一个简单的数据库:

                                Table
                               _______

                               ProvaHS
                               --------
                          (PK) LoginID   int 
                               UserName  nvarchar(50)
                               Password  nvarchar(50)
                               Salt      nvarchar(50)

所以我创建了一个表单,用这段代码将新记录添加到数据库中:

 public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();
    }

    #region SALT
    public static class PasswordCrypto
    {
        private static SHA1CryptoServiceProvider Hasher = new SHA1CryptoServiceProvider();
        //Private Hasher As New MD5CryptoServiceProvider()

        static internal string GetSalt(int saltSize)
        {
            byte[] buffer = new byte[saltSize + 1];
            RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
            rng.GetBytes(buffer);
            return Convert.ToBase64String(buffer);
        }

        static internal string HashEncryptString(string s)
        {
            byte[] clearBytes = Encoding.UTF8.GetBytes(s);
            byte[] hashedBytes = Hasher.ComputeHash(clearBytes);
            return Convert.ToBase64String(hashedBytes);
        }

        static internal string HashEncryptStringWithSalt(string s, string salt)
        {
            return HashEncryptString(salt + s);
        }
    }
    #endregion

    private void GetSalt()
    {
        this.textBoxSalt.Text = PasswordCrypto.GetSalt(16);
    }

      private void GetSaltHash()
      {
          // It's how i salt and hash the password before to save it to the Database
          this.textBoxPassword.Text = PasswordCrypto.HashEncryptStringWithSalt(this.textBoxClear.Text, this.textBoxSalt.Text);
      }

    private void GetHash()
    {
        //Demo purposes -- this is an unsalted hash
        this.textBoxClear.Text = PasswordCrypto.HashEncryptString(this.textBoxPassword.Text);
    }

    private void Add(object sender, RoutedEventArgs e)
    {
        DataClasses1DataContext dc = new DataClasses1DataContext();

        try
        {
            if (textBoxUserName.Text.Length > 0)
            {
                ProvaH tab = new ProvaH();
                tab.UserName = textBoxUserName.Text;
                tab.Password = textBoxPassword.Text;
                tab.Salt = textBoxSalt.Text;
                dc.ProvaHs.InsertOnSubmit(tab);
                dc.SubmitChanges();

            }
        }
        catch (Exception ex)
        {

            MessageBox.Show("Error!!!");
        }

    }

    private void HashButton(object sender, RoutedEventArgs e)
    {
        GetHash();
    }

    private void SaltButton(object sender, RoutedEventArgs e)
    {
        GetSalt();
    }

    private void HashSaltButton(object sender, RoutedEventArgs e)
    {
        GetSaltHash();
    }

    private void Close_W(object sender, RoutedEventArgs e)
    {
        this.Close();
    }

}

}

  • 使用这种方法我可以对数据库进行加盐,散列和保存密码..(以下是建议StackOverflow的成员)谢谢..

现在我正在测试数据库中的商店密码,这里我遇到了麻烦......

  public partial class Login : Window
{
    public Login()
    {
        InitializeComponent();
    }
    #region SALT
    public static class PasswordCrypto
    {
        private static SHA1CryptoServiceProvider Hasher = new SHA1CryptoServiceProvider();
        //Private Hasher As New MD5CryptoServiceProvider()

        static internal string GetSalt(int saltSize)
        {
            byte[] buffer = new byte[saltSize + 1];
            RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
            rng.GetBytes(buffer);
            return Convert.ToBase64String(buffer);
        }

        static internal string HashEncryptString(string s)
        {
            byte[] clearBytes = Encoding.UTF8.GetBytes(s);
            byte[] hashedBytes = Hasher.ComputeHash(clearBytes);
            return Convert.ToBase64String(hashedBytes);
        }

        static internal string HashEncryptStringWithSalt(string s, string salt)
        {
            return HashEncryptString(salt + s);
        }
    }
    #endregion

    private void closs(object sender, RoutedEventArgs e)
    {
        this.Close();
    }


      public bool ValidateApplicationUser(string userName, string password)
      {

        bool OK = false;
          DataClasses1DataContext dc = new DataClasses1DataContext();

          object saltValue = from c in dc.ProvaHs where c.UserName == userName  select c.Salt;
          if (!(saltValue == System.DBNull.Value))
          {
              password = PasswordCrypto.HashEncryptStringWithSalt(passwordTextBox.Password, saltValue.ToString());

          }
          var query = from c in dc.ProvaHs where c.UserName == userName && c.Password == password select new { c.LoginID, c.UserName, c.Password };
          if (query.Count() != 0)
          {
              return true;
          }
       return false;
      }

    private void Confirm(object sender, RoutedEventArgs e)
    {
           bool authenticated = true;

        if (usernameTextBox.Text != "" && passwordTextBox.Password.ToString() != "") 
           {
               authenticated = ValidateApplicationUser(usernameTextBox.Text, passwordTextBox.Password.ToString());
           }
           if (!authenticated)
           {
               MessageBox.Show("Invalid login. Try again.");
           }
           else
           {
               MessageBox.Show("Aaaaahhhh.JOB DONE!!!!....");
           }
    }
}

当我调试应用程序时,我总是在此代码行收到错误:   “query”中的if(query.Count()!= 0)=空:“枚举没有产生结果” 你有什么建议如何解决这个错误并在我的情况下从数据库存储密码? 感谢

3 个答案:

答案 0 :(得分:2)

尝试:

public bool ValidateApplicationUser(string userName, string password)
{
  DataClasses1DataContext dc = new DataClasses1DataContext();

  var saltValue = dc.ProvaHs.Where(c => c.UserName == userName)
                            .Select(c => c.Salt)
                            .SingleOrDefault();

  if (saltValue == null) return false;

  password = PasswordCrypto.HashEncryptStringWithSalt(passwordTextBox.Password, saltValue.ToString());

  return dc.ProvaHs.Any(c => c.UserName == userName && c.Password == password);
}

答案 1 :(得分:2)

不要使用SHA1。使用SHA256,实际随机盐和很多(即8000)SHA256迭代。因为SHA是为速度而设计的,但这意味着字典攻击很快。还有更好的方法,比如scrypt算法。或SRP协议。

答案 2 :(得分:1)

(不是严格回答你的问题,但无论如何我都会添加它)

您是否只想对输出进行十六进制编码(而不是base64)?

public static string SHA256Hash(string Data)  
{  
    SHA256 sha = new SHA256Managed();  
    byte[] hash = sha.ComputeHash( Encoding.ASCII.GetBytes(Data) );  

    StringBuilder stringBuilder = new StringBuilder();  
    foreach( byte b in hash )   
    {  
        stringBuilder.AppendFormat("{0:x2}", b);  
    }  
    return stringBuilder.ToString();  
}

(那是SHA-2,只需用SHA1交换SHA256,用SHA1管理用SHA256管理交换)。

Other snippet implementations here