当前位置: 首页 > 知识库问答 >
问题:

用PBKDF2进行盐析和散列

陶超
2023-03-14

我试图学习密码学,用散列和盐析在数据库中保存密码,所以我决定做一个登录系统来实现这个系统。

我的数据库包括

  • UserID int PK
  • 用户名varchar(250)
  • Salt 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。但这是正确的方法吗?这是杂凑还是腌制?

共有1个答案

冯永长
2023-03-14

你基本上朝着正确的方向前进,但是我要指出一些需要考虑的事情:

>

  • PBKDF2方法的默认迭代次数可能不够,您可能不想将事情留给默认值。我建议指定至少10K的迭代计数。

    另一方面,密钥大小和salt大小由该实现以字节为单位进行计数。64字节有点太多了。将两者都保持在16字节就足够了。建议不要超过20个字节,因为这是底层哈希函数/HMAC的最大大小。这样做只会给攻击者带来好处(根据许多人的说法,这是PBKDF2中的一个设计错误)。当然,您可以将varbinary的大小设置为更高的值,以便将来升级。

    建议您使用盐和散列密码保留协议号。这样做使得您可以在以后的日期和每次条目中升级该计划,当用户可以重置他/她的密码时。

    小结;MSDN未指定何时生成盐。我会检查salt的随机性(检查每次是否不同),并且只在调用getBytes后询问salt,以确保salt确实是随机的,即使实现发生了变化。否则,使用加密安全的随机数生成器自己生成它。

  •  类似资料:
    • 问题内容: 我正在开发一个小型的Web应用程序,该应用程序在内部对用户进行身份验证。一旦用户通过身份验证,我的Web应用程序便会将一些信息(例如userID和Person的名称)传递给第三方Web应用程序。第三方开发人员建议我们对值进行哈希处理和加盐处理。 原谅我的无知,但这到底意味着什么? 我正在用Java编写应用程序。因此,我打算做的是使用Apache Commons Digest Utils

    • 我模拟存储密码散列,并在登录过程中验证它。 我有一个名为的方法来获取字符串密码,并通过添加盐返回它的哈希值。 我选择一个静态值,在本例中,我选择一个相同的密码值() 但结果是: 为什么这两个值不相同? 我的代码有什么问题?

    • 大家好! 我正试图找到一种方法,以盐和散列我的密码在Java为一个web应用程序,需要一个密码登录。 我试图使用Bouncy Castle bcrypt和scrypt类来获得salting、哈希和密码验证的方法,结果发现这两个类中都没有密码验证方法。如果我在这个评估中是不正确的,请让我知道密码验证的方法是什么或者如果我遗漏了什么。 作为另一种选择,我决定在分解并转到PDBKF2之前试用bcrypt

    • 我对哈希比较陌生,我使用SHA-256和一种自制的生成盐的方法生成了值的哈希。它涉及为随机盐生成器的每个输入确定地找到种子。现在我想验证散列值的完整性,并检查添加的盐的有效性。然而,我不知道该怎么做。有人能帮忙吗?

    • 我正在使用pbkdf2算法来散列密码。为每个密码生成一个随机salt,并设置迭代次数,以使计算持续约1秒。 我也在sambe缓冲区中保存盐和哈希: 我的问题是,这个散列密码没有链接到一个用户(一个用户可以有多个密码),我需要有可能取消密码只使用密码本身。我看到的唯一方法是将密码散列到数据库中的每一个salt中取消,直到找到相同的散列,这将花费永远的时间(每一个salt 1秒)。 还有更好的方法吗?

    • 我正在使用以下代码创建哈希密码和salt: 我正在数据库中存储HashedPassword和Salt。 现在我要验证用户登录时的密码: 这不起作用,我得到了一个完全不同的哈希密码,而不是存储在数据库中的密码。据我所知,您应该在用户登录时输入的密码之前预置salt,然后运行相同的哈希密码函数。上面不是等价于那个吗?