[GUIDE] 9 Min. Lesezeit

[GUIDE] Was ist Base64 und wie funktioniert es?

Eine praxisnahe Erklärung von Grund auf. Lernen Sie den 6-Bit-Gruppierungs-Trick hinter Base64, warum die Ausgabe 33% größer ist, woher das =-Padding kommt und wann Sie es verwenden sollten.

April 2026 | fundamentals

// DIE DEFINITION IN EINEM SATZ

Base64 ist eine Textdarstellung von Binärdaten, die ausschließlich 64 druckbare ASCII-Zeichen verwendet: A–Z, a–z, 0–9 und zwei Symbole (typischerweise + und /, mit = als Padding-Markierung). Das ist die gesamte Idee. Jeweils drei Bytes Binärdaten werden in vier Base64-Zeichen umgruppiert, und sonst ändert sich nichts.

Es handelt sich um eine Kodierung, nicht um eine Verschlüsselung — jeder kann sie in Millisekunden rückgängig machen. Der Zweck ist nicht Vertraulichkeit, sondern sicherer Transport. Mit Base64 lassen sich binäre Nutzdaten (Bilder, Zertifikate, PDF-Dateien, kryptografische Schlüssel) an Stellen unterbringen, die nur Text akzeptieren: HTML-Attribute, JSON-Strings, URLs, E-Mail-Bodies, YAML-Konfigurationen, TEXT-Spalten in Datenbanken, Umgebungsvariablen.

// WARUM WIR ES ÜBERHAUPT BRAUCHEN

Reine Textkanäle verwerfen oder verändern Bytes, die sie nicht kennen. Ein E-Mail-Gateway, das nur 7-Bit-ASCII versteht, zerstört das höchste Bit jedes nicht-englischen Zeichens. Ein JSON-Parser lehnt eingebettete Null-Bytes ab. Eine URL, die ein wortwörtliches Leerzeichen, Anführungszeichen oder Kaufmanns-Und enthält, ist ungültig, bis diese Zeichen prozentkodiert werden. Die SMTP-Standards der 1990er-Jahre gingen davon aus, dass E-Mail-Bodies immer einfacher englischer Text seien — doch die Menschen wollten auch Fotos und Tabellen verschicken.

Base64 löst das, indem die Ausgabe auf 64 Zeichen beschränkt wird, die jeden bekannten Textkanal unbeschadet überstehen: 26 Großbuchstaben, 26 Kleinbuchstaben, 10 Ziffern und zwei Symbole, die (a) druckbar sind, (b) von gängigen Escape-Mechanismen nicht verwendet werden und (c) hinreichend eindeutig sind, um den Umweg durch ASCII zu überstehen. Hinzu kommt das Padding-Zeichen =, das ebenfalls sicher ist.

// DER 6-BIT-GRUPPIERUNGS-TRICK

Hier ist der mechanische Kern von Base64 in einer Zeile: Betrachten Sie die Eingabe als Bitstrom, zerlegen Sie ihn in 6-Bit-Stücke und schlagen Sie jedes Stück in einem 64-Zeichen-Alphabet nach.

Warum 6 Bit? Weil 2^6 = 64 ist, sodass jedes 6-Bit-Stück exakt auf ein Zeichen des Alphabets abgebildet wird. Warum nicht 7 oder 8 Bit? 7 Bit ergeben 128 Werte (zu viele — nicht alle sind druckbar), und 8 Bit sind wieder bloßes Binär. 6 Bit sind der optimale Punkt, an dem jeder mögliche Wert ein für Menschen lesbares Zeichen hat.

Drei Eingabebytes = 24 Bit = genau vier 6-Bit-Gruppen = vier Base64-Zeichen. Dieses Verhältnis von 3 rein zu 4 raus ist fest; es ist der Grund, warum die Base64-Ausgabe ca. 4/3 der Eingabe beträgt, also etwa 33% größer ist.

// Worked example: encoding the 3 bytes 'Man' (77 97 110)
// ASCII:  M        a        n
// Binary: 01001101 01100001 01101110
// Re-group into 6-bit chunks:
//         010011 010110 000101 101110
// Decimal: 19     22     5      46
// Base64:  T      W      F      u
// Result:  'TWFu'  (stored as 4 ASCII bytes: 84 87 70 117)

// DAS BASE64-ALPHABET

RFC 4648 §4 definiert das Standardalphabet. Positionen 0–25 sind A–Z, 26–51 sind a–z, 52–61 sind 0–9, Position 62 ist +, Position 63 ist /.

Die URL-sichere Variante (RFC 4648 §5, auch als base64url bekannt) tauscht + gegen - und / gegen _, damit die Ausgabe ohne weiteres Escaping in URLs und Dateinamen eingesetzt werden kann. Beide Varianten dekodieren identisch, wenn das entsprechende Alphabet angewendet wird.

