Salting and Hashing with PBKDF2
我正在尝试学习密码术,通过散列和跳跃将密码保存在数据库中,所以我决定创建一个登录系统来尝试实现这个系统。
我的数据库由
- 用户ID int pk
- 用户名varchar(250)
- 盐变二元(64)
- 密码varbinary(64)
- RegDate日期时间
- 电子邮件varchar(250)
我正在使用pbkdf2,但这似乎不是一个哈希/加盐方法,如果不是,它是什么?
如果是这样,我做得对吗?
我的钥匙
1 2 | private const int SALT_SIZE = 64; private const int KEY_SIZE = 64; |
将数据插入数据库
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | 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(); } } |
号
检查用户是否有效
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | 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方法的默认迭代次数可能不够,您可能不希望将其保留为默认值。我建议指定至少10公里的迭代计数。
另一方面,这个实现以字节为单位计算密钥大小和salt大小。64字节太多了。两个字节都保持在16个字节就足够了。不建议超过20个字节,因为这是底层哈希函数/hmac的最大大小。浏览这些信息只会给攻击者带来优势(根据许多人的说法,这是PBKdf2中的一个设计错误)。当然,您可以将varbinary的大小设置为更高的值,以便将来进行升级。
建议您使用SALT和哈希密码保留协议号。这样做可以使您在用户可以重置其密码时,在以后的日期和每次输入时升级方案。
次要点;msdn未指定何时生成盐。我会检查salt的随机性(每次检查是否不同),并且只在调用