Signatur
Beschreibung
Die Methode getRemoteCertificates() des Interfaces RTCDtlsTransport liefert die Zertifikate, die der entfernte Peer beim DTLS-Handshake vorgelegt hat. Jedes Zertifikat liegt als ArrayBuffer mit den rohen DER-kodierten Bytes vor. Bei WebRTC ist das meist ein einzelnes selbstsigniertes Zertifikat.
Einsatzgebiete sind vor allem Diagnose, Protokollierung und eigene Identitätsprüfungen. Du kannst zum Beispiel den SHA-256-Fingerabdruck des Zertifikats selbst berechnen und mit der Zeile a=fingerprint aus der entfernten SDP vergleichen. Oder du gleichst ihn mit einem Fingerabdruck ab, den du über einen vertrauenswürdigen Kanal bekommen hast. So lassen sich Man-in-the-Middle-Angriffe über einen kompromittierten Signalisierungsserver erkennen.
An das RTCDtlsTransport-Objekt kommst du über RTCRtpSender.transport, RTCRtpReceiver.transport oder RTCSctpTransport.transport (bei Datenkanälen über pc.sctp.transport). Sinnvolle Daten gibt es erst, wenn der Handshake abgeschlossen ist, also wenn transport.state den Wert "connected" hat.
Rückgabewert
Beispiele
Zertifikate nach dem Verbindungsaufbau auslesen
const pc = new RTCPeerConnection();
pc.addTransceiver('audio');
// ... Signalisierung (Offer/Answer, ICE) wie gewohnt ...
const dtls = pc.getSenders()[0].transport;
dtls.addEventListener('statechange', () => {
if (dtls.state === 'connected') {
const certs = dtls.getRemoteCertificates();
console.log('Anzahl Zertifikate:', certs.length);
console.log('Größe des ersten Zertifikats:', certs[0].byteLength, 'Bytes');
}
});
SHA-256-Fingerabdruck berechnen und mit der SDP vergleichen
const fingerprintOf = async (derBuffer) => {
const hash = await crypto.subtle.digest('SHA-256', derBuffer);
return [...new Uint8Array(hash)]
.map((b) => b.toString(16).padStart(2, '0').toUpperCase())
.join(':');
};
const verifyRemoteFingerprint = async (pc) => {
const dtls = pc.getReceivers()[0]?.transport;
if (!dtls || dtls.state !== 'connected') return false;
const [cert] = dtls.getRemoteCertificates();
const actual = await fingerprintOf(cert);
const match = pc.remoteDescription.sdp.match(/a=fingerprint:sha-256 ([0-9A-F:]+)/i);
const expected = match?.[1].toUpperCase();
console.log('Berechnet:', actual);
console.log('Aus SDP: ', expected);
return actual === expected;
};
// Aufruf, z. B. im connectionstatechange-Handler:
// console.log('Fingerabdruck stimmt:', await verifyRemoteFingerprint(pc));
Zertifikat als PEM exportieren (z. B. für Logs)
const toPem = (derBuffer) => {
const bytes = new Uint8Array(derBuffer);
let binary = '';
bytes.forEach((b) => { binary += String.fromCharCode(b); });
const base64 = btoa(binary).match(/.{1,64}/g).join('\n');
return `-----BEGIN CERTIFICATE-----\n${base64}\n-----END CERTIFICATE-----`;
};
const dtls = pc.sctp?.transport; // DTLS-Transport des Datenkanals
if (dtls?.state === 'connected') {
dtls.getRemoteCertificates().forEach((cert, i) => {
console.log(`Zertifikat ${i}:\n${toPem(cert)}`);
});
}
// Wichtig · Fallstricke
- Zeitpunkt: Vor Abschluss des DTLS-Handshakes (
stateist"new"oder"connecting") liefert die Methode ein leeres Array. Warte deshalb auf das Ereignisstatechangemitstate === "connected". - Browser-Kompatibilität: Unterstützt wird die Methode vor allem in Chromium-basierten Browsern (Chrome, Edge, Opera). Firefox implementiert sie nicht, und die Unterstützung in Safari ist uneinheitlich. Prüfe sie vorher per Feature-Erkennung:
typeof RTCDtlsTransport !== 'undefined' && 'getRemoteCertificates' in RTCDtlsTransport.prototype. - Rohdaten: Die Rückgabe enthält nur DER-Bytes. Einen eingebauten X.509-Parser gibt es nicht. Für Felder wie Ablaufdatum oder Subject brauchst du eine Bibliothek (z. B.
pkijs) oder einen eigenen ASN.1-Parser. - Sicherheit: WebRTC-Zertifikate sind meist selbstsigniert und haben keine vertrauenswürdige Zertifizierungsstelle. Echten Schutz vor Man-in-the-Middle-Angriffen bietet ein Fingerabdruckvergleich nur, wenn der erwartete Wert über einen anderen vertrauenswürdigen Kanal kommt als die SDP.
- Bei
bundlePolicy: "max-bundle"teilen sich alle Sender, Empfänger und der Datenkanal meist einen einzigenRTCDtlsTransport.