Zum Inhalt springen
LeedyBox
Unterstützen

Base64, URL-Kodierung und JWT erklärt

Diese drei begegnen Ihnen überall dort, wo Daten als Text unterwegs sind: in URLs, HTTP-Headern, JSON und Anmelde-Tokens. Keines davon verbirgt etwas. Diese Anleitung erklärt, wie jedes funktioniert, wo Sie ihm begegnen und welche Fehler hinter den meisten Problemen stecken.

Kodieren ist nicht Verschlüsseln

Beim Kodieren ändert sich die Schreibweise der Daten, damit sie einen Kanal passieren, der nur bestimmte Zeichen erlaubt. Jeder kann das rückgängig machen, denn es ist kein Schlüssel im Spiel. Auch Verschlüsselung verändert die Daten, aber nur wer den Schlüssel hat, kann sie zurückverwandeln. Ein Hash ist wieder etwas anderes: ein Einweg-Fingerabdruck, der sich überhaupt nicht zurückrechnen lässt, wie in Hashfunktionen erklärt beschrieben.

Base64 und URL-Kodierung sind Kodierungen. Ein JWT ist meist signiert; das belegt, wer ihn ausgestellt hat und dass er nicht verändert wurde, sein Inhalt ist aber nur kodiert. Muss ein Wert geheim bleiben, braucht er Verschlüsselung, nicht eines dieser Formate.

So funktioniert Base64

Base64 liest die Daten in Gruppen von drei Bytes (24 Bit) und teilt sie in vier Gruppen zu je sechs Bit. Jede Gruppe ist eine Zahl von 0 bis 63 und wird als ein Zeichen eines Alphabets mit 64 Zeichen geschrieben: A–Z für 0–25, a–z für 26–51, 0–9 für 52–61, dann + und /. Das Wort „Man“ zeigt die Schritte:

SchrittMan
Bytewerte7797110
Bits010011010110000101101110
Vier 6-Bit-Gruppen010011 · 010110 · 000101 · 101110 = 19 · 22 · 5 · 46
Base64T W F u → TWFu

Ist die Länge der Eingabe kein Vielfaches von drei, wird die letzte Gruppe aufgefüllt und mit Padding markiert: Ein übriges Byte ergibt zwei Zeichen und ==, zwei übrige Bytes ergeben drei Zeichen und =. „Ma“ wird zu TWE= und „M“ zu TQ==.

Weil aus je drei Bytes vier Zeichen werden, macht Base64 die Daten um etwa ein Drittel größer, dazu kommen Zeilenumbrüche, wo ein Format sie einfügt. Ein 3-MB-Foto als E-Mail-Anhang reist als rund 4 MB Text, und ein als Data-URL in ein Stylesheet eingebettetes Bild ist etwa ein Drittel schwerer als die Datei.

Wo Ihnen Base64 begegnet

  • E-Mail-Anhänge (MIME) sind Base64-Text, umbrochen nach 76 Zeichen pro Zeile.
  • Data-URLs wie data:image/png;base64,iVBORw0… betten eine kleine Datei direkt in HTML oder CSS ein.
  • HTTP-Basic-Authentifizierung sendet user:password als Base64 im Authorization-Header. Das verbirgt das Passwort nur vor flüchtigen Blicken und ist deshalb nur über HTTPS sicher.
  • Zertifikate und Schlüssel in PEM-Dateien sind Base64 zwischen den Zeilen -----BEGIN …----- und -----END …-----, umbrochen nach 64 Zeichen.
  • JSON und XML tragen Binärwerte wie eine Signatur oder ein Vorschaubild als Base64-Zeichenketten, weil sie keinen Binärtyp haben.

Base64URL und Padding

Das + und der / des Standard-Base64 haben in URLs und Dateipfaden eine Bedeutung, daher verwendet ein zweites Alphabet, Base64URL, stattdessen - und _. Meist lässt es auch das =-Padding weg, da der Decoder die Länge berechnen kann. JWTs, viele API-Tokens und manche Dateinamen nutzen Base64URL. Um Standard-Base64 in Base64URL umzuwandeln, ersetzen Sie + durch -, / durch _ und entfernen abschließende =; für den Rückweg kehren Sie die Ersetzungen um und hängen = an, bis die Länge ein Vielfaches von vier ist.

