pbkdf2

Node.js pbkdf2 sha256 to Java


I'm moving the hash logic to convert a project developed in Node.js to Spring Boot.

The digest value and salt value generated in Node.js are stored in the DB, and when I search for the salt value stored in the DB for the same password and verify it with Java, different values ​​are displayed. Is there a problem with my code?

When creating in Node.js

crypto.randomBytes(64,(err,buf)=>{
        if(err){
            logger.error(err);
            throw(err);
        }
        const salt = buf.toString('base64');
        crypto.pbkdf2(login_pw,salt,100000,64,'sha256',(err2,key)=>{
            if(err2){
                logger.error(err2);
                throw(err2);
            }
        const hashepassword = key.toString('base64');

Result:

When generating a digest in Java with a salt value generated using Node.js and stored in the DB

public String matches(String salt_str,String password){
        try{
            byte[] salt = Base64.getDecoder().decode(salt_str);
            PBEKeySpec spec = new PBEKeySpec(password.toCharArray(),salt,100000,64 * 8);
            SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
            byte[] key = factory.generateSecret(spec).getEncoded();
            return Base64.getEncoder().encodeToString(key);

        } catch (Exception e){
            throw new RuntimeException(e);
        }

    }

Result:

How do I make the digest values ​​generated in Node.js the same as in Java?


Solution

  • In your Node.js code, when you pass the salt, pbkdf2 actually accept it as a string, not a base64 string to be decoded. Thus, it's the UTF-8 byte array that is used.

    If that's not an error in your Node.js code and you want the Java code to work that way, do it like this

    byte[] salt = salt_str.getBytes(StandardCharsets.UTF_8);
    

    It's... weird, but it works. Probably not much security risk considering it's just salt, and it's already long enough.

    If instead you want to properly use the buf as the byte array, change your Node.js code to use buf instead of salt, eg

    crypto.pbkdf2(login_pw,buf,100000,64,'sha256',(err2,key)=>{
            if(err2){
                logger.error(err2);
                throw(err2);
            }
            else
            {
              const hashepassword = key.toString('base64');
              console.log(hashepassword);
            }
        })