Exercise 1: Zero Configuration vs. a Hasher Swap — Possible Solution ==================================================================== WHY LARAVEL NEEDS NO HASHER-CONFIGURATION CHANGE ------------------------------ Per this chapter, config/hashing.php already sets 'driver' => 'bcrypt' as Laravel's own out-of-the-box default. The legacy site's existing admin credential is itself a bcrypt hash - the same algorithm PHP's own password_hash() has defaulted to for years. Since Auth::attempt() checks the submitted password against the stored hash using whatever driver config/hashing.php names, and that driver is already bcrypt, the framework's own default already matches the legacy hash with nothing to configure. WHY DJANGO NEEDED BCryptSHA256PasswordHasher ------------------------------ Per this chapter, Django's own default password hasher is PBKDF2, not bcrypt. Because the legacy hash is bcrypt, Django's own default hasher would not recognize or correctly verify it - Django Rebuild 9 had to explicitly add BCryptSHA256PasswordHasher to the PASSWORD_HASHERS list so that Django's own authentication check would use an algorithm actually matching the legacy hash's format. WHY THIS WORKS AS AN ANSWER ------------------------------ It correctly identifies that Laravel's default hasher (bcrypt) already matches the legacy hash's algorithm, and correctly identifies that Django's default hasher (PBKDF2) does not, which is exactly why Django needed an explicit PASSWORD_HASHERS configuration change and Laravel did not.