57 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			57 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| 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;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| } |