Java and typescript generate difference PBKDF2 hash

Viewed 864

I want communicate between java and typescript with encrypted AES-GCM data (PBKDF2 hash used for password) .
I used random bytes for pbkdf2 :

randomBytes(Base64): wqzowTahVBaxuxcN8vKAEUBEo0wOfcg4e6u4M9tPDFk=   

This is my java PBKDF2 Code :

    private String salt = "1234";
    private static final String KEY_ALGORITHM = "AES";
    private Key generateKey(byte[] randomBytes) throws Exception {
        var randomPassword = new String(randomBytes);
        KeySpec keySpec = new PBEKeySpec(randomPassword.toCharArray(), salt.getBytes(), 10000, 256);
        SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
        var kdf2SecurePassword = secretKeyFactory.generateSecret(keySpec).getEncoded();
        return new SecretKeySpec(kdf2SecurePassword, KEY_ALGORITHM);
    }   

and this is typescript code :

  private static importKey(randomBytes: ArrayBuffer) {
    return crypto.subtle.importKey(
      'raw',
      randomBytes,
      {name: 'PBKDF2', length: 256},
      true,
      ['deriveKey']
    );
  }

  private generateAESKey(baseKey, salt) {
    const encSalt = new TextEncoder().encode(salt);
    const algorithm = {
      name: 'PBKDF2',
      hash: 'SHA-256',
      iterations: 10000,
      salt: encSalt
    };
    return crypto.subtle.deriveKey(
      algorithm,
      baseKey,
      {name: 'AES-GCM', length: 256},
      true,
      ['encrypt', 'decrypt']
    );
  }     

Result in java and typescript :

Java Key       : hrG2Hw/bec9JoI+EcemfUxR/5lGw718kYOcCWRRbulk=
typescript Key : EGPcTUQUmYpNHoCDuD7rkIVaHkPSqEZYan4HnWfhFSc=     

Why i have difference result ?
What part of code has wrong ?

UPDATE
Interesting, I try to generate pbkdf2 key with linux nettle-pbkdf2 command, result exactly match by javascript output :

USERNAME@HOSTNAME:~$ echo -n "wqzowTahVBaxuxcN8vKAEUBEo0wOfcg4e6u4M9tPDFk=" | base64 -d | nettle-pbkdf2 -i 10000 -l 32 --raw "1234"  | base64
EGPcTUQUmYpNHoCDuD7rkIVaHkPSqEZYan4HnWfhFSc=    
1 Answers

After too many research in internet and compare 3 programming languages (Java,Javascript,Python) and linu nettle-pbkdf2 command .
I noticed Java JCE and also Bouncycastle has a bug in PBKDF2 algorithm implementation .

this is python exmaple code :

#!/usr/bin/python3
import base64
import hashlib

b64 = "wqzowTahVBaxuxcN8vKAEUBEo0wOfcg4e6u4M9tPDFk="
bytePass = base64.b64decode(b64)
key = hashlib.pbkdf2_hmac('sha256', bytePass, '1234'.encode(), 10000, 32)
keyB64 = base64.b64encode(key)
print(keyB64)      

result is same by javascript and linux nettle-pbkdf2 command :

EGPcTUQUmYpNHoCDuD7rkIVaHkPSqEZYan4HnWfhFSc=      

in java when i change randomBytes to a simple string like Password123456 , result in java, javascript, python is similar .

Java       : nCpOvPbsb62/jfYIlPClEEGNzpD7Wt/qwkIC00Rkx24=
JavaScript : nCpOvPbsb62/jfYIlPClEEGNzpD7Wt/qwkIC00Rkx24= 
Python     : nCpOvPbsb62/jfYIlPClEEGNzpD7Wt/qwkIC00Rkx24= 

Note: Actually randomBits in my example codes is ECDH shared secret . I think Java can not calculate some bits on PBKDF2 or implementation have problem .

Anyway, I migrate from PBKDF2 to Argon2.

UPDATE
This PBKDF2 Source code do work in java without any problem : PBKDF2 Source Code

Related