Datei hochladen
  1. base64hub
  2. Base64 im Code
  3. PowerShell
Code

Base64 in PowerShell

PowerShell hat kein Base64-Cmdlet; es ruft direkt die .NET-Klasse [Convert] auf. Der Haken ist die Wahl der richtigen Textkodierung. Die Ausgaben unten stammen von PowerShell 7.4 unter Linux.

Einen String kodieren und dekodieren

Wandeln Sie den String mit einer expliziten Kodierung in Bytes um und rufen Sie dann [Convert] auf:

$enc = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("héllo wörld"))
$enc                                                     # aMOpbGxvIHfDtnJsZA==

[Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($enc))   # héllo wörld

Die Kodierung bestimmt die Ausgabe. [Text.Encoding]::Unicode ist UTF-16LE, dieselben zwei Buchstaben ergeben also ein anderes Ergebnis:

[Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("hi"))      # aGk=
[Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes("hi"))   # aABpAA==

Verwenden Sie UTF-8 für alles, was an Web-APIs, Konfigurationsdateien oder andere Sprachen geht. Unicode nur für -EncodedCommand. Zeigt ein dekodierter String zwischen allen Buchstaben eine Lücke, war es UTF-16; das Tool Base64 in UTF-16 dekodiert solche Strings.

Für einen Basic-Auth-Header in einem REST-Aufruf:

$token = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("user:pass"))
$headers = @{ Authorization = "Basic $token" }
$headers.Authorization                                   # Basic dXNlcjpwYXNz
Invoke-RestMethod -Uri $url -Headers $headers

PowerShell ab 6 kann den Header auch selbst bauen, mit Invoke-RestMethod -Authentication Basic -Credential $cred, was das Passwort aus einem einfachen String heraushält.

-EncodedCommand

powershell.exe und pwsh nehmen über -EncodedCommand (Kurzformen -enc, -e) ein Skript in Base64 entgegen. Das gibt es, um Skripte mit Anführungszeichen und Sonderzeichen ohne Escape-Probleme durch cmd.exe, Scheduler und Remote-Tools zu reichen. Der Text muss UTF-16LE sein:

$cmd = 'Write-Output "hi from base64"'
$b = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($cmd))
$b
# VwByAGkAdABlAC0ATwB1AHQAcAB1AHQAIAAiAGgAaQAgAGYAcgBvAG0AIABiAGEAcwBlADYANAAiAA==

pwsh -NoProfile -EncodedCommand $b                       # hi from base64

Da auch Angreifer -enc nutzen, um Skripte vor flüchtigen Blicken zu verbergen, schlagen Sicherheitstools dabei Alarm. So lesen Sie ein solches Skript, ohne es auszuführen:

[Text.Encoding]::Unicode.GetString([Convert]::FromBase64String($b))
# Write-Output "hi from base64"

Das Tool Kodierter PowerShell-Befehl erledigt beide Richtungen im Browser und führt das Skript nie aus.

URL-sicheres Base64

[Convert] hat keinen eingebauten URL-sicheren Modus. Ersetzen Sie Zeichen und Padding selbst:

$u = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("<<???>>"))
$u.TrimEnd('=').Replace('+', '-').Replace('/', '_')      # PDw_Pz8-Pg

$s = "PDw_Pz8-Pg".Replace('-', '+').Replace('_', '/')
$s = $s.PadRight($s.Length + (4 - $s.Length % 4) % 4, '=')
[Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($s))    # <<???>>

PowerShell 7.5 läuft auf .NET 9, dort steht also auch [System.Buffers.Text.Base64Url]::EncodeToString($bytes) zur Verfügung; unter 7.4 und Windows PowerShell 5.1 bleiben Sie bei den Ersetzungen oben. Wo welche Variante verwendet wird, steht unter Base64 vs. Base64URL.

Eine Datei kodieren und dekodieren

[Convert]::ToBase64String([IO.File]::ReadAllBytes("$PWD/hello.txt"))   # aGVsbG8K

[IO.File]::WriteAllBytes("$PWD/copy.txt", [Convert]::FromBase64String("aGVsbG8K"))

Das Präfix $PWD/ ist nötig, weil .NET-Methoden relative Pfade gegen das Arbeitsverzeichnis des Prozesses auflösen und Set-Location dieses nicht ändert. Wer pwsh in /tmp startet, Set-Location /w ausführt und dann [IO.File]::ReadAllBytes("hello.txt") aufruft, bekommt eine FileNotFoundException, obwohl die Datei direkt daliegt.

