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