Not Applicable
Not Applicable

Reputation: 75

Password Hash does not match

I am unable to login the user because the password Hash does not match. What am I doing wrong. My sql server which hold the password hash has the datatype of nvarchar. I used binary data type before but it did not work.

 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;
    }

This is the code that I've written to register and login my client. I am unable to find what am I doing wrong.

Upvotes: 3

Views: 1131

Answers (2)

Usman Ahmed
Usman Ahmed

Reputation: 18

enter code hereI had the same problem because I was storing the data in the data type of binary(64) in sql server then i change

        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;
        }

    }

Upvotes: 0

Wiktor Zychla
Wiktor Zychla

Reputation: 48230

Just replace UTF8.GetBytes with Convert.FromBase64String and UTF8.GetString with Convert.ToBase64String upon registering/validation

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;
}

and

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;

}

The reason for your invalid result is that what your GetString is returning a string that contains non printable characters which are not properly persisted/retrieved from/to the database.

Just print out these strings to see what you get there.

In contrast, base64 encoding makes sure byte arrays are converted to safe strings in a sense that you can safely store/retrieve them.

Here's a fiddle of slightly modified version (async & dbcontext removed),

https://dotnetfiddle.net/fH5mXh

Upvotes: 8

Related Questions