这是在Db中盐和存储密码的方式吗? [英] Is this the way to salt and store a Password in Db?
问题描述
有几种方式(即使在这里SO),他们都提到在数据库上保存密码的最佳方式是保存密码而不是密码,而不是存储盐渍的哈希值
There are seveal ways (even here in SO) and they all mention that the best way to keep password on database is to save, not the password, not the hased password, but to store the hash of a salted password.
我的问题很简单,把一些代码放在上面,这是正确的吗?
My question is simple, putting some code on it, is this the correct way?
string username = "myUsr";
string password = "myPwd";
DateTime createDate = DateTime.UtcNow;
// Salt it
string saltedPwd = String.Concat(password, createDate.Ticks.ToString());
// Hash it
HMACSHA1 hash = new HMACSHA1(Encoding.Unicode.GetBytes(Helper.EncryptKey));
string encodedPwd = Convert.ToBase64String(
hash.ComputeHash(Encoding.Unicode.GetBytes(saltedPwd)));
// Create User in the database
db.CreateUser(username, encodedPwd, createDate);
数据库用户表
user_id | username | password | create_date | last_access | active
并且在登录使用时再次执行该过程,并检查 encodedPwd
与提供的盐渍,已获得密码相同。
and upon Login use do the process again and check if the encodedPwd
is the same as the salted, hased password that was provided.
我唯一关心的是,这是盐的最佳方法密码?可以使用创建日期(因为这将永远改变,我读到最好每次都使用不同的 salt
编码密码...
My only concern is, is this the best way to salt a password? Is it ok to use the Created Date (as that will always change, and I read that it is best to use always a different salt
every time we encode a password...
或者应该是 salt
一个完全不同的变量?
Or should be the salt
a completely different variable?
推荐答案
您的实现可能已经足够好了,但使用更多熵的盐会更好:您当前使用的ticks值将永远在一个较小的范围内。
Your implementation is probably good enough, but it would be better to use a salt with more entropy: the ticks value that you're currently using will always be in a relatively small range.
我会建议使用类似 PBKDF2 为您工作,通过 Rfc2898DeriveBytes
:
I would suggest using something like PBKDF2 to do the work for you, via Rfc2898DeriveBytes
:
string username = "myUsr";
string password = "myPwd";
using (var deriveBytes = new Rfc2898DeriveBytes(password, 20)) // 20-byte salt
{
byte[] salt = deriveBytes.Salt;
byte[] key = deriveBytes.GetBytes(20); // 20-byte key
string encodedSalt = Convert.ToBase64String(salt);
string encodedKey = Convert.ToBase64String(key);
// store encodedSalt and encodedKey in database
// you could optionally skip the encoding and store the byte arrays directly
db.CreateUser(username, encodedSalt, encodedKey);
}
并验证...
string username = "myUsr";
string password = "myPwd";
string encodedSalt, encodedKey;
// load encodedSalt and encodedKey from database for the given username
byte[] salt = Convert.FromBase64String(encodedSalt);
byte[] key = Convert.FromBase64String(encodedKey);
using (var deriveBytes = new Rfc2898DeriveBytes(password, salt))
{
byte[] testKey = deriveBytes.GetBytes(20); // 20-byte key
if (!testKey.SequenceEqual(key))
throw new InvalidOperationException("Password is invalid!");
}
这篇关于这是在Db中盐和存储密码的方式吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!