Использовать char[]Array Over String для манипулирования паролями в Java?

Используйте char [] Array Over String для манипулирования паролями в Java?

1. обзор

В этой статье мы объясним, почему мы должны использовать массивchar[] для представления паролей вместоString в Java.

Обратите внимание, что в этом руководстве основное внимание уделяется способам управления паролями в памяти, а не фактическим способам их хранения, которые обычно обрабатываются на уровне сохраняемости.

Мы также предполагаем, что не можем контролировать формат пароля (например, пароль поступает от стороннего API в видеString). Хотя казалось очевидным использование объекта типаjava.lang.String для управления паролями, команда разработчиков Java рекомендует вместо этого использоватьchar[].

Например, если мы посмотрим наJPasswordFieldjavax.swing, мы увидим, что методgetText(), который возвращаетString, устарел с Java 2 и заменен наgetPassword(), который возвращаетchar[].

Итак, давайте рассмотрим несколько веских причин, почему это так.

2. Струны неизменны

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

Следовательно, пароль, хранящийся вString, будет доступен в памяти, пока сборщик мусора не очистит его. Мы не можем контролировать, когда это произойдет, но этот период может быть значительно дольше, чем для обычных объектов, посколькуStrings хранятся в пуле строк для повторного использования.

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

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

Давайте теперь посмотрим на фрагменты кода, которые демонстрируют то, что мы только что обсудили.

Сначала дляString:

System.out.print("Original String password value: ");
System.out.println(stringPassword);
System.out.println("Original String password hashCode: "
  + Integer.toHexString(stringPassword.hashCode()));

String newString = "********";
stringPassword.replace(stringPassword, newString);

System.out.print("String password value after trying to replace it: ");
System.out.println(stringPassword);
System.out.println(
  "hashCode after trying to replace the original String: "
  + Integer.toHexString(stringPassword.hashCode()));

Выход будет:

Original String password value: password
Original String password hashCode: 4889ba9b
String value after trying to replace it: password
hashCode after trying to replace the original String: 4889ba9b

Теперь дляchar[]:

char[] charPassword = new char[]{'p', 'a', 's', 's', 'w', 'o', 'r', 'd'};

System.out.print("Original char password value: ");
System.out.println(charPassword);
System.out.println(
  "Original char password hashCode: "
  + Integer.toHexString(charPassword.hashCode()));

Arrays.fill(charPassword, '*');

System.out.print("Changed char password value: ");
System.out.println(charPassword);
System.out.println(
  "Changed char password hashCode: "
  + Integer.toHexString(charPassword.hashCode()));

Выход:

Original char password value: password
Original char password hashCode: 7cc355be
Changed char password value: ********
Changed char password hashCode: 7cc355be

Как мы видим, после того, как мы попытались заменить содержимое исходногоString, значение осталось прежним, а методhashCode() не вернул другое значение при том же выполнении приложения, что означает, что исходныйString остался нетронутым.

А для массиваchar[] мы смогли изменить данные в том же объекте.

3. Мы можем случайно распечатать пароли

Еще одно преимущество работы с паролями в массивеchar[] - это предотвращение случайной регистрации пароля в консолях, мониторах или других более или менее небезопасных местах.

Давайте посмотрим на следующий код:

String passwordString = "password";
char[] passwordArray = new char[]{'p', 'a', 's', 's', 'w', 'o', 'r', 'd'};
System.out.println("Printing String password -> " + passwordString);
System.out.println("Printing char[] password -> " + passwordArray);

С выходом:

Printing String password -> password
Printing char[] password -> [[email protected]

Мы видим, что в первом случае печатается сам контент, а во втором случае данные не так полезны, что делаетchar[] менее уязвимым.

4. Заключение

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

Как всегда, фрагменты кода можно найтиover on GitHub.