Start · Sprachen · JavaScript · Referenz · MediaKeys.setServerCertificate()

MediaKeys.setServerCertificate()

Methode

Übergibt dem Content Decryption Module (CDM) ein Serverzertifikat, mit dem Nachrichten an den Lizenzserver verschlüsselt werden.

seit JavaScript Encrypted Media Extensions (EME); Baseline: Chrome Kategorie: webapi

Signatur

MediaKeys.prototype.setServerCertificate(serverCertificate)

Beschreibung

Die Methode setServerCertificate() gehört zur Encrypted-Media-Extensions-API (EME). Sie übergibt dem Content Decryption Module (CDM), das hinter einem MediaKeys-Objekt steht, das Zertifikat des Lizenzservers. Das CDM verschlüsselt damit die Lizenzanfragen (message-Events der MediaKeySession), sodass nur der echte Lizenzserver sie lesen kann. Das nennt man Privacy Mode: Geräte-Kennungen und andere Client-Daten bleiben auf dem Übertragungsweg geschützt.

Typischer Einsatz ist Widevine: Ohne vorab gesetztes Zertifikat schickt das CDM zuerst eine eigene Zertifikatsanfrage an den Server, was einen zusätzlichen Round-Trip kostet. Wer das Zertifikat vorher lädt (oder im Cache hält) und per setServerCertificate() setzt, spart diesen Schritt. Bei FairPlay (Safari) ist das Zertifikat sogar Pflicht, bevor Lizenzanfragen erzeugt werden können.

Die Methode sollte nach MediaKeySystemAccess.createMediaKeys() und vor MediaKeys.createSession() bzw. generateRequest() aufgerufen werden. Das Zertifikat wird als Binärdaten übergeben (ArrayBuffer oder TypedArray/DataView). Welches Format es haben muss, legt das jeweilige Key-System fest.

Parameter

Name Typ Default Beschreibung
$serverCertificate Pflicht ArrayBuffer | TypedArray | DataView Das Serverzertifikat als Binärdaten. Das Format hängt vom Key-System ab. Bei Widevine ist es z. B. ein signiertes DrmCertificate, bei FairPlay ein DER-codiertes Zertifikat. Ein leerer Puffer führt zu einem TypeError.

Rückgabewert

Typ
Promise<boolean>
Beschreibung
Ein Promise, das mit true erfüllt wird, wenn das CDM das Zertifikat übernommen hat. Unterstützt das Key-System keine Serverzertifikate, wird es mit false erfüllt. Ist das Zertifikat leer, wird das Promise mit einem TypeError abgelehnt. Bei anderen Fehlern, etwa einem ungültigen Zertifikat, wird es mit einer DOMException abgelehnt.

Beispiele

Widevine-Zertifikat laden und setzen

const video = document.querySelector('video');

const config = [{
  initDataTypes: ['cenc'],
  videoCapabilities: [{ contentType: 'video/mp4; codecs="avc1.42E01E"' }]
}];

const setupDrm = async () => {
  const access = await navigator.requestMediaKeySystemAccess('com.widevine.alpha', config);
  const mediaKeys = await access.createMediaKeys();

  // Zertifikat vom Lizenzserver holen
  const res = await fetch('https://license.example.com/widevine/cert');
  const cert = await res.arrayBuffer();

  const ok = await mediaKeys.setServerCertificate(cert);
  console.log('Zertifikat akzeptiert:', ok);

  await video.setMediaKeys(mediaKeys);
};

setupDrm().catch(err => console.error('DRM-Setup fehlgeschlagen:', err));
Zertifikat akzeptiert: true

Fehlerbehandlung und Unterstützung prüfen

const applyCertificate = async (mediaKeys, certBytes) => {
  try {
    const supported = await mediaKeys.setServerCertificate(certBytes);
    if (!supported) {
      console.warn('Key-System unterstützt keine Serverzertifikate – fahre ohne fort.');
    }
    return supported;
  } catch (err) {
    if (err instanceof TypeError) {
      console.error('Leeres oder ungültiges Zertifikat übergeben.');
    } else {
      console.error(`CDM hat das Zertifikat abgelehnt: ${err.name}`);
    }
    throw err;
  }
};

Zertifikat als Base64 aus der Konfiguration (Caching)

// Zertifikat einmalig ausliefern, z. B. eingebettet in die App-Konfiguration
const CERT_BASE64 = localStorage.getItem('drmCert') ?? '';

const base64ToBytes = (b64) =>
  Uint8Array.from(atob(b64), c => c.charCodeAt(0));

const initKeys = async (access) => {
  const mediaKeys = await access.createMediaKeys();
  if (CERT_BASE64) {
    // Spart den zusätzlichen Zertifikats-Round-Trip des CDM
    await mediaKeys.setServerCertificate(base64ToBytes(CERT_BASE64));
  }
  const session = mediaKeys.createSession('temporary');
  return { mediaKeys, session };
};

// Wichtig · Fallstricke

  • Reihenfolge: Setze das Zertifikat, bevor generateRequest() auf einer Session aufgerufen wird. Sessions, die schon laufen, verwenden das neue Zertifikat unter Umständen nicht mehr.
  • Rückgabewert false ist kein Fehler: Einige Key-Systeme, z. B. org.w3.clearkey, unterstützen keine Serverzertifikate. Das Promise wird dann mit false erfüllt und nicht abgelehnt.
  • Leerer Puffer: Ein ArrayBuffer der Länge 0 führt sofort zur Ablehnung mit TypeError. Das passiert leicht, wenn fetch einen Fehler liefert und der Statuscode nicht geprüft wird (res.ok).
  • Sicherheit: EME steht nur in sicheren Kontexten (HTTPS) zur Verfügung. Lade das Zertifikat ebenfalls über HTTPS und von einer vertrauenswürdigen Quelle. Das Zertifikat selbst ist öffentlich, aber ein gefälschtes Zertifikat könnte Lizenzanfragen an Dritte umleiten. Die CDMs prüfen in der Regel die Signatur.
  • Kompatibilität: Wird von allen aktuellen Desktop-Browsern mit EME unterstützt. Bei Safari/FairPlay ist ein Zertifikat zwingend nötig. In älteren Safari-Versionen gab es stattdessen das präfixierte WebKitMediaKeys ohne diese Methode.