Использует ли отражение для очистки String
с помощью String
безопасно использовать char[]
для паролей?
С точки зрения безопасности, как правило, рекомендуется использовать char[]
для хранения/передачи паролей, поскольку можно как можно скорее обнулить его содержимое в коде, что может быть значительно до того, как сбор мусора очистит его и память повторно используется (вытирая всю трассировку), ограничивая время для атаки на память.
Однако char[]
не так удобен, как String
, поэтому было бы удобно, если бы можно было "скрасить" String
при необходимости, тем самым сделав String
безопасным, как char[]
.
Ниже приведен метод, который использует отражение для обнуления полей String
.
Является ли этот метод "ОК" и позволяет ли он сделать String
безопаснее, чем char[]
для паролей?
public static void scrub(String str) throws NoSuchFieldException, IllegalAccessException {
Field valueField = String.class.getDeclaredField("value");
Field offsetField = String.class.getDeclaredField("offset");
Field countField = String.class.getDeclaredField("count");
Field hashField = String.class.getDeclaredField("hash");
valueField.setAccessible(true);
offsetField.setAccessible(true);
countField.setAccessible(true);
hashField.setAccessible(true);
char[] value = (char[]) valueField.get(str);
// overwrite the relevant array contents with null chars
Arrays.fill(value, offsetField.getInt(str), countField.getInt(str), '\0');
countField.set(str, 0); // scrub password length too
hashField.set(str, 0); // the hash could be used to crack a password
valueField.setAccessible(false);
offsetField.setAccessible(false);
countField.setAccessible(false);
hashField.setAccessible(false);
}
Вот простой тест:
String str = "password";
scrub(str);
System.out.println('"' + str + '"');
Вывод:
""
Примечание.. Вы можете предположить, что пароли не являются константами String
, и поэтому вызов этого метода не окажет отрицательного влияния на интернированные строки.
Кроме того, я оставил метод довольно "сырым" состоянием для простоты. Если бы я использовал его, я бы не объявил исключений (try/catch/ignoring them) и повторил повторный код.