Start · Sprachen · JavaScript · Referenz · AuthenticatorAttestationResponse.getPublicKey()

AuthenticatorAttestationResponse.getPublicKey()

Methode

Gibt den öffentlichen Schlüssel eines neu erzeugten WebAuthn-Berechtigungsnachweises als DER-kodiertes <code>SubjectPublicKeyInfo</code> in einem <code>ArrayBuffer</code> zurück, oder <code>null</code>.

seit JavaScript Baseline 2023: Chrome 85+, Edge 85+, Firefox 119+, Kategorie: webapi

Signatur

AuthenticatorAttestationResponse.prototype.getPublicKey()

Beschreibung

Die Methode getPublicKey() der Schnittstelle AuthenticatorAttestationResponse liefert den öffentlichen Schlüssel eines Berechtigungsnachweises (Passkey), der gerade mit navigator.credentials.create() registriert wurde. Das Ergebnis ist ein ArrayBuffer mit der DER-Kodierung einer SubjectPublicKeyInfo-Struktur (X.509, RFC 5280).

Der große Vorteil: Ohne diese Methode müsste man das CBOR-kodierte attestationObject selbst parsen, die authenticatorData zerlegen und den COSE-Schlüssel in ein verwendbares Format umwandeln. Mit getPublicKey() erhält man direkt ein Standardformat, das Server-Bibliotheken (z. B. Node.js crypto.createPublicKey(), OpenSSL, Java, Go) oder SubtleCrypto.importKey("spki", …) verstehen.

Typischer Einsatz: Der Client liest bei der Registrierung den Schlüssel, zusammen mit getPublicKeyAlgorithm() und der Credential-ID, kodiert alles (meist Base64URL) und sendet es an die Relying Party, die den Schlüssel speichert und später zur Prüfung von Anmelde-Signaturen (AuthenticatorAssertionResponse.signature) verwendet.

Ist der verwendete Algorithmus dem Browser unbekannt oder lässt er sich nicht als SubjectPublicKeyInfo darstellen, gibt die Methode null zurück. Garantiert unterstützt werden EdDSA (−8), ES256 (−7) und RS256 (−257).

Rückgabewert

Typ
ArrayBuffer | null
Beschreibung
Ein ArrayBuffer mit dem DER-kodierten SubjectPublicKeyInfo des neuen öffentlichen Schlüssels, oder null, wenn der Algorithmus nicht in diesem Format darstellbar ist bzw. vom Browser nicht unterstützt wird.

Beispiele

Passkey registrieren und öffentlichen Schlüssel an den Server senden

const toBase64Url = (buffer) =>
  btoa(String.fromCharCode(...new Uint8Array(buffer)))
    .replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');

const registerPasskey = async (challenge, userId) => {
  const credential = await navigator.credentials.create({
    publicKey: {
      challenge, // Uint8Array vom Server
      rp: { name: 'Beispiel GmbH', id: location.hostname },
      user: { id: userId, name: 'max@example.com', displayName: 'Max Mustermann' },
      pubKeyCredParams: [
        { type: 'public-key', alg: -7 },   // ES256
        { type: 'public-key', alg: -257 }  // RS256
      ],
      authenticatorSelection: { residentKey: 'preferred', userVerification: 'preferred' }
    }
  });

  const response = credential.response; // AuthenticatorAttestationResponse
  const publicKey = response.getPublicKey();

  if (publicKey === null) {
    throw new Error('Algorithmus nicht als SPKI darstellbar – attestationObject serverseitig auswerten');
  }

  await fetch('/api/passkeys', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      id: credential.id,
      publicKey: toBase64Url(publicKey),
      algorithm: response.getPublicKeyAlgorithm(),
      clientDataJSON: toBase64Url(response.clientDataJSON),
      attestationObject: toBase64Url(response.attestationObject)
    })
  });
};

Schlüssel im Browser mit SubtleCrypto importieren

const importCredentialKey = async (response) => {
  const spki = response.getPublicKey();
  const alg = response.getPublicKeyAlgorithm();

  if (alg !== -7 || !spki) return null; // nur ES256 in diesem Beispiel

  const key = await crypto.subtle.importKey(
    'spki',
    spki,
    { name: 'ECDSA', namedCurve: 'P-256' },
    true,
    ['verify']
  );
  console.log(key.type, key.algorithm.name, key.algorithm.namedCurve);
  return key;
};
public ECDSA P-256

Serverseitig (Node.js) in PEM umwandeln

import { createPublicKey } from 'node:crypto';

// publicKeyB64Url wurde vom Client gesendet
const toPem = (publicKeyB64Url) => {
  const der = Buffer.from(publicKeyB64Url, 'base64url');
  const key = createPublicKey({ key: der, format: 'der', type: 'spki' });
  return key.export({ format: 'pem', type: 'spki' });
};

console.log(toPem(storedPublicKey).split('\n')[0]);
-----BEGIN PUBLIC KEY-----

// Wichtig · Fallstricke

  • Nur bei Registrierung verfügbar: Die Methode existiert ausschließlich auf AuthenticatorAttestationResponse (Ergebnis von credentials.create()), nicht auf AuthenticatorAssertionResponse bei der Anmeldung. Den Schlüssel also sofort speichern.
  • null behandeln: Bei unbekannten Algorithmen liefert die Methode null. Für diesen Fall sollte der Server das attestationObject weiterhin selbst (CBOR/COSE) auswerten können.
  • Keine Sicherheitsgarantie: Der Wert stammt vom Client und ist nicht vertrauenswürdig. Der Server muss Challenge, Origin (clientDataJSON) und ggf. die Attestierung prüfen; bei Bedarf sollte der Schlüssel aus dem attestationObject abgeglichen werden.
  • Binärdaten transportieren: ArrayBuffer lässt sich nicht direkt per JSON senden – vorher Base64URL-kodieren. Das Spread in String.fromCharCode(...) kann bei sehr großen Puffern (z. B. RSA) an Stack-Grenzen stoßen; dann in Blöcken kodieren.
  • Kompatibilität: Firefox unterstützt die Methode erst ab Version 119; ältere Browser benötigen einen Fallback über das attestationObject. WebAuthn erfordert einen sicheren Kontext (HTTPS oder localhost).