使用哈希密码验证用户的流程?

Cod*_*per 2 c# passwords

当我进入这一部分时,我正在阅读有关散列密码的文章

验证密码

  1. 从数据库中检索用户的盐和哈希值。
  2. 将盐添加到给定的密码之前,并使用相同的哈希函数对其进行哈希处理。
  3. 将给定密码的哈希与数据库中的哈希进行比较。如果它们匹配,则密码正确。否则,密码错误。

但是我对接下来的流程有些困惑,例如,假设我有一个数据库,其中包含一个包含ID,名称,密码和电子邮件的用户表,并且要登录某个应用程序,我需要输入电子邮件和密码。

按照上述步骤,我首先需要获取存储在数据库中的该用户的salt + hash密码。

题:

假设我正在使用一个简单的存储过程,那么唯一的方法就是像这样...

    CREATE PROCEDURE [dbo].[sp_validate_user]

@us_email VARCHAR (MAX)
AS
BEGIN
 -- SET NOCOUNT ON added to prevent extra result sets from
 -- interfering with SELECT statements.
 SET NOCOUNT ON;

    -- Insert statements for procedure here

SELECT  us_id,
        us_name,
        us_pass,
        us_email


 FROM  Users
 WHERE us_email = @us_email

END
Run Code Online (Sandbox Code Playgroud)

然后执行第二步和第三步:

    public static bool ValidatePassword(string inputPassword, string storedPassword)
    {
        // Extract the parameters from the hash
        char[] delimiter = { ':' };
        string[] split = storedPassword.Split(delimiter);
        int iterations = Int32.Parse(split[ITERATION_INDEX]);
        byte[] salt = Convert.FromBase64String(split[SALT_INDEX]);
        byte[] hash = Convert.FromBase64String(split[PBKDF2_INDEX]);

        byte[] testHash = PBKDF2(inputPassword, salt, iterations, hash.Length);
        return SlowEquals(hash, testHash);
    }
Run Code Online (Sandbox Code Playgroud)

我担心的事实是,如果我使用从表中提取的数据来创建对象,这是否会使信息容易受到影响?

这是否还意味着使用此验证的唯一方法是仅基于用户名/电子邮件提取所有用户信息,只是在运行时检查输入密码和哈希值是否匹配,然后让该用户访问信息?

很抱歉,这听起来令人困惑,但是任何见解都会很棒。

cod*_*eim 5

看来您可能是在倒想。在传递给哈希函数之前,将盐添加到明文密码中。将最终结果存储在数据库中。

通常,盐是用户名。用户独有的,但用户之间有所不同的东西,可以抵抗字典攻击。

因此,对于用户名u,密码p,假设SHA2是哈希函数。将u + p连接起来得到一个盐值,然后对其进行哈希处理。

hashtext = SHA2(u + p)     // in this case, + is concatenate
Run Code Online (Sandbox Code Playgroud)

hashtext是您存储在数据库中的内容。

对于登录,用户输入用户名u2和密码p2

tryhash = SHA2(u2 + p2)
Run Code Online (Sandbox Code Playgroud)

在数据库中查询与u2匹配的用户记录,并带有tryhash的密码哈希文本

假设您有一个MVC动作,它接收loginViewModel,该动作由在页面中输入的明文电子邮件或用户名以及明文密码填充:

var loginUser = new User(loginViewModel);
CalcHash(loginUser);

var realUser = users.Find(loginUser.username);
if(realUser.HashPassword == loginUser.HashPassword)
    // success
Run Code Online (Sandbox Code Playgroud)

虽然也可以将散列密码添加为数据访问方法的第二个参数,即。users.Find(username, hashPass),因此通常不会采用这种方式,因为即使密码失败,您也需要访问用户记录,以便增加密码失败次数并锁定帐户。

  • 好吧,如果我理解正确,您的意思是散列用户名并将其用作盐吗?这至少可以缓解短盐的问题 1,但其他问题没有解决,因为它仍然是可预测的。在实践中,这可能不会产生很大的影响,但我自己并不知道所有可能的攻击。最好的方法仍然是使用随机盐,并且由于其他参数(如成本因素),使用衍生盐没有优势(您还需要成本因素和算法来验证密码)。 (2认同)