Layer 8Ehrlicher Tech-Support

Base64 ist keine Verschlüsselung – und ein Hash keine Rückfahrkarte

Der Eintrag sieht kryptisch aus und ist nur Base64: in einer Sekunde zurückgerechnet. Kodieren, Hashen und Verschlüsseln sind drei verschiedene Dinge.

Aufwand:
ca. 20 Min.
Voraussetzung:
Python 3, Eine Kommandozeile, Gesundes Misstrauen gegenüber kryptisch aussehenden Zeichenketten
Gilt für:
Konfigurationsdateien, HTTP-Header, Datenbankfelder, Alles, was nach Buchstabensalat aussieht

Das Symptom

In einer Konfigurationsdatei, einem Cookie oder einem Datenbankfeld steht etwas, das eindeutig nach Geheimnis aussieht:

Z2VoZWltMTIz

Der Kollege sagt beruhigt, das sei ja verschlüsselt. Oder umgekehrt: Ein Nutzer hat sein Passwort vergessen, und jemand fragt allen Ernstes, ob man den Hash in der Datenbank nicht einfach entschlüsseln könne.

Die „Layer 8“-Wahrheit

Beide Sätze beschreiben dasselbe Missverständnis aus entgegengesetzter Richtung: Kodieren, Hashen und Verschlüsseln werden für dasselbe gehalten, weil das Ergebnis in allen drei Fällen gleich unleserlich aussieht. Unleserlich ist aber keine Eigenschaft, sondern ein Eindruck. Base64 ist eine Verpackung: Der Standard, der es festlegt, sagt selbst, dass diese Kodierung Informationen wie Passwörter nur optisch versteckt und keinerlei rechnerische Vertraulichkeit bietet. Sie wurde erfunden, damit beliebige Bytes durch Kanäle passen, die nur US-ASCII vertragen – E-Mail-Anhänge, HTTP-Kopfzeilen, eingebettete Bilder. Ein Schlüssel kommt in dem Verfahren nirgends vor, und was ohne Schlüssel auskommt, kann jeder rückgängig machen. Eine Zeile in der Kommandozeile genügt.

Die andere Hälfte des Missverständnisses ist genauso hartnäckig. Ein Hash ist keine Verschlüsselung mit verlorenem Schlüssel, sondern eine Einbahnstraße: Er bildet jede Eingabe auf einen Wert fester Länge ab, und es gibt nichts, was man zurückrechnen könnte. Deshalb kann kein seriöser Dienst dein altes Passwort zurückschicken, sondern nur ein neues setzen lassen – wenn doch eines im Postfach landet, ist das kein Service, sondern ein Befund. Was Angreifer tun, ist raten und vergleichen, und genau dagegen zielen die Vorgaben: salzen, damit fertige Tabellen nichts nützen, und absichtlich langsam ableiten, damit jeder Ratevorgang etwas kostet. Der Computer hat in allen drei Fällen recht. Nur das Wort, das man ihm untergeschoben hat, war falsch.

Die echte, verifizierte Lösung

1000 % faktenbasiert. Jeder Befehl ist real, jeder Pfad existiert. Schritt für Schritt:

  1. 1.

    Base64 erkennen

    Base64 besteht laut RFC 4648 aus einem 65 Zeichen großen Ausschnitt von US-ASCII: den Buchstaben A bis Z und a bis z, den Ziffern 0 bis 9, dazu Plus und Schrägstrich – und dem Gleichheitszeichen als 65. Zeichen mit Sonderaufgabe. Je 24 Bit Eingabe werden zu vier Zeichen Ausgabe. Wer also eine Zeichenkette ohne Umlaute, ohne Sonderzeichen und mit einem oder zwei Gleichheitszeichen am Ende sieht, hat mit hoher Wahrscheinlichkeit keine Chiffre vor sich, sondern eine Verpackung.

  2. 2.

    Den Beweis antreten: in einer Zeile zurückrechnen

    Statt zu diskutieren, rechnet man es vor. Es braucht keinen Schlüssel, kein Passwort und keine Software, die nicht ohnehin auf jedem System liegt. Wenn das in einer Sekunde geht, war es nie geschützt.

    printf '%s' 'geheim123' | base64
    # Z2VoZWltMTIz
    echo 'Z2VoZWltMTIz' | base64 -d
    # geheim123
    
  3. 3.

    Aufhören, Base64 als Schutzmaßnahme zu verkaufen

    Ein base64-kodiertes Passwort in einer Konfigurationsdatei, in einem Cookie oder in einem Datenbankfeld ist ein Klartextpasswort mit Sonnenbrille. Es hilft nur gegen versehentliches Mitlesen über die Schulter – und laut RFC 4648 nicht einmal zuverlässig dagegen, weil Leute genau deshalb ihre Zugangsdaten in Fehlerberichte kopieren. Wer Vertraulichkeit braucht, braucht Verschlüsselung mit einem Schlüssel, der nicht danebenliegt.

  4. 4.

    Passwörter salzen und mit einer langsamen Einwegfunktion hashen

    Für gespeicherte Passwörter gilt die Vorgabe der NIST-Richtlinie SP 800-63B: gesalzen und mit einer geeigneten Einweg-Schlüsselableitungsfunktion gehasht. Die Zahl der Durchläufe soll so hoch sein, wie der Server es verkraftet; eine speicherharte Funktion ist zu bevorzugen, weil sie einen Angriff teurer macht. Ein nacktes SHA-256 ohne Salz und ohne Iterationen erfüllt das nicht.

    python3 -c "import hashlib, os; salt = os.urandom(16); dk = hashlib.pbkdf2_hmac('sha256', b'geheim123', salt, 600000); print(salt.hex(), dk.hex())"
    
  5. 5.

    Verstehen, warum der Hash nicht zurückgeht

    Ein Hash hat immer dieselbe Länge, egal wie lang die Eingabe war – bei SHA-256 sind es 64 Hexadezimalzeichen. Schon eine um eins geänderte Ziffer erzeugt ein völlig anderes Ergebnis. Aus dieser festen Länge lässt sich die Eingabe nicht rekonstruieren; es gibt schlicht nichts zurückzurechnen. Wer im Werkzeug einen Knopf `Hash entschlüsseln` sucht, sucht etwas, das es nicht gibt.

    python3 -c "import hashlib; a = hashlib.sha256(b'geheim123').hexdigest(); b = hashlib.sha256(b'geheim124').hexdigest(); print(a, len(a)); print(b)"
    
  6. 6.

    Die drei Begriffe auseinanderhalten und sie auch so nennen

    Kodieren macht Daten transportierbar und ist ohne Geheimnis umkehrbar – das ist Base64. Hashen macht Daten wiedererkennbar und ist gar nicht umkehrbar – das ist SHA-256 oder eine Schlüsselableitung. Verschlüsseln macht Daten vertraulich und ist genau mit dem passenden Schlüssel umkehrbar. Die meisten Sicherheitsdiskussionen im Büro lösen sich auf, sobald jemand diese drei Wörter nicht mehr durcheinanderwirft.

  7. 7.

    Geheimnisse dorthin legen, wo sie hingehören

    Wo etwas wirklich geheim bleiben muss, hilft kein Kodierungstrick, sondern nur, dass das Geheimnis gar nicht erst an der falschen Stelle liegt: nicht im Quelltext, nicht im Versionsverwaltungssystem, nicht in einer Konfigurationsdatei, die mit ausgeliefert wird. Und falls es dort doch schon liegt, gilt es als offengelegt und muss ersetzt werden – Löschen allein reicht nicht, denn die Historie vergisst nichts.

