Haben Sie mit dem Base64-Format zu tun? Dann ist diese Website genau das Richtige für Sie! Nutzen Sie unser superpraktisches Online-Tool, um Ihre Daten zu kodieren oder zu dekodieren.

Base64-Kodierung in Bash: Ein vollständiger Leitfaden

Sie haben Bytes und Sie brauchen eine Zeichenkette. Eine Textdatei, die in einem JSON-Body leben muss. Ein Bild, das in einer Konfigurationszeile sitzen muss. Ein Token, das durch eine URL, eine Umgebungsvariable oder einen HTTP-Header reisen wird. Ein privater Key, der in einen Zertifikatsspeicher gehört. Das ist der Alltag der Base64-Kodierung in der Shell, und die Antwort der Shell ist ein einzelnes, kleines, bemerkenswert portables Kommando.

Der Tausch in einem Atemzug: Base64 schreibt je drei Bytes roher Daten als vier Zeichen aus einem Alphabet von 64 Buchstaben um (A-Z, a-z, 0-9, dazu + und /) und füllt das Ende mit einem oder zwei = auf, wenn die Anzahl der Bytes kein Vielfaches von drei ist. Die Startseite dieser Site erklärt das Format in voller Breite; hier verbringen wir unsere Zeit damit, den Text zu erzeugen, den richtigen Dialekt für das Ziel zu wählen und die Größenrechnung mit offenen Augen zu bezahlen. Eine Zahl zum Mitnehmen in der Tasche: Die kodierte Form ist normalerweise etwa ein Drittel größer als das Original, vier Zeichen pro drei Bytes, und sie kommt immer wieder vor.

Die Besetzung ist klein. Das base64-Kommando aus coreutils (GNU oder die neuere Rust-uutils-Familie), basenc aus derselben Familie für den URL-sicheren Dialekt, openssl base64 für Maschinen ohne coreutils, das BusyBox-Applet für eingebettete Systeme und die BSD-Variante auf macOS. Fünf Werkzeuge, eine Aufgabe, ein paar Flags, die sich zu kennen lohnen.

Ihren Encoder wählen

Jedes dieser Werkzeuge liest Bytes von der Standardeingabe oder einer Datei und schreibt Text auf die Standardausgabe, also passen sie alle in dieselben Pipelines. Die Unterschiede sind der Standard-Zeilenumbruch und die verfügbaren Dialekte:

Werkzeug Wo es zuhause ist Standard-Zeilenumbruch Greifen Sie danach, wenn
base64 (coreutils) Linux, und macOS über Homebrew 76 Zeichen die Standardwahl; für eine Zeile -w 0 dazunehmen
basenc (GNU coreutils) Linux mit coreutils 76 Zeichen Sie --base64url, base32, base16 oder Bekannte brauchen
openssl base64 überall, wo OpenSSL installiert ist 64 Zeichen coreutils fehlt; -A für eine Zeile
busybox base64 Alpine, eingebettetes Linux 76 Zeichen minimale Systeme; dieselben Flags in einem kleineren Körper
base64 (BSD/macOS) macOS, die BSDs keiner (eine lange Zeile) natives macOS-Handwerk; -b setzt die Breite

Lesen Sie die Umbruch-Spalte noch einmal, denn das ist der stille Unterschied zwischen den Familien. Coreutils und BusyBox brechen standardmäßig bei 76 um, OpenSSL bei 64, und das BSD-Werkzeug bricht überhaupt nicht um. Keines davon ist falsch; sie haben nur unterschiedliche Konventionen geerbt (MIME sagt 76, PEM sagt 64, und das BSD-Werkzeug ist einfach älter als die Umbruch-Gewohnheit). Wenn es auf den Empfänger ankommt, setzen Sie die Breite explizit und verlassen Sie sich nie auf den Standard.

Zuerst Text: Das unsichtbare Zeilenende

