Externalisierung des Bytecode-Array-Verschlüsselungsschlüssels
Stellen Sie Ihren eigenen VM-Bytecode-Verschlüsselungsschlüssel mit vmBytecodeArrayEncodingKey bereit und geben Sie ihn zur Laufzeit über einen Key-Getter zurück — außerhalb des Bundles gehalten, aus dem Client-Speicher gelesen oder von Ihrem Backend abgerufen.
Was diese Optionen bewirken
vmBytecodeArrayEncoding verschlüsselt das VM-Bytecode-Array, sodass es nicht als
Klartext in der Ausgabe vorliegt. Standardmäßig wird der Verschlüsselungsschlüssel aus der Umgebung abgeleitet und auf
dem Client rekonstruiert, sodass Sie ihn nie selbst handhaben. Das ist praktisch, aber das Schlüsselmaterial befindet
sich weiterhin im Bundle.
Zwei Optionen ermöglichen es Ihnen, den Schlüssel aus dem Bundle herauszunehmen und selbst zu kontrollieren:
vmBytecodeArrayEncodingKey— der Schlüssel, den Sie zur Kompilierzeit angeben. Wenn gesetzt, wird er anstelle des standardmäßig aus der Umgebung abgeleiteten Schlüssels verwendet und ist in der obfuskierten Ausgabe nicht eingebettet.vmBytecodeArrayEncodingKeyGetter— ein JavaScript-Ausdruck, der denselben Schlüssel zur Laufzeit zurückgibt. Er wird wortwörtlich eingebettet und im Browser ausgewertet, wenn der obfuskierte Code geladen wird.
Der Kernpunkt ist die Trennung: Da der Schlüssel nicht im Code steht, kann ihn ein rein statischer Scan des Bundles nicht wiederherstellen. Er muss zur Laufzeit dennoch vorhanden sein, damit der Code läuft, ist also nicht wirklich geheim — aber Sie entscheiden, woher er stammt und wer ihn zu sehen bekommt.
Wie die beiden Schlüssel kombiniert werden
Ihr Schlüssel wird niemals allein verwendet — auf beiden Seiten wird er mit einem internen Schlüssel vermischt, den der Obfuskator kontrolliert:
- Kompilierzeit.
vmBytecodeArrayEncodingKeywird mit einem internen Schlüssel kombiniert, den der Obfuskator ableitet, und das Bytecode-Array wird mit dem resultierenden gemischten Schlüssel codiert. - Laufzeit. Der Wert, zu dem Ihr
vmBytecodeArrayEncodingKeyGetteraufgelöst wird, wird mit demselben internen Schlüssel kombiniert — auf dem Client aus verschiedenen Laufzeitfaktoren rekonstruiert —, um den Bytecode zu decodieren.
Da beide Seiten Ihren Schlüssel mit dem internen Schlüssel vermischen, muss der Getter zu exakt derselben
Zeichenkette aufgelöst werden, die Sie als vmBytecodeArrayEncodingKey übergeben haben. Kein Teil genügt für sich
allein: Ihr Schlüssel kann ohne den internen Schlüssel den Bytecode nicht decodieren, und der interne Schlüssel ist ohne
Ihren nutzlos — weshalb die Kontrolle darüber, wer Ihren Schlüssel erhält, das ist, was den Code tatsächlich schützt.
Den Schlüssel zur Laufzeit bereitstellen
Standardmäßig ist der Getter synchron: Der Ausdruck muss den Schlüssel sofort zurückgeben, wenn der obfuskierte Code
geladen wird. Lesen Sie ihn aus einer beliebigen Quelle, die bereits auf dem Client vorhanden ist — einem Cookie,
localStorage, einer globalen Variable oder einem serverseitig injizierten DOM-Element.
JavaScriptObfuscator.obfuscate(sourceCode, {
vmObfuscation: true,
vmBytecodeArrayEncoding: true,
vmBytecodeArrayEncodingKey: process.env.VM_KEY, // e.g. 'mySecretKey123'
vmBytecodeArrayEncodingKeyGetter: "window.__VM_KEY__" // returns the key at runtime
});
Der Schlüssel muss vor der Ausführung des obfuskierten Codes existieren:
// Set by a different script, a server-injected inline script, etc.
window.__VM_KEY__ = 'mySecretKey123';
Andere synchrone Quellen funktionieren genauso — wählen Sie diejenige, die Ihre App bereits befüllt:
// 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"
Den Schlüssel von Ihrem Backend abrufen (async)
Erfordert vmAsyncExecutor · v7.3.0+Ein synchroner Getter kann nur lesen, was bereits auf dem Client vorhanden ist. Um den Schlüssel von Ihrem Server
abzurufen — sodass Sie ihn hinter einer Authentifizierung absichern und widerrufen können —, muss der Getter asynchron
sein, und das erfordert vmAsyncExecutor. Wenn der Async-Executor aktiviert ist,
darf der Getter ein Promise zurückgeben, und die VM wartet darauf, bevor sie ausgeführt wird.
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())'
});
Entscheiden Sie auf dem Server anhand dessen, was Ihre Anwendung als vertrauenswürdig einstuft, welchen Schlüssel Sie
zurückgeben — eine gültige Sitzung, einen erwarteten Origin oder Referer, eine Lizenzprüfung und so weiter. Der
Kniff: Statt nicht vertrauenswürdige Aufrufer abzulehnen, geben Sie einen falschen Schlüssel zurück. Der Bytecode
wird dann zu Datenmüll decodiert und der geschützte Code schlägt von selbst fehl, was unauffälliger ist als ein
offensichtlicher 401, der einem Angreifer genau sagt, was er umgehen muss.
// 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
);
});
Liefern Sie über diesen Endpunkt exakt dieselbe Zeichenkette aus, die Sie zur Build-Zeit als
vmBytecodeArrayEncodingKey übergeben haben. Eine Kopie des Bundles, die außerhalb Ihrer Umgebung läuft, erhält den
Köderschlüssel, entschlüsselt zu nichts und ist funktionslos.
Wenn der Schlüssel nicht übereinstimmt
Der obfuskierte Code funktioniert nur, wenn der Getter exakt denselben Schlüssel zurückgibt, der bei der Obfuskation
verwendet wurde. Wenn sich die Schlüssel unterscheiden — oder der Getter undefined, null oder eine leere
Zeichenkette zurückgibt —, erzeugt die Entschlüsselung einen falschen Keystream und der Code schlägt zur Laufzeit mit
Datenmüll als Ausgabe oder einem gewöhnlichen Laufzeitfehler fehl.
Es gibt bewusst keine eigene, schlüsselspezifische Fehlermeldung: Ein fehlgeschlagener Schlüssel ist von jedem anderen Laufzeitfehler nicht zu unterscheiden. Wenn ein VM-geschütztes Bundle also erst dann einen Fehler wirft, sobald diese Option im Spiel ist, prüfen Sie zuerst den Schlüsselpfad — dass der Getter auf der Seite aufgelöst wird, eine nicht leere Zeichenkette zurückgibt und denselben Wert zurückgibt, mit dem Sie gebaut haben.
