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