Signatur
Beschreibung
Die Eigenschaft crypto.subtle gibt ein SubtleCrypto-Objekt zurück. Darüber läuft die Web Crypto API: Hashwerte berechnen (digest()), Daten ver- und entschlüsseln (encrypt(), decrypt()), signieren und prüfen (sign(), verify()), Schlüssel erzeugen, ableiten, importieren und exportieren (generateKey(), deriveKey(), importKey(), exportKey()) sowie Schlüssel ein- und auspacken (wrapKey(), unwrapKey()).
Alle Methoden arbeiten asynchron und geben ein Promise zurück. Eingaben erwarten sie als ArrayBuffer, TypedArray oder DataView. Texte wandelst du deshalb zuerst mit TextEncoder um. Schlüssel werden als CryptoKey-Objekte verwaltet. Wird ein Schlüssel mit extractable: false erzeugt, lässt er sich nicht exportieren. Das schützt ihn gegen Auslesen per Skript.
Der Name „subtle“ (heikel) ist Absicht: Die API enthält einfache Bausteine, die man leicht falsch zusammensetzt, zum Beispiel durch wiederverwendete IVs, schwache Parameter oder ungeeignete Algorithmen. Nimm deshalb möglichst bewährte Kombinationen wie AES-GCM mit zufälligem IV, ECDSA/Ed25519 für Signaturen und PBKDF2 mit hoher Iterationszahl für die Ableitung aus Passwörtern.
Die Eigenschaft gibt es nur in einem sicheren Kontext (HTTPS oder localhost). Auf unsicheren Seiten ist crypto.subtle undefined. Du erreichst sie im Fenster und in Web Workern über das globale crypto-Objekt.
Rückgabewert
SubtleCrypto-Objekt des aktuellen Kontexts. In unsicheren Kontexten (HTTP) ist der Wert undefined.Beispiele
SHA-256-Hash eines Textes als Hex-String
const sha256 = async (text) => {
const data = new TextEncoder().encode(text);
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
return [...new Uint8Array(hashBuffer)]
.map((b) => b.toString(16).padStart(2, '0'))
.join('');
};
console.log(await sha256('hallo'));
Daten mit AES-GCM ver- und entschlüsseln
const key = await crypto.subtle.generateKey(
{ name: 'AES-GCM', length: 256 },
false, // nicht exportierbar
['encrypt', 'decrypt']
);
const iv = crypto.getRandomValues(new Uint8Array(12)); // für jede Nachricht neu erzeugen!
const plaintext = new TextEncoder().encode('Geheime Nachricht');
const ciphertext = await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, key, plaintext);
const decrypted = await crypto.subtle.decrypt({ name: 'AES-GCM', iv }, key, ciphertext);
console.log(new TextDecoder().decode(decrypted));
Nachricht mit ECDSA signieren und prüfen
const { privateKey, publicKey } = await crypto.subtle.generateKey(
{ name: 'ECDSA', namedCurve: 'P-256' },
true,
['sign', 'verify']
);
const message = new TextEncoder().encode('Bestellung #4711');
const algo = { name: 'ECDSA', hash: 'SHA-256' };
const signature = await crypto.subtle.sign(algo, privateKey, message);
const valid = await crypto.subtle.verify(algo, publicKey, signature, message);
console.log('Signatur gültig:', valid);
Verfügbarkeit prüfen (sicherer Kontext)
if (!window.isSecureContext || !crypto?.subtle) {
console.warn('Web Crypto nicht verfügbar – Seite über HTTPS ausliefern.');
} else {
console.log('SubtleCrypto bereit:', crypto.subtle instanceof SubtleCrypto);
}
// Wichtig · Fallstricke
- Nur sicherer Kontext: Über
http://(außerlocalhost) istcrypto.subtleundefined. Das führt oft zu Fehlern wie „Cannot read properties of undefined (reading 'digest')“. - IV bzw. Nonce nie wiederverwenden: Wenn du bei AES-GCM denselben IV zweimal mit demselben Schlüssel nutzt, bricht die Sicherheit komplett zusammen. Erzeuge den IV deshalb jedes Mal mit
crypto.getRandomValues(). - Nicht mit
crypto.randomUUID()/getRandomValues()verwechseln: Diese Methoden sitzen direkt aufCryptound funktionieren synchron. Alle Methoden vonsubtlegeben dagegen ein Promise zurück. - Keine Passwort-Hashes per
digest(): SHA-256 ist zu schnell zum Speichern von Passwörtern. Verwende PBKDF2 überderiveBits()/deriveKey()oder, auf dem Server, Argon2/bcrypt. - Clientseitige Kryptografie hat Grenzen: Wird die Seite durch XSS kompromittiert, kann der Angreifer die API selbst benutzen. Nicht exportierbare Schlüssel verhindern nur, dass das Schlüsselmaterial ausgelesen wird.
- Algorithmen-Unterstützung: Ed25519/X25519 sind erst in neueren Browserversionen verfügbar. MD5 wird nicht unterstützt, SHA-1 nur aus Kompatibilitätsgründen.
- Node.js: Ab Version 19 ist
globalThis.crypto.subtleglobal verfügbar, davor überrequire('node:crypto').webcrypto.subtle(ab Node.js 15).