Text in einer Shell zu kodieren beginnt mit einer Falle: echo fügt ein Zeilenende hinzu. Diese fünf Buchstaben "hello" werden im Moment, in dem sie durch echo gehen, sechs Bytes, und das sechste Byte reitet unsichtbar und dauerhaft mit in die Ausgabe:

echo "hello" | base64

Das gibt aGVsbG8K aus, und das letzte Zeichen kodiert das Zeilenende. Die Lösung ist die, die Sie für Text verwenden sollten, wo die Byte-Anzahl zählt: printf mit Format, ohne Dekoration:

printf '%s' "hello" | base64

Nun ist die Ausgabe aGVsbG8=, genau fünf Bytes wert, und das letzte Zeichen ist ein Padding-Zeichen statt eines lebendigen Bytes. Dieselbe Regel gilt für Here-Strings, die ein abschließendes Zeilenende anhängen, genau wie echo: base64 <<< "hello" gibt Ihnen wieder die aGVsbG8K-Version. Im Zweifel fragen Sie sich, was das letzte Byte ist, bevor Sie es kodieren.

Für alles, was Sie auf einer einzigen Zeile wollen, fügen Sie -w 0 hinzu (oder die Vettern von -w 0 unten), was auch das abschließende Zeilenende entfernt, das das Kommando andernfalls ausgeben würde:

printf '%s' "hello world and more" | base64 -w 0

Das ist eine saubere, ununterbrochene Zeile ohne abschließendes Zeilenende, bereit, ohne weitere Zeremonie in eine URL, einen JSON-Wert oder eine Konfigurationsdatei zu fallen.

Dateien und die Umbruchbreite

Dateien sind der häufige Fall, und jede Implementierung nimmt ein FILE-Argument, was die Bytes gänzlich fernhält vom Quoting-Mechanismus der Shell:

base64 -w 0 report.pdf > report.b64

Ohne -w 0 kommt die Ausgabe umgebrochen bei 76 Zeichen, und genau das will ein MIME-Empfänger:

base64 report.pdf > report.mime.b64

Die Breite ist ein Regler, den Sie pro Empfänger steuern. Sechsundsiebzig ist die MIME-Konvention aus RFC 2045, vierundsechzig die PEM-Konvention, die von Zertifikaten und Keys verwendet wird, und null bedeutet eine ununterbrochene Zeile für URLs und APIs:

base64 -w 64 key.bin | head -2

Wenn der Empfänger auf Windows lebt und CRLF-Zeilenenden erwartet, konvertieren Sie nach dem Umbruch, nicht vorher:

base64 -w 76 attachment.bin | sed 's/$/\r/' > attachment.crlf.b64

Auf dem OpenSSL-Weg ist das Äquivalent zum Ein-Zeilen-Modus das -A-Flag, das auch das abschließende Zeilenende unterdrückt:

openssl base64 -A < report.pdf

Bevor Sie eine umgebrochene Datei verschicken, kostet eine Größen-Plausibilitätsprüfung nichts und fängt eine erstaunliche Anzahl von Fehlern ab (eine zweifach kodierte Datei, eine Datei mit der falschen Eingabe kodiert):

wc -c report.pdf
base64 report.pdf | wc -c

Die zweite Zahl sollte etwa vier Drittel der ersten sein, plus ein Byte pro umgebrochener Zeile für die Zeilenenden. Wenn sie weit abweicht, halten Sie an und schauen Sie, was Sie dem Encoder tatsächlich gefüttert haben.

URL-sicheres Base64: Die zwei unangenehmen Zeichen tauschen

Zwei Zeichen im Standardalphabet, + und /, sind die Problemkinder: Ein + in einer URL-Query-String bedeutet Leerzeichen, ein / kann wie ein Pfadtrenner aussehen, und beide erzwingen Prozent-Kodierung im Moment, in dem die Zeichenkette eine URL, ein Cookie oder einen Dateinamen betritt. Abschnitt 5 von RFC 4648 löst das mit einem Dialekt, der genau diese zwei Zeichen durch - und _ ersetzt und das Padding weglässt, denn eine URL muss selten die genaue Byte-Länge ankündigen.

