Я получил следующее:
public async Task<IUser> Authenticate(ICredentials credentials)
{
using var connection = _databaseGateway.Connection;
connection.Open();
var users = await connection.GetAllAsync<User>();
const int expectedUserCount = 1;
var existingUsers = users
.Where(u => u.Username == credentials.Username);
if (existingUsers.Count() != expectedUserCount)
throw new AuthenticationException(Error.UserDoesNotExist,
"Error: There is no single user exists with the username given.");
var existingUser = existingUsers.Single();
var salt = existingUser.PasswordSalt;
// TURN ON FOR REGISTERING USER PW
// salt = PasswordHash.ScryptGenerateSalt();
var password = Encoding.UTF8.GetBytes(credentials.Password);
var hash = PasswordHash.ScryptHashBinary(password, salt);
// TURN ON FOR REGISTERING USER PW
// await connection.ExecuteAsync(
// "UPDATE user SET PasswordHash=@hash, PasswordSalt=@salt WHERE UserName=@username;",
// new {hash, salt, username = credentials.Username});
var wrongPassword = !hash.SequenceEqual(existingUser.PasswordHash);
if (wrongPassword)
throw new AuthenticationException(Error.WrongPassword,
"Error: Incorrect Password.");
return AddToken(existingUser);
}
Подозрение здесь было правильным, я думаю. Кажется, что каждый раз генерируется случайная соль с string
перегрузками метода (ов).
Затем я добавил вспомогательный класс:
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Sodium;
namespace Services
{
public static class HashingService
{
public static bool IsGeneratedBy(
this IEnumerable<byte> existingHash,
string plaintextPassword,
byte[] salt
)
{
var password = Encoding.UTF8.GetBytes(plaintextPassword);
var generatedHash = PasswordHash.ScryptHashBinary(password, salt);
var passwordIsCorrect = generatedHash.SequenceEqual(existingHash);
return passwordIsCorrect;
}
}
}
и использовал его как:
public async Task<IUser> Authenticate(ICredentials credentials)
{
using var connection = _databaseGateway.Connection;
connection.Open();
var users = await connection.GetAllAsync<User>();
const int expectedUserCount = 1;
var existingUser = users
.Single(u => u.Username == credentials.Username);
var wrongPassword = !existingUser.PasswordHash.IsGeneratedBy(
credentials.Password, existingUser.PasswordSalt);
if (wrongPassword)
throw new AuthenticationException(Error.WrongPassword,
"Error: Incorrect Password.");
return AddToken(existingUser);
}