Documentazione
/
Ricette
/

Chiave di codifica dell'array di bytecode

Esternalizzare la chiave di codifica dell'array di bytecode

Pro

Fornisci la tua chiave di crittografia del bytecode della VM con vmBytecodeArrayEncodingKey e restituiscila a runtime tramite un key getter — tenuta fuori dal bundle, letta dallo storage del client o recuperata dal tuo backend.

Cosa fanno queste opzioni

vmBytecodeArrayEncoding cifra l'array di bytecode della VM in modo che non compaia nell'output come testo in chiaro. Per impostazione predefinita la chiave di crittografia viene derivata dall'ambiente e ricostruita sul client, quindi non devi mai gestirla direttamente. È comodo, ma il materiale della chiave risiede comunque nel bundle.

Due opzioni ti permettono di estrarre la chiave dal bundle e di controllarla tu stesso:

  • vmBytecodeArrayEncodingKey — la chiave che fornisci in fase di compilazione. Quando è impostata, viene usata al posto della chiave predefinita derivata dall'ambiente e non viene incorporata nell'output offuscato.
  • vmBytecodeArrayEncodingKeyGetter — un'espressione JavaScript che restituisce quella stessa chiave a runtime. Viene incorporata testualmente e valutata nel browser quando il codice offuscato viene caricato.

Il punto è la separazione: poiché la chiave non è nel codice, una scansione puramente statica del bundle non può recuperarla. Deve comunque essere presente a runtime perché il codice funzioni, quindi non è davvero segreta — ma sei tu a decidere da dove proviene e chi può vederla.

Come si combinano le due chiavi

La tua chiave non viene mai usata da sola — su entrambi i lati viene combinata con una chiave interna controllata dall'offuscatore:

  • Fase di compilazione. vmBytecodeArrayEncodingKey viene combinata con una chiave interna derivata dall'offuscatore, e l'array di bytecode viene codificato con la chiave mista risultante.
  • Runtime. Il valore a cui si risolve il tuo vmBytecodeArrayEncodingKeyGetter viene combinato con la stessa chiave interna, ricostruita sul client a partire da vari fattori di runtime, per decodificare il bytecode.

Poiché entrambi i lati combinano la tua chiave con la chiave interna, il getter deve risolversi esattamente nella stessa stringa che hai passato come vmBytecodeArrayEncodingKey. Nessuno dei due elementi è sufficiente da solo: la tua chiave senza la chiave interna non può decodificare il bytecode, e la chiave interna è inutile senza la tua — ecco perché controllare chi riceve la tua chiave è ciò che protegge davvero il codice.

Fornire la chiave a runtime

Per impostazione predefinita il getter è sincrono: l'espressione deve restituire la chiave immediatamente quando il codice offuscato viene caricato. Leggila da qualsiasi sorgente già presente sul client — un cookie, localStorage, una variabile globale o un elemento del DOM iniettato dal server.

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 chiave deve esistere prima che il codice offuscato venga eseguito:

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

Altre sorgenti sincrone funzionano allo stesso modo — scegli quella che la tua applicazione già popola:

// 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"

Recuperare la chiave dal tuo backend (asincrono)

Richiede vmAsyncExecutor · v7.3.0+

Un getter sincrono può leggere solo ciò che è già presente sul client. Per recuperare la chiave dal tuo server — così da poterla proteggere dietro un'autenticazione e revocarla — il getter deve essere asincrono, e ciò richiede vmAsyncExecutor. Con l'executor asincrono abilitato, il getter può restituire una Promise, e la VM la attende prima dell'esecuzione.

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())'
});

Sul server, decidi quale chiave restituire in base a ciò di cui la tua applicazione si fida — una sessione valida, un Origin o Referer atteso, un controllo di licenza e così via. Il trucco: invece di rifiutare i chiamanti non attendibili, restituisci una chiave sbagliata. Il bytecode viene così decodificato in dati privi di senso e il codice protetto fallisce da solo, il che è più discreto di un evidente 401 che indica a un attaccante esattamente cosa aggirare.

// 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
    );
});

Restituisci da questo endpoint esattamente la stessa stringa che hai passato come vmBytecodeArrayEncodingKey in fase di build. Una copia del bundle in esecuzione al di fuori del tuo ambiente ottiene la chiave esca, si decifra in nulla ed è inerte.

Quando la chiave non corrisponde

Il codice offuscato funziona solo quando il getter restituisce esattamente la stessa chiave usata durante l'offuscamento. Se le chiavi differiscono — o se il getter restituisce undefined, null o una stringa vuota — la decifratura produce un keystream errato e il codice fallisce a runtime con output privo di senso o con un normale errore di runtime.

Non esiste deliberatamente alcun messaggio di errore distinto e specifico della chiave: una chiave fallita è indistinguibile da qualsiasi altro guasto a runtime. Quindi, quando un bundle protetto dalla VM genera un errore solo quando questa opzione è in gioco, controlla prima il percorso della chiave — che il getter si risolva sulla pagina, restituisca una stringa non vuota e restituisca lo stesso valore con cui hai eseguito la build.