// Standard Base64 alphabet (index → character)
// 0–25:  A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
// 26–51: a b c d e f g h i j k l m n o p q r s t u v w x y z
// 52–61: 0 1 2 3 4 5 6 7 8 9
// 62:    +       (or  -  in URL-safe)
// 63:    /       (or  _  in URL-safe)
// pad:   =

// WOHER DAS =-PADDING STAMMT

Der Algorithmus erwartet Eingabegrößen, die Vielfache von 3 Bytes sind (damit sie sich sauber in 4 Base64-Zeichen gruppieren). Ist die Eingabelänge kein Vielfaches von 3, bleiben ein oder zwei Bytes übrig, was nicht ausreicht, um die letzte 4-Zeichen-Ausgabegruppe zu füllen. Das Auffüllen mit = zeigt an, wie viele Bytes gefehlt haben.

• Eingabelänge mod 3 == 0 → kein Padding (z. B. 'Man' → 'TWFu').
• Eingabelänge mod 3 == 1 → zwei Padding-Zeichen (z. B. 'M' → 'TQ==').
• Eingabelänge mod 3 == 2 → ein Padding-Zeichen (z. B. 'Ma' → 'TWE=').

// Why 'M' becomes 'TQ==':
// Byte: M = 01001101                   (8 bits)
// Padded to 12 bits with zeros: 010011 010000
// Decimal: 19, 16  →  'T', 'Q'
// Output length must be multiple of 4 → add '==' padding
// Result: 'TQ=='
//
// When decoding, the decoder strips '==' and recovers the first 8 bits,
// discarding the trailing zero bits.

// IST DER OVERHEAD VON 33% EXAKT?

Annähernd, aber nicht ganz. Die genaue Formel lautet ceil(n / 3) × 4 Zeichen für eine Byte-Eingabe der Länge n. Für eine Eingabe von 100 KB ergibt das ceil(102400 / 3) × 4 = 136.534 Zeichen — 33,3% mehr als 100 KB. In der Praxis liegt der tatsächliche Mehraufwand über die Leitung bei etwa 10–15%, sobald HTTP-Level-Komprimierung mit gzip oder Brotli hinzukommt, da sich Base64-Text einigermaßen gut komprimieren lässt (wenn auch nicht so gut wie rohes Binär).

Bei kleinen Nutzdaten fällt das Padding stärker ins Gewicht: Die Kodierung von 1 Byte kostet 4 Zeichen (das Vierfache der Größe), und die Kodierung von 2 Bytes kostet ebenfalls 4 Zeichen. Winzige Base64-Strings wirken daher im Vergleich zu ihrer Eingabe überraschend lang.

// WO BASE64 IN DER PRAXIS EINGESETZT WIRD

  • > Data-URIs in HTML/CSS — Einbetten von Icons und Logos inline: <img src="data:image/png;base64,…">
  • > JSON- und GraphQL-Nutzdaten — APIs, die Binärdaten (Datei-Uploads, Thumbnails) innerhalb eines Textprotokolls transportieren müssen
  • > JWT-Tokens — die drei durch Punkte getrennten Teile eines JWT sind base64url-Strings
  • > HTTP Basic Auth — username:password wird im Authorization-Header Base64-kodiert (ohne TLS dennoch nicht sicher!)
  • > E-Mail (MIME) — Anhänge werden Base64-kodiert, um 7-Bit-SMTP-Server aus der Altlast zu überleben
  • > Zertifikate und Schlüssel im PEM-Format — der Block -----BEGIN CERTIFICATE----- umschließt einen Base64-kodierten DER-Blob
  • > SSH-Schlüssel — Zeilen in id_rsa.pub und authorized_keys sind Base64-kodierte öffentliche Schlüssel
  • > TEXT-Spalten in Datenbanken — wenn kein BLOB-Typ verfügbar ist, speichert Base64 Binärdaten als Text
  • > Umgebungsvariablen — Werte in Kubernetes Secrets sind Base64-kodiert (jedoch NICHT verschlüsselt)
  • > QR-Codes und Magic Links — kurze Base64-Tokens, die sich sicher in URLs einbetten lassen

// BASE64 IST KEINE VERSCHLÜSSELUNG

Dies ist das häufigste Missverständnis überhaupt. Base64 verbirgt den Inhalt Ihrer Daten nicht — es schreibt Binärdaten mittels einer öffentlichen, gut dokumentierten Abbildung als Text um. Ein als cGFzc3dvcmQ= Base64-kodiertes Passwort ist genauso angreifbar wie der Klartext password; jeder kann es mit einem Funktionsaufruf dekodieren. Behandeln Sie Base64 wie Hexadezimal: Es ist eine Darstellung, kein Schutz.

Wenn Sie Vertraulichkeit benötigen, wenden Sie zuerst eine echte kryptografische Primitive (AES-GCM, ChaCha20-Poly1305, age, PGP) auf den Klartext an und kodieren Sie danach bei Bedarf den Chiffretext mit Base64, um ihn durch einen Textkanal zu schleusen. Der Base64-Schritt ist die letzte Meile, nicht die Sicherheitsschicht.

