Documentación
/
Recetas
/

Clave de codificación del array de bytecode

Externalizar la clave de cifrado del array de bytecode

Pro

Proporcione su propia clave de cifrado del bytecode de la VM con vmBytecodeArrayEncodingKey y devuélvala en tiempo de ejecución mediante un getter de clave — mantenida fuera del bundle, leída desde el almacenamiento del cliente o recuperada desde su backend.

Qué hacen estas opciones

vmBytecodeArrayEncoding cifra el array de bytecode de la VM para que no aparezca como texto plano en la salida. De forma predeterminada, la clave de cifrado se deriva del entorno y se reconstruye en el cliente, por lo que usted nunca la manipula. Esto es cómodo, pero el material de la clave sigue residiendo en el bundle.

Dos opciones le permiten sacar la clave del bundle y controlarla usted mismo:

  • vmBytecodeArrayEncodingKey — la clave que usted proporciona en tiempo de compilación. Cuando se define, se utiliza en lugar de la clave predeterminada derivada del entorno, y no se incrusta en la salida ofuscada.
  • vmBytecodeArrayEncodingKeyGetter — una expresión de JavaScript que devuelve esa misma clave en tiempo de ejecución. Se incrusta literalmente y se evalúa en el navegador cuando se carga el código ofuscado.

La clave está en la separación: como la clave no está en el código, un análisis puramente estático del bundle no puede recuperarla. Aun así debe estar presente en tiempo de ejecución para que el código funcione, por lo que no es verdaderamente secreta — pero usted decide de dónde proviene y quién puede verla.

Cómo se combinan las dos claves

Su clave nunca se utiliza por sí sola — en ambos lados se mezcla con una clave interna que controla el ofuscador:

  • Tiempo de compilación. vmBytecodeArrayEncodingKey se combina con una clave interna que deriva el ofuscador, y el array de bytecode se codifica con la clave mixta resultante.
  • Tiempo de ejecución. El valor al que se resuelve su vmBytecodeArrayEncodingKeyGetter se combina con la misma clave interna, reconstruida en el cliente a partir de diversos factores de ejecución, para decodificar el bytecode.

Como ambos lados mezclan su clave con la clave interna, el getter debe resolverse a exactamente la misma cadena que pasó como vmBytecodeArrayEncodingKey. Ninguna de las dos partes basta por sí sola: su clave sin la clave interna no puede decodificar el bytecode, y la clave interna es inútil sin la suya — por eso controlar quién recibe su clave es lo que realmente protege el código.

Proporcionar la clave en tiempo de ejecución

De forma predeterminada, el getter es síncrono: la expresión debe devolver la clave de inmediato cuando se carga el código ofuscado. Léala desde cualquier fuente que ya esté presente en el cliente — una cookie, localStorage, una variable global o un elemento del DOM inyectado por el servidor.

JavaScriptObfuscator.obfuscate(sourceCode, {
    vmObfuscation: true,
    vmBytecodeArrayEncoding: true,
    vmBytecodeArrayEncodingKey: process.env.VM_KEY,       // e.g. 'mySecretKey123'
    vmBytecodeArrayEncodingKeyGetter: "window.__VM_KEY__" // returns the key at runtime
});

La clave debe existir antes de que se ejecute el código ofuscado:

// Set by a different script, a server-injected inline script, etc.
window.__VM_KEY__ = 'mySecretKey123';

Otras fuentes síncronas funcionan de la misma manera — elija la que su aplicación ya rellene:

// From a cookie
vmBytecodeArrayEncodingKeyGetter: "document.cookie.match(/vmKey=([^;]+)/)?.[1]"

// From localStorage
vmBytecodeArrayEncodingKeyGetter: "localStorage.getItem('vmKey')"

// From a server-injected meta tag
vmBytecodeArrayEncodingKeyGetter: "document.querySelector('meta[name=\"vm-key\"]').content"

// From a nested object
vmBytecodeArrayEncodingKeyGetter: "window.config.encryption.key"

Recuperar la clave desde su backend (async)

Requiere vmAsyncExecutor · v7.3.0+

Un getter síncrono solo puede leer lo que ya está en el cliente. Para recuperar la clave desde su servidor — de modo que pueda protegerla tras una autenticación y revocarla —, el getter debe ser asíncrono, y eso requiere vmAsyncExecutor. Con el ejecutor asíncrono habilitado, el getter puede devolver una Promise, y la VM la espera antes de ejecutarse.

JavaScriptObfuscator.obfuscate(sourceCode, {
    vmObfuscation: true,
    vmAsyncExecutor: true,
    vmBytecodeArrayEncoding: true,
    vmBytecodeArrayEncodingKey: process.env.VM_KEY,       // kept on your server, not in the bundle
    vmBytecodeArrayEncodingKeyGetter:
        'fetch("/api/vm-key", { credentials: "include" }).then((res) => res.text())'
});

En el servidor, decida qué clave devolver en función de aquello en lo que su aplicación confíe — una sesión válida, un Origin o Referer esperado, una comprobación de licencia, etc. El truco: en lugar de rechazar a los llamadores no confiables, devuelva una clave incorrecta. El bytecode se decodifica entonces en datos basura y el código protegido falla por sí solo, lo cual es más sigiloso que un 401 evidente que le indica a un atacante exactamente qué debe eludir.

// Express example — the exact checks depend on your app
app.get('/api/vm-key', (req, res) => {
    const origin = req.get('origin');
    const trusted =
        req.session?.user &&                       // a valid session, and
        origin === 'https://app.example.com';      // the expected production origin

    res.type('text/plain').send(
        // Real key for valid users; a decoy for everyone else
        // (no session, or a localhost / unexpected origin).
        trusted ? process.env.VM_KEY : process.env.VM_DECOY_KEY
    );
});

Sirva desde este endpoint exactamente la misma cadena que pasó como vmBytecodeArrayEncodingKey en tiempo de compilación. Una copia del bundle que se ejecute fuera de su entorno recibe la clave señuelo, se descifra en nada y queda inerte.

Cuando la clave no coincide

El código ofuscado solo funciona cuando el getter devuelve exactamente la misma clave utilizada durante la ofuscación. Si las claves difieren — o si el getter devuelve undefined, null o una cadena vacía —, el descifrado produce un flujo de claves incorrecto y el código falla en tiempo de ejecución con una salida basura o un error de ejecución ordinario.

Deliberadamente no existe un mensaje de error propio y específico de la clave: una clave fallida es indistinguible de cualquier otro fallo en tiempo de ejecución. Por eso, cuando un bundle protegido por la VM lanza un error solo una vez que esta opción entra en juego, compruebe primero la ruta de la clave — que el getter se resuelve en la página, devuelve una cadena no vacía y devuelve el mismo valor con el que compiló.