Das Shell-Rezept ist ein Tausch plus ein Zuschnitt, ein Durchlauf durch tr für das Alphabet und einer zum Entfernen des Paddings:

printf '\376\117\202' | base64 -w 0 | tr '+/' '-_' | tr -d '='

Diese drei Bytes kodieren normalerweise zu /k+C, was in einer URL hässlich wäre; die Pipeline macht daraus _k-C, vier Zeichen, die überall reisen können. Der Tausch ist positionell, also ist die Richtung leicht zu verwechseln: Kodieren läuft als tr '+/' '-_' (Plus wird Dash, Slash wird Unterstrich), und die Umkehrung, die zum Dekodieren gehört, läuft als tr '_-' '/+'. Eine verwechselte Richtung meldet keinen Fehler, sie produziert nur andere Bytes, und das ist die schlimmste Art von Bug, die man ausliefert.

Der Dialekt wird wichtig, wann immer die Zeichenkette die Kontrolle der Shell verlässt: JWT-Segmente, Tokens in Query-Strings, Werte in Cookies oder Dateinamen und jeder Bezeichner, den ein anderes System als Teil einer URL liest. Das GNU-basenc erzeugt den Dialekt nativ, mit dem Padding noch an Ort und Stelle:

printf '%s' "hello" | basenc --base64url

Streifen Sie das Padding mit tr -d '=', wenn der Empfänger die gestreifte Form will, wie die meisten.

Ein JWT in der Shell prägen

JSON Web Tokens sind der sichtbarste Empfänger von URL-sicherem Base64 in der API-Welt. Ein kompaktes JWT sind drei base64url-Segmente, durch Punkte verbunden: der Header, die Payload und die Signatur, laut RFC 7515. Die ersten zwei sind schlichtes JSON; die Signatur ist eine binäre Prüfsumme der ersten zwei Segmente, durch einen Punkt verbunden, und genau das ist die Art von Dingen, die openssl gut kann.

key="supersecretkey"
h=$(printf '%s' '{"alg":"HS256","typ":"JWT"}' | base64 -w 0 | tr '+/' '-_' | tr -d '=')
p=$(printf '%s' '{"sub":"42","name":"homer"}' | base64 -w 0 | tr '+/' '-_' | tr -d '=')
s=$(printf '%s' "$h.$p" | openssl dgst -sha256 -hmac "$key" -binary | base64 -w 0 | tr '+/' '-_' | tr -d '=')
printf '%s.%s.%s\n' "$h" "$p" "$s"

Das gibt ein kompaktes HS256-JWT aus, das jede Standard-Bibliothek auf jeder Plattform akzeptiert. Beachten Sie die Arbeitsteilung: Der Base64-Teil ist das Alphabet, der openssl dgst -sha256 -hmac-Teil ist die Kryptographie, und das Verbinden durch Punkte ist das Format. Halten Sie die drei Aufgaben im Kopf getrennt, und die Pipeline bleibt offensichtlich.

Drei Warnungen für die Praxis. Erstens wird der MAC über dem ASCII-Text der ersten zwei Segmente plus dem Punkt berechnet, also müssen die Segmente beim Signieren schon in ihrer endgültigen base64url-Form sein; Neuumbruch oder Neuauffüllen nach dem Signieren bricht das Token. Zweitens bleibt der Key aus dem Token heraus: Die Signatur beweist, wer signiert hat, der Key hält das Geheimnis geheim. Drittens ist das Prägen in einem Shell-Skript ein Test- und Automatisierungswerkzeug, kein Ersatz für den Server, der diese Tokens tatsächlich ausstellen und verifizieren wird, und ein Token, das mit alg: none geprägt wurde, beweist überhaupt nichts.

Data-URIs: Dateien, die in Strings reisen