Kubernetes Secrets sind die klassische Stolperfalle: Kubernetes speichert Secret-Werte Base64-kodiert, wodurch sie vage geschützt wirken. Sind sie aber nicht — jeder mit Lesezugriff auf den Namespace kann sie zurückrechnen. Echter Secret-Schutz erfordert Werkzeuge wie SealedSecrets, Vault, SOPS oder cloud-native KMS-Integrationen.

// KURZES KODIEREN / DEKODIEREN IN JEDER SPRACHE

// JavaScript (browser):
//   btoa('Hello')            → 'SGVsbG8='
//   atob('SGVsbG8=')         → 'Hello'
//   (btoa/atob only handle Latin-1; use TextEncoder for Unicode)
//
// Node.js:
//   Buffer.from('Hello').toString('base64')     → 'SGVsbG8='
//   Buffer.from('SGVsbG8=', 'base64').toString() → 'Hello'
//
// Python:
//   import base64
//   base64.b64encode(b'Hello')       → b'SGVsbG8='
//   base64.b64decode('SGVsbG8=')     → b'Hello'
//
// Go:
//   base64.StdEncoding.EncodeToString([]byte("Hello")) → "SGVsbG8="
//
// Ruby:
//   Base64.strict_encode64('Hello')   → 'SGVsbG8='
//
// Shell:
//   echo -n 'Hello' | base64          → 'SGVsbG8='
//   echo 'SGVsbG8=' | base64 -d        → 'Hello'

// HÄUFIGE FEHLER, DIE SIE VERMEIDEN SOLLTEN

  • > Einen URL-sicheren String mit dem Standardalphabet kodieren — der Decoder des Empfängers wird + und / zurückweisen. Verwenden Sie base64url, wenn die Ausgabe in eine URL, einen Cookie oder einen Dateinamen fließt.
  • > Doppelkodierung — bereits Base64-kodierten Text erneut durch den Encoder jagen. Prüfen Sie stets, ob die Daten bereits Base64 sind, bevor Sie kodieren.
  • > UTF-8 vergessenbtoa('héllo') wirft im Browser eine Exception, weil é außerhalb von Latin-1 liegt. Nutzen Sie zuerst TextEncoder, um den String in Bytes umzuwandeln.
  • > Padding-Unstimmigkeiten — base64url lässt das =-Padding oft weg. Ist Ihr Decoder strikt, müssen Sie das Padding rekonstruieren: input + '==='.slice((input.length + 3) % 4).
  • > Annehmen, dass Base64 sicher sei — ist es nicht. Verschlüsselung ist ein separates Thema. Immer.
  • > Base64 für riesige Binärdaten verwenden — eine 500-MB-Datei in einen einzigen String zu kodieren, sprengt den Speicher. Streamen Sie stattdessen.
  • > Zeilenumbrüche vs. keine Umbrüche — MIME/PEM bricht Base64 bei 64 oder 76 Spalten mit \n um. Die meisten anderen Kontexte erwarten eine einzige Zeile. Entfernen oder fügen Sie Zeilenumbrüche je nach Bedarf ein.

// BASE64 IN 30 SEKUNDEN — DER SPICKZETTEL

  • > 64 druckbare ASCII-Zeichen (A–Z, a–z, 0–9, +, /) plus =-Padding
  • > 3 Bytes rein → 4 Zeichen raus (festes Verhältnis)
  • > Die Ausgabe ist ca. 33% größer als die Eingabe
  • > Reversibel: es ist Kodierung, keine Verschlüsselung
  • > Verwenden Sie base64url (ersetzen Sie + → -, / → _) für URLs und Dateinamen
  • > Füllen Sie kurze Eingaben mit 1 oder 2 =-Zeichen auf, damit die Ausgabelänge ein Vielfaches von 4 ist
  • > Für Unicode-Text: kodieren Sie den String zuerst in UTF-8-Bytes, dann Base64 diese Bytes
  • > Dekodierbar von der Standardbibliothek jeder gängigen Sprache
  • > Sicher in HTML, JSON, URLs, E-Mails und PEM-Dateien
  • > Keine Sicherheitsschicht — kombinieren Sie stets mit echter Verschlüsselung für sensible Daten

// NÄCHSTE SCHRITTE

Nun, da Sie die Mechanik kennen, probieren Sie unseren Base64-Encoder oder Base64-Decoder aus und untersuchen Sie die Ausgabe zeichenweise. Für URL-sichere Nutzdaten wechseln Sie zu base64url. Für Bilder siehe Bild → Base64.

Verwandte Tiefengänge:
Base64 URL-sicher vs. Standard — wann welches Alphabet
Base64 für UTF-8 und Unicode — die btoa()-Falle umgehen
Base64 in JavaScript & Node.js — atob, btoa, Buffer
Base64 vs. Base64URL vs. Base32 — Vergleichstabelle