Prozentkodierung in URLs

Eine URL darf nur eine begrenzte Menge an Zeichen enthalten, und einige davon strukturieren die Adresse: / und ? trennen Pfad und Abfrage, & und = trennen Parameter, # leitet das Fragment ein. Enthält ein Wert eines dieser Zeichen oder irgendetwas außerhalb von ASCII, wird er prozentkodiert: Jedes Byte seiner UTF-8-Form wird als % mit zwei Hexadezimalziffern geschrieben. „café“ wird zu caf%C3%A9, weil é aus den zwei Bytes C3 A9 besteht.

Buchstaben, Ziffern und - . _ ~ müssen nie kodiert werden. Diese Zeichen verursachen am häufigsten Probleme:

ZeichenKodiertWarum es wichtig ist
Leerzeichen%20In einer URL nicht erlaubt
&%26Würde einen neuen Parameter beginnen
=%3DWürde den Parameternamen beenden
?%3FWürde die Abfrage beginnen
#%23Würde das Fragment beginnen, das nicht an den Server gesendet wird
/%2FWürde ein Pfadsegment hinzufügen
+%2BWird in Formulardaten als Leerzeichen gelesen
%%25Würde eine Escape-Sequenz beginnen

Kodieren Sie jeden Wert einzeln und setzen Sie dann die URL zusammen. In JavaScript erledigt encodeURIComponent das für einen Wert und kodiert auch / ? & = #, während encodeURI für eine ganze Adresse gedacht ist und diese Zeichen unverändert lässt. encodeURI auf einen einzelnen Wert anzuwenden, ist eine häufige Ursache für kaputte Abfragezeichenketten.

Pluszeichen, Leerzeichen und doppelte Kodierung

HTML-Formulare senden ihre Felder als application/x-www-form-urlencoded, wobei ein Leerzeichen zu + wird. In der allgemeinen URL-Syntax ist + einfach ein Pluszeichen. Eine Suche nach „C++“, gesendet als q=C++, kommt daher bei einem Server, der Formulardaten dekodiert, als „C“ mit zwei Leerzeichen an; richtig wäre q=C%2B%2B. Wenn Sie eine Abfragezeichenkette von Hand dekodieren, finden Sie zuerst heraus, nach welcher Regel sie entstanden ist.

Doppelte Kodierung entsteht, wenn ein bereits kodierter Wert erneut kodiert wird: Aus %20 wird %2520, weil das % selbst zu %25 wird. Sehen Sie in einer URL %25 gefolgt von zwei Hexadezimalziffern, hat irgendein Schritt der Kette doppelt kodiert; dekodieren Sie einmal und suchen Sie den überzähligen Schritt.

Was in einem JWT steht

Ein JSON Web Token (JWT) transportiert Angaben (Claims), etwa wer der Benutzer ist und bis wann das Token gilt, von dem System, das es ausstellt, zu den Systemen, die es akzeptieren. Die übliche signierte Form besteht aus drei Base64URL-Teilen, getrennt durch Punkte: Header, Payload und Signatur. Dekodiert sind die ersten beiden normales JSON:

Header:  {"alg": "HS256", "typ": "JWT"}
Payload: {"sub": "user-42", "role": "editor", "iat": 1767225600, "exp": 1767229200}

Der Standard (RFC 7519) legt einige registrierte Claims fest; Anwendungen ergänzen eigene wie role oben.

ClaimBedeutung
issAussteller: wer das Token erstellt hat
subSubjekt: meist die Benutzer- oder Konto-ID
audZielgruppe: der Dienst, für den das Token bestimmt ist
exp, nbf, iatAblauf, nicht vor, ausgestellt am: Unix-Zeit in Sekunden
jtiToken-ID, um Wiederverwendung zu erkennen oder ein einzelnes Token zu widerrufen

