Невозможно проверить passwordhash+salt, созданный с помощью php password_hash() с помощью jBcrypt

Мы переносим наш модуль аутентификации с PHP на Java. В настоящее время пароль хэш + соль хранится в базе данных с использованием алгоритма BCrypt. Это значение генерируется с помощью PHP-функции password_hash(). Для проверки обычного текстового пароля мы используем функцию PHP password_verify().

Код PHP

$hash = password_hash($password,PASSWORD_DEFAULT); //stored in db

if(password_verify($candidate,$hash)===TRUE) { //$hash fetched from DB
    echo "valid";
}

Для переноса этого модуля авторизации на Java мы используем библиотеку jBCrypt с помощью jBCrypt-0.4.jar

Java-код

private static String hashPassword(String password) {
    String hashed = BCrypt.hashpw(password, BCrypt.gensalt());
    return hashed;
}

private static boolean checkpasword(String candidate, String hashed){
    boolean matches = false;

    if (BCrypt.checkpw(candidate, hashed)){
        matches = true;
    }

    return matches;
}

Тем не менее, пароль хэш + соль, сгенерированный из php, не проверяется в Java. Для строки 'abcd' сгенерированный хеш + соль

PHP - $2y$10$SA4iLMAniuNO6p9P1ZJElePaJvlN5eHGZ2dDt2Mutle4FQr1OY4hC

Java - $2a$10$YnqJT5NPCPTI8qKBbLfgIOIOW4eckdbE1R85tJGNRUJKmxz1TLkWG

Когда я попытался сопоставить строку, сгенерированную с помощью PHP в Java, используя

if (BCrypt.checkpw("abcd", "$2y$10$SA4iLMAniuNO6p9P1ZJElePaJvlN5eHGZ2dDt2Mutle4FQr1OY4hC")){
    matches = true;
}

Я получал ниже

Исключение в потоке "main" java.lang.IllegalArgumentException: недопустимая ревизия соли в org.mindrot.jbcrypt.BCrypt.hashpw(BCrypt.java:665) в org.mindrot.jbcrypt.BCrypt.checkpw(BCrypt.java:764)...`

Как мне сделать оба совместимых?

1 ответ

Хеш, сгенерированный password_hash() в PHP входит соль. Это означает, что когда вы проверяете его по простому текстовому паролю, то же самое соль используется для генерации хеша по простому текстовому паролю, и эти два хеша сравниваются в постоянном времени для проверки.

То, что вы делаете в Java, каждый раз генерирует различную соль, что означает, что вы не можете сравнить их. Ваша реализация Java использует другую версию, обозначенную $2a$ в твоем хеше Обратите внимание, что PHP использует $2y$ и соли явно разные.

Из руководства по PHP

Поддерживаются только версии PHP до 5.3.7 "$2a$"как солевой префикс: PHP 5.3.7 представил новые префиксы для исправления уязвимости безопасности в реализации Blowfish. Пожалуйста, обратитесь к " этому документу для получения полной информации об исправлении безопасности, но, чтобы подвести итог, разработчики нацелены только на PHP 5.3.7 и позже следует использовать$2y$"в предпочтении"$2a$".

Поэтому вам не следует создавать новый хеш в Java для проверки существующего хеша, который был сгенерирован PHP и сохранен в вашей базе данных. Вместо этого предоставьте сохраненный хеш BCrypt.checkpasword для проверки.

Другие вопросы по тегам