Java и машинопись генерирует разницу в хешах PBKDF2 - PullRequest
5 голосов
/ 06 марта 2020

Я хочу общаться между java и машинописью с зашифрованными данными AES-GCM (PBKDF2 га sh используется для пароля).
Я использовал случайные байты для pbkdf2:

randomBytes(Base64): wqzowTahVBaxuxcN8vKAEUBEo0wOfcg4e6u4M9tPDFk=   

Это my java PBKDF2 Код:

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

и это код машинописного текста:

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

Результат java и машинопись:

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

Почему я есть разница в результате?
Какая часть кода имеет ошибки?

ОБНОВЛЕНИЕ
Интересно, я пытаюсь сгенерировать ключ pbkdf2 с помощью команды linux nettle-pbkdf2, результат точно совпадает с выводом javascript:

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

1 Ответ

0 голосов
/ 08 марта 2020

После слишком большого количества исследований в inte rnet и сравнения 3 языков программирования (Java, Javascript, Python) и команды linu nettle-pbkdf2.
Я заметил Java JCE, а также Bouncycastle имеет ошибка в реализации алгоритма PBKDF2.

это python пример кода:

#!/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)      

результат одинаков для команд javascript и linux nettle-pbkdf2:

EGPcTUQUmYpNHoCDuD7rkIVaHkPSqEZYan4HnWfhFSc=      

in java когда я меняю randomBytes на простую строку, такую ​​как Password123456, результат будет java, javascript, python аналогично.

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

Примечание: На самом деле randomBits в моих примерах кодов является общим секретом ECDH. Я думаю, что Java не может рассчитать некоторые биты на PBKDF2 или реализация имеет проблемы.

В любом случае, я мигрирую с PBKDF2 на Argon2 .

ОБНОВЛЕНИЕ
Этот исходный код PBKDF2 работает в java без проблем: Исходный код PBKDF2

...