简体   繁体   中英

What is wrong with my PBKDF2 in Node here?

Can't seem to figure out what I am doing wrong here, I can't get the same hash twice nor validate a password so specs 2 and 4 are failing. Does anyone see any obvious issues here that is causing me to have problems with generating the same hash twice? I'm using node v8.9.1 (and Typescript 2.6.1 which shouldn't matter I hope). I've tried using only Buffers and base64 strings (below) but nothing has worked.

Implementation:

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');
  }
}

Specs:

  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;
  });
});

});

You are not supposed to be able to generate the same PBKDF2 hash twice, that is the point of the random seed.

WRT verifying you are Base64 encoding the salt and hash in create but not Base64 decoding them in verify .

For debugging display the inputs and outputs of pbkdf2 for both create and verify , use hex for binary values such as salt and hash and add that to the question. This may be enough for you to see the error.

When debugging make things as simple as possible, using call backs adds a level of debugging complexity.

I've pinpointed my bug. I falsely assumed that since pbkdf2 accepts either a Buffer or a string that it would work with a Buffer, however I was storing the salt in base64 to later verify it with pdkdf2 would result in a different salt being used.

In case someone comes across this:

// 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');
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM