2015-05-31 4 views
2

Примерно несколько часов назад я спросил о переполнении стека о методах преобразования char [] в хэш MD5. Решение было предоставлено, но было сочтено небезопасным - как описано несколькими парами: Generating an MD5 Hash with a char[]Использование BCrypt с char []

Нейл Смитлайн рекомендовал использовать BCrypt, но я не могу использовать его с char [].

Причина, по которой я использую char [] для хранения извлеченного пароля из формы входа, состоит в том, что .getPassword() поддерживает только char [].

 char[] passwordChars = passwordInputField.getPassword(); 
     String hashed = BCrypt.hashpw(passwordChars, BCrypt.gensalt(12)); 

В настоящее время я пытаюсь использовать приведенный выше код, чтобы сгенерировать хеш, но в качестве переменной passwordCars имеет тип полукокса [], оно не поддерживается BCrypt.haspw()

Теперь единственная причина, почему я Я не использую регулярную строку, потому что она не может быть очищена из памяти.

Мой вопрос сейчас - возможно ли каким-то образом использовать char [] с BCrypt?

Заранее благодарен!

+1

Это нехорошая идея, но вам нужно будет взять char [] и вернуться обратно в строку (на основе того, что я могу сказать из api), который кажется плохим дизайном ... – MadProgrammer

+0

Что бы вы сделали рекомендовать тогда? MD5 кажется небезопасным, и BCrypt, похоже, не работает с char []. –

+1

Найти реализацию, которая не использует String – MadProgrammer

ответ

1

Оба Java-приложения bcrypt, которые я нашел, берут строку в качестве входных данных. Как вы, кажется, знаете, ввод пароля в строку открывает вам атаку памяти.

Вы можете использовать PBKDF2, а также bcrypt. Оба они считаются первоклассными. Существуют образцы кода Java PBKDF2 here и here. Оба позволяют передавать функции char[].

Чтобы ответить на неявный вопрос из комментариев, причина, по которой вы не используете MD5 или любой хеш, заключается в том, что они слишком быстры. С их помощью возможен принудительный ввод паролей со специальным оборудованием. Bcrypt и PBKDF2 рассчитаны на замедление.

Даже если вы собираетесь использовать хэш (который я рекомендую против), вы должны его солить. Реверсирование несостоявшихся хэшей паролей тривиально (см. this tool).

CrackStation's reference на хранении пароля является хорошей общей ссылкой.

+0

Если вы не рекомендуете использовать хеши, то что бы вы рекомендовали использовать? –

+0

Также, для второго примера, мне нужно будет изменить какой-либо исходный код и вы могли бы предоставить пример использования? –

4

Таким образом, на основе реализации, представленной на https://github.com/jeremyh/jBCrypt, вам необходимо изменить hashpw и checkpw методы принять char[] вместо String

Вероятно, самая трудная часть в hashpw ...

try { 
     passwordb = (password + (minor >= 'a' ? "\000" : "")).getBytes("UTF-8"); 
    } catch (UnsupportedEncodingException uee) { 
     throw new AssertionError("UTF-8 is not supported"); 
    } 

Простейшим решением было бы обернуть char[] обратно в String, но мы пытаемся избежать этого. Вместо этого, основываясь на самом высоком выигрыше ответа от Converting char[] to byte[], мы можем сделать что-то больше похоже ...

char[] expanded = password; 
    if (minor >= 'a') { 
     expanded = Arrays.copyOf(expanded, expanded.length + 1); 
     expanded[expanded.length - 1] = '\000'; 
    } 

    CharBuffer charBuffer = CharBuffer.wrap(expanded); 
    ByteBuffer byteBuffer = Charset.forName("UTF-8").encode(charBuffer); 
    passwordb = Arrays.copyOfRange(byteBuffer.array(), byteBuffer.position(), byteBuffer.limit()); 

Метод checkpw фактически не нуждается в каких-либо изменений (кроме параметров), так как она использует метод hashpw для проверки результатов.

Итак, тестирование ...

// We want the same salt for comparison 
String salt = BCrypt.gensalt(12); 
String original = BCrypt.hashpw("Testing", salt); 
System.out.println(original); 
String hash = BCrypt.hashpw("Testing".toCharArray(), salt); 
System.out.println(hash); 
System.out.println(BCrypt.checkpw("Testing", hash)); 
System.out.println(BCrypt.checkpw("Testing".toCharArray(), hash)); 

выходов ...

$2a$12$KclXlnca78yhcrg1/mNrRepLYqeJE//SRhrh1X3UM7YUQMjY4x8gy 
$2a$12$KclXlnca78yhcrg1/mNrRepLYqeJE//SRhrh1X3UM7YUQMjY4x8gy 
true 
true 

Теперь, если у вас есть аккаунт GitHub, вы можете фактически клонировать исходный репозиторий, внести предложенные изменения и генерировать тянуть запросы. Я, лично, быть temptered, чтобы избавиться от checkpw и hashpw методов, которые требуют String

Я также нашел this реализацию PDKDF2, которая использует String, но затем быстро преобразовал его в char[] ... так, что ОЧЕНЬ просто изменилось ...

0

Короткий ответ на ваш вопрос: да, можно использовать char[] s с BCrypt в Java.

Bouncy Castle crypto packages for Java добавлен алгоритм хэширования паролей BCrypt (используя формат строки и кодировки Base64 в эталонной реализации на OpenBSD) в версии   1,52 (Мар 2015), и он поддерживает только char[] пароли.

Соответствующий метод для создания строки BCrypt можно найти в org.bouncycastle.crypto.generators.OpenBSDBCrypt классе и имеет следующую подпись:

String generate(char[] password, 
       byte[] salt, 
       int cost) 

Если вы хотите, чтобы убедиться в исходном коде, что char[] сохраняется без преобразованные в строку, соответствующие классы: OpenBSDBcrypt, Strings и BCrypt.

Смежные вопросы