OK, I’ve translated Drupal 7’s password.inc file into commonJS module here.
It now correctly identifies correct passwords from the database pass field.
I’ve added a _password_base64_decode function which correctly reverses the Drupal 7 _password_base64_encode function and this round trips correctly. (This isn’t intended to be production code - its very brute force).
I’ve created auth0 user imports from this by using my _password_base64_decode function separately on the hashed password and the hashed salt fields and then encoding these to hex. These import successfully.
But, as I expected, I still get wrong password errors when I log in using the imported user and the correct password.
I think I’ve eliminated all other possible errors and the problem must now be that auth0 does not support stretching the hash.
I think to support Drupal 7 import we need to add an iterations field to the custom_password_hash object and implement the stretching functionality.
The code is:
count = 1 << count_log2;
const pb = Buffer.from(password);
do {
hash = crypto.createHash(algo);
hash.update(Buffer.concat([buffer, pb]));
buffer = hash.digest();
} while (--count);
as in lines 184 to 190 in my gist.
count_log2 is 15 in current Drupal 7 configurations and signalled in the settings as the ‘D’ in ‘$S$D’.
This is what my convert function looks like now with an assumed log2_iterations field:
const drupal = require('./password');
function convert({ mail, pass }) {
const settings = pass.slice(0,4);
const hashedSalt = pass.slice(4,12);
const hashedPass = pass.slice(12);
const salt = drupal._password_base64_decode(hashedSalt);
const hash = drupal._password_base64_decode(hashedPass);
const log2_iterations = settings.charCodeAt(3)-53;
return {
"email": mail,
"email_verified": true,
"custom_password_hash": {
"algorithm": 'sha512',
log2_iterations,
"hash": {
"value": hash.toString('hex')
},
"salt": {
"value": salt.toString('hex'),
"position": "prefix",
}
}
};
}
FYI the Drupal folks pointed me at this link which describes the stretching.