Я участвую в обсуждении того, как защищать конфиденциальную информацию (например, пароли), хранящуюся в программе Java. В соответствии с требованиями безопасности память, содержащая конфиденциальную информацию, очищается, например. путем установки значений байтов для всех нулей. Вызывает беспокойство, что злоумышленник может наблюдать за памятью, связанной с процессом приложения, и поэтому мы хотим как можно больше ограничить время, в течение которого такая конфиденциальная информация зависает. Раньше проекты включали С++, поэтому достаточно было memset().
(Кстати, использование memset() было подвергнуто сомнению, поскольку некоторые компиляторы, как известно, оптимизируют его использование из полученного двоичного кода на основе предположения, что, поскольку память не используется позже, нет необходимости нуль в первую очередь. Этот комментарий является отказом для тех, кто Google для "memset" и "clear memory" и т.д.).
Теперь у нас есть на руках Java-проект, который прижимается к этому требованию.
Для объектов Java я понимаю, что:
- нулевая ссылка только изменяет значение ссылки; память в куче для объекта по-прежнему содержит данные
- неизменяемый объект, такой как String, не сможет изменить его данные (или, по крайней мере, не легко, в пределах виртуальной машины с соответствующим образом включенным менеджером безопасности).
- коллекционеры мусора поколения могут делать копии объектов повсюду (как указано здесь).
И для примитивов я понимаю, что:
- переменная примитивного типа в локальном методе будет выделена в стеке и:
- когда вы меняете его значение, вы изменяете его непосредственно в памяти (в отличие от использования ссылки для обработки объекта в куче).
- копии могут/будут выполняться "за кадром" в некоторых ситуациях, например, передавать его в качестве аргумента в методы или бокс (автоматически или нет), создавая экземпляры оболочек, которые содержат другую примитивную переменную с одинаковым значением.
Мой коллега утверждает, что Java-примитивы неизменяемы и что есть документация от NSA и Oracle относительно отсутствия поддержки Java для этого требования.
Моя позиция заключается в том, что примитивы могут (по крайней мере в некоторых ситуациях) обнуляться, устанавливая значение в ноль (или логическое на false), и память очищается таким образом.
Я пытаюсь проверить, есть ли в JLS или другой "официальной" документации о необходимости поведения JVM, когда дело касается управления памятью в отношении примитивов. Самое близкое, что я мог найти, - это "Правила безопасного кодирования для языка программирования Java" на сайте Oracle, в котором упоминается очистка массивов char после использования.
Я бы опротестовал определения, когда мой коллега назвал примитивы неизменными, но я уверен, что он имел в виду, что "память не может быть надлежащим образом обнулена" - не стоит беспокоиться об этом. Мы не обсуждали, имел ли он в виду конечные переменные - из контекста, о котором мы говорили вообще.
Есть ли окончательные ответы или ссылки на это? Я был бы признателен за все, что могло бы показать мне, где я ошибаюсь, или подтвердить, что я прав.
Изменить: после дальнейшего обсуждения я смог уточнить, что мой коллега думал о примитивных обертках, а не о самих примитивах. Таким образом, мы остаемся с оригинальной проблемой, как безопасно очищать память, желательно от объектов. Кроме того, для уточнения важная информация - это не только пароли, но и такие вещи, как IP-адреса или ключи шифрования.
Существуют ли какие-либо коммерческие JVM, которые предлагают функцию, такую как приоритетная обработка определенных объектов? (Я предполагаю, что это фактически нарушит спецификацию Java, но я думал, что попрошу на всякий случай, если я ошибаюсь.)