Start · Sprachen · JavaScript · Referenz · EcdhKeyDeriveParams

EcdhKeyDeriveParams

Schnittstelle

Parameter-Wörterbuch für <code>SubtleCrypto.deriveKey()</code> und <code>deriveBits()</code>, wenn ein gemeinsames Geheimnis per ECDH oder X25519 abgeleitet wird.

seit JavaScript Baseline: alle modernen Browser (ECDH); X25519 in Kategorie: webapi

Signatur

interface EcdhKeyDeriveParams extends Algorithm { name: "ECDH" | "X25519"; public: CryptoKey }

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);
{ name: "AES-GCM", length: 256 }

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));
true

Ö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);
32

// 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 public muss type === \"public\" gelten, sonst wird eine InvalidAccessError geworfen. Das passiert auch, wenn Algorithmus oder Kurve nicht übereinstimmen.
  • Der private Schlüssel braucht die Verwendung \"deriveKey\" bzw. \"deriveBits\" in keyUsages. Beim importierten öffentlichen Schlüssel ist keyUsages ein leeres Array.
  • Die Web Crypto API ist nur in sicheren Kontexten (HTTPS, localhost) verfügbar. X25519 wird erst seit Kurzem von allen großen Browsern unterstützt. Für ältere Umgebungen sollte man auf ECDH mit P-256 zurü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.