Elk .NET-project dat ik heb meegemaakt heeft uiteindelijk Base64 nodig om te decoderen β verbindingsstrings ophalen uit Kubernetes-secrets, binaire payloads lezen van webhooks, of JWT-tokens inspecteren tijdens een debugging-sessie. De primaire methode om Base64 te decoderen in C# is Convert.FromBase64String(), die een byte[] teruggeeft die je vervolgens doorgeeft aan Encoding.UTF8.GetString() om leesbare tekst te krijgen. Voor een snelle controle zonder code te schrijven, ToolDeck's Base64-decoder doet het direct in de browser. Deze handleiding behandelt Convert.FromBase64String(), de span-gebaseerde TryFromBase64String() voor .NET 5+, de hoge-prestatie System.Buffers.Text.Base64 API, JWT-payload-extractie, bestand- en API-responsdecoding, streaming met CryptoStream, en de vier fouten die C#-ontwikkelaars het vaakst maken.
- βConvert.FromBase64String(s) + Encoding.UTF8.GetString(bytes) is de standaard twee-staps-pipeline β werkt in alle .NET-versies.
- βConvert.TryFromBase64String() vermijdt exceptions bij ongeldige invoer en schrijft naar een Span<byte> β ideaal voor hot paths op .NET 5+.
- βSystem.Buffers.Text.Base64.DecodeFromUtf8() biedt nul-allocatie decodering voor UTF-8 byte-buffers in prestatiegevoelige services.
- βJWT-tokens gebruiken Base64url (- en _ in plaats van + en /) β je moet de invoer normaliseren voor je Convert.FromBase64String() aanroept.
- βCryptoStream met FromBase64Transform verwerkt streaming-decodering voor grote bestanden zonder alles in geheugen te laden.
Wat is Base64-decodering?
Base64-codering converteert binaire data naar een alfabet van 64 tekens zodat het teksttransport overleeft β JSON-velden, HTTP-headers, e-mailbodies, XML-attributen. Elke 3 bytes invoer worden 4 Base64-tekens, waardoor Base64-uitvoer altijd ongeveer 33% groter is dan het origineel. Decodering keert deze transformatie om. De =-padding aan het einde vertelt de decoder hoeveel bytes hij van de laatste groep moet verwijderen. Een enkele = betekent dat het laatste blok 2 bytes had; == betekent dat het 1 byte had. Base64 is geen versleuteling β iedereen kan het terugdraaien. Het doel is veilig transport via kanalen die ruwe binaire data beschadigen, niet vertrouwelijkheid.
cmVkaXM6Ly9jYWNoZS1wcm9kLmludGVybmFsOjYzNzkvc2Vzc2lvbi1zdG9yZQ==
redis://cache-prod.internal:6379/session-store
Convert.FromBase64String() β De standaard decoderingsmethode
De methode Convert.FromBase64String() is al in .NET aanwezig sinds Framework 1.1. Geen NuGet-pakketten, geen extra imports buiten System β gewoon aanroepen en een byte[] terug krijgen. De twee-staps-pipeline om Base64 naar een C#-string te decoderen is altijd hetzelfde: Convert.FromBase64String() om bytes te krijgen, dan Encoding.UTF8.GetString() om die bytes als tekst te interpreteren. Het addertje is dat de methode ruwe bytes teruggeeft, geen string. Je moet de juiste Encoding kiezen om die bytes terug naar tekst te converteren, en die keuze maakt meer verschil dan de meeste mensen verwachten. Een verkeerde codering produceert stil mojibake β onleesbare tekens zonder exception als waarschuwing.
Minimaal werkend voorbeeld
using System; using System.Text; // Verbindingsstring opgeslagen als Base64 in een Kubernetes-secret string encoded = "cmVkaXM6Ly9jYWNoZS1wcm9kLmludGVybmFsOjYzNzkvc2Vzc2lvbi1zdG9yZQ=="; byte[] decodedBytes = Convert.FromBase64String(encoded); string connectionString = Encoding.UTF8.GetString(decodedBytes); Console.WriteLine(connectionString); // redis://cache-prod.internal:6379/session-store
Gebruik altijd Encoding.UTF8 tenzij je een specifieke reden hebt om dat niet te doen. De .NET-runtime slaat strings intern op als UTF-16, maar de meeste data die systeemgrenzen oversteekt (API-responses, configuratiebestanden, secrets) is gecodeerd als UTF-8. Het gebruik van Encoding.ASCII op data met multi-byte tekens vervangt die stil door ? β geen exception, alleen beschadigde uitvoer.
Round-trip verificatie
using System; using System.Text; string original = "postgres://db-admin:Kx8!mQ@db-prod.us-east-1.internal:5432/orders"; // Encoderen string encoded = Convert.ToBase64String(Encoding.UTF8.GetBytes(original)); Console.WriteLine(encoded); // cG9zdGdyZXM6Ly9kYi1hZG1pbjpLeDghbVFAZGItcHJvZC51cy1lYXN0LTEuaW50ZXJuYWw6NTQzMi9vcmRlcnM= // Decoderen byte[] decoded = Convert.FromBase64String(encoded); string recovered = Encoding.UTF8.GetString(decoded); Console.WriteLine(recovered == original); // True
De juiste Encoding kiezen
De Encoding die je doorgeeft aan GetString() moet overeenkomen met wat gebruikt werd bij het origineel coderen van de data. Kies de verkeerde en je krijgt onleesbare tekens zonder exception β de decoder produceert vrolijk onzin. Dit is de praktische samenvatting:
Encoding.UTF8β veilige standaard. Verwerkt ASCII en alle Unicode. Gebruik dit tenzij je anders weet.Encoding.ASCIIβ alleen voor pure 7-bit ASCII-data. Multi-byte tekens worden?.Encoding.Unicodeβ dit is UTF-16LE in .NET. Sommige Windows-interne strings en PowerShell-exports gebruiken dit.Encoding.Latin1β verouderde West-Europese codering. Komt voor in oude SOAP-services en mainframe-integraties.
using System;
using System.Text;
// Dezelfde bytes, verschillende coderingen β verschillende resultaten
byte[] decoded = Convert.FromBase64String("w7bDvMOk");
Console.WriteLine(Encoding.UTF8.GetString(decoded)); // oua (correct)
Console.WriteLine(Encoding.ASCII.GetString(decoded)); // ?????? (verloren)
Console.WriteLine(Encoding.Latin1.GetString(decoded)); // ΓΒΆΓΒΌΓΒ€ (mojibake)Een herbruikbare decode-helper met foutafhandeling
Omdat Convert.FromBase64String() gooit bij slechte invoer en de witruimte-stripping steeds terugkomt, houd ik een kleine helper bij in de meeste projecten:
using System;
using System.Text;
static class Base64Helper
{
public static string? DecodeToString(string encoded)
{
if (string.IsNullOrWhiteSpace(encoded))
return null;
// Witruimte verwijderen die .NET's decoder afwijst
string cleaned = encoded
.Replace("
", "")
.Replace("
", "")
.Replace(" ", "")
.Trim();
try
{
byte[] bytes = Convert.FromBase64String(cleaned);
return Encoding.UTF8.GetString(bytes);
}
catch (FormatException)
{
return null; // of gooi een domein-specifieke exception
}
}
}
// Gebruik
string? decoded = Base64Helper.DecodeToString(" cmVkaXM6Ly9jYWNoZQ== \n");
Console.WriteLine(decoded); // redis://cacheConvert.FromBase64String() gooit een FormatException als de invoer tekens bevat buiten het Base64-alfabet β inclusief spaties, regeleinden, en URL-veilige tekens zoals - en _. De bovenstaande helper verwerkt witruimte automatisch.Base64 decoderen naar niet-standaard types
De decoder geeft je altijd een byte[]. Wat je met die bytes doet hangt af van de originele data. Soms is het een GUID opgeslagen als 16 ruwe bytes, soms een geserialiseerd protobuf-bericht, soms een tijdstempel in binair formaat. Dit zijn de conversies die ik het vaakst gebruik.
Base64 naar GUID
using System; // Sommige API's sturen GUIDs als 22-teken Base64 in plaats van 36-teken hex-strings string compactGuid = "C0HqetxMckKlZw4CssPUeQ=="; byte[] guidBytes = Convert.FromBase64String(compactGuid); Guid recovered = new Guid(guidBytes); Console.WriteLine(recovered); // 7aea41c0-4cdc-4272-a567-0e02b2c3d479
Base64 naar gedeserialiseerde JSON met System.Text.Json
using System;
using System.Text;
using System.Text.Json;
// Base64-gecodeerde JSON-payload van een berichtenwachtrij
string encoded = "eyJzZXJ2aWNlIjoicGF5bWVudC1nYXRld2F5IiwicmVnaW9uIjoiZXUtd2VzdC0xIiwicmVwbGljYXMiOjR9";
byte[] jsonBytes = Convert.FromBase64String(encoded);
string json = Encoding.UTF8.GetString(jsonBytes);
Console.WriteLine(json);
// {"service":"payment-gateway","region":"eu-west-1","replicas":4}
// Deserialiseren naar een record
var deployEvent = JsonSerializer.Deserialize<DeployEvent>(jsonBytes);
Console.WriteLine($"{deployEvent!.Service} in {deployEvent.Region}");
// payment-gateway in eu-west-1
record DeployEvent(string Service, string Region, int Replicas);Base64 naar hex-string
using System; // SHA-256-hash opgeslagen als Base64 string hashBase64 = "n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg="; byte[] hashBytes = Convert.FromBase64String(hashBase64); string hex = Convert.ToHexString(hashBytes); Console.WriteLine(hex); // 9F86D081884C7D659A2FEAA0C55AD015A3BF4F1B2B0B822CD15D6C15B0F00A08
BinaryFormatter. Het heeft bekende kwetsbaarheden voor remote code execution en is verouderd in .NET 8+. Als de gecodeerde inhoud van een externe bron komt, parseer het dan als JSON of protobuf in plaats van .NET-binaire serialisatie te gebruiken.Referentie: Base64-decoderingsmethoden
.NET biedt meerdere decoderingsmethoden verspreid over twee namespaces. De Convert klasse verwerkt algemene decodering, terwijl System.Buffers.Text.Base64 gericht is op hoge-doorvoer-scenario's waar je al werkt met ruwe UTF-8 byte-buffers.
Convert.TryFromBase64String() β Decoderen zonder exceptions
Het Try-patroon is standaard in .NET voor bewerkingen die kunnen mislukken bij gebruikersinvoer. Convert.TryFromBase64String(), beschikbaar sinds .NET 5, geeft een bool terug in plaats van een FormatException te gooien. Het schrijft de gedecodeerde bytes naar een caller-gealloceerde Span<byte>, wat betekent dat je stack-gealloceerd geheugen kunt gebruiken voor kleine payloads en de heap volledig kunt omzeilen.
using System;
using System.Text;
string userInput = "eyJob3N0IjoiMTAuMC4xLjUwIiwicG9ydCI6ODQ0M30=";
// Stack-alloceren voor kleine payloads (< 1KB is een goede vuistregel)
Span<byte> buffer = stackalloc byte[256];
if (Convert.TryFromBase64String(userInput, buffer, out int bytesWritten))
{
string result = Encoding.UTF8.GetString(buffer[..bytesWritten]);
Console.WriteLine(result);
// {"host":"10.0.1.50","port":8443}
}
else
{
Console.WriteLine("Ongeldige Base64-invoer β overgeslagen");
}Deze aanpak blinkt uit in request-middleware of validatiepipelines waar slechte invoer verwacht wordt, niet uitzonderlijk is. Het gooien en vangen van een FormatException bij elk misvormd verzoek voegt merkbare overhead toe op schaal β TryFromBase64String() vermijdt dat volledig.
Base64-invoer valideren zonder te decoderen
Een veelvoorkomend patroon in API-controllers: controleren of de invoer geldige Base64 is voor je hem doorgeeft. Je kunt TryFromBase64String() als validator gebruiken door een weggooi-buffer te alloceren:
using System;
static bool IsValidBase64(string input)
{
// Bereken maximale gedecodeerde grootte
Span<byte> buffer = stackalloc byte[((input.Length + 3) / 4) * 3];
return Convert.TryFromBase64String(input, buffer, out _);
}
// Gebruik in een API-controller
Console.WriteLine(IsValidBase64("eyJob3N0IjoiMTAuMC4xLjUwIn0=")); // True
Console.WriteLine(IsValidBase64("not!!valid!!base64")); // False
Console.WriteLine(IsValidBase64("")); // True (leeg is geldig)TryFromBase64String() geeft false terug zelfs als de invoer geldig is. Bereken de vereiste grootte als (inputLength / 4) * 3 om veilig te zijn.Base64 decoderen van een bestand en API-response
Een Base64-gecodeerd bestand van schijf lezen
Certificaten, versleutelde blobs en data-exportbestanden worden soms geleverd als Base64-tekst. Het typische patroon: het bestand als string lezen, witruimte of regeleinden verwijderen die een FormatException zouden veroorzaken, decoderen naar bytes, en de binaire uitvoer schrijven. Let op de foutafhandeling β bestand-I/O-fouten en Base64-formaatfouten moeten apart worden opgevangen.
using System;
using System.IO;
string inputPath = "tls-cert.pem.b64";
string outputPath = "tls-cert.pem";
try
{
string encoded = File.ReadAllText(inputPath).Trim();
// Regeleinden verwijderen β .NET's decoder weigert ze
encoded = encoded.Replace("
", "").Replace("
", "");
byte[] decoded = Convert.FromBase64String(encoded);
File.WriteAllBytes(outputPath, decoded);
Console.WriteLine($"Gedecodeerd {decoded.Length} bytes -> {outputPath}");
}
catch (IOException ex)
{
Console.Error.WriteLine($"Bestandsfout: {ex.Message}");
}
catch (FormatException ex)
{
Console.Error.WriteLine($"Ongeldige Base64: {ex.Message}");
}Een Base64-veld decoderen uit een HTTP API-response
Cloud-API's (Azure Key Vault, AWS Secrets Manager, GitHub Contents API) sturen binaire data vaak terug als Base64-strings ingebed in JSON. De workflow is altijd hetzelfde: het HTTP-verzoek doen, de JSON-response parsen, het Base64-veld extraheren en decoderen. Het onderstaande voorbeeld gebruikt HttpClient en System.Text.Json β beiden ingebouwd in .NET 6+.
using System;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer sk-prod-9f8e7d6c");
try
{
var response = await client.GetAsync("https://api.example.com/secrets/db-password");
response.EnsureSuccessStatusCode();
string body = await response.Content.ReadAsStringAsync();
// API geeft terug: {"name":"db-password","value":"cG9zdGdyZXM6eGs5bVAycVI=","version":3}
using var doc = JsonDocument.Parse(body);
string encodedValue = doc.RootElement.GetProperty("value").GetString()!;
byte[] decoded = Convert.FromBase64String(encodedValue);
string secret = Encoding.UTF8.GetString(decoded);
Console.WriteLine($"Secret: {secret}");
// Secret: postgres:xk9mP2qR
}
catch (HttpRequestException ex)
{
Console.Error.WriteLine($"HTTP-fout: {ex.Message}");
}
catch (FormatException ex)
{
Console.Error.WriteLine($"Base64-decodering mislukt: {ex.Message}");
}catch-blokken voor netwerkfouten en FormatException. Ze samenvoegen maakt het moeilijk te bepalen of de API slechte data heeft teruggestuurd of het verzoek zelf is mislukt. Log in productie de ruwe Base64-waarde (of op zijn minst de lengte en eerste 20 tekens) wanneer je een FormatException opvangt β dat maakt debuggen aanzienlijk makkelijker.Base64-decodering via de opdrachtregel
Je hebt niet altijd een gecompileerd project nodig. De dotnet-script-tool en PowerShell verwerken Base64-decodering met one-liners. Voor snelle inspectie tijdens het debuggen zijn deze sneller dan het aanmaken van een console-app.
# PowerShell (ingebouwd in Windows, beschikbaar op Linux/macOS)
[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String("eyJob3N0IjoiMTAuMC4xLjUwIn0="))
# {"host":"10.0.1.50"}
# Linux / macOS native base64-commando
echo "eyJob3N0IjoiMTAuMC4xLjUwIn0=" | base64 --decode
# {"host":"10.0.1.50"}
# macOS gebruikt -D in plaats van --decode
echo "eyJob3N0IjoiMTAuMC4xLjUwIn0=" | base64 -D
# dotnet-script (installeer: dotnet tool install -g dotnet-script)
echo 'Console.WriteLine(System.Text.Encoding.UTF8.GetString(Convert.FromBase64String("eyJob3N0IjoiMTAuMC4xLjUwIn0=")));' | dotnet-script eval
# Decoderen en JSON mooi afdrukken met jq
echo "eyJob3N0IjoiMTAuMC4xLjUwIiwicG9ydCI6ODQ0M30=" | base64 --decode | jq .Voor het plakken van gecodeerde strings direct in een browser, ToolDeck's Base64-decoder verwerkt zowel standaard als URL-veilige varianten zonder enige installatie.
Hoge-prestatie alternatief: System.Buffers.Text.Base64
De klasse System.Buffers.Text.Base64, beschikbaar sinds .NET Core 2.1, werkt op ruwe UTF-8 byte-spans in plaats van .NET-strings. Dit omzeilt de overhead van string-naar-byte-conversie volledig β geen tussenliggende string-allocatie, geen UTF-16-coderingsstap. Ik gebruik het in ASP.NET Core-middleware waar de inkomende data al een ReadOnlySpan<byte> is uit de request body. Een string aanmaken om door te geven aan Convert.FromBase64String() verdubbelt de allocaties zonder reden. In BenchmarkDotNet-tests op .NET 8 is het span-gebaseerde pad ruwweg 2-3x sneller voor payloads kleiner dan 1 KB en het verschil groeit met grotere invoer doordat de GC-druk constant blijft.
using System;
using System.Buffers.Text;
using System.Text;
// Simuleer ruwe UTF-8 bytes van een HTTP-request body
byte[] utf8Input = Encoding.UTF8.GetBytes("eyJob3N0IjoiMTAuMC4xLjUwIiwicG9ydCI6ODQ0M30=");
byte[] output = new byte[Base64.GetMaxDecodedFromUtf8Length(utf8Input.Length)];
OperationStatus status = Base64.DecodeFromUtf8(
utf8Input, output, out int bytesConsumed, out int bytesWritten);
if (status == OperationStatus.Done)
{
string result = Encoding.UTF8.GetString(output.AsSpan(0, bytesWritten));
Console.WriteLine(result);
// {"host":"10.0.1.50","port":8443}
Console.WriteLine($"Verbruikt: {bytesConsumed}, Geschreven: {bytesWritten}");
// Consumed: 44, Written: 31
}
else
{
Console.WriteLine($"Decodering mislukt: {status}");
// Mogelijk: InvalidData, DestinationTooSmall, NeedMoreData
}Het retourtype is OperationStatus β een enum met vier waarden: Done, InvalidData, DestinationTooSmall, en NeedMoreData. De laatste is nuttig voor gedeeltelijk decoderen van streamingdata. Voor absolute nul-allocatie, combineer dit met ArrayPool<byte>.Shared.Rent() in plaats van new byte[].
DecodeFromUtf8InPlace β de invoerbuffer overschrijven
using System;
using System.Buffers.Text;
using System.Text;
// De invoerbuffer wordt overschreven met gedecodeerde bytes
byte[] data = Encoding.UTF8.GetBytes("c2VydmVyLWNvbmZpZw==");
OperationStatus status = Base64.DecodeFromUtf8InPlace(data, out int bytesWritten);
if (status == OperationStatus.Done)
{
Console.WriteLine(Encoding.UTF8.GetString(data.AsSpan(0, bytesWritten)));
// server-config
}DecodeFromUtf8InPlace wijzigt de invoerbuffer. Gebruik het niet als je de originele Base64-string daarna nog nodig hebt β de eerste bytesWritten bytes van de array bevatten nu de gedecodeerde data, de rest is rommel.Iets om rekening mee te houden: System.Buffers.Text.Base64 verwerkt URL-veilige Base64 niet direct. Als de invoer - en _ tekens gebruikt (JWT-tokens, bijvoorbeeld), moet je ze nog steeds vervangen door + en /voor je deze methoden aanroept. De span-gebaseerde API's werken strikt met het RFC 4648-standaardalfabet. Er is geen DecodeFromUtf8Url-variant β een verrassende leemte gezien hoe gangbaar Base64url is in moderne API's.
Terminaluitvoer met syntaxismarkering
De bibliotheek Spectre.Console biedt rijke terminaluitvoer inclusief JSON-markering β handig bij het bouwen van CLI-tools die Base64 decoderen en het resultaat weergeven. Installeer het met dotnet add package Spectre.Console.
using System;
using System.Text;
using Spectre.Console;
using Spectre.Console.Json;
string encoded = "eyJob3N0IjoiMTAuMC4xLjUwIiwicG9ydCI6ODQ0MywibWF4Q29ubiI6MTAwfQ==";
byte[] decoded = Convert.FromBase64String(encoded);
string json = Encoding.UTF8.GetString(decoded);
// Mooi afdrukken met syntaxismarkering in de terminal
AnsiConsole.Write(new JsonText(json));
// Geeft gekleurd JSON weer:
// {
// "host": "10.0.1.50",
// "port": 8443,
// "maxConn": 100
// }Dit is bijzonder handig voor CLI-tools die configuratie ophalen en decoderen van externe services. Decodeer de Base64-config, deserialiseer naar JSON, en druk de gemarkeerde uitvoer af β allemaal in een paar regels. Spectre.Console heeft ook tabelweergave, voortgangsbalken en boomstructuren als je complexere gedecodeerde datastructuren in de terminal wilt weergeven.
Grote Base64-bestanden streamen met CryptoStream
Een 500 MB Base64-bestand laden met File.ReadAllText() en daarnaConvert.FromBase64String() aanroepen alloceert ruwweg 700 MB heap: de string zelf (UTF-16, dus dubbel de bestandsgrootte) plus de gedecodeerde byte-array. De combinatie CryptoStream + FromBase64Transform decodeert in stukken, waardoor het geheugengebruik constant blijft.
using System.IO;
using System.Security.Cryptography;
string inputPath = "database-export.sql.b64";
string outputPath = "database-export.sql";
using var inputStream = new FileStream(inputPath, FileMode.Open, FileAccess.Read);
using var transform = new FromBase64Transform(FromBase64TransformMode.IgnoreWhiteSpaces);
using var base64Stream = new CryptoStream(inputStream, transform, CryptoStreamMode.Read);
using var outputStream = new FileStream(outputPath, FileMode.Create, FileAccess.Write);
base64Stream.CopyTo(outputStream);
Console.WriteLine($"Gedecodeerd {new FileInfo(outputPath).Length} bytes -> {outputPath}");De vlag FromBase64TransformMode.IgnoreWhiteSpaces verwerkt regelomgebroken Base64 (PEM-bestanden, e-mailexports) zonder handmatig opschonen. Zonder deze vlag veroorzaken regeleinden in de invoer een FormatException. Dit is .NET's dichtstbijzijnde equivalent van Java's getMimeDecoder() β het slaat witruimtetekens tijdens het decoderen stil over.
De naam CryptoStream is misleidend β er is niets cryptografisch aan Base64. Microsoft plaatste FromBase64Transform in de System.Security.Cryptography-namespace omdat het ICryptoTransform implementeert, dezelfde interface die gebruikt wordt voor AES en andere cipher-transforms. De stream zelf stuurt data gewoon in stukken door elke transform. Zie het als een algemene streaming-transformatiepipeline die toevallig in de verkeerde namespace zit.
Async streaming voor ASP.NET Core-scenario's
using System.IO;
using System.Security.Cryptography;
async Task DecodeStreamAsync(Stream inputStream, string outputPath)
{
using var transform = new FromBase64Transform(FromBase64TransformMode.IgnoreWhiteSpaces);
using var base64Stream = new CryptoStream(inputStream, transform, CryptoStreamMode.Read);
await using var outputStream = new FileStream(
outputPath, FileMode.Create, FileAccess.Write, FileShare.None,
bufferSize: 81920, useAsync: true);
await base64Stream.CopyToAsync(outputStream);
}
// Gebruik in een endpoint:
// await DecodeStreamAsync(Request.Body, "uploaded-file.bin");CopyToAsync in plaats van CopyTo in ASP.NET Core-handlers. Synchrone I/O op de request-thread wordt standaard geblokkeerd door Kestrel en gooit een InvalidOperationException.Een Base64 JWT-token-payload decoderen in C#
Een JWT heeft drie Base64url-gecodeerde segmenten gescheiden door punten. Het middelste segment is de payload. Je kunt het decoderen zonder een JWT-bibliotheek te importeren β splits op ., normaliseer de Base64url-tekens, herstel de padding, en roep Convert.FromBase64String() aan. Dit gaat bijna iedereen de eerste keer mis omdat JWT - en _ gebruikt in plaats van + en /, en de =-padding weglaat.
using System;
using System.Text;
static string DecodeJwtPayload(string token)
{
string[] parts = token.Split('.');
if (parts.Length != 3)
throw new ArgumentException($"Ongeldige JWT: verwacht 3 segmenten, kreeg {parts.Length}");
// Neem de payload (tweede segment)
string payload = parts[1];
// URL-veilige tekens vervangen door standaard Base64
payload = payload.Replace('-', '+').Replace('_', '/');
// Aanvullen tot veelvoud van 4
switch (payload.Length % 4)
{
case 2: payload += "=="; break;
case 3: payload += "="; break;
}
byte[] bytes = Convert.FromBase64String(payload);
return Encoding.UTF8.GetString(bytes);
}
// Testen met een token in echte vorm
string token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9"
+ ".eyJzdWIiOiJ1c3ItNjcyIiwiaXNzIjoiYXV0aC5leGFtcGxlLmNvbSIsImV4cCI6MTc0MTk1NjgwMCwicm9sZXMiOlsiYWRtaW4iLCJiaWxsaW5nIl19"
+ ".SIGNATURE_PLACEHOLDER";
Console.WriteLine(DecodeJwtPayload(token));
// {"sub":"usr-672","iss":"auth.example.com","exp":1741956800,"roles":["admin","billing"]}Korte opmerking: dit leest alleen de payload. Het verifieert niet de handtekening. Voor productie-authenticatievalidatie gebruik je een goede bibliotheek zoals Microsoft.IdentityModel.JsonWebTokens. Maar voor debuggen, loggen en testassertaties is deze handmatige aanpak alles wat je nodig hebt.
De gedecodeerde JWT-payload parsen naar een getypeerd object
Zodra je de JSON-string hebt, deserialiseer je hem met System.Text.Json om individuele claims te benaderen zonder stringmanipulatie:
using System;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
record JwtPayload(
[property: JsonPropertyName("sub")] string Subject,
[property: JsonPropertyName("iss")] string Issuer,
[property: JsonPropertyName("exp")] long Expiration,
[property: JsonPropertyName("roles")] string[] Roles
);
// Na DecodeJwtPayload() van hierboven
string json = DecodeJwtPayload(token);
var claims = JsonSerializer.Deserialize<JwtPayload>(json)!;
Console.WriteLine($"Gebruiker: {claims.Subject}");
Console.WriteLine($"Uitgever: {claims.Issuer}");
Console.WriteLine($"Vervalt: {DateTimeOffset.FromUnixTimeSeconds(claims.Expiration):u}");
Console.WriteLine($"Rollen: {string.Join(", ", claims.Roles)}");
// Gebruiker: usr-672
// Uitgever: auth.example.com
// Vervalt: 2025-03-14 12:00:00Z
// Rollen: admin, billingVeelgemaakte fouten
Ik heb elk van deze fouten zelf gemaakt in productie-C#-services. De eerste twee zijn verantwoordelijk voor de meerderheid van Base64-gerelateerde bugs die ik zie in code reviews. Elke fout lijkt voor de hand liggend in isolatie, maar ze zijn makkelijk te missen als je diep in een grotere feature zit en Base64-decodering slechts één stap in de pipeline is.
Probleem: Base64-strings gelezen uit configuratiebestanden, omgevingsvariabelen of gebruikersinvoer hebben vaak afsluitende regeleinden. Convert.FromBase64String() weigert elk teken buiten het Base64-alfabet, inclusief \r\n.
Oplossing: Roep .Trim() of .Replace() aan om witruimte te verwijderen voor het decoderen.
// Omgevingsvariabele heeft een afsluitend regeleinde
string encoded = Environment.GetEnvironmentVariable("DB_PASS_B64")!;
byte[] decoded = Convert.FromBase64String(encoded);
// FormatException: The input is not a valid Base-64 stringstring encoded = Environment.GetEnvironmentVariable("DB_PASS_B64")!;
string cleaned = encoded.Replace("\n", "").Replace("\r", "").Trim();
byte[] decoded = Convert.FromBase64String(cleaned);
Console.WriteLine(Encoding.UTF8.GetString(decoded));Probleem: JWT-tokens en sommige API-payloads gebruiken - en _ (URL-veilig alfabet). De standaarddecoder accepteert alleen + en / β hij gooit FormatException bij het eerste - teken.
Oplossing: Vervang - door + en _ door / voor het decoderen. Herstel ook de padding.
// JWT-payload β gebruikt URL-veilige Base64 string payload = "eyJzdWIiOiJ1c3ItNjcyIn0"; byte[] decoded = Convert.FromBase64String(payload); // FormatException
string payload = "eyJzdWIiOiJ1c3ItNjcyIn0";
payload = payload.Replace('-', '+').Replace('_', '/');
switch (payload.Length % 4)
{
case 2: payload += "=="; break;
case 3: payload += "="; break;
}
byte[] decoded = Convert.FromBase64String(payload);
Console.WriteLine(Encoding.UTF8.GetString(decoded));
// {"sub":"usr-672"}Probleem: Encoding.UTF8.GetString() aanroepen op gedecodeerde afbeelding- of protobuf-bytes produceert onzin. Erger nog, die string terugconverteren naar bytes beschadigt de data stil omdat ongeldige UTF-8-reeksen worden vervangen.
Oplossing: Houd binaire data als byte[] door je volledige pipeline. Roep GetString() alleen aan als je weet dat de inhoud tekst is.
byte[] decoded = Convert.FromBase64String(pngBase64);
string imageStr = Encoding.UTF8.GetString(decoded); // beschadigt binaire data
File.WriteAllText("image.png", imageStr); // kapot bestandbyte[] decoded = Convert.FromBase64String(pngBase64);
// Bytes direct schrijven β geen stringconversie
File.WriteAllBytes("image.png", decoded);Probleem: Sommige oudere .NET Framework API's gebruiken standaard de huidige ANSI-codepagina van het systeem, die verschilt tussen machines. Een Windows-server met codepagina 1252 en een Linux-container met UTF-8 produceren verschillende strings van dezelfde bytes.
Oplossing: Geef Encoding.UTF8 altijd expliciet op. Vertrouw nooit op de platformstandaard.
byte[] decoded = Convert.FromBase64String(encoded); // Encoding.Default varieert per platform string result = Encoding.Default.GetString(decoded);
byte[] decoded = Convert.FromBase64String(encoded); string result = Encoding.UTF8.GetString(decoded); // consistent op Windows, Linux, macOS
Methodevergelijking
.NET biedt meer Base64-decoderingsmethoden dan de meeste ontwikkelaars beseffen. De tabel hieronder behandelt elke ingebouwde optie plus de twee meest voorkomende externe alternatieven. De kolom "Allocatie" is het belangrijkst in hoge-doorvoer-services β een methode die bij elke aanroep een nieuwe byte[] alloceert legt druk op de GC in nauwe lussen.
Voor dagelijks gebruik: Convert.FromBase64String(). Voor hot paths waar je gebruikersinvoer valideert: TryFromBase64String(). Voor ASP.NET Core-middleware die op ruwe request-bytes werkt: Base64.DecodeFromUtf8(). Voor grote bestanden: CryptoStream + FromBase64Transform. BouncyCastle is alleen zinvol als het al in je dependency-tree zit voor andere cryptografische bewerkingen.
Voor snelle verificatie zonder iets te compileren, is de online Base64-decoder sneller dan het schrijven van een weggooi-console-app.
Veelgestelde vragen
Hoe decodeer ik een Base64-string naar tekst in C#?
Roep Convert.FromBase64String() aan om een byte-array te krijgen, geef die dan door aan Encoding.UTF8.GetString(). De codering moet overeenkomen met wat gebruikt werd tijdens het encoderen β UTF-8 is de veilige standaard voor vrijwel alle moderne systemen. Als de invoer witruimte of regeleinden kan bevatten, roep dan .Trim() aan of verwijder ze voor het decoderen.
using System; using System.Text; string encoded = "cG9zdGdyZXM6eGs5bVAycVI="; byte[] bytes = Convert.FromBase64String(encoded); string result = Encoding.UTF8.GetString(bytes); Console.WriteLine(result); // postgres:xk9mP2qR
Wat is het verschil tussen Convert.FromBase64String() en Convert.TryFromBase64String()?
FromBase64String() gooit een FormatException bij ongeldige invoer. TryFromBase64String() geeft een bool terug en schrijft het resultaat naar een caller-gealloceerde Span<byte>, waardoor het geschikt is voor hot paths waar je exception-overhead wilt vermijden. TryFromBase64String() vereist .NET 5 of hoger.
using System;
string input = "maybe-not-valid-base64!!";
Span<byte> buffer = stackalloc byte[256];
if (Convert.TryFromBase64String(input, buffer, out int written))
Console.WriteLine($"Gedecodeerd {written} bytes");
else
Console.WriteLine("Ongeldige Base64-invoer");Hoe decodeer ik een Base64url JWT-payload in C#?
Splits het token op punten, neem het tweede segment, vervang - door + en _ door /, vul aan tot een veelvoud van 4 met =, en roep dan Convert.FromBase64String() aan. JWT-tokens gebruiken het URL-veilige Base64-alfabet, dat de standaard .NET-decoder niet direct ondersteunt.
string token = "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ1c3ItNjcyIn0.SIG";
string payload = token.Split('.')[1];
payload = payload.Replace('-', '+').Replace('_', '/');
switch (payload.Length % 4)
{
case 2: payload += "=="; break;
case 3: payload += "="; break;
}
byte[] bytes = Convert.FromBase64String(payload);
Console.WriteLine(Encoding.UTF8.GetString(bytes));
// {"sub":"usr-672"}Hoe kies ik de juiste Encoding bij het decoderen van Base64 in C#?
Gebruik Encoding.UTF8 als standaard β het verwerkt ASCII en multi-byte Unicode-tekens. Gebruik Encoding.ASCII alleen als je zeker weet dat de data pure 7-bit ASCII is. Gebruik Encoding.Unicode (dat is UTF-16LE in .NET) alleen als de originele data als UTF-16 was gecodeerd, wat soms voorkomt bij Windows-interne strings en PowerShell-exports.
Waarom gooit Convert.FromBase64String() een FormatException?
Drie veelvoorkomende oorzaken: de invoer bevat witruimte of regeleinden (verwijder die voor het decoderen), de invoer gebruikt URL-veilige tekens zoals - en _ (vervang ze door + en / respectievelijk), of de padding ontbreekt of is onjuist (de totale lengte moet een veelvoud van 4 zijn na padding). Anders dan Java heeft .NET geen ingebouwde MIME-decoder die witruimte tolereert β je moet de invoer zelf opschonen of CryptoStream gebruiken met FromBase64Transform en IgnoreWhiteSpaces-modus.
// Witruimte opschonen
string cleaned = rawInput.Replace("\n", "").Replace("\r", "").Trim();
byte[] decoded = Convert.FromBase64String(cleaned);Kan ik grote Base64-gegevens stream-decoderen in C#?
Ja. Gebruik een CryptoStream met FromBase64Transform uit System.Security.Cryptography. Dit decodeert in stukken terwijl je leest, zodat het geheugengebruik constant blijft ongeacht de bestandsgrootte. Geef FromBase64TransformMode.IgnoreWhiteSpaces door als de invoer regeleinden bevat. Op .NET 6+ kun je ook het IAsyncEnumerable-patroon gebruiken met Base64.DecodeFromUtf8() voor handmatige chunk-verwerking, maar CryptoStream is eenvoudiger voor bestand-naar-bestand decodering.
using System.IO;
using System.Security.Cryptography;
using var input = File.OpenRead("payload.b64");
using var transform = new FromBase64Transform();
using var cryptoStream = new CryptoStream(input, transform, CryptoStreamMode.Read);
using var output = File.Create("payload.bin");
cryptoStream.CopyTo(output);Gerelateerde tools
- Base64 Encoder β tekst of binaire data naar Base64 encoderen in de browser, handig voor het genereren van testfixtures om in je C#-unit tests te plakken.
- JWT Decoder β alle drie JWT-segmenten tegelijk decoderen en inspecteren, met veld-voor-veld payload-inspectie β sneller dan een C#-helper schrijven als je gewoon een token wilt lezen.
- URL Decoder β percent-gecodeerde URL-strings decoderen, handig wanneer API-responses Base64url-data mixen met percent-gecodeerde queryparameters.
- JSON Formatter β na het decoderen van een Base64 JWT-payload of API-config, plak de JSON hier om de structuur mooi af te drukken en te valideren.