Signatur
Beschreibung
EcdhKeyDeriveParams ist ein Wörterbuch (Dictionary) der Web Crypto API. Es ist keine Klasse, die man mit new erzeugt, sondern ein einfaches Objekt. Man übergibt es als algorithm-Argument an SubtleCrypto.deriveKey() oder SubtleCrypto.deriveBits(), wenn die Algorithmen ECDH (Elliptic Curve Diffie-Hellman) oder X25519 verwendet werden.
Beim Schlüsselaustausch erzeugen beide Seiten ein eigenes Schlüsselpaar und tauschen ihre öffentlichen Schlüssel aus. Jede Seite verbindet dann den eigenen privaten Schlüssel (als baseKey) mit dem öffentlichen Schlüssel der Gegenseite (im Feld public dieses Wörterbuchs). Beide erhalten so dasselbe gemeinsame Geheimnis, ohne dass es je über die Leitung gegangen ist.
Typische Einsatzfälle sind Ende-zu-Ende-Verschlüsselung in Chat-Anwendungen, verschlüsselte WebRTC-Datenkanäle oder das Aushandeln eines Sitzungsschlüssels für AES-GCM. Beide Schlüssel müssen denselben Algorithmus und bei ECDH dieselbe Kurve (P-256, P-384 oder P-521) haben.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $name Pflicht | string | Name des Algorithmus: "ECDH" oder "X25519". Muss zum Algorithmus des baseKey passen. |
|
| $public Pflicht | CryptoKey | Der öffentliche Schlüssel der Gegenseite (type === "public"). Algorithmus und Kurve müssen mit dem eigenen privaten Schlüssel übereinstimmen. |
Beispiele
Gemeinsamen AES-GCM-Schlüssel per ECDH ableiten
const genPair = () => crypto.subtle.generateKey(
{ name: "ECDH", namedCurve: "P-256" },
false,
["deriveKey", "deriveBits"]
);
const alice = await genPair();
const bob = await genPair();
// Alice verbindet ihren privaten Schlüssel mit Bobs öffentlichem Schlüssel
const ecdhParams = { name: "ECDH", public: bob.publicKey };
const aesKey = await crypto.subtle.deriveKey(
ecdhParams,
alice.privateKey,
{ name: "AES-GCM", length: 256 },
false,
["encrypt", "decrypt"]
);
console.log(aesKey.algorithm);
Beide Seiten erhalten dasselbe Geheimnis (deriveBits)
const params = { name: "ECDH", namedCurve: "P-384" };
const a = await crypto.subtle.generateKey(params, false, ["deriveBits"]);
const b = await crypto.subtle.generateKey(params, false, ["deriveBits"]);
const bitsA = await crypto.subtle.deriveBits(
{ name: "ECDH", public: b.publicKey }, a.privateKey, 384
);
const bitsB = await crypto.subtle.deriveBits(
{ name: "ECDH", public: a.publicKey }, b.privateKey, 384
);
const toHex = (buf) => [...new Uint8Array(buf)]
.map((x) => x.toString(16).padStart(2, "0")).join("");
console.log(toHex(bitsA) === toHex(bitsB));
Öffentlichen Schlüssel der Gegenseite importieren und X25519 nutzen
const mine = await crypto.subtle.generateKey(
{ name: "X25519" }, false, ["deriveBits"]
);
// Öffentlicher Schlüssel der Gegenseite, z. B. als Raw-Bytes vom Server empfangen
const peer = await crypto.subtle.generateKey({ name: "X25519" }, true, ["deriveBits"]);
const rawPeer = await crypto.subtle.exportKey("raw", peer.publicKey);
const peerPublic = await crypto.subtle.importKey(
"raw", rawPeer, { name: "X25519" }, false, []
);
const secret = await crypto.subtle.deriveBits(
{ name: "X25519", public: peerPublic }, mine.privateKey, 256
);
console.log(secret.byteLength);
// Wichtig · Fallstricke
- Rohes Geheimnis nicht direkt als Schlüssel verwenden: Das Ergebnis von
deriveBits()ist nicht gleichmäßig zufällig. Man sollte es besser über HKDF weiterverarbeiten (importKey(\"raw\", bits, \"HKDF\", …)) und dabei Kontextinformationen (info,salt) einbeziehen. - Keine Authentifizierung: ECDH allein schützt nicht vor Man-in-the-Middle-Angriffen. Die öffentlichen Schlüssel müssen zusätzlich verifiziert werden, z. B. per ECDSA-Signatur, Zertifikat oder Vergleich eines Fingerabdrucks.
- Für den öffentlichen Schlüssel in
publicmusstype === \"public\"gelten, sonst wird eineInvalidAccessErrorgeworfen. Das passiert auch, wenn Algorithmus oder Kurve nicht übereinstimmen. - Der private Schlüssel braucht die Verwendung
\"deriveKey\"bzw.\"deriveBits\"inkeyUsages. Beim importierten öffentlichen Schlüssel istkeyUsagesein leeres Array. - Die Web Crypto API ist nur in sicheren Kontexten (HTTPS,
localhost) verfügbar.X25519wird erst seit Kurzem von allen großen Browsern unterstützt. Für ältere Umgebungen sollte man auf ECDH mitP-256zurückfallen. - Bei
deriveBits()darf die Bitlänge die Kurvengröße nicht überschreiten: 256 für P-256, 384 für P-384, 528 für P-521 und 256 für X25519.