Документация
/

Ключ кодирования массива байт-кода

Вынесение ключа кодирования массива байт-кода

Pro

Задайте собственный ключ шифрования байт-кода VM с помощью vmBytecodeArrayEncodingKey и верните его во время выполнения через геттер ключа - он не попадает в бандл, читается из клиентского хранилища или запрашивается с вашего бэкенда.

Что делают эти опции

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

Две опции позволяют вынести ключ из бандла и управлять им самостоятельно:

  • vmBytecodeArrayEncodingKey - ключ, который вы задаёте на этапе компиляции. Если он задан, то используется вместо ключа по умолчанию, выведенного из окружения, и не встраивается в обфусцированный вывод.
  • vmBytecodeArrayEncodingKeyGetter - выражение JavaScript, которое возвращает тот же самый ключ во время выполнения. Оно встраивается дословно и вычисляется в браузере при загрузке обфусцированного кода.

Суть в разделении: поскольку ключа нет в коде, чисто статический анализ бандла не сможет его восстановить. Он всё равно должен присутствовать во время выполнения, чтобы код заработал, поэтому он не является по-настоящему секретным - но вы решаете, откуда он берётся и кто его видит.

Эти две опции работают в паре. vmBytecodeArrayEncodingKey без геттера оставляет обфусцированный код без возможности получить ключ во время выполнения, а геттер без соответствующего ключа этапа компиляции не с чем сопоставить. Задайте обе, вместе с vmBytecodeArrayEncoding: true.

Как объединяются два ключа

Ваш ключ никогда не используется сам по себе - с обеих сторон он смешивается с внутренним ключом, которым управляет обфускатор:

  • Этап компиляции. vmBytecodeArrayEncodingKey объединяется с внутренним ключом, который выводит обфускатор, и массив байт-кода кодируется получившимся смешанным ключом.
  • Время выполнения. Значение, к которому разрешается ваш vmBytecodeArrayEncodingKeyGetter, объединяется с тем же внутренним ключом, восстановленным на клиенте из различных факторов времени выполнения, чтобы декодировать байт-код.

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

Предоставление ключа во время выполнения

По умолчанию геттер синхронный: выражение должно вернуть ключ немедленно при загрузке обфусцированного кода. Читайте его из любого источника, который уже присутствует на клиенте - из cookie, localStorage, глобальной переменной или внедрённого сервером элемента DOM.

JavaScript

Ключ должен существовать до запуска обфусцированного кода:

JavaScript

Другие синхронные источники работают так же - выберите тот, который ваше приложение уже заполняет:

JavaScript

Держите ключ отдельно от того же файла или скрипта, где находится обфусцированный код. Встраивание его туда сводит на нет весь смысл - статический анализ бандла восстановит и код, и его ключ. Храните его в отдельном источнике и внедряйте ключ этапа компиляции vmBytecodeArrayEncodingKey из переменной окружения или секрета, а не записывайте его в репозиторий.

Запрос ключа с вашего бэкенда (асинхронно)

Требует vmAsyncExecutor · v7.3.0+

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

JavaScript

Геттер, возвращающий Promise, требует vmAsyncExecutor. Это невозможно проверить на этапе сборки, поэтому геттер с Promise при выключенном vmAsyncExecutor завершается ошибкой во время выполнения - декодер получает объект Promise вместо строки ключа.

Разрешайте выдачу ключа по проверенной сессии и необходимым условиям лицензии. Origin или Referer сами по себе не аутентифицируют клиента; в same-origin GET заголовок Origin может отсутствовать. Отключите кэширование ответа. Свяжите ключи с версиями сборок и развёртывайте их согласованно. Получивший ключ клиент может изучить его во время выполнения.

JavaScript

Когда ключ не совпадает

Обфусцированный код работает только тогда, когда геттер возвращает точно тот же ключ, что использовался при обфускации. Если ключи различаются - или геттер возвращает undefined, null либо пустую строку - расшифровка порождает неправильный поток ключей, и код падает во время выполнения с мусорным выводом или обычной ошибкой времени выполнения.

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