Charger un fichier
  1. base64hub
  2. Base64 dans le code
  3. PowerShell
Code

Base64 en PowerShell

PowerShell n’a pas de cmdlet Base64 : il appelle directement la classe [Convert] de .NET. Toute la difficulté est de choisir le bon encodage de texte. Les sorties ci-dessous proviennent de PowerShell 7.4 sous Linux.

Encoder et décoder une chaîne

Convertissez la chaîne en octets avec un encodage explicite, puis appelez [Convert] :

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

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

C’est l’encodage qui détermine la sortie. [Text.Encoding]::Unicode correspond à UTF-16LE : les deux mêmes lettres donnent un autre résultat.

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

Utilisez UTF-8 pour tout ce que vous envoyez à des API web, des fichiers de configuration ou d’autres langages. Réservez Unicode à -EncodedCommand. Si une chaîne décodée montre un blanc entre chaque lettre, c’était de l’UTF-16 ; l’outil Base64 en UTF-16 décode ce genre de chaîne.

Pour un en-tête Basic Auth dans un appel REST :

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

PowerShell 6+ sait aussi construire l’en-tête lui-même avec Invoke-RestMethod -Authentication Basic -Credential $cred, ce qui évite de garder le mot de passe dans une chaîne en clair.

-EncodedCommand

powershell.exe et pwsh acceptent un script en Base64 via -EncodedCommand (formes courtes -enc, -e). L’option existe pour faire passer des scripts contenant des guillemets et des caractères spéciaux à travers cmd.exe, les planificateurs et les outils distants sans problèmes d’échappement. Le texte doit être en UTF-16LE :

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

pwsh -NoProfile -EncodedCommand $b                       # hi from base64

Comme les attaquants utilisent aussi -enc pour soustraire leurs scripts à un examen rapide, les outils de sécurité le signalent. Pour en lire un sans l’exécuter :

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

L’outil commande encodée PowerShell fonctionne dans les deux sens dans le navigateur et n’exécute jamais le script.

Base64 URL-safe

[Convert] n’a pas de mode URL-safe intégré. Remplacez vous-même les caractères et le remplissage :

$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 repose sur .NET 9 : [System.Buffers.Text.Base64Url]::EncodeToString($bytes) y est donc aussi disponible ; avec la 7.4 et Windows PowerShell 5.1, restez sur les remplacements ci-dessus. Voir Base64 ou Base64URL pour savoir où chaque variante est utilisée.

Encoder et décoder un fichier

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

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

Le préfixe $PWD/ est nécessaire, car les méthodes .NET résolvent les chemins relatifs par rapport au répertoire de travail du processus, que Set-Location ne modifie pas. Si vous lancez pwsh dans /tmp, exécutez Set-Location /w puis [IO.File]::ReadAllBytes("hello.txt"), vous obtenez une FileNotFoundException alors que le fichier est bien là.

La voie des cmdlets lit aussi des octets, mais le paramètre a changé selon les versions :

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

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

Sans -Raw, Get-Content renvoie un objet par octet, ce qui est très lent pour les gros fichiers.

Gros fichiers

ReadAllBytes charge le fichier entier. Pour des centaines de mégaoctets, passez le flux par le ToBase64Transform de .NET :

$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()

Libérez le CryptoStream avant d’utiliser la sortie, sinon le dernier bloc et le remplissage manquent. Notre fichier de test de 300 Ko a produit la même chaîne que ToBase64String. Le décodage fonctionne de la même façon avec FromBase64Transform en mode 'Read' ; la page Base64 en C# donne cette version.

Sous Windows, certutil -encode in.bin out.txt et certutil -decode fonctionnent aussi, mais -encode entoure la sortie de lignes -----BEGIN CERTIFICATE----- : supprimez-les avant de l’utiliser ailleurs.

Sauts de ligne MIME

Passez InsertLineBreaks pour obtenir des lignes de 76 caractères avec CRLF :

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

Erreurs et validation

Une entrée invalide déclenche une System.FormatException .NET, que PowerShell enveloppe dans une MethodInvocationException :

[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 échoue parce que le remplissage manque. Le même message apparaît pour les caractères URL-safe, les préfixes data: et les guillemets copiés avec la chaîne. Une fonction de test simple :

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

Quand une chaîne issue d’un log ou d’un e-mail refuse de se décoder, Réparer Base64 supprime les guillemets et les sauts de ligne et corrige le remplissage. Le guide des erreurs Base64 en explique les causes.

Notes de version

  • [Convert]::ToBase64String / FromBase64String : toutes les versions de PowerShell, y compris Windows PowerShell 5.1.
  • Get-Content -AsByteStream : PowerShell 6+. -Encoding Byte y a été supprimé.
  • Classe Base64Url : PowerShell 7.5+ (basé sur .NET 9).

FAQ

Quel encodage attend -EncodedCommand ?

UTF-16LE, que .NET appelle [Text.Encoding]::Unicode. Une commande encodée à partir d’octets UTF-8 se décode en charabia et échoue avec une erreur d’analyse.

Comment décoder sans risque une commande -enc suspecte ?

Décodez-la sans l’exécuter : [Text.Encoding]::Unicode.GetString([Convert]::FromBase64String($b)), ou collez-la dans le décodeur de commandes encodées PowerShell, qui se contente d’afficher le script.

Existe-t-il une cmdlet Base64 comme ConvertTo-Base64 ?

Pas dans PowerShell lui-même. Certains modules en ajoutent une, mais [Convert]::ToBase64String et [Convert]::FromBase64String fonctionnent partout sans rien installer.

Pourquoi [IO.File]::ReadAllBytes dit-il que le fichier est introuvable ?

.NET résout les chemins relatifs par rapport au répertoire de travail du processus, que Set-Location ne modifie pas. Passez plutôt (Resolve-Path file.bin) ou "$PWD/file.bin".

Continuer la lecture