这是在Db中加密和存储密码的方法吗?

bal*_*dre 13 c# encryption passwords hash

有几种方式(即使在这里),他们都提到保持密码在数据库上的最好方法是保存密码,而不是密码,但存储盐渍密码的哈希值.

我的问题很简单,把一些代码放在上面,这是正确的方法吗?

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);
Run Code Online (Sandbox Code Playgroud)

数据库用户表

user_id | username | password | create_date | last_access | active
Run Code Online (Sandbox Code Playgroud)

并在登录时使用再次执行该过程并检查是否encodedPwd与提供的盐渍密封密码相同.

我唯一担心的是,这是加密密码的最佳方法吗?是否可以使用创建日期(因为它总会改变,我读到salt每次编码密码时最好总是使用不同的...

或者应该是salt一个完全不同的变量?

Luk*_*keH 19

您的实现可能已经足够好了,但是使用具有更多熵的盐会更好:您当前使用的滴答值始终处于相对较小的范围内.

我建议使用像PBKDF2这样的东西为你做的工作,通过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);
}
Run Code Online (Sandbox Code Playgroud)

并进行身份验证......

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!");
}
Run Code Online (Sandbox Code Playgroud)

  • @Magnus:盐很容易找到并不重要; 重要的是每个用户都有一个独特的随机盐.即使攻击者可以访问所有代码和所有数据,也应该保持良好的身份验证方案. (5认同)
  • @Magnus:并允许找到盐的人为那些坐着的*所有*密码创建彩虹表?;) (2认同)

cce*_*lar 5

我想知道为什么还没有人提到BCrypt。有一个现成的 C# 实现。请参阅http://derekslager.com/blog/posts/2007/10/bcrypt-dotnet-strong-password-hashing-for-dotnet-and-mono.ashx

如果您的问题有经过验证的解决方案,请不要重新发明轮子。

  • @balexandre:我不明白你的担忧。**您应该使用 bcrypt 或由专业人士编写的其他库**。如果可以避免的话,永远不要使用自己的加密代码。它是由专家设计的,并且非常安全*即使攻击者知道密码系统的源代码*。这就是它的安全性。另外*不要把时间当作盐*。使用从加密强熵源派生的字节作为盐,并将这些字节与散列密码一起存储。(Bcrypt 自动执行此操作。) (6认同)