"C# PBKDF2 password hashing with Django-compatible format (pbkdf2_sha256), issues with password verification"

I am working on a C# application where I need to verify user passwords that were hashed using Django’s PBKDF2 algorithm (pbkdf2_sha256). The passwords are stored in the format:

pbkdf2_sha256$iterations$salt$hash

For example: pbkdf2_sha256$870000$wyEbTcPvbTOet9npIyftqZ$Xv274JNGq1ZMQQHzmZx8q5n+Nly/U5Wf1WYLRO4d8YY=

I'm trying to replicate the same process in C# using Rfc2898DeriveBytes to verify the password. However, I am encountering an issue where the computed hash does not match the stored hash, even though the entered password is correct.

Here's the C# code I’m using to verify the password:

    public static bool VerifyPassword(string enteredPassword, string storedPasswordHash) 
    { 
            var parts = storedPasswordHash.Split('$');
            if (parts.Length != 4 || parts[0] != "pbkdf2_sha256")
            {
                Console.WriteLine("Invalid password format.");
                return false;
            }
    
            string iterationsStr = parts[1];
            string salt = parts[2]; 
            string storedHash = parts[3]; 
    
            if (!int.TryParse(iterationsStr, out int iterations))
            {
                Console.WriteLine("Invalid iterations count.");
                return false;
            }
    
            byte[] saltBytes = DecodeBase64Salt(salt);
            if (saltBytes == null)
            {
                return false;
            }
    
            byte[] passwordBytes = Encoding.UTF8.GetBytes(enteredPassword);
            byte[] computedHashBytes;
    
           
            using (var pbkdf2 = new Rfc2898DeriveBytes(passwordBytes, saltBytes, iterations, HashAlgorithmName.SHA256))
            {
                computedHashBytes = pbkdf2.GetBytes(32); 
            }
    
            string computedHash = Convert.ToBase64String(computedHashBytes);
            Console.WriteLine($"Computed Hash: {computedHash}");
            return storedHash == computedHash;
        }
    
        private static byte[] DecodeBase64Salt(string salt)
        {
            switch (salt.Length % 4)
            {
                case 2: salt += "=="; break;
                case 3: salt += "="; break;
            }
    
            try
            {
                return Convert.FromBase64String(salt);
            }
            catch (FormatException)
            {
                Console.WriteLine("Error decoding Base64 salt.");
                return null;
            }
        }

I'm decoding the salt from the Base64 string and using Rfc2898DeriveBytes with SHA256, but the resulting hash doesn't match the one stored in the database. I've also tried adjusting Base64 padding, but the issue persists.

Does anyone know what might be causing this mismatch between the calculated and stored hashes? How can I fix the password verification to be compatible with Django's PBKDF2 implementation?

Вернуться на верх