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 Bytewurde 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".