Sprache: Deutsch
note · encoding
Pushkar Kumar 8 Min. Lesezeit
Base64 ist keine Verschlüsselung: wie du einen API-Key wirklich schützt
Ist Base64 Verschlüsselung? Nein. Was Base64 tut, wo kodierte Secrets lecken, was einen API-Key wirklich schützt und wann Base64 das richtige Werkzeug ist.
- security
- developer-experience
Auf dieser Seite
- Was Base64 tatsächlich tut
- Ist Base64 eine Verschlüsselung? Warum es so aussieht und warum nicht
- Der Fall Kubernetes-Secret
- Wo Base64-kodierte Secrets lecken
- Wie du einen API-Key wirklich schützt
- Lege ihn in einem Secret Manager oder KMS ab
- Injiziere ihn zur Laufzeit
- Halte den Scope eng
- Rotiere ihn
- Verschlüssele ihn auf dem Transportweg mit TLS
- Wann Base64 das richtige Werkzeug ist
- Prüfe den String, ohne ihn irgendwohin zu senden
- Checkliste: Base64 und API-Keys
Ein Pull Request kommt mit einer Konfigurationsdatei, die diese Zeile enthält:
PAYMENTS_API_KEY: b3BzX2xpdmVfN2YzYTljMmU=Der Autor schreibt dazu, der Key sei „kodiert, also okay zum Committen“. Ist er nicht. Wer diese Zeile lesen kann, bekommt den Key mit einem einzigen Befehl zurück — genau wie jeder Scanner, der öffentliche Repositories nach exakt diesem Muster durchsucht.
TL;DR
- Base64 ist eine Kodierung. Es gibt keinen Schlüssel, also kann jeder sie sofort umkehren.
- Kubernetes-
Secret.dataist Base64, weil YAML Text braucht, nicht weil dadurch etwas verborgen wird.- Einen Key schützt, wo er liegt und wer ihn lesen darf: ein Secret Manager oder KMS, Injektion zur Laufzeit, enger Scope, Rotation und TLS auf dem Transportweg.
- Base64 ist das richtige Werkzeug, um Bytes durch reine Textkanäle zu bringen. Mehr nicht.
Was Base64 tatsächlich tut
Base64, definiert in RFC 4648, verwandelt beliebige Bytes in einen String aus 64 druckbaren Zeichen: A–Z, a–z, 0–9, + und /, dazu = als Padding. Die Eingabe wird in Gruppen zu drei Bytes (24 Bit) gelesen und als vier Zeichen zu je sechs Bit ausgegeben. Die drei ASCII-Bytes von Man werden zu TWFu.
Dieses Verhältnis von 3 zu 4 ist der Grund, warum kodierte Daten etwa 33 % größer sind als das Original. Ist die Eingabelänge kein Vielfaches von drei, bekommt die Ausgabe ein oder zwei =, damit ihre Länge ein Vielfaches von vier bleibt.
Derselbe RFC definiert eine URL-sichere Variante, base64url, die + durch - und / durch _ ersetzt, damit das Ergebnis in einer URL oder einem Dateinamen stehen kann. JWTs nutzen sie, meist ohne Padding.
Nirgends in diesem Ablauf steckt ein Geheimnis. Dekodieren ist dieselbe Tabelle, rückwärts gelesen:
printf '%s' 'b3BzX2xpdmVfN2YzYTljMmU=' | base64 -d
# ops_live_7f3a9c2eAuf älteren macOS-Versionen lautet das Flag -D; --decode funktioniert sowohl mit GNU als auch mit BSD.
Tipp: Nutze beim Kodieren
printf '%s'oderecho -n. Ein einfachesechohängt einen Zeilenumbruch an, und der wird mitkodiert. Ein Base64-Wert, der aufCg==endet, bedeutet oft, dass jemand versehentlich"value\n"kodiert hat — und der überzählige Zeilenumbruch macht die Zugangsdaten unbemerkt kaputt.
Ist Base64 eine Verschlüsselung? Warum es so aussieht und warum nicht
Verschlüsselung transformiert Daten mit einem Schlüssel, sodass die Ausgabe für alle ohne diesen Schlüssel nutzlos ist. Base64 hat keinen Schlüssel. Der Algorithmus ist öffentlich, überall identisch und von jedem umkehrbar.
Es sieht nach Verschlüsselung aus, weil die Ausgabe für Menschen auf den ersten Blick unlesbar ist. YWRtaW46aHVudGVyMg== sagt nicht offensichtlich admin:hunter2, also fühlt es sich geschützt an. Ist es nicht. Die Tarnung hält einem flüchtigen Blick stand und sonst nichts, und automatische Secret-Scanner dekodieren Base64 routinemäßig.
Der Fall Kubernetes-Secret
Die häufigste Quelle dieser Verwechslung ist Kubernetes. Ein Secret-Manifest speichert seine Werte Base64-kodiert unter data:
apiVersion: v1
kind: Secret
metadata:
name: payments
type: Opaque
data:
api-key: b3BzX2xpdmVfN2YzYTljMmU=Die Kodierung existiert, damit Binärwerte wie ein Keystore oder ein Zertifikat in ein Textmanifest passen. Das Feld stringData nimmt dieselben Werte im Klartext an, und der API-Server kodiert sie für dich — was zeigt, wie wenig die Kodierung schützt.
Die Kubernetes-Dokumentation sagt das ausdrücklich: Standardmäßig werden Secrets unverschlüsselt im Datenspeicher des API-Servers, etcd, abgelegt. Verschlüsselung im Ruhezustand schaltest du separat ein, mit einer EncryptionConfiguration am API-Server oder einem KMS-Provider. Base64 gehört nicht dazu.
Wo Base64-kodierte Secrets lecken
Da die Kodierung nichts verbirgt, leckt ein kodiertes Secret über jeden Kanal, über den auch ein Klartext-Secret lecken würde. Die üblichen:
- Git-History. Ein committetes Secret-Manifest oder eine
.env-Datei bleibt in der History, auch wenn du sie an der Spitze löschst. Die Zeile in einem späteren Commit zu entfernen, entfernt den Key nicht. Rotiere ihn und erwäge dann, die History umzuschreiben. - Logs. Debug-Logging, das einen Request, eine Umgebung oder eine gerenderte Konfiguration ausgibt, schreibt den kodierten Wert gleich mit. Log-Pipelines kopieren ihn dann an Orte mit breiterem Lesezugriff.
kubectl get secret -o yaml. Wergetauf Secrets in einem Namespace hat, kann jeden Wert darin lesen, und diese Berechtigung ist oft breiter als beabsichtigt. In ein Ticket oder einen Chat kopierte Ausgabe nimmt die Keys mit.- Client-Bundles. Ein Key, der in Frontend-JavaScript oder einer Mobile-App ausgeliefert wird, ist öffentlich, kodiert oder nicht. Jeder kann die DevTools öffnen oder die App entpacken und ihn dekodieren.
- Container-Images. Ein mit
ENVeingebrannter oder beim Build hineinkopierter Key bleibt in den Image-Layern, unddocker historyoder ein Layer-Extrakt zeigt ihn.
Achtung: Wenn ein echter Key committet, geloggt oder in einem Bundle ausgeliefert wurde, heißt die Lösung Rotation. Die Datei zu löschen oder das Repo privat zu machen, verhindert künftige Offenlegung. Es sagt dir nicht, wer ihn schon gelesen hat.
Wie du einen API-Key wirklich schützt
Kein einzelner Schritt erledigt das. Schutz entsteht dadurch, dass du kontrollierst, wo ein Key liegt, wer ihn lesen kann und wie viel Schaden er anrichtet, wenn er entkommt.
Lege ihn in einem Secret Manager oder KMS ab
Nutze einen dafür gebauten Speicher: AWS Secrets Manager oder SSM Parameter Store, Google Secret Manager, Azure Key Vault oder HashiCorp Vault. Sie verschlüsseln Werte im Ruhezustand mit Schlüsseln, die du nicht direkt anfasst, protokollieren jeden Lesezugriff und stellen den Zugriff hinter IAM-Policies, die du prüfen kannst. Für Kubernetes aktivierst du die Verschlüsselung im Ruhezustand für Secrets und verschärfst RBAC, sodass nur wenige Identitäten sie per get lesen können. Werkzeuge wie External Secrets Operator oder Sealed Secrets halten Klartext aus deinen Manifesten heraus.
Injiziere ihn zur Laufzeit
Lass die Anwendung den Key beim Start lesen — aus dem Secret-Speicher oder aus einer Umgebungsvariable bzw. einer gemounteten Datei, die die Plattform befüllt. So taucht der Key nie im Quellcode, in Images oder in Build-Logs auf. Halte eine .env.example mit Platzhalternamen im Repo und die echte .env draußen. Der .env example checker meldet Abweichungen zwischen beiden.
Halte den Scope eng
Stelle Keys mit den kleinsten Berechtigungen aus, die der Job braucht: nur lesend, wo Lesen reicht, ein Key pro Service und Umgebung, IP- oder Referrer-Beschränkungen, wo der Anbieter sie unterstützt. Ein geleakter, nur lesender Staging-Key ist ärgerlich. Ein geleakter Admin-Key für Produktion ist ein Incident.
Rotiere ihn
Ablaufende Keys und geplante Rotation begrenzen, wie lange ein Leak nützlich bleibt. Mach Rotation zur Routine: Der Tag, an dem du sie brauchst, ist der Tag, an dem ein Key entkommen ist.
Verschlüssele ihn auf dem Transportweg mit TLS
Sende Keys nur über HTTPS. HTTP Basic Authentication (RFC 7617) schickt username:password als Base64 im Authorization-Header, und über reines HTTP kann jeder auf dem Weg es dekodieren. TLS schützt den Kanal. Base64 formatiert nur den Header.
Wann Base64 das richtige Werkzeug ist
Nichts davon macht Base64 schlecht. Es ist das richtige Werkzeug für seine eigentliche Aufgabe: Bytes durch einen Kanal zu transportieren, der nur Text verarbeitet.
- Binärdaten in JSON oder YAML. Keines der Formate hat einen Byte-Typ, also landen Bilder, Zertifikate und Keystores als Base64-Strings darin.
- HTTP Basic Auth. Das Header-Format verlangt es, wie oben beschrieben.
- Data-URIs. RFC 2397 erlaubt es, ein kleines Bild oder eine Schrift als
data:image/png;base64,…einzubetten. - E-Mail-Anhänge. MIME (RFC 2045) nutzt Base64, um Binärdaten über den Mailtransport zu bringen, umbrochen nach 76 Zeichen. GNU
base64bricht aus demselben Grund standardmäßig nach 76 um; mit-w 0bekommst du eine durchgehende Zeile. - Tokens und URLs. base64url transportiert binäre Bezeichner und JWT-Segmente ohne Escaping.
In jedem dieser Fälle soll der Empfänger den Wert dekodieren. Genau darum geht es.
Prüfe den String, ohne ihn irgendwohin zu senden
Wenn du einen verdächtigen String in einer Konfigurationsdatei oder einer Logzeile findest, dekodiere ihn, um zu sehen, was er ist. Aber füge keinen möglichen Produktions-Key in eine Seite ein, die ihn womöglich irgendwohin schickt.
Der Base64 Encoder / Decoder auf dieser Website läuft vollständig in deinem Browser. Er beherrscht das Standard- und das URL-sichere Alphabet sowie vollständiges UTF-8, und nichts, was du einfügst, wird hochgeladen. Wie bei jedem Werkzeug gilt: Verlass dich nicht blind darauf. Öffne die DevTools, leere den Network-Tab, füge den String ein und prüfe, dass keine Anfrage ihn enthält. Stellt sich der String als JWT heraus, zerlegt und dekodiert der JWT-Decoder alle drei Segmente.
Checkliste: Base64 und API-Keys
- Kein API-Key im Repo, kodiert oder nicht, auch nicht in der History.
- Kubernetes-Secrets im Ruhezustand verschlüsselt, und RBAC-
getauf Secrets auf die Identitäten beschränkt, die es brauchen. - Keys in einem Secret Manager oder KMS gehalten und zur Laufzeit injiziert, nie in Images oder Frontend-Bundles eingebrannt.
- Ein eng gefasster Key pro Service und Umgebung.
- Ein Rotationsverfahren, das mindestens einmal durchgespielt wurde.
- Zugangsdaten nur über TLS gesendet, Basic Auth eingeschlossen.
- Logs bereinigt um Header, Umgebungs-Dumps und gerenderte Konfigurationen.
- Base64 nur genutzt, um Bytes durch Text zu bringen, nie um sie zu verstecken.
Wie fängt dein Team kodierte Secrets ab, bevor sie gemergt werden: mit einem Pre-Commit-Scanner, einem CI-Check oder mit Reviewern, die wissen, wie b3Bz aussieht?
Ähnliche Beiträge
-
9 Min. Lesezeit
Eine jwt.io-Alternative: JWTs dekodieren, ohne sie in fremde Seiten einzufügen
Eine jwt.io-Alternative gesucht? Was ein JWT-Decoder im Browser über deine Daten beweisen kann und was nicht, wie du es selbst prüfst, plus eine Offline-Option.
-
7 Min. Lesezeit
chown-Befehl in Linux: Besitzer und Gruppe von Dateien ändern
Der chown-Befehl in Linux erklärt: user:group-Syntax, chown -R und Symlinks, --reference, chgrp, chmod vs chown und Berechtigungsfehler bei Docker-Volumes mit numerischen IDs beheben.
-
10 Min. Lesezeit
chmod-Befehl in Linux: Syntax, Beispiele und typische Fehler
Der chmod-Befehl in Linux erklärt: oktale und symbolische Modi, chmod +x, chmod -R und seine Fallen, setuid, setgid und Sticky-Bit, umask und wie du Permission denied behebst.