Codificar e decodificar uma string
O Convert trabalha com bytes, então escolha uma codificação de forma explícita. Para qualquer coisa que saia do seu processo, ela quase sempre é UTF-8:
using System.Text;
string enc = Convert.ToBase64String(Encoding.UTF8.GetBytes("héllo wörld"));
Console.WriteLine(enc); // aMOpbGxvIHfDtnJsZA==
string dec = Encoding.UTF8.GetString(Convert.FromBase64String(enc));
Console.WriteLine(dec); // héllo wörld
Encoding.Unicode é UTF-16LE e dobra o tamanho de texto ASCII. Só é a escolha certa quando o outro lado espera UTF-16, por exemplo no formato de comando codificado do PowerShell.
Um uso real comum é o header HTTP Basic Auth:
string token = Convert.ToBase64String(Encoding.UTF8.GetBytes("user:pass"));
request.Headers.Authorization = new AuthenticationHeaderValue("Basic", token);
// Authorization: Basic dXNlcjpwYXNz
O gerador de header Basic Auth gera o mesmo valor no navegador.
Base64 URL-safe: Base64Url no .NET 9
O .NET 9 acrescentou o System.Buffers.Text.Base64Url. Ele codifica sem preenchimento e decodifica com ou sem ele:
using System.Buffers.Text;
byte[] d = Encoding.UTF8.GetBytes("<<???>>");
Console.WriteLine(Base64Url.EncodeToString(d)); // PDw_Pz8-Pg
byte[] a = Base64Url.DecodeFromChars("PDw_Pz8-Pg"); // <<???>>
byte[] b = Base64Url.DecodeFromChars("PDw_Pz8-Pg=="); // <<???>>
Ele rejeita o alfabeto padrão: Base64Url.DecodeFromChars("PDw/Pz8+Pg") lança FormatException. Também há sobrecargas com spans (EncodeToChars, DecodeFromUtf8, TryDecodeFromChars) que evitam alocações.
Em runtimes mais antigos sem o pacote Microsoft.Bcl.Memory, converta à mão:
string url = Convert.ToBase64String(d)
.TrimEnd('=').Replace('+', '-').Replace('/', '_'); // PDw_Pz8-Pg
Para decodificar, é preciso fazer as trocas inversas e completar com preenchimento até um múltiplo de 4:
static byte[] FromBase64Url(string s)
{
s = s.Replace('-', '+').Replace('_', '/');
s = s.PadRight(s.Length + (4 - s.Length % 4) % 4, '=');
return Convert.FromBase64String(s);
}
Encoding.UTF8.GetString(FromBase64Url("PDw_Pz8-Pg")); // <<???>>
Projetos ASP.NET Core podem usar o WebEncoders.Base64UrlEncode do Microsoft.AspNetCore.WebUtilities. Mais sobre os dois alfabetos em Base64 vs Base64URL.
Validar a entrada sem exceções
O Convert.FromBase64String lança System.FormatException para entrada inválida. No .NET 9, a mensagem é a mesma em quase todos os casos:
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.
Recebemos essa mensagem para PDw_Pz8-Pg== (URL-safe), aGk=!! (lixo), aGk (sem preenchimento), a e aGk==. Ele aceita espaços em branco (" aGk= " e "aGVs\nbG8K" decodificam normalmente) e bits de preenchimento diferentes de zero (aGl=).
Para evitar exceções em trechos críticos de desempenho, use a variante Try com um buffer, ou o Base64.IsValid (.NET 8+):
Span<byte> buf = stackalloc byte[16];
Convert.TryFromBase64String("aGk=", buf, out int n); // True, n = 2
Convert.TryFromBase64String("aGk", buf, out n); // False, n = 0
System.Buffers.Text.Base64.IsValid("aGk="); // True
System.Buffers.Text.Base64.IsValid("aGk"); // False
Base64Url.IsValid("PDw_Pz8-Pg"); // True
O buffer precisa ser grande o bastante para a saída decodificada, senão o TryFromBase64String retorna false mesmo para entrada válida. Dimensione-o como (s.Length * 3) / 4. O validador de Base64 e o guia de erros ajudam com strings que falham.
Quebras de linha (MIME)
O Base64FormattingOptions.InsertLineBreaks quebra a saída a cada 76 caracteres com \r\n, sem quebra de linha no final:
string mime = Convert.ToBase64String(
Encoding.ASCII.GetBytes(new string('x', 60)),
Base64FormattingOptions.InsertLineBreaks);
// "eHh4eHh4...eHh4" (76 chars) + "\r\n" + "eHh4"
O FromBase64String aceita a forma quebrada de volta sem alterações. O codificador Base64 MIME gera o mesmo layout.
Codificar e decodificar um arquivo
Console.WriteLine(Convert.ToBase64String(File.ReadAllBytes("hello.txt"))); // aGVsbG8K
File.WriteAllBytes("copy.txt", Convert.FromBase64String("aGVsbG8K"));
Arquivos grandes com CryptoStream
O ToBase64Transform e o FromBase64Transform se encaixam num CryptoStream, que mantém o uso de memória estável. Apesar do namespace, não há criptografia envolvida:
using System.Security.Cryptography;
using (var input = File.OpenRead("big.bin"))
using (var output = File.Create("big.b64"))
using (var b64 = new CryptoStream(output, new ToBase64Transform(), CryptoStreamMode.Write))
{
input.CopyTo(b64);
}
using (var input = new CryptoStream(File.OpenRead("big.b64"),
new FromBase64Transform(), CryptoStreamMode.Read))
using (var output = File.Create("big.out"))
{
input.CopyTo(output);
}
Descartar o CryptoStream (Dispose) grava o último bloco e o preenchimento; sem isso, a saída fica truncada. Num arquivo de teste de 300 KB, as duas direções bateram com o resultado em memória. Para uma conferência manual rápida, abra o resultado com Base64 para arquivo.
Armadilhas comuns
- Prefixos de data URI.
data:image/png;base64,contém:e;, que disparamFormatException. Remova tudo até a vírgula. - Tokens URL-safe no
Convert. Partes de JWT falham com a mensagem genérica acima. Use oBase64Urlou o decodificador de JWT. Encoding.Default. No .NET Framework é a code page ANSI; no .NET Core e posteriores é UTF-8. Código levado de um para o outro muda a saída para texto não ASCII.- Base64 não é criptografia. Connection strings “protegidas” com Base64 são texto puro para qualquer pessoa. Veja codificação vs criptografia.
Notas de versão
- .NET Framework 1.0+:
Convert.ToBase64String,FromBase64String,ToBase64Transform. - .NET Core 2.1+: sobrecargas com spans
Convert.TryFromBase64String,TryToBase64Charse a classeSystem.Buffers.Text.Base64para UTF-8. - .NET 8:
Base64.IsValid. - .NET 9:
Base64Url, também disponível para versões mais antigas peloMicrosoft.Bcl.Memory.
Perguntas frequentes
Como resolver 'The input is not a valid Base-64 string'?
Procure caracteres URL-safe (-, _), preenchimento ausente e prefixos de data URI. O Convert.FromBase64String só aceita o alfabeto padrão com o preenchimento correto. Para tokens, use Base64Url.DecodeFromChars no .NET 9, que aceita entrada com e sem preenchimento.
Dá para usar o Base64Url no .NET 8 ou no .NET Framework?
O Base64Url vem embutido no .NET 9 e posteriores. Para versões mais antigas, a Microsoft distribui o mesmo tipo no pacote Microsoft.Bcl.Memory. Sem ele, converta a saída padrão com TrimEnd('=') e duas chamadas de Replace.
Por que Encoding.Unicode está errado para Base64 de texto?
Encoding.Unicode é UTF-16LE, então hi vira aABpAA== em vez de aGk=. Use Encoding.UTF8, a menos que o destinatário espere UTF-16, como faz o -EncodedCommand do PowerShell.