腌制和PBKDF2哈希 [英] Salting and Hashing with PBKDF2

查看:279
本文介绍了腌制和PBKDF2哈希的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图通过哈希和盐化在数据库中保存密码来学习加密,所以我决定使用一个登录系统尝试实现这个系统。

I am trying to learn cryptography with saving passwords in database with hashing and salting, so I decided to make a login-system trying implementing this system.

我的数据库由


  • UserID int PK

  • 用户名 varchar (250)

  • varbinary(64) / strong>


  • 电子邮件 varchar(250)
  • UserID int PK
  • Username varchar(250)
  • Salt varbinary(64)
  • Password varbinary(64)
  • RegDate datetime
  • Email varchar(250)

我使用 PBKDF2 ,但似乎这不是一个哈希/ salting方法,是不是?

I am using PBKDF2, but it seems like this isn't a hashing / salting method, what is it if it isn't?

如果是这样,我可以这样做吗?

If so I am doing this right?

>

My Keys

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。但这是正确的方式吗?这是甚至哈希/盐?

My system works, it is setting data into the database as bytes and if the user is typing the correct password it returns true. But is this the right way? Is this even hashing / salting?

推荐答案

你基本上走向正确的方向,但我会指出一些要考虑的事情:

You're basically going in the right direction, but I'll point out some things to think about:


  1. PBKDF2方法的默认迭代次数可能不足,您可能不希望将事情保留为默认值。我建议指定一个至少为10K的迭代计数。

  1. The default number of iterations of the PBKDF2 method may not be sufficient, and you may not want to leave things to the default. I would recommend specifying an iteration count of at least 10K.

另一方面,密钥大小和盐大小由字节计算。 64字节有点太多了。保持两个16字节每个应该是充分的。不建议超过20个字节,因为这是底层哈希函数/ HMAC的最大大小。这将只给攻击者一个优势(这,据许多人,是在PBKDF2的设计错误)。您可以将varbinary的大小设置为更高的值,以便将来升级。

On the other hand, the key size and salt size are counted by this implementation in bytes. 64 bytes is a bit too much. Keeping both to 16 bytes each should be ample. It's not recommended to go over 20 bytes as that's the maximum size of the underlying hash function / HMAC. Going over that will only give an advantage to the attacker (this, according to many, is a design mistake in PBKDF2). You may of course set the size of varbinary to a higher value to allow for future upgrades.

建议您使用盐和哈希密码。这样,当用户可以重置其密码时,可以在稍后的日期和每个条目下升级该方案。

It's recommended that you keep a protocol number with your salt and hashed password. Doing so makes it possible for you to upgrade the scheme at a later date and per entry, when the user is available to reset his/her password.

次要点;当生成盐时,MSDN不指定 我会检查盐的随机性(检查它是否每次都不同),只是在调用 getBytes 后询问盐,以确保盐确实是随机的,即使实施变化。

Minor point; MSDN does not specify when the salt is generated. I would check the randomness of the salt (check if it is different each time) and only ask the salt after calling getBytes to make sure that the salt is indeed random, even if the implementation changes. Otherwise generate it yourself using a cryptographically secure random number generator.

这篇关于腌制和PBKDF2哈希的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