RFC 2397 definiert das data:-URL-Schema, und seine Base64-Form lässt eine Datei in einer URL leben: data:, dann ein optionaler Medientyp, dann ;base64, wenn der Payload Base64-kodiert ist, dann ein Komma, dann die Daten. Lassen Sie den Medientyp weg, und der Standard ist text/plain;charset=US-ASCII, eine Fußangel, die sich zu kennen lohnt, denn die meisten meinen ein Bild oder ein JSON-Dokument, keinen ASCII-Text.

printf 'data:text/plain;base64,%s\n' "$(printf '%s' "hi there" | base64 -w 0)"

Das gibt data:text/plain;base64,aGkgdGhlcmU= aus, eine komplette, in sich geschlossene URL, die ein Browser fröhlich anzeigt. Für ein Bild dieselbe Form mit einem echten Medientyp:

printf 'data:image/png;base64,%s\n' "$(base64 -w 0 icon.png)" > icon.uri

Kopieren Sie das Ergebnis in das src eines HTML-img-Tags oder in ein CSS-background, und das Bild reist mit dem Dokument, ohne zweite HTTP-Anfrage. Die Fallen drehen sich alle um Größe: Der RFC selbst sagt, das Schema sei nur für kurze Werte nützlich, Browser verhängen ihre eigenen URL-Längengrenzen, jedes inline gesetzte Byte kostet 33 Prozent Aufschlag auf die eigene Größe des Bildes, und eine Seite voller Data-URIs ist eine Seite ohne Caching-Geschichte für diese Bilder. Für kleine Icons und einmalige eingebettete Grafiken ist es ein Vergnügen; für eine Fotobibliothek eine Abgabe.

Secrets, Konfiguration und Umgebungsvariablen

Base64 taucht in der Konfigurations- und Secrets-Arbeit aus einem bestimmten Grund auf: Es verwandelt beliebige Bytes, einschließlich Leerzeichen, Anführungszeichen und Zeilenenden, in eine Zeichenkette, die ein export, eine Konfigurationszeile oder ein JSON-Feld überlebt, ohne jede Quoting-Akrobatik. Kubernetes ist das sichtbarste Beispiel: Jedes Feld unter .data eines Secrets ist Base64, also ist das Erstellen eines Secrets in der Shell einfach nur Kodieren:

kubectl create secret generic app --from-literal=password='s3cret'

Der API-Server speichert das Passwort unter .data als czNjcmV0, und jeder Node mit Zugang zum Secret kann es mit einem einzigen Dekodieren wieder lesen. Derselbe Zug funktioniert für Ihre eigenen Konfigurationsdateien:

export API_TOKEN_B64=$(printf '%s' "$API_TOKEN" | base64 -w 0)

Oder, für eine Datei, die die Anwendung beim Start liest:

printf 'token=%s\n' "$(printf '%s' "$API_TOKEN" | base64 -w 0)" >> app.conf

Und jetzt kommt die Warnung, die an eine Wand gehört: Base64 ist Kodierung, keine Verschlüsselung. Der Sicherheitsabschnitt von RFC 4648 ist dabei offen und merkt an, dass die Kodierung "sonst leicht erkennbare Informationen, wie Passwörter, optisch verdeckt, aber keine berechnete Vertraulichkeit bietet", und dass genau dieses Missverständnis echte Sicherheitsvorfälle verursacht hat, als jemand einen "geschützten" Protokollaustausch in einen Bug-Report kopierte und versehentlich die Zugangsdaten preisgab. Wenn der Wert geheim sein muss, verschlüsseln Sie ihn (und kodieren Sie dann den Chiffretext mit Base64 für die Speicherung); wenn Base64 alles ist, was Sie haben, behandeln Sie den kodierten Wert als Klartext, im Moment, in dem er den Bildschirm verlässt.

Unicode, Charsets und die Bytes darunter

Der Encoder liest Bytes, keine Zeichen, und die Shell reicht ihm die Bytes, die die Locale und das Kommando erzeugt haben. Für UTF-8-Text ist das meistens genau das, was Sie wollen: Das é in héllo ist schon zwei Bytes, c3 a9, und die Kodierung trägt sie einfach mit:

