我正在测试哈希和盐密码。 好吧,我可以向数据库添加哈希和盐密码,但我坚持从数据库存储密码。 我有一个简单的数据库:
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();
}
}
}
现在我正在测试数据库中的商店密码,这里我遇到了麻烦......
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)=空:“枚举没有产生结果” 你有什么建议如何解决这个错误并在我的情况下从数据库存储密码? 感谢
答案 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管理交换)。