Signatur
Beschreibung
RTCCertificate stellt ein X.509-Zertifikat mit dem zugehörigen privaten Schlüssel dar. Eine RTCPeerConnection braucht es für den DTLS-Handshake, über den die Schlüssel für die verschlüsselten Medien- und Datenkanäle (SRTP bzw. SCTP) ausgehandelt werden. Den privaten Schlüssel kann JavaScript nicht lesen. Er bleibt im Browser.
Einen Konstruktor gibt es nicht. Instanzen erzeugst du über die statische Methode RTCPeerConnection.generateCertificate(). Das Zertifikat übergibst du dann im Konfigurationsobjekt unter certificates. Ohne diese Angabe erzeugt der Browser für jede Verbindung selbst ein neues Zertifikat.
Wichtige Bestandteile:
expires(nur lesbar,number): Ablaufzeitpunkt in Millisekunden seit der Unix-Epoche. Nach diesem Zeitpunkt lehnt der Browser das Zertifikat für neue Verbindungen ab.getFingerprints(): Gibt ein Array vonRTCDtlsFingerprint-Objekten zurück, jeweils mitalgorithm(z. B."sha-256") undvalue(Hex-Zeichenfolge mit Doppelpunkten). Diese Werte erscheinen auch in der SDP alsa=fingerprint.
RTCCertificate ist serialisierbar. Du kannst es also in IndexedDB speichern und später wiederverwenden. So bleibt der Fingerabdruck über mehrere Sitzungen gleich, und die Gegenseite kann ihn zum Beispiel zur Identitätsprüfung oder zum Zertifikat-Pinning nutzen.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $keygenAlgorithm Pflicht | string | RsaHashedKeyGenParams | EcKeyGenParams | Parameter für RTCPeerConnection.generateCertificate(), das Instanzen dieses Interfaces erzeugt. Browser müssen mindestens { name: "ECDSA", namedCurve: "P-256" } und { name: "RSASSA-PKCS1-v1_5", modulusLength: 2048, publicExponent: new Uint8Array([1, 0, 1]), hash: "SHA-256" } unterstützen. Optional kannst du mit expires (in Millisekunden) die Gültigkeitsdauer festlegen. |
Beispiele
Zertifikat erzeugen und in einer Verbindung verwenden
const cert = await RTCPeerConnection.generateCertificate({
name: 'ECDSA',
namedCurve: 'P-256'
});
console.log('Läuft ab am:', new Date(cert.expires).toISOString());
const pc = new RTCPeerConnection({
iceServers: [{ urls: 'stun:stun.l.google.com:19302' }],
certificates: [cert]
});
console.log(pc.getConfiguration().certificates.length);
Fingerabdruck auslesen und mit der SDP vergleichen
const cert = await RTCPeerConnection.generateCertificate({
name: 'RSASSA-PKCS1-v1_5',
modulusLength: 2048,
publicExponent: new Uint8Array([1, 0, 1]),
hash: 'SHA-256'
});
const [fp] = cert.getFingerprints();
console.log(fp.algorithm, fp.value);
const pc = new RTCPeerConnection({ certificates: [cert] });
pc.createDataChannel('chat');
const offer = await pc.createOffer();
// Der Fingerabdruck steht als a=fingerprint in der SDP
const inSdp = offer.sdp.toLowerCase().includes(fp.value.toLowerCase());
console.log('In SDP enthalten:', inSdp);
Zertifikat in IndexedDB speichern und wiederverwenden
const openDb = () => new Promise((resolve, reject) => {
const req = indexedDB.open('webrtc', 1);
req.onupgradeneeded = () => req.result.createObjectStore('certs');
req.onsuccess = () => resolve(req.result);
req.onerror = () => reject(req.error);
});
const idbRequest = (req) => new Promise((resolve, reject) => {
req.onsuccess = () => resolve(req.result);
req.onerror = () => reject(req.error);
});
const getCertificate = async () => {
const db = await openDb();
const stored = await idbRequest(
db.transaction('certs').objectStore('certs').get('main')
);
// Noch gültig? Mit Puffer von einem Tag
if (stored && stored.expires > Date.now() + 86_400_000) {
return stored;
}
const cert = await RTCPeerConnection.generateCertificate({
name: 'ECDSA',
namedCurve: 'P-256'
});
await idbRequest(
db.transaction('certs', 'readwrite').objectStore('certs').put(cert, 'main')
);
return cert;
};
const cert = await getCertificate();
const pc = new RTCPeerConnection({ certificates: [cert] });
console.log('Fingerabdruck:', cert.getFingerprints()[0].value);
// Wichtig · Fallstricke
- Kein Konstruktor:
new RTCCertificate()wirft einenTypeError. Erzeuge Instanzen ausschließlich überRTCPeerConnection.generateCertificate(). - Konfiguration nicht nachträglich änderbar: Zertifikate legst du beim Erzeugen der
RTCPeerConnectionfest. WennsetConfiguration()abweichendecertificateserhält, wirft der Aufruf einenInvalidModificationError. - Ablauf: Laut Spezifikation darf ein Zertifikat höchstens 365 Tage gültig sein, standardmäßig sind es 30 Tage. Abgelaufene Zertifikate führen beim Erzeugen der Verbindung zu einem Fehler. Prüfe deshalb
expires, bevor du ein gespeichertes Zertifikat wiederverwendest. - Datenschutz: Ein dauerhaft gespeichertes Zertifikat hat einen gleichbleibenden Fingerabdruck. Darüber lässt sich ein Nutzer wiedererkennen, ähnlich wie mit einem Cookie. Setze langlebige Zertifikate nur bewusst ein.
- Sicherheit: Der Fingerabdruck schützt nur dann vor Man-in-the-Middle-Angriffen, wenn die SDP über einen vertrauenswürdigen, verschlüsselten Signalisierungskanal übertragen wird.
- Kompatibilität:
expiresundgenerateCertificate()werden breit unterstützt.getFingerprints()kam in einigen Browsern (u. a. älteren Firefox-Versionen) erst spät oder fehlt dort. Prüfe die Methode vor der Nutzung mittypeof cert.getFingerprints === 'function'. Welche Algorithmen außer ECDSA P-256 und RSA unterstützt werden, hängt vom Browser ab.