printf 'h\xc3\xa9llo' | base64

Das gibt aMOpbGxv aus, und ein UTF-8-Empfänger auf der anderen Seite bekommt héllo zurück, Byte für Byte. Die Schwierigkeiten beginnen, wenn die Quelle kein UTF-8 ist. Eine Latin-1-Datei mit demselben Wort hält ein einzelnes Byte e9 für das é, und diese Bytes geradeaus zu kodieren erzeugt Text, den nur ein Latin-1-Empfänger wieder lesen kann. Erst konvertieren, zweitens kodieren:

iconv -f ISO-8859-1 -t UTF-8 note.txt | base64 -w 0

Zwei weitere Fakten auf Byte-Ebene. Ein UTF-8-BOM, drei Bytes am Anfang einer Datei, kodiert zu 77u/ und wird für immer am Anfang Ihrer dekodierten Ausgabe sitzen, wenn Sie es nicht zuerst streichen:

sed '1s/^\xef\xbb\xbf//' file.txt | base64 -w 0

Und die Locale verändert nie die Kodierung selbst, denn der Encoder ist eine Byte-Maschine; sie verändert nur das, was Sie eingegeben haben. Wenn die Ausgabe falsch aussieht, prüfen Sie die Bytes, die Sie gefüttert haben, nicht die Kodierung, die Sie gefahren haben.

E-Mail, APIs und Uploads

E-Mail ist der Ort, an dem Base64 seine Manieren gelernt hat, und die Manieren sind immer noch die Konvention. SMTP hat historisch nur 7-Bit-ASCII getragen, also reisen Anhänge als Base64, umgebrochen bei 76 Zeichen mit CRLF-Zeilenenden, laut RFC 2045. Die exakte Form für einen MIME-Teil zu erzeugen ist der Umbruch plus die Zeilenenden-Konvertierung:

base64 -w 76 attachment.bin | sed 's/$/\r/' > attachment.mime

Die alte Garde ist in eingebetteten Systemen immer noch im Dienst: Das BusyBox-uuencode mit dem -m-Flag erzeugt MIME-Base64, umwickelt im vertrauten begin-base64-Rahmen, und sein Bruder uudecode liest es wieder ein:

busybox uuencode -m photo.jpg < photo.jpg > photo.uu

APIs und Uploads nutzen dieselbe Idee in JSON-Kleidung: Das Binär wird zu einer Base64-Zeichenkette in einem JSON-Feld, und curl trägt sie. Den Body in einer Shell-Variable aufzubauen hält das Quoting ehrlich:

body="{\"file\":\"$(base64 -w 0 upload.bin)\"}"
curl -fsS -X POST https://httpbin.org/post -H "Content-Type: application/json" -d "$body"

Zwei Interoperabilitätsfallen wohnen hier. Erstens: Prüfen Sie, welches Alphabet die API will; manche erwarten Standard-Base64, manche den URL-sicheren Dialekt, und eine Zeichenkette mit +-Zeichen, die an einen URL-sicheren Endpunkt gesendet wird (oder umgekehrt), wird die Validierung zum Scheitern bringen oder, schlimmer, zu falschen Bytes dekodiert. Zweitens: Achten Sie auf Doppel-Kodierung, den klassischen Bug, bei dem ein Skript einen Wert kodiert, den der Server wieder kodiert, und der Round-Trip zwei Dekodierungen braucht, um aufgewickelt zu werden.

Wenn der Payload groß wird

Der Encoder ist, wie der Decoder, eine Streaming-Maschine: Er liest in Chunks und schreibt in Chunks, also braucht ein 10-GB-Tarball keine 13 GB RAM, und das Kommando läuft fröhlich minutenlang auf großen Eingaben mit flachem Speicherverbrauch. Die Größenrechnung ist das einzige Planungswerkzeug, das Sie brauchen: Die Ausgabe ist vier Zeichen pro drei Eingabe-Bytes, plus ein Byte pro umgebrochener Zeile, also wird eine 300-MB-Datei zu etwa 400 MB Text. Für einen schnellen Realitätscheck bei jeder Datei:

