Logo Logo
GitHub Designed by Logto

Was ist ein Signierschlüssel?

Im Kontext von OpenID Connect (OIDC) wird ein Signierschlüssel, in der Regel ein asymmetrisches Schlüsselpaar, verwendet, um JSON Web Tokens (JWTs) zu signieren und zu verifizieren. OpenID-Anbieter verwenden Signierschlüssel, um Tokens wie ID-Tokens und Access Tokens zu signieren, um deren Integrität und Authentizität zu gewährleisten.

Obwohl das Konzept der Signierschlüssel breiter gefächert sein kann, konzentrieren wir uns darauf, wie sie in OIDC zur Sicherung von Tokens verwendet werden. Andere Anwendungsfälle wie das Signieren von E-Mails, Dokumenten und Softwarepaketen können aus denselben Prinzipien abgeleitet werden.

Beispiel: Signieren eines ID-Tokens

Wenn sich ein Benutzer bei einem OpenID-Anbieter authentifiziert (Authentication), stellt der Anbieter ein ID-Token aus, das Benutzerinformationen ( Claims ) enthält und vom Signierschlüssel des Anbieters signiert wird. Da das ID-Token ein JWT ist, besteht es aus drei Teilen: Header, Payload und Signatur.

1. Header

Angenommen, der Header lautet:

{
  "alg": "ES384",
  "typ": "JWT"
}

Das JSON gibt an, dass das ID-Token mit dem ECDSA -Algorithmus mit der P-384-Kurve signiert ist. Das typ-Feld gibt an, dass der Token-Typ JWT ist.

2. Payload

Der Payload enthält grundlegende Benutzerinformationen:

{
  "sub": "1234567890",
  "name": "Alice"
}

Der sub-Claim ist die eindeutige Kennung des Benutzers, und name ist der Anzeigename.

3. Token signieren

Gemäß dem JWT-Format sollten Header und Payload Base64URL-codiert und mit einem . zum Signieren verbunden werden:

{{header}}.{{payload}}

In diesem Fall wäre der Wert:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkFsaWNlIn0

Angenommen, der OpenID-Anbieter verwendet den folgenden privaten Schlüssel, um das Token zu signieren:

-----BEGIN PRIVATE KEY-----
MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDBW9PDXInlNT2hjOtQr
g4pkVkyJsKia33dHrsbOG4Z77pfYN7SYZCHh9YdLXTTKinehZANiAAQX/FB1s6Gj
YnDSGCY08PRUAQ8CCRCt8Ph/VDHfLj1xSbrjp8wFf0NjH7jcfNebpV1fvu4XKbP3
Ro7h0G6elN1TMsVECJPv4ieDNkYOsgT4UboJypC5E/rmvrlJTMM6Y/k=
-----END PRIVATE KEY-----

Um das Token zu signieren, muss der OpenID-Anbieter den privaten Schlüssel verwenden, um eine Signatur zu generieren:

signature = sign(header + '.' + payload, private_key)

Dann ist die Base64URL-codierte Signatur:

Cjy6A_FHnwQBP0hRawoGTkRy8m8o0Ncc1q4BeyxYr0fxhKYmJJinIWZPXJdaAXRO9wOFuH2-UML2yWHjot_LnCPO6362asMvgNkEJMZ6UtqyOPlsCOJ7voTPOCT6sYu2

4. JWT zusammenstellen

Schließlich stellt der OpenID-Anbieter das JWT zusammen, indem er den Header, den Payload und die Signatur mit . verbindet:

{{header}}.{{payload}}.{{signature}}

In diesem Fall wäre das ID-Token:

eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkFsaWNlIn0.Cjy6A_FHnwQBP0hRawoGTkRy8m8o0Ncc1q4BeyxYr0fxhKYmJJinIWZPXJdaAXRO9wOFuH2-UML2yWHjot_LnCPO6362asMvgNkEJMZ6UtqyOPlsCOJ7voTPOCT6sYu2

