Files
GestionIntegralWeb/tools/PasswordMigrationUtil/PasswordHasherService.cs

57 lines
2.2 KiB
C#
Raw Permalink Normal View History

using System.Security.Cryptography;
using System.Text;
namespace PasswordMigrationUtil
{
public class PasswordHasherService
{
private const int SaltSize = 16; // 128 bit
private const int HashSize = 32; // 256 bit
private const int Iterations = 10000; // Número de iteraciones (ajustable)
// Genera un hash y una salt para una contraseña dada
public (string hash, string salt) HashPassword(string password)
{
// Generar una salt aleatoria
byte[] saltBytes = RandomNumberGenerator.GetBytes(SaltSize);
// Crear el hash usando PBKDF2
var pbkdf2 = new Rfc2898DeriveBytes(password, saltBytes, Iterations, HashAlgorithmName.SHA256);
byte[] hashBytes = pbkdf2.GetBytes(HashSize);
// Convertir bytes a strings Base64 para almacenamiento
string saltString = Convert.ToBase64String(saltBytes);
string hashString = Convert.ToBase64String(hashBytes);
return (hashString, saltString);
}
// Verifica si una contraseña coincide con un hash y salt almacenados
public bool VerifyPassword(string password, string storedHash, string storedSalt)
{
try
{
// Convertir strings Base64 de vuelta a bytes
byte[] saltBytes = Convert.FromBase64String(storedSalt);
byte[] storedHashBytes = Convert.FromBase64String(storedHash);
// Crear el hash de la contraseña ingresada usando la misma salt e iteraciones
var pbkdf2 = new Rfc2898DeriveBytes(password, saltBytes, Iterations, HashAlgorithmName.SHA256);
byte[] testHashBytes = pbkdf2.GetBytes(HashSize);
// Comparar los hashes de forma segura (evita timing attacks)
return CryptographicOperations.FixedTimeEquals(storedHashBytes, testHashBytes);
}
catch (FormatException)
{
// Manejar el caso donde las strings almacenadas no son Base64 válidas
return false;
}
catch (Exception)
{
// Loggear la excepción si es necesario
return false;
}
}
}
}