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

В любом случае в Java можно удалить данные (например, значение переменной, объект) и быть уверенным, что он не может быть восстановлен из памяти? Назначает ли null переменной в Java, удаляет значение из памяти? Есть идеи? Ответы, применимые к другим языкам, также приемлемы.

Ответ 1

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

  • Это не означает, что старая (незамеренная) копия объекта не останется на неиспользуемой странице подкачки, которая может сохраняться при перезагрузке.
  • Ничто не мешает кому-либо подключить отладчик к вашему приложению и выкалывать до того, как объект обнуляется или сбивает виртуальную машину и выкапывает в дампе кучи.

Ответ 2

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

Любые данные в ОЗУ могут быть скопированы на диск с помощью системы виртуальной памяти. Данные в ОЗУ (или дампе ядра) также могут быть проверены средствами отладки. Чтобы свести к минимуму вероятность этого, вы должны стремиться к следующему

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

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

В идеале вы должны использовать блок finally для нулевого массива, например:

KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream is = …
char[] pw = System.console().readPassword();
try {
 ks.load(is, pw);
}
finally {
  Arrays.fill(pw, '\0');
}

Ответ 3

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

Ответ 4

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

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

Ответ 5

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

Ответ 6

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

Ответ 7

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

Ответ 8

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

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

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

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

Ответ 9

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

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

Ответ 10

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

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

i sudgest либо TinyShredder, либо используя CCleaner, установленный в Gutmann-pass