using System; using System.Security.Cryptography; using System.Text; namespace atakanozbancom.Models.classes { public static class PasswordHasher { private const string Prefix = "pbkdf2"; private const int DefaultIterations = 100000; private const int SaltSize = 16; private const int HashSize = 32; public static string Hash(string password) { if (password == null) throw new ArgumentNullException("password"); var salt = new byte[SaltSize]; using (var rng = RandomNumberGenerator.Create()) { rng.GetBytes(salt); } var hash = Pbkdf2(password, salt, DefaultIterations, HashSize); return string.Format( "{0}${1}${2}${3}", Prefix, DefaultIterations, Convert.ToBase64String(salt), Convert.ToBase64String(hash)); } public static bool IsHashed(string stored) { return !string.IsNullOrWhiteSpace(stored) && stored.StartsWith(Prefix + "$", StringComparison.Ordinal); } public static bool Verify(string password, string stored) { if (string.IsNullOrEmpty(password) || string.IsNullOrEmpty(stored)) return false; if (!IsHashed(stored)) return FixedTimeEquals(password, stored); var parts = stored.Split('$'); if (parts.Length != 4 || !string.Equals(parts[0], Prefix, StringComparison.Ordinal)) return false; int iterations; if (!int.TryParse(parts[1], out iterations) || iterations < 1000) return false; byte[] salt; byte[] expected; try { salt = Convert.FromBase64String(parts[2]); expected = Convert.FromBase64String(parts[3]); } catch { return false; } var actual = Pbkdf2(password, salt, iterations, expected.Length); return FixedTimeEquals(actual, expected); } private static byte[] Pbkdf2(string password, byte[] salt, int iterations, int length) { using (var derive = new Rfc2898DeriveBytes(password, salt, iterations, HashAlgorithmName.SHA256)) { return derive.GetBytes(length); } } private static bool FixedTimeEquals(byte[] a, byte[] b) { if (a == null || b == null || a.Length != b.Length) return false; var diff = 0; for (var i = 0; i < a.Length; i++) diff |= a[i] ^ b[i]; return diff == 0; } private static bool FixedTimeEquals(string a, string b) { if (a == null || b == null || a.Length != b.Length) return false; var diff = 0; for (var i = 0; i < a.Length; i++) diff |= a[i] ^ b[i]; return diff == 0; } } }