Signatur
Beschreibung
Über self.crypto (oder kurz crypto) greift man in einem Web Worker, Shared Worker oder Service Worker auf dasselbe Crypto-Objekt zu, das es im Hauptthread als window.crypto gibt. Damit stehen kryptografisch sichere Zufallszahlen (getRandomValues()), UUIDs der Version 4 (randomUUID()) und über crypto.subtle die komplette SubtleCrypto-Schnittstelle zum Hashen, Verschlüsseln, Signieren und Ableiten von Schlüsseln bereit.
Gerade in Workern ist das nützlich: Aufwendige Operationen wie das Hashen großer Dateien, PBKDF2-Schlüsselableitung oder das Ver- und Entschlüsseln von großen Datenmengen blockieren so nicht den UI-Thread. Die Ergebnisse, meist ArrayBuffer, kann man per postMessage() ohne Kopie (als Transferable) an den Hauptthread zurückgeben.
Die Eigenschaft ist schreibgeschützt. Jeder Worker hat eine eigene Crypto-Instanz. CryptoKey-Objekte lassen sich aber per Structured Clone zwischen Hauptthread und Worker verschicken, auch wenn sie nicht exportierbar sind.
Rückgabewert
Crypto-Objekt des aktuellen Worker-Kontexts mit getRandomValues(), randomUUID() und der Eigenschaft subtle (SubtleCrypto).Beispiele
Zufallswerte und UUID im Worker erzeugen
// worker.js
self.addEventListener('message', () => {
const bytes = self.crypto.getRandomValues(new Uint8Array(8));
const id = self.crypto.randomUUID();
self.postMessage({ id, token: Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('') });
});
// main.js
const worker = new Worker('worker.js');
worker.onmessage = ({ data }) => console.log(data);
worker.postMessage('start');
SHA-256-Hash einer Datei im Worker berechnen
// hash-worker.js
self.onmessage = async ({ data: file }) => {
const buffer = await file.arrayBuffer();
const digest = await crypto.subtle.digest('SHA-256', buffer);
const hex = [...new Uint8Array(digest)]
.map((b) => b.toString(16).padStart(2, '0'))
.join('');
self.postMessage(hex);
};
// main.js
const hashWorker = new Worker('hash-worker.js');
hashWorker.onmessage = ({ data }) => console.log('SHA-256:', data);
document.querySelector('input[type=file]').addEventListener('change', (e) => {
hashWorker.postMessage(e.target.files[0]);
});
Passwortbasierte AES-GCM-Verschlüsselung im Worker
// crypto-worker.js
const enc = new TextEncoder();
const deriveKey = async (password, salt) => {
const base = await crypto.subtle.importKey('raw', enc.encode(password), 'PBKDF2', false, ['deriveKey']);
return crypto.subtle.deriveKey(
{ name: 'PBKDF2', salt, iterations: 600000, hash: 'SHA-256' },
base,
{ name: 'AES-GCM', length: 256 },
false,
['encrypt', 'decrypt']
);
};
self.onmessage = async ({ data: { password, text } }) => {
const salt = crypto.getRandomValues(new Uint8Array(16));
const iv = crypto.getRandomValues(new Uint8Array(12));
const key = await deriveKey(password, salt);
const cipher = await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, key, enc.encode(text));
// ArrayBuffer ohne Kopie übertragen
self.postMessage({ salt, iv, cipher }, [cipher]);
};
// Wichtig · Fallstricke
- Sicherer Kontext:
crypto.subtleundcrypto.randomUUID()gibt es nur in sicheren Kontexten (HTTPS oderlocalhost). Sonst istcrypto.subtleundefined.getRandomValues()funktioniert auch ohne sicheren Kontext. - Größenlimit:
getRandomValues()erzeugt pro Aufruf höchstens 65.536 Bytes, darüber wird einQuotaExceededErrorgeworfen.Float32Array/Float64Arraysind nicht erlaubt. - Nicht
Math.random()nutzen, wenn es um Tokens, Schlüssel oder IDs mit Sicherheitsbezug geht, denn das ist nicht kryptografisch sicher. - AES-GCM: Mit demselben Schlüssel niemals eine IV zweimal verwenden.
- Kompatibilität: Alle aktuellen Browser unterstützen die Eigenschaft in Dedicated, Shared und Service Workern.
randomUUID()gibt es erst seit 2021/2022 (Chrome 92, Firefox 95, Safari 15.4).