Почему char [] предпочтительнее, чем String для паролей? - PullRequest
3198 голосов
/ 16 января 2012

В Swing поле пароля имеет метод getPassword() (возвращает char[]) вместо обычного метода getText() (возвращает String). Точно так же я натолкнулся на предложение не использовать String для обработки паролей.

Почему String представляет угрозу безопасности, когда речь идет о паролях? Это неудобно для использования char[].

Ответы [ 18 ]

39 голосов
/ 08 апреля 2015

Редактировать: Возвращаясь к этому ответу после года исследований в области безопасности, я понимаю, что это весьма печальное следствие того, что вы когда-либо будете сравнивать незашифрованные пароли.Пожалуйста, не надо. Используйте безопасный односторонний хеш с солью и разумным количеством итераций .Подумайте об использовании библиотеки: этот материал трудно понять правильно!

Оригинальный ответ: А как насчет того факта, что String.equals () использует оценку короткого замыкания ,и поэтому уязвим для временной атаки?Это может быть маловероятно, но вы можете теоретически проверить время сопоставления паролей, чтобы определить правильную последовательность символов.

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        // Quits here if Strings are different lengths.
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            // Quits here at first different character.
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

Еще несколько ресурсов о временных атаках:

33 голосов
/ 24 января 2015

Нет ничего, что массив char дает вам против String, если вы не очистите его вручную после использования, и я не видел, чтобы кто-нибудь на самом деле делал это. Поэтому для меня предпочтение char [] vs String немного преувеличено.

Взгляните на широко используемую библиотеку Spring Security здесь и спросите себя - неуместны ли парни из Spring Security или пароли char [] просто не имеют особого смысла. Когда какой-нибудь злобный хакер захватит дампы памяти вашей оперативной памяти, убедитесь, что он получит все пароли, даже если вы используете сложные способы их скрытия.

Тем не менее, Java постоянно меняется, и некоторые страшные функции, такие как Функция дедупликации строк в Java 8 , могут включать объекты String без вашего ведома. Но это другой разговор.

29 голосов
/ 28 июля 2015

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

С другой стороны, char [] изменчивы, как только аутентификация выполнена, вы можете перезаписать их любым символом, напримервсе М или обратный слеш.Теперь, даже если кто-то получит дамп кучи, он не сможет получить пароли, которые в данный момент не используются.Это дает вам больше контроля в том смысле, как вы сами очищаете содержимое объекта от ожидания, пока GC сделает это.

16 голосов
/ 26 апреля 2018

Строка является неизменной и идет в пул строк. После написания его нельзя перезаписать.

char[] - это массив, который вы должны перезаписать после того, как вы использовали пароль, и вот как это должно быть сделано:

char[] passw = request.getPassword().toCharArray()
if (comparePasswords(dbPassword, passw) {
 allowUser = true;
 cleanPassword(passw);
 cleanPassword(dbPassword);
 passw=null;
}

private static void cleanPassword (char[] pass) {
 for (char ch: pass) {
  ch = '0';
 }
}

Одним из сценариев, в котором злоумышленник может использовать его, является аварийный дамп - когда JVM дает сбой и генерирует дамп памяти - вы сможете увидеть пароль.

Это не обязательно злонамеренный внешний злоумышленник. Это может быть пользователь поддержки, который имеет доступ к серверу для целей мониторинга. Он может заглянуть в сбой и найти пароли.

16 голосов
/ 07 сентября 2017

1) Поскольку строки являются неизменяемыми в Java, если вы храните пароль в виде обычного текста, он будет доступен в памяти до тех пор, пока сборщик мусора не очистит его, и поскольку String используется в пуле строк для повторного использования, существует довольно высокая вероятность того, что он будетостаются в памяти на длительный срок, что создает угрозу безопасности.Поскольку любой, кто имеет доступ к дампу памяти, может найти пароль в виде открытого текста, и это еще одна причина, по которой вы всегда должны использовать зашифрованный пароль, а не обычный текст.Поскольку строки являются неизменяемыми, содержимое строк не может быть изменено, потому что любое изменение приведет к созданию новой строки, в то время как если вы выберете char [], вы все равно можете установить все его элементы как пустые или нулевые.Таким образом, хранение пароля в массиве символов снижает риск безопасности при краже пароля.

2) Сама Java рекомендует использовать метод getPassword () из JPasswordField, который возвращает метод char [] и устаревший метод getText (), который возвращает пароль в виде открытого текста.с указанием причины безопасности.Хорошо следовать советам команды Java и придерживаться стандарта, а не идти против него.

16 голосов
/ 09 декабря 2016

Короткий и простой ответ будет потому, что char[] является изменяемым, в то время как String объекты не являются.

Strings в Java являются неизменяемыми объектами.Вот почему они не могут быть изменены после создания, и поэтому единственный способ удаления их содержимого из памяти - сбор мусора.Это будет только тогда, когда память, освобожденная объектом, может быть перезаписана, и данные исчезнут.

Теперь сборка мусора в Java не происходит с гарантированным интервалом.Таким образом, String может сохраняться в памяти в течение длительного времени, и если в течение этого времени произойдет сбой процесса, содержимое строки может оказаться в дампе памяти или в каком-либо журнале.

С массивом символов вы можете прочитать пароль, закончить работу с ним, как только сможете, а затем немедленно изменить содержимое.

12 голосов
/ 28 июля 2017

Строка в Java неизменна. Поэтому, когда бы ни была создана строка, она будет оставаться в памяти до тех пор, пока не будет собрана сборка мусора. Таким образом, любой, кто имеет доступ к памяти, может прочитать значение строки.
Если значение строки будет изменено, то это приведет к созданию новой строки. Таким образом, как исходное значение, так и измененное значение остаются в памяти до тех пор, пока они не будут удалены.

С массивом символов содержимое массива может быть изменено или стерто после того, как цель пароля будет достигнута. Исходное содержимое массива не будет найдено в памяти после его изменения и даже до начала сборки мусора.

Из соображений безопасности лучше хранить пароль в виде массива символов.

1 голос
/ 03 декабря 2018

Это спорно, следует ли использовать строку или использовать Char [] для этой цели, потому что оба имеют свои преимущества и недостатки. Это зависит от того, что нужно пользователю.

Поскольку строки в Java являются неизменяемыми, всякий раз, когда кто-то пытается манипулировать вашей строкой, он создает новый объект, и существующая строка остается неизменной. Это можно рассматривать как преимущество для хранения пароля в виде строки, но объект остается в памяти даже после использования. Так что, если кто-то каким-то образом обнаружил местоположение объекта в памяти, он может легко отследить ваш пароль, хранящийся в этом месте.

Char [] является изменяемым, но имеет то преимущество, что после его использования программист может явно очистить массив или переопределить значения. Поэтому, когда он используется, он очищается, и никто никогда не узнает о сохраненной вами информации.

Исходя из вышеизложенных обстоятельств, можно получить представление о том, использовать ли String или Char [] для их требований.

...