在过去,当处理密码时,我总是在我的数据存储中分别存储一个盐密码和一个散列密码。今天,我希望更新一些遗留代码,以使用RFC2898散列值。我偶然发现了来自System.Web.Helpers的Crypto.Hash方法。看起来这些将为我做大部分繁重的工作。有GenerateSalt()、HashPassword()和VerifyHashedPassword()方法。HashPassword()和VerifyHashedPassword()方法不接受Salt值。HashPassword()方法的MSDN文档中写道:
“生成的哈希字节流的格式为{0x00,salt,subkey},它在返回之前采用base-64编码。”
我需要担心盐吗?文档似乎说盐将自动生成并存储在base-64编码值中?这是正确的吗?我只需要存储从HashPassword()返回的字符串
发布于 2013-07-20 11:01:21
回答
所有密码都需要加盐,以便安全地散列它们。然而,在这种情况下,您是正确的。System.Web.Helpers.Crypto会为你创建一个salt。您不需要创建一个。它存储在由Crypto.HashPassword()返回的字符串中。
示例
你所需要做的就是这样。
using System.Web.Helpers;
public void SavePassword(string unhashedPassword)
{
string hashedPassword = Crypto.HashPassword(unhashedPassword);
//Save hashedPassword somewhere that you can retrieve it again.
//Don't save unhashedPassword! Just let it go.
}
public bool CheckPassword(string unhashedPassword)
{
string savedHashedPassword = //get hashedPassword from where you saved it
return Crypto.VerifyHashedPassword(savedHashedPassword, unhashedPassword)
}更多信息
如果你想看Crypto类的源代码,可以查看here.
发布于 2014-07-01 15:14:58
我只想分享这篇文章:
http://forums.asp.net/t/1842429.aspx?System+Web+Helpers+Crypto+HashPassword
你好,
我一直在研究System.Web.Helpers中新的Crypto HashPassword和VerifyMethod方法。
这两种方法都使用了Salt,但它们都不返回Salt,只返回Hash。
我不需要Salt把它存储在数据库里吗?我是不是遗漏了什么?
谢谢,
米格尔
。。
您将在用户创建帐户时生成salt,然后在调用HashPassword之前将其附加到
。然后将该盐和散列密码存储在数据库中。在验证凭据时,只需在调用VerifyHashedPassword之前从数据库中读取salt并将其附加到登录的密码之后。BrockAllen
。。
不确定我是否理解它...因为在HashPassword中,Salt是在方法内部生成的:
米格尔
// Method in Crypto class
public static string HashPassword(string password)
{
if (password == null)
{
throw new ArgumentNullException("password");
}
// Produce a version 0 (see comment above) password hash.
byte[] salt;
byte[] subkey;
using (var deriveBytes = new Rfc2898DeriveBytes(password, SaltSize, PBKDF2IterCount))
{
salt = deriveBytes.Salt;
subkey = deriveBytes.GetBytes(PBKDF2SubkeyLength);
}
byte[] outputBytes = new byte[1 + SaltSize + PBKDF2SubkeyLength];
Buffer.BlockCopy(salt, 0, outputBytes, 1, SaltSize);
Buffer.BlockCopy(subkey, 0, outputBytes, 1 + SaltSize, PBKDF2SubkeyLength);
return Convert.ToBase64String(outputBytes);
}。。
BrockAllen 2012年9月11日下午07:50
是的,忽略这一点--它是Rfc2898DeriveBytes的内部盐,它派生自密码,所以在存储密码的上下文中,它不是真正的盐,因为它总是为相同的密码重新创建。您将仍然希望在密码字符串级执行您自己的salt。所以就像这样:
public void CreateAccount(string username, string password)
{
var salt = Crypto.GenerateSalt();
var saltedPassword = password + salt;
var hashedPassword = Crypto.HashPassword(saltedPassword);
CreateAccount(username, salt, hashedPassword);
}
public void Verify(string username, string password)
{
var salt = GetSaltForUserFromDatabase(username);
var hashedPassword = GetHashedPasswordForUserFromDatabase(username);
var saltedPassword = password + salt;
if (Crypto.VerifyHashedPassword(hashedPassword, saltedPassword))
{
// valid password for this username
}
}这将允许您在数据库中存储您的盐以及散列的加盐密码。
有关使用salt进行密码散列的其他信息,请参阅本文:https://crackstation.net/hashing-security.htm
存储密码的步骤
验证密码的步骤
Crypto类的源代码:
http://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Helpers/Crypto.cs
https://stackoverflow.com/questions/17693918
复制相似问题