PBKDF2 - Невозможно сгенерировать тот же ключ в кодировке Base64 с Node и Java - PullRequest
0 голосов
/ 24 сентября 2019

Я работаю над проектом, в котором реализовано ручное хеширование паролей в Java, и мне поручено продублировать схему хеширования в NodeJS, чтобы пользователи не могли сбросить свои пароли.

Я не могу показатьсянаписать хеш-функцию, которая генерирует ключ, идентичный ключу, сгенерированному унаследованным кодом.

Я немного покопался во внутренностях каждой реализации и определил ключевое отличие в том, что NodeJSверсия измеряет keyLength в байтах, а версия Java использует биты.Я учел это в своей текущей попытке, но все еще не повезло.

Реализация Java:

public static String hash(byte[] salt, String password) throws HashException {
    try {
        KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 128);
        SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        return encode(f.generateSecret(spec).getEncoded());
    } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
        throw new HashException("Issues hashing the password", e);
    }
}

Моя попытка в NodeJS:

const crypto = require("crypto")

const encodedsalt = "oFoz+aZuGX5Ad/HAa35HLw=="
const encodedpass = "fp+gXqcO7fBKuXuhZQPY/A=="

// decode 
const decodedsalt = Buffer.from(encodedsalt, "base64")
const decodedpass = Buffer.from(encodedpass, "base64")

var key = crypto.pbkdf2Sync("13111789", decodedsalt, 65536, 16, "sha1")
var encodedKey = key.toString("base64")

Я ожидаю совпадения ключей, потому что каждая реализация использует одинаковый байтовый массив для соли и одинаковую строку для пароля.Вместо этого ключи совпадают только по длине.Я уверен, что есть некоторые особенности реализации, которые я не замечаю, но я не вижу этого!Любая помощь приветствуется - все остальные вопросы PBKDF2 были сосредоточены на какой-то другой незначительной проблеме, поэтому я в растерянности.

1 Ответ

0 голосов
/ 30 сентября 2019

код, который вы разместили, в основном нормально.вы не определили encode в своем коде Java, поэтому проблема может быть там.Вот код Java для рабочего примера:

import java.util.Base64;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;

public static String hash(byte[] salt, String password) throws Exception {
    SecretKeyFactory pbkdf2 = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");

    PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 128);
    byte[] secret = pbkdf2.generateSecret(spec).getEncoded();

    return Base64.getEncoder().encodeToString(secret);
}

это может быть выполнено как:

String base64_salt = "oFoz+aZuGX5Ad/HAa35HLw==";
byte[] salt = Base64.getDecoder().decode(base64_salt);

System.out.println(hash(salt, "13111789"));

, давая мне: On7VbkKDXdz8aTWo5tDBXw==

эквивалентный код JS будетбыть:

const crypto = require("crypto");

function hash(salt, password) {
    const key = crypto.pbkdf2Sync(password, salt, 65536, 16, "sha1");
    return key.toString("base64");
}

, который может быть запущен как:

const base64_salt = "oFoz+aZuGX5Ad/HAa35HLw==";
const salt = Buffer.from(base64_salt, "base64");

console.log(hash(salt, "13111789"));

также дает мне: On7VbkKDXdz8aTWo5tDBXw==

...