base64 -w 0 big.bin | wc -c

Wenn der Text selbst durch einen Kanal mit Größenlimit muss (ein E-Mail-Anhang-Limit, ein Ticket-System, eine IM-Nachricht), teilen Sie die kodierte Form, niemals das rohe Binär, damit jeder Chunk gewöhnlicher Text bleibt, den Sie einfügen, komprimieren oder weiterleiten können:

base64 -w 0 big.bin | split -b 4000 - part_

Das erzeugt eine Reihe von 4000-Zeichen-Teilen; der Empfänger setzt sie in der richtigen Reihenfolge wieder zusammen und dekodiert einmal. Und wenn der Payload komprimierbar ist, komprimieren Sie vor dem Kodieren, denn Base64 fügt Redundanz hinzu, auf alles, was die Daten bereits enthalten: Ein Tarball eines Projektdirectory schrumpft typischerweise mehrmals unter gzip, bevor der 33-Prozent-Base64-Zuschlag angesetzt wird:

tar czf - project/ | base64 -w 0 > project.b64

Geschwindigkeit wird nicht Ihre Grenze sein. Diese Encoder drücken auf einer modernen Maschine Gigabytes in deutlich unter einer Sekunde durch; eine 200-MB-Datei braucht mit den coreutils- und OpenSSL-Implementierungen etwa ein Zehntel einer Sekunde, und selbst BusyBox, der langsamste der gängigen, ist noch in einem Bruchteil einer Sekunde fertig (gemessen bei etwa einem Viertel einer Sekunde für 200 MB auf einer modernen Maschine, einige Male langsamer als coreutils, aber keineswegs ein Flaschenhals). Der Flaschenhals in echten Pipelines ist fast immer das Netzwerk, nicht die Kodierung.

Die kleinen Zeichen, die beißen

Die Fallen der Kodier-Seite sind kleiner als die der Dekodier-Seite, und das ist nur fair:

Falle Was passiert Die Lösung
echo füttert den Encoder ein abschließendes Zeilenende reitet in die Ausgabe, und das letzte Zeichen kodiert es printf '%s' für Text, wo die Byte-Anzahl zählt
Auf den Standard-Umbruch vertrauen 76, 64 oder null je nach Werkzeug; ein Ein-Zeilen-Empfänger erstickt an umgebrochener Eingabe -w 0 (oder die Breite, die der Empfänger will) explizit setzen
Ein abschließendes Zeilenende in der Ausgabe umbruch-Modi enden mit einem Zeilenende, das URLs und JSON verschmutzt, wenn es eingefangen wird -w 0 für eine Zeile, oder einfangen über $(...), das es streift
+ oder / in einer URL Plus wird in einem Query-String als Leerzeichen gelesen; beide erzwingen Prozent-Kodierung den URL-sicheren Dialekt für alles verwenden, was eine URL betritt
Verwechselte tr-Richtung der Tausch produziert gültige, aber falsche Bytes, nirgends ein Fehler Kodieren ist tr '+/' '-_'; Dekodieren ist tr '_-' '/+'
Einen bereits kodierten Wert kodieren Doppel-Kodierung, die zwei Dekodierungen braucht, um aufgewickelt zu werden prüfen, ob die Quelle schon Base64 ist, bevor Sie kodieren
Ein UTF-8-BOM in der Eingabe drei zusätzliche Bytes am Anfang jeder dekodierten Ausgabe das BOM zuerst streichen: sed '1s/^\xef\xbb\xbf//'
Ein echtes Secret als Base64 speichern ein einziges Kommando macht es rückgängig; der RFC dokumentiert echte Vorfälle von auslaufenden Zugangsdaten verschlüsseln für Geheimhaltung, Base64 nur für die Transportform
Das Alphabet des Empfängers annehmen eine Diskrepanz zwischen Standard und URL-sicher scheitert an der Validierung oder dekodiert falsch die API-Doku lesen; in dem Dialekt kodieren, den der Empfänger verlangt

