密码哈希值不匹配。

3

我无法登录用户,因为密码哈希值不匹配。我做错了什么。我的sql服务器保存的密码哈希值数据类型是nvarchar。我之前使用了二进制数据类型,但没有成功。

 private readonly MovieHubContext _context;
    public AuthRepository(MovieHubContext context)
    {
        _context = context;
    }

    //method is called when the user hits the login button
    public async Task<Users> Login(string username, string password)
    {
        //returns the username from the databse
        var user = await _context.Users.FirstOrDefaultAsync(x => x.UserName == username);
        if (user == null)
        {
            return null;
        }

        if (!VerifyPasswordHash(password, System.Text.Encoding.UTF8.GetBytes(user.PasswordHash),
            System.Text.Encoding.UTF8.GetBytes(user.PasswordSalt)))
            return null;
        return user;

    }
    // this method is used to verify the password 
    private bool VerifyPasswordHash(string password, byte[] passwordHash, byte[] passwordSalt)
    {
        using (var hmac = new System.Security.Cryptography.HMACSHA512(passwordSalt))
        {
            //changes the string into byte and them computes the hash
            byte[] computedHash = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));
            for (int i = 0; i < computedHash.Length; i++)
            {
                //compares the hashed password(user input) with the hashed password from the database
                if (computedHash[i] != passwordHash[i])
                    return false;
            }
        }
        return true;
    }
    // This method is used to register the users
    public async Task<Users> Register(Users users, string password)
    {
        byte[] passwordHash, passwordSalt;
        CreatePasswordHash(password, out passwordHash, out passwordSalt);

        users.PasswordHash = System.Text.Encoding.UTF8.GetString(passwordHash);
        users.PasswordSalt = System.Text.Encoding.UTF8.GetString(passwordSalt);

        //save into database
        await _context.Users.AddAsync(users);
        await _context.SaveChangesAsync();

        return users;


    }

    private void CreatePasswordHash(string password, out byte[] passwordHash, out byte[] passwordSalt)
    {
        using (var hmac = new System.Security.Cryptography.HMACSHA512())
        {
            passwordSalt = hmac.Key;
            passwordHash = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));
        }
    }

    public async Task<bool> UserExists(string username)
    {
        if (await _context.Users.AnyAsync(x => x.UserName == username))
            return true;

        return false;
    }

这是我编写的用于注册和登录客户端的代码。我找不到错在哪里。
2个回答

8

只需在注册/验证时将UTF8.GetBytes替换为Convert.FromBase64String,将UTF8.GetString替换为Convert.ToBase64String即可。

public async Task<Users> Register(Users users, string password)
{
    byte[] passwordHash, passwordSalt;
    CreatePasswordHash(password, out passwordHash, out passwordSalt);

    users.PasswordHash = Convert.ToBase64String(passwordHash);
    users.PasswordSalt = Convert.ToBase64String(passwordSalt);

    //save into database
    await _context.Users.AddAsync(users);
    await _context.SaveChangesAsync();

    return users;
}

并且

public async Task<Users> Login(string username, string password)
{
    //returns the username from the databse
    var user = await _context.Users.FirstOrDefaultAsync(x => x.UserName == username);
    if (user == null)
    {
        return null;
    }

    if (!VerifyPasswordHash(password, Convert.FromBase64String(user.PasswordHash),
        Convert.FromBase64String(user.PasswordSalt)))
        return null;
    return user;

}

你的结果无效的原因在于,GetString 返回一个包含非可打印字符的字符串,这些字符没有被正确保存或检索到数据库中。只需将这些字符串打印出来以查看其内容。
相反,使用 base64 编码可以确保字节数组被转换为“安全”的字符串,这样你就可以安全地存储和检索它们。
下面是稍微修改过(去掉了异步和 dbcontext)的示例代码:

https://dotnetfiddle.net/fH5mXh


1
非常感谢。我在转换数据方面遇到了困难。您的解释让我明白了。 - Not Applicable

0

我曾经遇到过同样的问题,因为我在SQL Server中将数据存储在二进制(64)数据类型中,然后我进行了更改。

        public async Task<User> Login(string username, string password)
    {
        var user = await _context.Users.FirstOrDefaultAsync(x => x.Username == username);
        if(user == null)
        return null;
        if(!VerifyPasswordHash(password, user.PasswordHash, user.PasswordSalt))
        return null;

        return user;
    }
    public async Task<User> Register(User user, string password)
    {
        byte[] passwordHash, passwordSalt;
        CreatePasswordHash(password, out passwordHash, out passwordSalt);
        user.PasswordHash = passwordHash;
        user.PasswordSalt = passwordSalt;

        await _context.Users.AddAsync(user);
        await _context.SaveChangesAsync();

        return user;
    }
    private void CreatePasswordHash(string password, out byte[] passwordHash, out byte[] passwordSalt)
    {
        using (var hmaic = new System.Security.Cryptography.HMACSHA512())
        {
          passwordSalt = hmaic.Key;
          passwordHash = hmaic.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));
        }
    }
    private bool VerifyPasswordHash(string password, byte[] passwordHash, byte[] passwordSalt)
    {
       using (var hmaic = new System.Security.Cryptography.HMACSHA512(passwordSalt))
        {             
          var computedHash = hmaic.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));

          for(int i =0; i < computedHash.Length; i++)
          {
              if(computedHash[i] != passwordHash[i])
              return false;
          }

          return true;
        }

    }

你能详细说明一下你修改了什么吗? - THess

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接