Codificar e decodificar uma string
Converta a string em bytes com uma codificação explícita e depois chame o [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
A codificação decide a saída. [Text.Encoding]::Unicode é UTF-16LE, então as mesmas duas letras dão outro resultado:
[Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("hi")) # aGk=
[Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes("hi")) # aABpAA==
Use UTF-8 para tudo o que você envia para APIs web, arquivos de configuração ou outras linguagens. Use Unicode só para o -EncodedCommand. Se uma string decodificada mostra um espaço entre cada letra, ela era UTF-16; a ferramenta Base64 para UTF-16 decodifica essas strings.
Para um header Basic Auth numa chamada REST:
$token = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("user:pass"))
$headers = @{ Authorization = "Basic $token" }
$headers.Authorization # Basic dXNlcjpwYXNz
Invoke-RestMethod -Uri $url -Headers $headers
O PowerShell 6+ também consegue montar o header sozinho com Invoke-RestMethod -Authentication Basic -Credential $cred, o que mantém a senha fora de uma string simples.
-EncodedCommand
O powershell.exe e o pwsh aceitam um script em Base64 pelo -EncodedCommand (formas curtas -enc, -e). Ele existe para passar scripts com aspas e caracteres especiais pelo cmd.exe, por agendadores e por ferramentas remotas sem problemas de escape. O texto precisa ser 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
Como atacantes também usam o -enc para esconder scripts de uma olhada rápida, as ferramentas de segurança o sinalizam. Para ler um sem executá-lo:
[Text.Encoding]::Unicode.GetString([Convert]::FromBase64String($b))
# Write-Output "hi from base64"
A ferramenta comando codificado do PowerShell faz as duas direções no navegador e nunca executa o script.
Base64 URL-safe
O [Convert] não tem modo URL-safe embutido. Troque os caracteres e o preenchimento você mesmo:
$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)) # <<???>>
O PowerShell 7.5 roda sobre o .NET 9, então o [System.Buffers.Text.Base64Url]::EncodeToString($bytes) também está disponível nele; no 7.4 e no Windows PowerShell 5.1, fique com as trocas acima. Veja Base64 vs Base64URL para saber onde cada variante é usada.
Codificar e decodificar um arquivo
[Convert]::ToBase64String([IO.File]::ReadAllBytes("$PWD/hello.txt")) # aGVsbG8K
[IO.File]::WriteAllBytes("$PWD/copy.txt", [Convert]::FromBase64String("aGVsbG8K"))
O prefixo $PWD/ é necessário porque os métodos do .NET resolvem caminhos relativos a partir do diretório de trabalho do processo, e o Set-Location não o altera. Iniciar o pwsh em /tmp, rodar Set-Location /w e depois [IO.File]::ReadAllBytes("hello.txt") lança FileNotFoundException, mesmo com o arquivo bem ali.
O caminho pelos cmdlets também lê bytes, mas o parâmetro mudou entre as versões:
# PowerShell 7+
[Convert]::ToBase64String((Get-Content hello.txt -AsByteStream -Raw))
# Windows PowerShell 5.1
[Convert]::ToBase64String((Get-Content hello.txt -Encoding Byte -Raw))
Sem -Raw, o Get-Content retorna um objeto por byte, o que é muito lento para arquivos grandes.
Arquivos grandes
O ReadAllBytes carrega o arquivo inteiro. Para centenas de megabytes, passe-o em fluxo pelo ToBase64Transform do .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()
Chame o Dispose do CryptoStream antes de usar a saída, senão o último bloco e o preenchimento ficam faltando. Nosso arquivo de teste de 300 KB gerou a mesma string que o ToBase64String. A decodificação funciona do mesmo jeito com FromBase64Transform no modo 'Read'; a página Base64 em C# traz essa versão.
No Windows, certutil -encode in.bin out.txt e certutil -decode também funcionam, mas o -encode envolve a saída em linhas -----BEGIN CERTIFICATE-----, então remova-as antes de usar o resultado em outro lugar.
Quebras de linha MIME
Passe InsertLineBreaks para obter linhas de 76 caracteres com CRLF:
[Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("x" * 60), 'InsertLineBreaks')
# eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4
# eHh4
Erros e validação
Entrada inválida gera uma System.FormatException do .NET, que o PowerShell envolve numa 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 falha porque falta o preenchimento. A mesma mensagem aparece para caracteres URL-safe, prefixos data: e aspas copiadas junto com a string. Uma função de teste simples:
function Test-Base64([string]$s) {
try { $null = [Convert]::FromBase64String($s); $true } catch { $false }
}
Test-Base64 "aGk=" # True
Test-Base64 "aGk" # False
Quando uma string tirada de um log ou de um e-mail se recusa a decodificar, o Reparar Base64 remove aspas e quebras de linha e corrige o preenchimento. O guia de erros de Base64 explica as causas.
Notas de versão
[Convert]::ToBase64String/FromBase64String: todas as versões do PowerShell, inclusive o Windows PowerShell 5.1.Get-Content -AsByteStream: PowerShell 6+. O-Encoding Bytefoi removido nessa versão.- Classe
Base64Url: PowerShell 7.5+ (sobre o .NET 9).
Perguntas frequentes
Que codificação o -EncodedCommand espera?
UTF-16LE, que o .NET chama de [Text.Encoding]::Unicode. Um comando codificado a partir de bytes UTF-8 decodifica para lixo e falha com erro de parsing.
Como decodificar com segurança um comando -enc suspeito?
Decodifique sem executar: [Text.Encoding]::Unicode.GetString([Convert]::FromBase64String($b)), ou cole no decodificador de comandos codificados do PowerShell, que só exibe o script.
Existe um cmdlet de Base64, como ConvertTo-Base64?
Não no próprio PowerShell. Alguns módulos acrescentam um, mas [Convert]::ToBase64String e [Convert]::FromBase64String funcionam em qualquer lugar sem instalar nada.
Por que o [IO.File]::ReadAllBytes diz que o arquivo não existe?
O .NET resolve caminhos relativos a partir do diretório de trabalho do processo, que o Set-Location não altera. Passe (Resolve-Path file.bin) ou "$PWD/file.bin".