Django pbkdf2_sha256 JS implementation
Asked Answered
T

4

11

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

Taryn answered 9/7, 2013 at 9:21 Comment(1)
Did you try to get the same number of bytes from the PBKDF? Getting 49 bytes in return is a bit strange if you did not specify that number. Also make sure you use the same character-encoding of the password in both functions - the character encoding of PBKDF2 is not specified (although UTF-8 is hinted at).Misusage
G
11

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.

Gingivitis answered 9/5, 2014 at 9:13 Comment(2)
pbkdf2-sha256 is deprecated. you should use pbkdf2 . npmjs.com/package/pbkdf2Repand
For some reason it doesn't work on my data: #51614490. The only thing I can think about is the 4th parameter 32 you pass for the dkLen. Where did you get it from?Sarcous
P
2

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.

Periodical answered 18/3, 2016 at 23:9 Comment(0)
U
0

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.

Unseal answered 29/10, 2013 at 14:13 Comment(1)
For a Java way to do Django's pbkdf2_sha256: gist.github.com/JustinTArthur/3528cfca7e644547d6ceLionel
O
0

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"
Odilo answered 12/1, 2020 at 6:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.