Externaliser la clé de chiffrement du tableau de bytecode
Fournissez votre propre clé de chiffrement du bytecode de la VM avec vmBytecodeArrayEncodingKey et restituez-la à l'exécution via un getter de clé — conservée hors du bundle, lue depuis le stockage client ou récupérée depuis votre backend.
Ce que font ces options
vmBytecodeArrayEncoding chiffre le tableau de bytecode de la VM afin qu'il ne
figure pas en clair dans la sortie. Par défaut, la clé de chiffrement est dérivée de l'environnement et reconstruite sur
le client, de sorte que vous n'avez jamais à la manipuler. C'est pratique, mais le matériel de clé réside toujours dans
le bundle.
Deux options vous permettent de sortir la clé du bundle et de la contrôler vous-même :
vmBytecodeArrayEncodingKey— la clé que vous fournissez à la compilation. Lorsqu'elle est définie, elle est utilisée à la place de la clé par défaut dérivée de l'environnement, et elle n'est pas intégrée à la sortie obfusquée.vmBytecodeArrayEncodingKeyGetter— une expression JavaScript qui renvoie cette même clé à l'exécution. Elle est intégrée telle quelle et évaluée dans le navigateur au chargement du code obfusqué.
L'intérêt réside dans la séparation : comme la clé ne figure pas dans le code, une analyse purement statique du bundle ne peut pas la récupérer. Elle doit tout de même être présente à l'exécution pour que le code fonctionne, elle n'est donc pas véritablement secrète — mais vous décidez d'où elle provient et qui peut la voir.
Comment les deux clés se combinent
Votre clé n'est jamais utilisée seule — des deux côtés, elle est mélangée à une clé interne que l'obfuscateur contrôle :
- À la compilation.
vmBytecodeArrayEncodingKeyest combinée à une clé interne dérivée par l'obfuscateur, et le tableau de bytecode est encodé avec la clé mixte résultante. - À l'exécution. La valeur à laquelle se résout votre
vmBytecodeArrayEncodingKeyGetterest combinée à la même clé interne, reconstruite sur le client à partir de divers facteurs d'exécution, pour décoder le bytecode.
Comme les deux côtés mélangent votre clé à la clé interne, le getter doit se résoudre à exactement la même chaîne
que celle que vous avez passée en tant que vmBytecodeArrayEncodingKey. Aucune des deux parties ne suffit à elle seule :
votre clé sans la clé interne ne peut pas décoder le bytecode, et la clé interne est inutile sans la vôtre — c'est
pourquoi contrôler qui reçoit votre clé est ce qui protège réellement le code.
Fournir la clé à l'exécution
Par défaut, le getter est synchrone : l'expression doit renvoyer la clé immédiatement au chargement du code
obfusqué. Lisez-la depuis n'importe quelle source déjà présente sur le client — un cookie, localStorage, une variable
globale ou un élément du DOM injecté par le serveur.
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 clé doit exister avant l'exécution du code obfusqué :
// Set by a different script, a server-injected inline script, etc.
window.__VM_KEY__ = 'mySecretKey123';
D'autres sources synchrones fonctionnent de la même manière — choisissez celle que votre application renseigne déjà :
// 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"
Récupérer la clé depuis votre backend (async)
Requiert vmAsyncExecutor · v7.3.0+Un getter synchrone ne peut lire que ce qui se trouve déjà sur le client. Pour récupérer la clé depuis votre
serveur — afin de pouvoir la protéger derrière une authentification et la révoquer —, le getter doit être
asynchrone, ce qui requiert vmAsyncExecutor. Lorsque l'exécuteur asynchrone est
activé, le getter peut renvoyer une Promise, et la VM l'attend avant de s'exécuter.
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())'
});
Sur le serveur, décidez quelle clé renvoyer en fonction de ce à quoi votre application fait confiance — une session
valide, un Origin ou un Referer attendu, une vérification de licence, et ainsi de suite. L'astuce : au lieu de
rejeter les appelants non fiables, renvoyez une mauvaise clé. Le bytecode se décode alors en données inutilisables
et le code protégé échoue de lui-même, ce qui est plus discret qu'un 401 évident qui indique à un attaquant exactement
ce qu'il doit contourner.
// 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
);
});
Servez depuis ce point de terminaison exactement la même chaîne que celle que vous avez passée en tant que
vmBytecodeArrayEncodingKey lors du build. Une copie du bundle exécutée en dehors de votre environnement reçoit la clé
leurre, se déchiffre en rien du tout et reste inerte.
Lorsque la clé ne correspond pas
Le code obfusqué ne fonctionne que lorsque le getter renvoie exactement la même clé que celle utilisée lors de
l'obfuscation. Si les clés diffèrent — ou si le getter renvoie undefined, null ou une chaîne vide —, le déchiffrement
produit un mauvais flux de clé et le code échoue à l'exécution avec une sortie inutilisable ou une erreur d'exécution
ordinaire.
Il n'existe volontairement aucun message d'erreur distinct et propre à la clé : une clé défaillante est indiscernable de toute autre défaillance à l'exécution. Ainsi, lorsqu'un bundle protégé par la VM ne lève une erreur qu'une fois cette option en jeu, vérifiez d'abord le chemin de la clé — que le getter se résout sur la page, renvoie une chaîne non vide et renvoie la même valeur que celle avec laquelle vous avez compilé.
