Is this the way to salt and store a Password in Db?(这是在数据库中加盐和存储密码的方法吗?)
问题描述
有几种方法(即使在 SO 中也是如此),他们都提到在数据库中保存密码的最佳方法是保存,不是密码,不是 hased 密码,而是 存储 salted 的哈希密码.
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?
推荐答案
您的实现可能已经足够好,但最好使用熵更大的盐:您当前使用的刻度值将始终在范围相对较小.
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);
}
然后进行身份验证...
And to authenticate...
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!");
}
这篇关于这是在数据库中加盐和存储密码的方法吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:这是在数据库中加盐和存储密码的方法吗?
基础教程推荐
- 如何使用 .Net 检查 Active Directory 服务器是否已启动并正在运行? 2022-01-01
- 如果有人提交恶意软件Nuget包怎么办? 2022-01-01
- .NET SerialPort DataReceived 事件未触发 2022-01-01
- 禁止输入少量字符,例如'<'、'&a 2022-01-01
- C# 从 List<List<int>> 中删除重 2022-01-01
- Azure Functions:CosmosDBTrigger 未在 Visual Studio 中触发 2022-01-01
- 当值可以是对象或空数组时反序列化 JSON 2022-01-01
- WPF 模态进度窗口 2022-01-01
- 我应该在后面的代码中直接使用 Linq To SQL 还是使 2022-01-01
- Moq It.Is<>不匹配 2022-01-01