Das ID-Token ist nun bereit, an den Client zur weiteren Verarbeitung gesendet zu werden.

5. Token verifizieren

Wenn der Client das ID-Token erhält, kann er die Signatur mit dem öffentlichen Schlüssel des OpenID-Anbieters verifizieren. Normalerweise wird der öffentliche Schlüssel über den OpenID Connect (OIDC) Discovery -Endpunkt (jwks_uri) im Format eines JSON-Web-Schlüsselset (JSON Web Key Set, JWKS) bereitgestellt.

Für dieses Beispiel lautet der öffentliche Schlüssel:

-----BEGIN PUBLIC KEY-----
MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEF/xQdbOho2Jw0hgmNPD0VAEPAgkQrfD4
f1Qx3y49cUm646fMBX9DYx-43HzXm6VdX77uFymz90aO4dBunpTdUzLFRAiT7+In
gzZGDrIE+FG6CcqQuRP65r65SUzDOmP5
-----END PUBLIC KEY-----

Und der entsprechende JWK-Wert ist:

{
  "kty": "EC",
  "crv": "P-384",
  "x": "F_xQdbOho2Jw0hgmNPD0VAEPAgkQrfD4f1Qx3y49cUm646fMBX9DYx-43HzXm6Vd",
  "y": "X77uFymz90aO4dBunpTdUzLFRAiT7-IngzZGDrIE-FG6CcqQuRP65r65SUzDOmP5"
}

Nun kann der Client die Signatur mit dem öffentlichen Schlüssel verifizieren.

Den richtigen Algorithmus wählen

Es gibt verschiedene Algorithmen zum Signieren von JWTs:

  • Symmetrische Algorithmen: HMAC mit SHA-Familie (z. B. HS256, HS384, HS512) ist ein symmetrischer Algorithmus, der denselben Schlüssel sowohl zum Signieren als auch zum Verifizieren verwendet. Es wird nicht für die meisten Fälle empfohlen, da der geheime Schlüssel zwischen den Parteien geteilt werden muss.
  • Asymmetrische Algorithmen: RSA (z. B. RS256, RS384, RS512) und ECDSA (z. B. ES256, ES384, ES512) sind asymmetrische Algorithmen, die ein Schlüsselpaar verwenden: einen privaten Schlüssel zum Signieren und einen öffentlichen Schlüssel zum Verifizieren.
    • RSA wird weithin verwendet und von vielen Bibliotheken und Plattformen unterstützt. Es hat jedoch eine viel größere Schlüssel- und Signaturgröße im Vergleich zu ECDSA.
    • ECDSA ist leistungsfähiger und erzeugt kleinere Signaturen, was es zu einer besseren Wahl für eingeschränkte Umgebungen macht. Da es weniger verbreitet ist, stelle sicher, dass deine Plattform es unterstützt.

ECDSA sollte aufgrund seiner Leistungs- und Sicherheitsvorteile die bevorzugte Wahl für neue Anwendungen sein.

Andere Szenarien für Signierschlüssel

Während das obige Beispiel sich auf ID-Tokens in OIDC konzentriert, wird das Signierschlüsselkonzept in verschiedenen Szenarien weit verbreitet eingesetzt, wie z. B. beim Signieren von E-Mails, Dokumenten und Softwarepaketen. Die grundlegenden Prinzipien bleiben gleich:

  • Bei symmetrischen Schlüsseln wird derselbe Schlüssel sowohl zum Signieren als auch zum Verifizieren verwendet. Dies ist geeignet für Szenarien, in denen die Parteien den Schlüssel sicher teilen können oder es eine einzelne Instanz gibt, die sowohl für das Signieren als auch Verifizieren verantwortlich ist.
  • Bei asymmetrischen Schlüsseln wird ein privater Schlüssel zum Signieren und ein entsprechender öffentlicher Schlüssel zum Verifizieren verwendet. Dies eignet sich für die meisten Szenarien, in denen die Parteien, die signieren und verifizieren, unterschiedliche Einheiten sind.

Siehe auch