Почему org.mindrot.JBCrypt говорит, что здесь плохая длина соли?

Надеюсь, пример стоит тысячи слов. Если это не так, вот пара тестов для хеширования простого текста hello world используя соленое семя static seed to be used в первом тесте и static seed to be usedd во втором тесте. Соленое семя используется для создания статической соли, которая может быть передана в BCrypt.hashpw(plainText, staticSalt) функция. Как видите, солевые байты и солевые байты имеют одинаковую длину, но выдает ошибку. Я знаю, что это плохо, но у меня есть причины для статической соли, поэтому, пожалуйста, сфокусируйтесь на этом вопросе.

org.mindrot.jbcrypt.BCrypt с JDK1.7 Тест 1 - PlainText: "hello world", seedseed: "статическое семя, которое будет использоваться":

Salt bytes for "static seed to be used": [-30, -8, 86, -8, 6, -126, -64, -30, -82, -82, -104, -64, -8, -118, -64, 108, -82, -64, 14, -30, -82, -104]
Salt bytes string: 4vhW+AaCwOKurpjA+IrAbK7ADuKumA==, length: 32
complete salt: $2a$12$4vhW+AaCwOKurpjA+IrAbK7ADuKumA==
Exception in thread "main" java.lang.IllegalArgumentException: Bad salt length
at org.mindrot.jbcrypt.BCrypt.crypt_raw(BCrypt.java:619)
at org.mindrot.jbcrypt.BCrypt.hashpw(BCrypt.java:684)

org.springframework.security.crypto.bcrypt.BCrypt с JDK1.8 Тест 1 - PlainText: "hello world", saltseed: "статическое семя, которое будет использоваться":

Salt bytes for "static seed to be used": [-30, -8, 86, -8, 6, -126, -64, -30, -82, -82, -104, -64, -8, -118, -64, 108, -82, -64, 14, -30, -82, -104]
Salt bytes string: 4vhW+AaCwOKurpjA+IrAbK7ADuKumA==, length: 32
complete salt: $2a$12$4vhW+AaCwOKurpjA+IrAbK7ADuKumA==
Plain text: hello world, Hash text: $2a$12$4vhWHrTxEMtyyv6wmpOtX.YYbTqHwHv/dxe

org.mindrot.jbcrypt.BCrypt с JDK1.7 Тест 2 - PlainText: "hello world", seedseed: "статическое семя, которое будет использоваться":

Salt bytes for "static seed to be usedd": [85, 108, -73, 108, 111, -27, -32, 85, 19, 19, -4, -32, 108, -7, -32, -50, 19, -32, -125, 85, 19, -4]
Salt bytes string: VWy3bG/l4FUTE/zgbPngzhPgg1UT/A==, length: 32
complete salt: $2a$12$VWy3bG/l4FUTE/zgbPngzhPgg1UT/A==
Plain text: hello world, Hash text: $2a$12$VWy3bG/l4FUTE/zgbPngze9KDSXjF72NBMBNE6ZJk4StahyAhykgO

org.springframework.security.crypto.bcrypt.BCrypt с JDK1.8 Тест 2 - PlainText: "привет мир", seedseed: "статическое семя, которое будет использоваться":

Salt bytes for "static seed to be usedd": [85, 108, -73, 108, 111, -27, -32, 85, 19, 19, -4, -32, 108, -7, -32, -50, 19, -32, -125, 85, 19, -4]
Salt bytes string: VWy3bG/l4FUTE/zgbPngzhPgg1UT/A==, length: 32
complete salt: $2a$12$VWy3bG/l4FUTE/zgbPngzhPgg1UT/A==
Plain text: hello world, Hash text: $2a$12$VWy3bG/l4FUTE/zgbPngze9KDSXjF72NBMBNE6ZJk4StahyAhykgO

Я попытался добавить и удалить больше писем и получил успешные хэши. Я был отчасти счастлив, что первая строка, использованная в тесте JUnit, вызвала ошибку.

Заранее спасибо.

1 ответ

Я нашел причину, посмотрев его реализацию на странице GitHub... Эта реализация BCrypt поддерживает символ base64 точка (.) Вместо стандартного символа плюс (+).

static private final byte index_64[] = {
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, 0, 1, 54, 55,
        56, 57, 58, 59, 60, 61, 62, 63, -1, -1,
        -1, -1, -1, -1, -1, 2, 3, 4, 5, 6,
        7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
        17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
        -1, -1, -1, -1, -1, -1, 28, 29, 30,
        31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
        41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
        51, 52, 53, -1, -1, -1, -1, -1
};

Символ "+" имеет целочисленное значение 43, таким образом возвращает -1 из этого массива, а функция, которая извлекает солевые байты из солевых разрывов ранее, оставляет меня с 4-байтовыми солями. Даже его реализация говорит, что не поддерживает стандартную строку кодировки base64:

/**
 * Decode a string encoded using bcrypt's base64 scheme to a
 * byte array. Note that this is *not* compatible with
 * the standard MIME-base64 encoding.
 */
static byte[] decode_base64(String s, int maxolen)
        throws IllegalArgumentException {

Переключение с. + дает мне другое хэширование от Spring для солей, содержащих +. Не очень знаком с shift и &, чтобы вносить изменения, поэтому вместо этого буду искать реализацию Spring-Security.

РЕДАКТИРОВАТЬ: Просто взглянул на реализацию Spring. Не удивительно, что это не сработало... Это точно так же, за исключением того, что Spring продолжает хешировать с 4-байтовой солью, в то время как jbcrypt выдает ошибку, поэтому в Spring есть ошибка, тогда как если вы генерируете свой собственный хеш и он содержит +, то checkpw(plainText, hashedText) вернет false, потому что сгенерированная солт-часть hashtedText отличается от сгенерированной пользователем соли.

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