Что не так с моим PBKDF2 в узле здесь?
Кажется, я не могу понять, что я делаю здесь неправильно, я не могу получить один и тот же хэш дважды, ни подтвердить пароль, поэтому спецификации 2 и 4 не работают. Кто-нибудь видит здесь очевидные проблемы, которые вызывают у меня проблемы с генерацией одного и того же хэша дважды? Я использую узел v8.9.1 (и Typescript 2.6.1, который не должен иметь значения, я надеюсь). Я пытался использовать только буферы и строки base64 (ниже), но ничего не получалось.
Реализация:
import { pbkdf2Sync, randomBytes } from 'crypto';
export class Auth {
private iters = 1e1; // TODO: increase later
private keylen = 64;
private digest = 'sha512';
create(password: string) {
const salt = randomBytes(128);
const hash = pbkdf2Sync(password, salt, this.iters, this.keylen, this.digest);
console.log(hash.toString('hex'));
return [salt.toString('base64'), hash.toString('base64'), this.iters].join('::');
}
verify(stored: string, password: string) {
const [salt, hash, iters] = stored.split('::');
const verify = pbkdf2Sync(password, salt, parseInt(iters, 10), this.keylen, this.digest);
console.log(verify.toString('hex'));
return hash === verify.toString('base64');
}
}
Технические характеристики:
describe('Auth', () => {
const auth = new Auth();
const password = 'test';
it('should hash a password', () => {
const hash = auth.create(password);
expect(hash).to.be.string;
});
it('should verify valid password', () => {
const hash = auth.create(password);
const valid = auth.verify(hash, password);
expect(valid).to.be.true;
});
it('should reject invalid password', () => {
const hash = auth.create(password);
const invalid = auth.verify(hash, 'wrong input');
expect(invalid).to.be.false;
});
});
});
2 ответа
Я точно определил свою ошибку. Я ошибочно предположил, что, поскольку pbkdf2 принимает либо Buffer, либо строку, что он будет работать с Buffer, тем не менее, я хранил соль в base64, чтобы позже проверить ее с помощью pdkdf2, что приведет к использованию другой соли.
В случае, если кто-то сталкивается с этим:
// tslint:disable:no-shadowed-variable
import { pbkdf2Sync, randomBytes } from 'crypto';
export class Auth {
private iters = 1e1; // TODO: increase later
private keylen = 64;
private digest = 'sha512';
create(password: string) {
const salt = randomBytes(128).toString('base64'); // <- salt
// salt was not base64 before being used by pbkdf2
const hash = pbkdf2Sync(password, salt, this.iters, this.keylen, this.digest).toString('base64');
return [salt, hash, this.iters].join('::');
}
verify(stored: string, password: string) {
const [salt, hash, iters] = stored.split('::');
const verify = pbkdf2Sync(password, salt, parseInt(iters, 10), this.keylen, this.digest);
return hash === verify.toString('base64');
}
}
Вы не должны иметь возможность генерировать один и тот же хэш PBKDF2 дважды, то есть точку случайного начального числа.
WRT проверяет, что вы Base64 кодируете соль и хеш в create
но не Base64, декодирующий их в verify
,
Для отладки отобразите входы и выходы pbkdf2
для обоих create
а также verify
используйте hex для двоичных значений, таких как salt
а также hash
и добавьте это к вопросу. Это может быть достаточно для вас, чтобы увидеть ошибку.
Когда отладка упрощает работу, использование обратных вызовов добавляет уровень сложности отладки.