Willcode4cash icon

PBKDF2Hash

Willcode4cash | PRO | 03/11/19 03:26:30 PM UTC | 0 ⭐ | 290 👁️ | Never ⏰ | []
C# |

1.61 KB

|

None

|

0 👍

/

0 👎

public class PBKDF2Hash
{
    public const int SaltByteSize = 24;
    public const int HashByteSize = 20; // to match the size of the PBKDF2-HMAC-SHA-1 hash 
    public const int PBKDF2Iterations = 1000;
    public const int IterationIndex = 0;
    public const int SaltIndex = 1;
    public const int PBKDF2Index = 2;
 
    public static string HashPassword(string password)
    {
        var cryptoProvider = new System.Security.Cryptography.RNGCryptoServiceProvider();
        byte[] salt = new byte[SaltByteSize];
        cryptoProvider.GetBytes(salt);
        var hash = GetPBKDF2Bytes(password, salt, PBKDF2Iterations, HashByteSize);
        return $"{PBKDF2Iterations}:{Convert.ToBase64String(salt)}:{Convert.ToBase64String(hash)}";
    }
 
    public static bool ValidatePassword(string password, string correctHash)
    {
        char[] delimiter = { ':' };
        var split = correctHash.Split(delimiter);
        var iterations = Int32.Parse(split[IterationIndex]);
        var salt = Convert.FromBase64String(split[SaltIndex]);
        var hash = Convert.FromBase64String(split[PBKDF2Index]);
        var testHash = GetPBKDF2Bytes(password, salt, iterations, hash.Length);
        return SlowEquals(hash, testHash);
    }
 
    private static bool SlowEquals(byte[] a, byte[] b)
    {
        var 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;
    }
 
    private static byte[] GetPBKDF2Bytes(string password, byte[] salt, int iterations, int outputBytes)
    {
        var PBKDF2 = new System.Security.Cryptography.Rfc2898DeriveBytes(password, salt);
        PBKDF2.IterationCount = iterations;
        return PBKDF2.GetBytes(outputBytes);
    }
}

Comments