Question

I have a database from django and I want to work with it from Node.js. I have a task: authenticate users. Known from database: algorithm pbkdf2_sha256, salt, 10000 iterations and base64-encoded hash. What steps I must to do in JS to encode some password to given base64-hash?

UPD: found the solution in here: python (django) hashlib vs Nodejs crypto but Django-generated hash and JS-generated hash not match...
Django generate next:

pbkdf2_sha256$10000$NmzpPCQiTe2R$U8ipSsOy3Xz7FwWDHdH/dTei8Xh4Q7NGtdzrCacSfvo=

JS:

pbkdf2_sha256$10000$NmzpPCQiTe2R$w4jCgWjDilrDmcOBd8K+I8OdwpkKwoVQZMKWH3FvYcKoAMKcwqlewobDocOEGMKZfQ==

Password: Simple123

Was it helpful?

Solution

By using pbkdf2-sha256 (from your own link) I'm able to generate a hash that is identical to the one you have from Django.

var pbkdf2 = require('pbkdf2-sha256');
var validatePassword = function (key, string) {
    var parts = string.split('$');
    var iterations = parts[1];
    var salt = parts[2];
    return pbkdf2(key, new Buffer(salt), iterations, 32).toString('base64') === parts[3];
};
var djangoPass = 'pbkdf2_sha256$10000$NmzpPCQiTe2R$U8ipSsOy3Xz7FwWDHdH/dTei8Xh4Q7NGtdzrCacSfvo=';
console.log(validatePassword('Simple123', djangoPass)); // Logs: true

The above code should be sufficient to validate passwords stored in Django using Node.

OTHER TIPS

I recently created a project to make this easier. My project is available for node and is called node-django-hashers. The code is below:

https://github.com/kalvish21/hashers

A sample usage:

var hashers = require('node-django-hashers');

var h = new hashers.PBKDF2PasswordHasher();
var hash1 = h.encode("password", h.salt());
console.log(h.verify("password", hash1)); // returns true
console.log(h.verify("wrong_password", hash1)); // returns false

This is compatible with django password hashing.

I faced a similar task where I have to authenticate users against Django passwords in Java. After trying unsuccessfully to achieve this goal using the default pbkdf2_sha256 hasher in Django, I ended up changing the method used to hash the Django password to be able to easily replicate the same algorithm in Java.

As described in Django documentation you can modify the order in which PASSWORD_HASHERS are defined in settings.py, I put this hasher in first position:

'django.contrib.auth.hashers.SHA1PasswordHasher'

In this way the password hash stored in the Django database is something like this:

sha1$upSZarr0w7CZ$304b22b1a9e7e5387e79f50e691043d3faf83c48

If you already have some passwords in the database they will be automatically converted by Django at first user login.

You can easily tokenize the hash using $ as separator; the first token is always sha1 (the algorithm used), the second token is the salt and the last token is the actual hash.

To match a password you can verify that

304b22b1a9e7e5387e79f50e691043d3faf83c48

is the SHA1 sum of the salt concatenated with the expected password:

SHA1(upSZarr0w7CZ + password) = 304b22b1a9e7e5387e79f50e691043d3faf83c48

In our case the security implications of using a weaker algorithm for password hashing was acceptable.

pbkdf2-sha256(https://github.com/cryptocoinjs/pbkdf2-sha256) is deprecated. We should use pbkdf2 (https://www.npmjs.com/package/pbkdf2)

var pbkdf2 = require("pbkdf2");

const password = "12345678";
const djangoPassword =
  "pbkdf2_sha256$120000$uUjHWJsRsQj4$d9eBwNfRW/AayPOSMjqYyT26Sm6bsC5GCK9ntDxB8jM=";

var validatePassword = function(key, string) {
  var parts = string.split("$");
  var iterations = parts[1];
  var salt = parts[2];
  const hashPassword = pbkdf2
    .pbkdf2Sync(key, Buffer.from(salt), Number(iterations), 32, "sha256")
    .toString("base64");
  return hashPassword === parts[3];
};

console.log(validatePassword(password, djangoPassword)); // it should be print "true"
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top