【发布时间】:2014-06-03 20:42:19
【问题描述】:
我正在尝试通过散列和加盐将密码保存在数据库中来学习密码学,因此我决定创建一个登录系统来尝试实现该系统。
我的数据库包括
- 用户ID int PK
- 用户名 varchar(250)
- 盐 varbinary(64)
- 密码varbinary(64)
- RegDate 日期时间
- 电子邮件 varchar(250)
我正在使用 PBKDF2,但这似乎不是散列/加盐方法,如果不是,那是什么?
如果是这样,我这样做对吗?
我的钥匙
private const int SALT_SIZE = 64;
private const int KEY_SIZE = 64;
将数据插入数据库
public static void RegisterMe(string _username, string _password, string _email)
{
using (var cn = new SqlConnection(User.strcon))
{
string _sqlins = @"
INSERT INTO
[User]
([Username],[Salt],[Password],[RegDate], [Email])
VALUES
(@Username, @Salt, @Password, CURRENT_TIMESTAMP, @Email)";
var cmd = new SqlCommand(_sqlins, cn);
cn.Open();
using (var deriveBytes = new Rfc2898DeriveBytes(_password, SALT_SIZE))
{
byte[] salt = deriveBytes.Salt;
byte[] key = deriveBytes.GetBytes(KEY_SIZE);
// save salt and key to database
cmd.Parameters.AddWithValue("@Username", _username);
cmd.Parameters.AddWithValue("@Password", key);
cmd.Parameters.AddWithValue("@Salt", salt);
cmd.Parameters.AddWithValue("@Email", _email);
}
cmd.ExecuteNonQuery();
}
}
检查用户是否有效
public bool IsValid(string _email, string _password)
{
using (var cn = new SqlConnection(strcon))
{
byte[] salt = { }, key = { };
string _sql = @"
SELECT
SALT,
[Password],
UserID
FROM
[User]
WHERE [Email] = @email";
SqlCommand cmd = new SqlCommand(_sql, cn);
cmd.Parameters.AddWithValue("@email", _email);
cn.Open();
SqlDataReader reader = cmd.ExecuteReader();
if (reader.Read())
{
salt = reader.GetSqlBytes(0).Value;
key = reader.GetSqlBytes(1).Value;
reader.Dispose();
cmd.Dispose();
using (var deriveBytes = new Rfc2898DeriveBytes(_password, salt))
{
byte[] newKey = deriveBytes.GetBytes(KEY_SIZE); // derive a 20-byte key
return newKey.SequenceEqual(key);
}
}
else
{
reader.Dispose();
cmd.Dispose();
return false;
}
}
}
我的系统工作正常,它将数据以字节的形式设置到数据库中,如果用户输入了正确的密码,它会返回 true。但这是正确的方法吗?这甚至是散列/加盐吗?
【问题讨论】:
-
我对使用 PBKDF2 不是很熟悉,但从外观上看,我认为你是正确的,你实际上并没有对密码进行哈希处理。尝试阅读此 MSDN 文档 (msdn.microsoft.com/en-us/library/…),其中显示了一些示例用法,但这是使用对称加密。散列是非对称的,因此一旦散列,您将永远无法取回原始明文。
-
@martin_costello 我认为它正在对密码进行哈希处理。它没有使用对称加密 PBKDF2 基于 HMAC,而不是一种密码。散列不是不对称的,但它确实是一种方式。我非常熟悉 PBKDF2。
-
@owlstead 我的意思是 MSDN 示例是对称的。
-
@martin_costello 是的;但是你想具体说什么?我的意思是,它使用输出作为键,这与存储它不同,但除此之外......
-
PBKDF2 在循环中使用 HMAC 构造作为 PRF(伪随机函数)。它根据输入创建 pseudo 随机字节 - 密钥(读取:UTF-8 编码密码)和密钥派生信息(读取:salt)。 HMAC 是基于散列的消息身份验证代码,因此是用于大多数实际目的的 PRF。对于散列,可以使用任何加密安全散列,但
Rfc2898DeriveBytes使用 SHA-1。检查密码是否正确,只需重新计算 PBKDF2 值并进行比较即可,无需额外加密。
标签: c# encryption hash cryptography pbkdf2