[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.
// 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 vergessen —
btoa('héllo')wirft im Browser eine Exception, weiléaußerhalb von Latin-1 liegt. Nutzen Sie zuerstTextEncoder, 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
\num. 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