Der Weg über Cmdlets liest ebenfalls Bytes, aber der Parameter hat sich zwischen den Versionen geändert:

# PowerShell 7+
[Convert]::ToBase64String((Get-Content hello.txt -AsByteStream -Raw))

# Windows PowerShell 5.1
[Convert]::ToBase64String((Get-Content hello.txt -Encoding Byte -Raw))

Ohne -Raw liefert Get-Content ein Objekt pro Byte, was bei großen Dateien sehr langsam ist.

Große Dateien

ReadAllBytes lädt die ganze Datei. Bei Hunderten von Megabytes streamen Sie sie durch den .NET-ToBase64Transform:

$in  = [IO.File]::OpenRead((Resolve-Path big.bin))
$out = [IO.File]::Create("$PWD/big.b64")
$b64 = [Security.Cryptography.CryptoStream]::new(
    $out, [Security.Cryptography.ToBase64Transform]::new(), 'Write')
$in.CopyTo($b64)
$b64.Dispose(); $in.Dispose()

Rufen Sie Dispose für den CryptoStream auf, bevor Sie die Ausgabe verwenden, sonst fehlen der letzte Block und das Padding. Unsere 300-KB-Testdatei ergab denselben String wie ToBase64String. Das Dekodieren funktioniert genauso mit FromBase64Transform im Modus 'Read'; die Seite Base64 in C# zeigt diese Variante.

Unter Windows funktionieren auch certutil -encode in.bin out.txt und certutil -decode, aber -encode umschließt die Ausgabe mit -----BEGIN CERTIFICATE------Zeilen; entfernen Sie diese, bevor Sie das Ergebnis anderswo verwenden.

MIME-Zeilenumbrüche

Übergeben Sie InsertLineBreaks, um Zeilen mit 76 Zeichen und CRLF zu erhalten:

[Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("x" * 60), 'InsertLineBreaks')
# eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4
# eHh4

Fehler und Validierung

Ungültige Eingaben lösen eine .NET-System.FormatException aus, die PowerShell in eine MethodInvocationException verpackt:

[Convert]::FromBase64String("aGk")
# Exception calling "FromBase64String" with "1" argument(s): "The input is not a
# valid Base-64 string as it contains a non-base 64 character, more than two
# padding characters, or an illegal character among the padding characters."

aGk scheitert, weil das Padding fehlt. Dieselbe Meldung erscheint bei URL-sicheren Zeichen, data:-Präfixen und mitkopierten Anführungszeichen. Eine einfache Testfunktion:

function Test-Base64([string]$s) {
    try { $null = [Convert]::FromBase64String($s); $true } catch { $false }
}
Test-Base64 "aGk="    # True
Test-Base64 "aGk"     # False

Weigert sich ein String aus einem Log oder einer E-Mail, sich dekodieren zu lassen, entfernt Base64 reparieren Anführungszeichen und Zeilenumbrüche und korrigiert das Padding. Die Anleitung zu Base64-Fehlern erklärt die Ursachen.

Versionshinweise

  • [Convert]::ToBase64String / FromBase64String: jede PowerShell-Version, einschließlich Windows PowerShell 5.1.
  • Get-Content -AsByteStream: PowerShell 6+. -Encoding Byte wurde dort entfernt.
  • Klasse Base64Url: PowerShell 7.5+ (auf Basis von .NET 9).

Häufige Fragen

Welche Kodierung erwartet -EncodedCommand?

UTF-16LE, in .NET [Text.Encoding]::Unicode genannt. Ein aus UTF-8-Bytes kodierter Befehl wird zu Zeichensalat dekodiert und scheitert mit einem Parse-Fehler.

Wie dekodiere ich einen verdächtigen -enc-Befehl gefahrlos?

Dekodieren Sie ihn, ohne ihn auszuführen: [Text.Encoding]::Unicode.GetString([Convert]::FromBase64String($b)), oder fügen Sie ihn in den Decoder für kodierte PowerShell-Befehle ein, der das Skript nur anzeigt.

Gibt es ein Base64-Cmdlet wie ConvertTo-Base64?

Nicht in PowerShell selbst. Manche Module bringen eines mit, aber [Convert]::ToBase64String und [Convert]::FromBase64String funktionieren überall, ohne etwas zu installieren.

Warum meldet [IO.File]::ReadAllBytes, die Datei sei nicht vorhanden?

.NET löst relative Pfade gegen das Arbeitsverzeichnis des Prozesses auf, und das ändert Set-Location nicht. Übergeben Sie stattdessen (Resolve-Path file.bin) oder "$PWD/file.bin".

Weiterlesen