Безвозвратно уничтожая данные в Java

String a = new String("foo");
String b = new String("foo");
System.out.println(a == b); // prints false
System.out.println(a.equals(b)); // prints true

Убедитесь, что вы понимаете, почему. Это потому, что сравнение == сравнивает только ссылки; equals() метод сопоставляет содержимое по символу.

Когда вы вызываете new для a и b, каждый получает новую ссылку, указывающую на "foo" в таблице строк. Ссылки разные, но контент один и тот же.

11
задан erickson 24 September 2008 в 16:09
поделиться

10 ответов

Из-за виртуальной памяти чудес, почти невозможно удалить что-то из памяти абсолютно невосполнимым способом. Ваш лучший выбор состоит в том, чтобы обнулить поля значения; однако:

  • Это не означает, что старую (необнуленную) копию объекта не оставят на неиспользованной странице подкачки, которая могла сохраниться через перезагрузки.
  • И при этом это не мешает кому-то присоединить отладчик к Вашему приложению и ввести по абсолютному адресу вокруг, прежде чем объект будет обнулен или катастрофический отказ VM и ввод по абсолютному адресу вокруг в дампе "кучи".
19
ответ дан 3 December 2019 в 01:34
поделиться

Храните уязвимые данные в массиве, затем "обнулите" их как можно скорее.

Любые данные в RAM могут быть скопированы в диск системой виртуальной памяти. Данные в RAM (или дамп ядра) могут также быть осмотрены средствами отладки. Для сведения к минимуму вероятности этого случая необходимо бороться за следующее

  • храните окно времени в тайне, присутствует в памяти, максимально короткой
  • будьте осторожны относительно конвейеров IO (например, BufferedInputStream) те внутренне буферные данные
  • сохраните ссылки на секрет на стеке и из "кучи"
  • не используйте неизменные типы, как String, содержать секреты

Криптографические API в Java используют этот подход, и любые API, которые Вы создаете, должны поддерживать его также. Например, KeyStore.load позволяет вызывающей стороне очищать пароль char[], и когда вызов завершается, как делает KeySpec для основанного на пароле шифрования.

Идеально, Вы использовали бы a finally блок для обнуления массива, как это:

KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream is = …
char[] pw = System.console().readPassword();
try {
 ks.load(is, pw);
}
finally {
  Arrays.fill(pw, '\0');
}
9
ответ дан 3 December 2019 в 01:34
поделиться

Ничто не удалено, то, что это примерно было доступным или не к приложению. Однажды недоступный, пространство становится кандидатом на последующее использование, когда потребность возникнет, и пространство будет перезаписано. В случае прямого доступа к памяти что-то должно всегда там читать, но это мог бы быть спам, и привычка имеют смысл.

3
ответ дан 3 December 2019 в 01:34
поделиться

Поскольку zacherates сказал, нуль чувствительные поля Вашего Объекта прежде, чем удалить ссылки на него. Обратите внимание, что Вы не можете обнулить содержание Строки, так используйте массивы символов и обнулите каждый элемент.

2
ответ дан 3 December 2019 в 01:34
поделиться

Путем установки Объекта в NULL не означает, что объект удален из памяти. Виртуальная машина отметит тот Объект как готовый к Сборке "мусора", если больше не будет ссылок на тот Объект. В зависимости от Вашего кода на это можно было бы все еще сослаться даже при том, что Вы установили его в NULL, в этом случае, это не будет удалено. (По существу, если Вы ожидаете, что это будет собрано "мусор", и это не Вы, имеют утечку памяти!)

После того как это отмечается как готовое к набору, Вы не имеете никакого контроля, когда Сборщик "мусора" удалит его. Можно бездельничать со стратегиями Сборки "мусора", но я не советовал бы ему. Представьте свое приложение и посмотрите на объект, и это - идентификатор, и Вы видите то, что ссылается на него. Java предоставляет VisualVM 1.6.0_07 и выше или можно использовать NetBeans

2
ответ дан 3 December 2019 в 01:34
поделиться

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

1
ответ дан 3 December 2019 в 01:34
поделиться

Нет, если у Вас нет прямого ответа на аппаратные средства. Существует шанс, что переменная будет кэшироваться где-нибудь. Уязвимые данные могут даже храниться в подкачке :) Если Вы касаетесь только о RAM, можно играть со сборщиком "мусора". На высоком уровне langs обычно у Вас нет прямого доступа к памяти, таким образом, не возможно управлять этим аспектом. Например, в.NET существует класс SecureString, который использует interop и прямой доступ к памяти.

1
ответ дан 3 December 2019 в 01:34
поделиться

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

Данные объектов должны быть санированы путем перезаписи их примитивных свойств; установка в NULL переменной просто делает объект доступным для GC, но не сразу мертвая. Дамп VM будет содержать их, чтобы любой видел.

Неизменные данные, такие как Строка не могут быть перезаписаны всегда. Любая модификация просто делает копию. Необходимо постараться не сохранять уязвимые данные в таких объектах.

P.S. Если мы говорим о паролях, лучше использовать crypto-сильные хеш-функции (MD5, SHA1...), и никогда не работать с паролями в открытом тексте.

1
ответ дан 3 December 2019 в 01:34
поделиться

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

Но все другие информация все еще там, непока она не перезаписывается кем-то еще.

я sudgest или TinyShredder, или использующий набор CCleaner для Gutmann-передачи

0
ответ дан 3 December 2019 в 01:34
поделиться

Если Вы думаете об обеспечении пароля/управления ключами, Вы могли бы написать некоторый код JNI, который использует определенный для платформы API, чтобы сохранить ключи в безопасном пути и не пропустить данные в память, управляемую JVM. Например, Вы могли сохранить ключи в странице, привязал физическую память и мог препятствовать тому, чтобы шина IO получила доступ к памяти.

Править: Для комментария некоторых предыдущих ответов JVM могла переместить объекты в памяти, не стирая их предыдущие местоположения, таким образом, даже символ [], байты, ints и другие "стираемые" типы данных не является ответом, если Вы действительно хотите удостовериться, что никакая уязвимая информация не хранится в памяти, управляемой JVM, или подкачала на жестком диске.

1
ответ дан 3 December 2019 в 01:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: