Datei hochladen
  1. base64hub
  2. Base64 im Code
  3. Go (Golang)
Code

Base64 in Go

Das Go-Paket encoding/base64 bringt vier fertige Kodierungen und Streaming-Wrapper mit. Die meiste Arbeit besteht darin, die richtige der vier auszuwählen. Die Ausgaben unten stammen von Go 1.25.

Einen String kodieren und dekodieren

Go-Strings sind bereits UTF-8, die Umwandlung in []byte genügt also:

package main

import (
	"encoding/base64"
	"fmt"
)

func main() {
	enc := base64.StdEncoding.EncodeToString([]byte("héllo wörld"))
	fmt.Println(enc) // aMOpbGxvIHfDtnJsZA==

	dec, err := base64.StdEncoding.DecodeString(enc)
	if err != nil {
		panic(err)
	}
	fmt.Println(string(dec)) // héllo wörld
}

Prüfen Sie immer err. Im Fehlerfall kann DecodeString die bis dahin dekodierten Bytes zusammen mit dem Fehler zurückgeben; wer das Ergebnis ohne Prüfung verwendet, bekommt stillschweigend abgeschnittene Daten.

Die vier Kodierungen: Std, URL, Raw

VariableAlphabetPadding<<???>> wird zu
StdEncoding+ /jaPDw/Pz8+Pg==
URLEncoding- _jaPDw_Pz8-Pg==
RawStdEncoding+ /neinPDw/Pz8+Pg
RawURLEncoding- _neinPDw_Pz8-Pg
d := []byte("<<???>>")
base64.URLEncoding.EncodeToString(d)    // PDw_Pz8-Pg==
base64.RawURLEncoding.EncodeToString(d) // PDw_Pz8-Pg

b, err := base64.RawURLEncoding.DecodeString("PDw_Pz8-Pg") // "<<???>>", nil

Beim Dekodieren ist Go in beide Richtungen streng, was das Padding angeht. Die Kodierungen mit Padding lehnen Eingaben ohne Padding ab, und die Raw-Varianten lehnen = ab:

base64.StdEncoding.DecodeString("aGk")
// illegal base64 data at input byte 0
base64.RawURLEncoding.DecodeString("PDw_Pz8-Pg==")
// illegal base64 data at input byte 10

Nehmen Sie Eingaben aus mehreren Quellen an, entfernen Sie abschließende = mit strings.TrimRight(s, "=") und dekodieren mit einer Raw-Kodierung. Eigene Kodierungen bauen Sie mit base64.NewEncoding(alphabet) und .WithPadding(base64.NoPadding). Die Seite Base64 vs. Base64URL erklärt, wo welche Variante vorkommt.

Eine Datei kodieren und dekodieren

data, err := os.ReadFile("hello.txt")
if err != nil {
	log.Fatal(err)
}
fmt.Println(base64.StdEncoding.EncodeToString(data)) // aGVsbG8K

raw, err := base64.StdEncoding.DecodeString("aGVsbG8K")
if err != nil {
	log.Fatal(err)
}
os.WriteFile("copy.txt", raw, 0o644)

Streaming mit NewEncoder und NewDecoder

Für große Dateien umhüllen Sie einen io.Writer oder io.Reader. Der Speicherverbrauch bleibt konstant:

in, _ := os.Open("big.bin")
defer in.Close()
out, _ := os.Create("big.b64")
defer out.Close()

w := base64.NewEncoder(base64.StdEncoding, out)
if _, err := io.Copy(w, in); err != nil {
	log.Fatal(err)
}
if err := w.Close(); err != nil { // flushes the last partial block
	log.Fatal(err)
}

w.Close() schließt out nicht, sondern schreibt die letzten ein oder zwei Bytes und das Padding. Es wegzulassen ist der klassische Base64-Bug in Go: Die Ausgabe sieht gut aus, ist aber um bis zu vier Zeichen zu kurz. Das Dekodieren funktioniert symmetrisch:

r := base64.NewDecoder(base64.StdEncoding, f)
io.Copy(dst, r)

Gestreamte und im Speicher berechnete Ergebnisse waren bei einer 300-KB-Testdatei identisch. Der Decoder überspringt \r und \n und liest MIME-umbrochene Eingaben daher direkt. Zum Vorausberechnen von Puffergrößen liefert EncodedLen(5) den Wert 8 und RawStdEncoding.EncodedLen(5) den Wert 7; die Formel dahinter steht in der Anleitung zum Größenzuwachs.

Go 1.22 hat AppendEncode und AppendDecode eingeführt, die an einen vorhandenen Slice anhängen. Praktisch für Header:

dst := base64.StdEncoding.AppendEncode([]byte("Basic "), []byte("user:pass"))
fmt.Println(string(dst)) // Basic dXNlcjpwYXNz

Der Basic-Auth-Header-Generator baut denselben Wert im Browser.

Validierung und CorruptInputError

Jeder Dekodierfehler ist ein base64.CorruptInputError, ein int64-Offset des ersten ungültigen Bytes:

_, err := base64.StdEncoding.DecodeString("PDw_Pz8-Pg==")
var ce base64.CorruptInputError
if errors.As(err, &ce) {
	fmt.Println(err) // illegal base64 data at input byte 3
}

Ergebnisse mit StdEncoding:

EingabeFehler
PDw_Pz8-Pg==illegal base64 data at input byte 3 (das _)
aGkillegal base64 data at input byte 0
aGk=!!illegal base64 data at input byte 4
aGk==illegal base64 data at input byte 4
aGVs bG8Killegal base64 data at input byte 4 (Leerzeichen)
aGl=kein Fehler, liefert hi
"aGVs\nbG8K"kein Fehler, Zeilenumbruch übersprungen

aGl= hat Padding-Bits ungleich null. Um solche nicht kanonischen Eingaben abzulehnen, verwenden Sie .Strict():

_, err = base64.StdEncoding.Strict().DecodeString("aGl=")
// illegal base64 data at input byte 3

Der Base64-Validator markiert dieselben Positionen; unter Häufige Base64-Fehler stehen die üblichen Ursachen.

Fallstricke

  • JWT-Teile mit StdEncoding dekodieren. Tokens sind Base64URL ohne Padding. Verwenden Sie RawURLEncoding oder sehen Sie sich das Token zuerst im JWT-Decoder an.
  • Das Teilergebnis ignorieren. "aGk=!!" liefert "hi" und einen Fehler. Verwenden Sie die Bytes nicht, wenn err != nil ist.
  • Close() am Encoder vergessen. Der letzte Block geht verloren.
  • Leerzeichen durch Kopieren und Einfügen. Der Decoder überspringt nur \r und \n. Entfernen Sie anderen Leerraum vorher mit strings.Join(strings.Fields(s), "").

Versionshinweise

  • RawStdEncoding und RawURLEncoding: Go 1.5.
  • Strict(): Go 1.8.
  • AppendEncode, AppendDecode: Go 1.22.
  • Das Paket hat keinen Encoder mit MIME-Zeilenumbruch; die Pakete mime und net/mail kümmern sich um E-Mail, oder Sie fügen selbst alle 76 Zeichen \r\n ein.

Häufige Fragen

Was ist der Unterschied zwischen URLEncoding und RawURLEncoding?

Beide verwenden das URL-sichere Alphabet mit - und _. URLEncoding schreibt =-Padding und verlangt es beim Dekodieren; RawURLEncoding lässt das Padding weg und lehnt es ab. JWTs verwenden RawURLEncoding.

Was bedeutet „illegal base64 data at input byte 0“?

Das ist ein base64.CorruptInputError, und die Zahl ist der Offset, an dem das Dekodieren gescheitert ist. Bei Byte 0 und einem kurzen String ist meist die Länge falsch, oft fehlt das Padding; verwenden Sie für Eingaben ohne Padding die Raw-Kodierung.

Ignoriert der Base64-Decoder von Go Zeilenumbrüche?

Ja. \r und \n werden von allen vier Kodierungen übersprungen, MIME-umbrochene Eingaben lassen sich also dekodieren. Leerzeichen und andere Zeichen sind Fehler.

Weiterlesen