Start · Sprachen · JavaScript · Referenz · Crypto.subtle

Crypto.subtle

Eigenschaft

Schreibgeschützte Eigenschaft, die das <code>SubtleCrypto</code>-Objekt für Low-Level-Kryptografie liefert, etwa Hashing, Verschlüsselung, Signaturen und Schlüsselverwaltung.

seit JavaScript Baseline: alle modernen Browser (seit 2015), Node. Kategorie: webapi

Signatur

Crypto.subtle

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

Typ
SubtleCrypto
Beschreibung
Das 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'));
d3751d33f9cd5049c4af2b462735457e4d3baf130bcbb87f389e349fbaeb20b9

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));
Geheime Nachricht

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);
Signatur gültig: true

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);
}
SubtleCrypto bereit: true

// Wichtig · Fallstricke

  • Nur sicherer Kontext: Über http:// (außer localhost) ist crypto.subtle undefined. 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 auf Crypto und funktionieren synchron. Alle Methoden von subtle geben dagegen ein Promise zurück.
  • Keine Passwort-Hashes per digest(): SHA-256 ist zu schnell zum Speichern von Passwörtern. Verwende PBKDF2 über deriveBits()/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.subtle global verfügbar, davor über require('node:crypto').webcrypto.subtle (ab Node.js 15).