Wednesday, May 24, 2023

.NET 6 minimal API hash password with salt

 In .NET 6, you can use the `Rfc2898DeriveBytes` class from the `System.Security.Cryptography` namespace to generate a hash-based password with a salt. Here's an example of how you can do this:



using System;

using System.Security.Cryptography;

using System.Text;


public class PasswordHasher

{

    private const int SaltSize = 16; // 128 bits

    private const int HashSize = 32; // 256 bits

    private const int Iterations = 10000;


    public static string HashPassword(string password)

    {

        byte[] salt = new byte[SaltSize];

        using (var rng = RandomNumberGenerator.Create())

        {

            rng.GetBytes(salt);

        }


        byte[] hash = HashPasswordWithSalt(password, salt);


        // Combine the salt and hash

        byte[] saltedHash = new byte[SaltSize + HashSize];

        Buffer.BlockCopy(salt, 0, saltedHash, 0, SaltSize);

        Buffer.BlockCopy(hash, 0, saltedHash, SaltSize, HashSize);


        return Convert.ToBase64String(saltedHash);

    }


    public static bool VerifyPassword(string password, string hashedPassword)

    {

        byte[] saltedHash = Convert.FromBase64String(hashedPassword);

        byte[] salt = new byte[SaltSize];

        byte[] hash = new byte[HashSize];


        // Extract the salt and hash from the combined bytes

        Buffer.BlockCopy(saltedHash, 0, salt, 0, SaltSize);

        Buffer.BlockCopy(saltedHash, SaltSize, hash, 0, HashSize);


        byte[] computedHash = HashPasswordWithSalt(password, salt);


        // Compare the computed hash with the stored hash

        return SlowEquals(hash, computedHash);

    }


    private static byte[] HashPasswordWithSalt(string password, byte[] salt)

    {

        using (var deriveBytes = new Rfc2898DeriveBytes(password, salt, Iterations))

        {

            return deriveBytes.GetBytes(HashSize);

        }

    }


    // Compares two byte arrays in a way that is resistant to timing attacks

    private static bool SlowEquals(byte[] a, byte[] b)

    {

        uint diff = (uint)a.Length ^ (uint)b.Length;

        for (int i = 0; i < a.Length && i < b.Length; i++)

        {

            diff |= (uint)(a[i] ^ b[i]);

        }

        return diff == 0;

    }

}



You can use the `HashPassword` method to hash a password and store it securely in your application's database. The `VerifyPassword` method can be used to compare a user-provided password with the stored hashed password to verify if they match.


No comments:

Post a Comment

ASP.NET Core

 Certainly! Here are 10 advanced .NET Core interview questions covering various topics: 1. **ASP.NET Core Middleware Pipeline**: Explain the...