Search code examples
phpdjangohashpasswordsencode

How do I replicate a django password validation function in PHP?


I need to check a password's validity in php. The password was hashed in django with a pbkdf2 hasher with the hashing algorithm as sha256.

https://gist.github.com/staydecent/1019680 <- This person was able to do the same with a simpler sha1 hash.

Verifying Django Password in Ruby on Rails gives non-matching password <- This person had a similar problem in ruby, instead of php.

As I understand it, django passwords are stored so that the hash style is the first component, the number of replications comes next, then then the salt, then the hash.

I have successfully extracted each component, but the following php does not work. It returns a string of the correct length, but not the correct content. I am fearful that the hash code does not work. The hasher I am using is from this website: https://defuse.ca/php-pbkdf2.htm

This is my php:

//$enc_password is the password from database
$pieces = explode('$', $enc_password);
$iterations = $pieces[1];
$salt = $pieces[2];
$hash = $pieces[3];
//raw_password is user's entered password
if ($hash ==  base64_encode(pbkdf2("sha256", $raw_password, $salt, $iterations, 32, true)))
{
    echo ("SUCCESS");
}
else
{
    echo ("FAILED");
}

Any and all help is appreciated!!


Solution

  • I just made a simple test in both Python and PHP.

    In Python:

    >>> from django.utils.crypto import pbkdf2
    >>> import base64, hashlib
    >>> hash = pbkdf2("test_password","myHash", 10000, 32, hashlib.sha256)
    >>> hash.encode('base64').strip()
    'lRKgL0zAmPwIMPNhTy1wJRXWZQwcHlbIW3glYA4LPU8='
    

    In PHP:

    <?php
    include 'pbkdf2.php';
    echo base64_encode(pbkdf2('sha256', 'test_password', 'myHash', 10000, 32, true));
    // result is: lRKgL0zAmPwIMPNhTy1wJRXWZQwcHlbIW3glYA4LPU8=
    ?>
    

    The results from both tests are identical, so there is nothing wrong with the hash code. Are you sure your Django test is using pbkdf2 algorithm? And your user input is example the same as the test password?