Häufige Fragen (FAQ)

?Das sieht doch aber verschlüsselt aus. Ist es das wirklich nicht?

Nein, und der zuständige Standard sagt es ungewöhnlich unverblümt. RFC 4648, der Base16, Base32 und Base64 festlegt, schreibt in den Sicherheitsbetrachtungen: Base-Kodierung versteckt sonst leicht erkennbare Informationen wie Passwörter zwar optisch, liefert aber keinerlei rechnerische Vertraulichkeit. Der Standard nennt sogar genau den Vorfall, um den es hier geht: Jemand schildert einen Protokollmitschnitt, um ein ganz anderes Problem zu zeigen, und gibt dabei versehentlich das Passwort preis, weil ihm nicht klar ist, dass die Kodierung es nicht schützt. Zum Zurückrechnen braucht es keinen Schlüssel, nur den Willen.

?Kann man einen Hash entschlüsseln?

Nein, weil dabei nichts verschlüsselt wurde. Verschlüsselung ist umkehrbar, sie hat einen Schlüssel und ein Gegenstück zum Zurückrechnen. Ein Hash ist eine Einbahnstraße: Er bildet eine Eingabe beliebiger Länge auf einen Wert fester Länge ab, und aus diesem Wert lässt sich die Eingabe nicht zurückgewinnen. Was Passwort-Knacker tatsächlich tun, ist deshalb kein Entschlüsseln, sondern Raten: Sie hashen Milliarden Kandidaten und vergleichen die Ergebnisse. Genau dagegen richtet sich die Vorgabe der US-Normungsbehörde NIST, gespeicherte Passwörter zu salzen und mit einer geeigneten Einweg-Schlüsselableitungsfunktion zu hashen – das Salz macht vorberechnete Tabellen wertlos, die absichtlich langsame Ableitung macht das Raten teuer.

?Wozu ist Base64 dann überhaupt da?

Für Transport, nicht für Geheimhaltung. RFC 4648 nennt den Zweck im ersten Satz: Base-Kodierung wird benutzt, um Daten in Umgebungen zu speichern oder zu übertragen, die – oft aus historischen Gründen – auf US-ASCII beschränkt sind. Deshalb steckt Base64 in E-Mail-Anhängen, in HTTP-Kopfzeilen und in eingebetteten Bildern: Es macht beliebige Bytes durch einen 65 Zeichen umfassenden Ausschnitt von US-ASCII darstellbar, wobei je 24 Bit Eingabe zu vier Zeichen Ausgabe werden. Das ist eine Verpackung, kein Tresor – und eine Verpackung, die den Inhalt um rund ein Drittel größer macht.

Belege

Diese Seite ist gegen die folgenden Primärquellen geprüft – Hersteller, Standard oder Gesetzestext. Wer es nicht glaubt, muss es nicht: Da steht, wo es nachzulesen ist.

Zuletzt geprüft am . Dokumentation altert – ein Datum daneben ist der einzige ehrliche Umgang damit.

Auch zu finden unter

Verwandte Fehler

SWLästigpassword authentication failed for user

PostgreSQL: password authentication failed for user

PostgreSQL meldet „password authentication failed“? Falsches Passwort, falscher Nutzer oder pg_hba.conf erlaubt die Methode nicht. So kommst du rein.

SWAnfängerfehlerrunning scripts is disabled on this system

PowerShell blockiert die Ausführung von Skripten

Ein Skript startet nicht, weil die Ausführung deaktiviert sei? Das ist kein Defekt, sondern eine Schutzeinstellung — mit bewusst gewähltem Ausweg.