Gewohnheiten, die Sie sicher halten

  • Die Byte-Anzahl benennen. printf '%s' für Text, das FILE-Argument für Dateien und eine wc -c-Plausibilitätsprüfung, bevor Sie etwas verschicken, wo Größe zählt.
  • Den Umbruch explizit setzen. -w 0 für URLs und JSON, -w 76 für MIME, -w 64 für PEM. Niemals die Breite dem Standard des Werkzeuges überlassen.
  • Das Alphabet für das Ziel wählen. Standard für E-Mail und Dateien, URL-sicher für Tokens und URLs, und die Doku des Empfängers lesen, bevor Sie kodieren.
  • Komprimieren, bevor Sie kodieren. Für jeden komprimierbaren Payload zuerst gzip oder tar czf; der 33-Prozent-Zuschlag gilt für alles, was Sie dem Encoder in die Hand geben.
  • Den Text teilen, nicht das Binär. Wenn ein Größenlimit im Weg steht, die kodierte Form mit split teilen, damit jeder Chunk einfügsicher bleibt, und in der richtigen Reihenfolge wieder zusammenbauen, vor dem einzigen Dekodieren.
  • Die drei JWT-Aufgaben getrennt halten. Alphabet, Kryptographie, Format: die Segmente kodieren, den ASCII-Text der verbundenen Segmente signieren, dann ausgeben. Die Reihenfolge tauschen, und das Token bricht.
  • Niemals Base64 als Ersatz für Verschlüsselung stehen lassen. Wenn der Wert geheim ist, verschlüsseln Sie ihn und kodieren Sie dann den Chiffretext. Wenn er nicht geheim ist, sagen Sie das, und machen Sie sich keine Sorgen mehr.

Eine kurze Geschichte des Kodierens in der Shell

  • 1980, Berkeley. Mary Ann Horton schreibt uuencode und uudecode an der University of California, Berkeley, um binäre Dateien per E-Mail zwischen Unix-Systemen zu tragen. Der Name, "Unix-zu-Unix-Kodierung", ist die Geburtsurkunde des Formats, und in der nächsten Dekade oder so ist das das, womit Shell-Nutzer kodieren.
  • Das Dial-up-Zeitalter. uuencode auf UNIX und BinHex auf dem TRS-80 und dem Apple II, das Macintosh einen Schritt hinterher, lösen dasselbe Problem mit unterschiedlichen Alphabeten, jede vertraut nur den Zeichen, die ihr eigenes Terminal drucken kann.
  • 1993. MIME standardisiert Base64 für E-Mail in RFC 1521, später RFC 2045, mit dem Zeilenumbruch bei 76 Zeichen, den der coreutils-Standard bis heute mit sich trägt.
  • Vor 2006 auf Linux. Es gibt kein base64-Kommando. Shell-Skripte greifen nach openssl base64, uuencode -m, Perl oder Python, und die OpenSSL-Gewohnheit ist so tief, dass die Hälfte der alten One-Liner in der Wildnis immer noch damit anfängt.
  • 15. August 2006. coreutils 6.0 liefert das base64-Kommando aus, seine NEWS-Datei bescheinigt es als "base64-Kodierung und -Dekodierung (RFC 3548) Funktionalität", und die Ein-Kommando-Ära beginnt. Ein paar Monate später, im Oktober 2006, formalisiert RFC 4648 die Alphabet-Familie, einschließlich des URL-sicheren Dialekts, nach dem dieser Artikel immer wieder greift.
  • OS X 10.7. macOS liefert sein eigenes base64 aus, die BSD-Variante ohne Standard-Umbruch, und deshalb braucht "einfach base64 ausführen" einen Plattform-Check in portablen Skripten.
  • 2024. coreutils 9.5 ändert, wie Decoder Eingaben ohne Padding und nicht kanonische Eingaben behandeln, was in der Praxis bedeutet, dass Encoder einen Freifahrtschein bekommen: Ausgabe, die ältere GNU-Versionen abgelehnt hätten, dekodiert jetzt sauber. Die Encoder-Seite des Formats ist die stabile; die Decoder sind die, die sich bewegt haben.
  • 2025. Das coreutils neu in Rust geschrieben (uutils) wird der Standard in aktuellen Ubuntu-Releases. Dasselbe Kommando, dieselben Flags, ein neuer Motor und derselbe 76-Zeichen-Standard, den es von der C-Version geerbt hat.

