Same password, same options, different verify result
See original GitHub issueHi,
I’m running identical container Docker Swarm Mode stacks on two identical servers. On one of the servers, password verification always works fine. On the other, it keeps failing regardless of whether the input password is correct or not. When it fails, it seems to fail for all passwords.
To make sure it was a problem with Secure Password and not with my (and others) typing, I copied a stored password hash directly from one database to the other, checked that the stored values were identical and then attempted to log in to each instance of my software by copying and pasting the same password into each log in form. One passed verification, the other failed.
This also happened a couple of days ago. At that time, I found https://github.com/emilbayes/secure-password/issues/10 and so changed the way I stored hashes to match:
const savedHash = Buffer.alloc(securePassword.HASH_BYTES);
savedHash.write(dbhashedvalue);
After deploying that change, everything worked fine for a couple of days. However, today I’ve noticed that password verification is failing again on the same server as before.
I don’t understand how this issue can arise on one server but not the other. Neither has significant usage at the moment and they’re running identical container stacks. One of the containers is a Node app which handles password hashing and verification via Secure Password. That container is currently limited to 150MB memory in each stack. I limit Secure Password to 64MB and have checked that the memory utilisation when not hashing passwords generally sits at 62MB, which leaves a little room for growth (not much, but this project is in early stages and for a small, fixed-size team of users, so trying to avoid increasing the cost of hosting).
I generate password hashes with the following function and save the resulting hash string to MongoDB (running in a separate container on the same stack):
const SecurePassword = require('secure-password');
const securePassword = SecurePassword({
memlimit: 67108864 # 64Mb
});
function hashPassword(userPassword) {
return new Promise((resolve, reject) => {
console.debug('Hashing password');
securePassword.hash(
Buffer.from(userPassword),
(error, hashBuffer) => {
if (error) {
reject(error);
}
resolve(hashBuffer.toString());
}
);
});
}
I verify the passwords with this function:
function verifyPassword(userPassword, correctHash) {
const passwordBuffer = Buffer.from(userPassword);
const hashBuffer = Buffer.alloc(SecurePassword.HASH_BYTES);
hashBuffer.write(correctHash);
return new Promise((resolve, reject) => {
securePassword.verify(passwordBuffer, hashBuffer, async (error, result) => {
if (error) {
reject(error);
}
switch (result) {
case SecurePassword.INVALID_UNRECOGNIZED_HASH:
reject({message: 'Unexpected error'});
break;
case SecurePassword.INVALID:
reject({invalid: true, message: 'Invalid password'});
break;
case SecurePassword.VALID:
resolve();
break;
case SecurePassword.VALID_NEEDS_REHASH:
try {
newHash = await hashPassword(userPassword);
resolve(newHash);
} catch (error) {
resolve(); // Resolve because password verified correctly although failed to create new hash
}
break
default:
reject({message: 'Unexpected error'});
}
});
});
}
On the failing server, it hits the SecurePassword.INVALID
case every time.
Any ideas why this could be failing on one server and not the other?
Issue Analytics
- State:
- Created 5 years ago
- Comments:18 (10 by maintainers)
Top GitHub Comments
@andrewfinnell You’re comparing two hashes, but the
verify
function takes a plaintext password and a hash:Hope this helps! 😃
No worries! 😃 For posterity, I will also clear up that if there would be any OOM issues during the hashing, no hash would result, and during the verification there would never be a positive match. What @djbingham is experiencing I’m almost certain is due to a
errno
not being re-set