Da die Payload nur kodiert ist, kann jeder sie lesen, der das Token besitzt. Halten Sie personenbezogene Daten und Geheimnisse heraus, und halten Sie Tokens klein: Sie werden mit jeder Anfrage mitgeschickt, und viele Server begrenzen die Größe von Anfrage-Headern.

Signiert heißt nicht geheim: wie ein JWT geprüft wird

Die Signatur wird über Header und Payload berechnet. Bei HS256 teilen Aussteller und Empfänger ein Geheimnis und verwenden HMAC mit SHA-256. Bei RS256 oder ES256 signiert der Aussteller mit einem privaten Schlüssel, und Empfänger prüfen mit dem passenden öffentlichen Schlüssel, sodass sie selbst keine Tokens erzeugen können.

Ein empfangender Server muss die Signatur mit dem erwarteten Algorithmus und Schlüssel prüfen sowie exp, nbf, iss und aud kontrollieren, bevor er irgendeinem Claim vertraut. Reines Dekodieren, wie es das LeedyBox-Werkzeug tut, überspringt all das: Es zeigt, was ein Token behauptet, nicht ob es echt ist. Bibliotheken müssen außerdem den Algorithmus „none“ ablehnen, der ein unsigniertes Token kennzeichnet, sofern unsignierte Tokens nicht ausdrücklich vorgesehen sind. Muss der Inhalt selbst verborgen bleiben, wird das Token stattdessen verschlüsselt (JWE); es hat dann fünf Teile, die sich ohne Schlüssel nicht lesen lassen.

Häufige Probleme und Lösungen

SymptomWahrscheinliche UrsacheLösung
Base64 ergibt beim Dekodieren ZeichensalatDie Daten sind binär oder Text in einer anderen KodierungPrüfen, was kodiert wurde; Binärdaten stattdessen als Datei speichern
„Ungültiges Zeichen“ beim DekodierenEin data:-Präfix, Anführungszeichen oder das Base64URL-AlphabetAlles vor dem Komma entfernen; einen Decoder verwenden, der - und _ akzeptiert
Ein Parameter kommt abgeschnitten anEin unkodiertes & oder # im WertJeden Wert mit encodeURIComponent kodieren
%2520 in einer URLDer Wert wurde doppelt kodiertEinmal kodieren, an der Stelle, an der die URL gebaut wird
Token abgelehnt, obwohl exp in der Zukunft liegtFalsche Zielgruppe oder falscher Aussteller, Uhrabweichung oder abweichender Schlüsselaud, iss und den Signaturschlüssel mit den Erwartungen des Servers vergleichen
Ablaufdatum Tausende Jahre in der Zukunftexp in Millisekunden statt Sekunden geschriebenexp, nbf und iat in Sekunden speichern

Häufig gestellte Fragen

Schützt Base64 ein Passwort oder einen API-Schlüssel?

Nein. Base64 lässt sich von jedem in einer Sekunde rückgängig machen. Ein in Base64 kodierter Zugangsschlüssel, etwa in einer Konfigurationsdatei oder einer URL, ist so offen wie Klartext.

Darf ich personenbezogene Daten in die Payload eines JWT schreiben?

Besser nicht. Jeder, der das Token hat, kann die Payload lesen, auch Browsererweiterungen, Protokolle und Proxys, die die Anfrage sehen. Legen Sie eine ID ins Token und rufen Sie die Details auf dem Server ab.

Schützt URL-Kodierung vor Injection-Angriffen?

Nur insofern, als ein Wert die Struktur der URL nicht zerstören kann. Der Server muss den dekodierten Wert trotzdem für den Ort prüfen und maskieren, an dem er ihn verwendet, etwa SQL, HTML oder einen Shell-Befehl.

Warum ist meine Base64-Zeichenkette länger als die Datei?

Aus je drei Bytes werden vier Zeichen, der Text ist also etwa 33 % größer, und Zeilenumbrüche kommen noch hinzu. Bei großen Dateien ist es effizienter, die Bytes direkt zu senden statt Base64 zu verwenden.