Kleine Wunder

  • Der Name des Formats ist auf jeder Maschine wahr. printf 'base64' | base64 gibt auf GNU, uutils, BusyBox, OpenSSL und macOS gleichermaßen YmFzZTY0 aus. Das ist seit 2006 wahr und wird es immer sein.
  • Eine Datei aus Nichts kodiert zu einer Wand aus A. Füttern Sie ihr drei NUL-Bytes, und die Ausgabe ist AAAA, denn drei Bytes mit Wert null werden auf vier Null-Indizes im Alphabet abgebildet, und jeder davon wird durch A dargestellt. Eine .b64-Datei, die mit einer langen Kette von A beginnt, ist meistens Null-Füllung in der Originaldatei (NUL-Bytes), kein Rätsel.
  • Die 33-Prozent-Abgabe hat keine Ermäßigungen. Vier Zeichen pro drei Bytes, keine Komprimierung, keine zweite Chance. Die einzige Flucht ist, die Daten zuerst zu komprimieren, und deshalb ist tar czf der echte Held der großen-Payload-Pipelines.
  • Zwei Zeichen haben das ganze URL-Chaos verursacht. + und / sind die einzigen Alphabet-Mitglieder, die jemals einen Ersatz gebraucht haben, und ein ganzer Dialekt des Formats existiert, um sie in den Ruhestand zu schicken. Zweiundsechzig und dreiundsechzig, die letzten zwei Plätze des Alphabets.
  • Elf Zeichen, vierundsechzig Bits. Eine YouTube-Video-ID ist eine 11-stellige base64url-Zeichenkette, eine 64-Bit-Zahl in URL-Kleidung, deshalb reist sie durch URLs ohne ein einziges Prozentzeichen.
  • Gits berühmtester Scharlatan. Die binären Blöcke in git diff --binary sehen wie Base64 aus, aber die mit z präfixten Zeilen sind ein base85-artiger Dialekt für sich. Ein Blick, und Sie wissen, dass es nicht Ihr Alphabet ist; ein Umweg über grep und Dekodieren, und Sie verlieren zwanzig Minuten.
  • Jedes Werkzeug bricht anders um, aus Absicht. 76 für MIME, 64 für PEM, null beim BSD-Werkzeug: drei Standards, drei geerbte Konventionen, ein Format. Die Breite war immer Ihre zu wählen; die Werkzeuge haben sich nur unterschiedliche Standards gemerkt.
  • Der Encoder scheitert nie an Ihren Daten. Im Gegensatz zu seinem Dekodier-Cousin hat der Encoder keine ungültige Eingabe, keine Beschädigung, keinen strikten Modus. Er nimmt Bytes und gibt Buchstaben, jedes Mal. Die Bugs in diesem Artikel sind alle in den Bytes, die Sie ihm in die Hand geben, und dem Ziel, an das Sie sie schicken.

Und wenn die Reise die andere Richtung zeigt, wenn eine lange Zeichenkette aus Buchstaben, Ziffern und dem gelegentlichen Dash oder Unterstrich in Ihrem Terminal landet und Sie die Bytes zurück brauchen, deckt der verknüpfte Base64-Dekodierungsartikel unten diesen Ritus in derselben Tiefe ab, von unpadded JWT-Segmenten bis zu jeder Zeilenenden-Falle, die die Decoder verstecken.

Zuletzt aktualisiert: 2026-09-08

Verwandter Artikel: Base64-Dekodierung in Bash: Ein vollständiger Leitfaden