В: Если я зашифрую свои файлы .class и использую собственный загрузчик классов для загрузки и дешифрования на лету, это предотвратит декомпиляцию?
A: Проблема предотвращения декомпиляции байт-кода Java почти так же стара, как сам язык. Несмотря на широкий спектр инструментов запутывания, доступных на рынке, начинающие Java-программисты продолжают думать о новых и умных способах защиты своей интеллектуальной собственности. В этой статье, посвященной вопросам и ответам на Java, я расскажу о некоторых мифах вокруг идеи, часто обсуждаемой в дискуссионных форумах.
Чрезвычайная легкость, с которой файлы Java .class могут быть преобразованы в источники Java, которые очень похожи на оригиналы, во многом связана с целями и компромиссами проектирования байт-кода Java. Помимо прочего, байт-код Java был разработан для обеспечения компактности, независимости от платформы, мобильности сети и простоты анализа с помощью интерпретаторов байт-кода и динамических компиляторов JIT (точно в срок) / HotSpot. Возможно, скомпилированные файлы .class выражают намерение программиста настолько ясно, что их легче проанализировать, чем исходный код.
Можно сделать несколько вещей, если не полностью предотвратить декомпиляцию, по крайней мере, сделать ее более сложной. Например, в качестве шага после компиляции вы могли бы массировать данные .class, чтобы сделать байт-код трудным для чтения при декомпиляции или сложным для декомпиляции в допустимый код Java (или оба). Такие методы, как выполнение экстремальной перегрузки имен методов, хорошо работают для первых и манипулируют потоком управления для создания структур управления, которые невозможно представить с помощью синтаксиса Java, хорошо работают для последних. Более успешные коммерческие обфускаторы используют сочетание этих и других методов.
К сожалению, оба подхода должны фактически изменить код, который будет запускать JVM, и многие пользователи опасаются (справедливо), что это преобразование может добавить новые ошибки в их приложения. Кроме того, переименование методов и полей может привести к прекращению работы вызовов отражений. Изменение фактических имен классов и пакетов может привести к поломке нескольких других API Java (JNDI (Java Naming and Directory Interface), провайдеров URL и т. Д.). В дополнение к измененным именам, если связь между смещениями байт-кода класса и номерами строк исходного кода изменяется, восстановление исходных трассировок стека исключений может стать затруднительным.
Тогда есть возможность обфусцировать оригинальный исходный код Java. Но в основном это вызывает аналогичный набор проблем.
Зашифровать, не запутать?
Возможно, вышеизложенное заставило вас задуматься: «Ну, что если вместо манипулирования байтовым кодом я зашифрую все свои классы после компиляции и расшифрую их на лету внутри JVM (что можно сделать с помощью специального загрузчика классов)? JVM выполняет мой оригинальный байт-код, но декомпилировать или перепроектировать нечего, верно? "
К сожалению, вы были бы неправы, думая, что вы первыми предложили эту идею, и думая, что она действительно работает. И причина не имеет ничего общего с силой вашей схемы шифрования.