Base64-Kodierung in Visual Basic: Ein vollständiger Leitfaden
Hier ist ein Problem, dem Visual-Basic-Entwickler seit fünfundzwanzig Jahren begegnen: Sie haben ein JPEG, einen binären Blob, eine Lizenzdatei oder einen ganz gewöhnlichen Satz, und der Kanal vor Ihnen akzeptiert nur Text. Ein JSON-Feld, eine Umgebungsvariable, ein E-Mail-Anhang, eine URL, eine Config-Datei, eine Datenbank-Spalte, die als Text typisiert ist, und alle anderen Türen im Gebäude haben eine Regel gemeinsam: Nur druckbare Zeichen. Base64 ist der Türsteher, der Binäres hineinlässt. Es schreibt Ihre Bytes als Strom aus Buchstaben, Ziffern, Plus, Schrägstrich und Gleichheitszeichen um, so dass alles, was als Text reist, sie tragen kann. Und die gute Nachricht: Jedes Teil des Kodierers, das Sie je brauchen könnten, ist bereits in der .NET-Runtime. Keine Pakete, keine Komponenten, keine Zeremonie.
In einem Atemzug, denn die Startseite dieser Site geht tief in das Format selbst ein: Base64 nimmt drei Eingabe-Bytes und schreibt sie als vier Zeichen aus einem Alphabet mit 64 Symbolen, und fügt ein oder zwei =-Zeichen an das Ende an, wenn die Byte-Anzahl sich nicht sauber teilen lässt. Dieser Vier-für-Drei-Tausch ist der Grund, warum kodierte Daten rund ein Drittel größer als das Original sind, die berühmte Größen-Steuer, die Sie einmal pro Kodierung zahlen. Alles Weitere in diesem Artikel beschäftigt sich damit, die Kodierung, die Sie produzieren, genau das tun zu lassen, was das nächste System erwartet: das richtige Alphabet, das richtige Padding, die richtigen Zeilenumbrüche und den richtigen Zeichensatz.
Die Kodierer-Werkzeugkiste: Alles ist an Bord
Die Kodier-Seite der Runtime wuchs über dieselben vier Wellen wie die Dekodier-Seite, also hat die Werkzeugkiste einen langen Schweif noch unterstützter Optionen. Hier ist die ganze Familie und der Job, für den jede einzelne gebaut wurde:
| API | Verfügbar seit | Wofür es gut ist |
|---|---|---|
System.Convert.ToBase64String |
.NET Framework 1.1 (2003) | Der Klassiker. Ein Array hinein, ein String hinaus, mit Overloads für Array-Ausschnitte, Spans und optionalen MIME-artigen Zeilenumbrüchen. |
System.Convert.ToBase64CharArray |
.NET Framework 1.1 (2003) | Schreibt die kodierten Zeichen in einen Zeichenpuffer, den Sie bereits alloziert haben, und gibt zurück, wie viele Zeichen er benutzt hat. |
System.Convert.TryToBase64Chars |
.NET Core 2.1 (2018) | Span-basierte, allozierungsarme Kodierung in einen Zeichen-Span, den Sie bereitstellen, mit einer Booleschen Antwort statt einer Exception. |
System.Buffers.Text.Base64 |
.NET Core 2.1 (2018) | Niedrigstufige, span-basierte Kodierung: Schreiben Sie in Ihren eigenen UTF-8-Puffer, dehnen Sie In-Place aus und bemessen Sie Puffer mit GetMaxEncodedToUtf8Length. |
System.Buffers.Text.Base64Url |
.NET 9 (2024) | Das URL-sichere Alphabet (- und _ statt + und /) ohne Padding. Auf älteren Runtimes reitet es auf dem Microsoft.Bcl.Memory-NuGet-Paket mit. |
ToBase64Transform + CryptoStream |
.NET Framework 1.1 (2003) | Streaming-Kodierung: Lesen Sie eine Datei in Chunks, schreiben Sie kodierten Text heraus und halten Sie den Speicher bei riesigen Eingaben flach. |
Zum Versions-Bild: .NET 10 ist das aktuelle Long-Term-Support-Release (November 2025, unterstützt bis November 2028), .NET 8 und .NET 9 sind bis November 2026 unterstützt, und .NET 11 ist in der Vorschau, mit einer frischen Ladung Base64-Bequemlichkeitsmethoden auf dem Weg. Alles in der Tabelle oben ist über all diese hinweg stabil. Das einzige Versions-Tor ist Base64Url: ab .NET 9 an Bord, auf .NET Framework 4.6.2 und neuer verfügbar über das Microsoft.Bcl.Memory-Paket, und das ist das einzige Paket, das dieser Artikel Sie je zu installieren bittet. Um ein Scratch-Projekt loszulegen, liefert das .NET-SDK Visual Basic im Karton:
dotnet new console -lang VB -o Packer
cd Packer
dotnet run
Ihr erstes Encoding: Bytes rein, Text raus
Neunzig Prozent des Kodier-Alltags in Visual Basic sind zwei Aufrufe, und die Reihenfolge zählt: Der Kodierer nimmt Bytes, nicht Text, also wählen Sie, wenn Sie mit einem String anfangen, zuerst eine Kodierung, die ihn in Bytes verwandelt, und erst dann kommt der Base64-Schritt. Hier ist der ganze Tanz:
Imports System
Imports System.Text
Module Encoder
Sub Main()
Dim text As String = "Man"
Dim bytes() As Byte = Encoding.UTF8.GetBytes(text)
Dim packed As String = System.Convert.ToBase64String(bytes)
Console.WriteLine(packed)
' TWFu
End Sub
End Module
Dieser dreizeilige Mittelteil ist das gesamte Handwerk, und der String "TWFu" ist der perfekte Smoke-Test für jeden Kodierer, den Sie schreiben. Die Overloads geben Ihnen Kontrolle, wenn Sie sie brauchen. Die Ausschnitt-Formen kodieren ein Stück eines Arrays, ohne es zuerst herauszukopieren, was praktisch ist, wenn der eigentliche Payload in einem größeren Puffer sitzt:
Imports System
Module SlicePacker
Sub Main()
Dim data() As Byte = {1, 2, 3, 4, 5, 6, 7, 8}
Dim packed As String = System.Convert.ToBase64String(data, 2, 4)
Console.WriteLine(packed)
' AwQFBg== (nur die Bytes 3 bis 6 wurden kodiert)
End Sub
End Module
Und die Array-zu-Zeichen-Form, ToBase64CharArray, schreibt in einen Zeichenpuffer, den Sie allozieren, und sagt Ihnen, wie viele Zeichen er füllte, was das richtige Werkzeug ist, wenn das Ziel Teil einer größeren Textstruktur ist, die Sie von Hand bauen. Beachten Sie die Haus-Regel der Visual-Basic-Syntax: Ein Byte-Array wird Byte() geschrieben, mit den leeren Klammern. Lassen Sie sie weg, und Sie haben ein einzelnes Byte, und Option Strict On (in den Vorlagen standardmäßig aus - in jedem Projekt zu empfehlen) fängt die Verwechslung zur Compile-Zeit.
Die Ausgabe formen: Padding, Zeilenumbrüche und exakte Größen
Dieselben Bytes zweimal zu kodieren kann zu Recht zwei verschiedene Strings produzieren, und die Unterschiede kommen alle auf die Formung der Ausgabe an. Erstens Padding: Wenn die Eingabe-Länge kein Vielfaches von drei ist, füllt der Kodierer die letzte Gruppe mit ein oder zwei =-Zeichen auf. Der RFC sagt, sie einzubeziehen, es sei denn, die Spezifikation, die Sie folgen, sagt das Gegenteil, und ToBase64String enthält sie standardmäßig. Zweitens Zeilenumbrüche: Der zweite Parameter der Formatierungs-Overloads, Base64FormattingOptions.InsertLineBreaks, lässt den Kodierer 76-Zeichen-Zeilen ausgeben, getrennt durch CRLF, was genau die MIME-Regel ist. MIME selbst benutzt eine Zeilenbeschränkung von 76 Zeichen, ein enger Verwandter der alten 64-Zeichen-Zeilen von PEM, und beide Limits gehen auf Beschränkungen innerhalb von SMTP zurück. Wenn Ihr Konsument eine E-Mail-Pipeline ist, schalten Sie Zeilenumbrüche ein; wenn es eine URL, ein JSON-Feld oder eine Datenbank-Spalte ist, lassen Sie sie aus, denn ein unsichtbares CRLF in Ihren Daten wird einen Weg finden, Sie später zu überraschen:
Imports System
Module MimePacker
Sub Main()
Dim data(113) As Byte
For i As Integer = 0 To 113
data(i) = CByte(i)
Next
Dim wrapped As String = System.Convert.ToBase64String(data, Base64FormattingOptions.InsertLineBreaks)
Console.WriteLine(wrapped.Length)
' 154: zwei 76-Zeichen-Zeilen plus ein CRLF dazwischen
End Sub
End Module
Drittens exakte Größen, denn Sie werden Puffer und Spaltenbreiten vorallozieren wollen. Die Regel lautet vier Zeichen für jede drei Eingabe-Bytes, aufgerundet: 1000 Bytes werden zu 1336 Zeichen. Anstatt die Arithmetik per Hand zu machen, hat die Runtime einen Helfer, der die maximale kodierte Länge für eine gegebene Eingabe-Größe zurückgibt, und das ist es, was Sie an die Puffer-Allozierung geben:
Imports System.Buffers.Text
Module Sizing
Sub Main()
Dim dataLength As Integer = 1000
Dim textNeeded As Integer = Base64.GetMaxEncodedToUtf8Length(dataLength)
Console.WriteLine(textNeeded)
' 1336
End Sub
End Module
Dieses selbe Vier-zu-Drei-Verhältnis ist die Größen-Steuer in ihrer reinsten Form: Jeder kodierte Wert ist ungefähr 33 Prozent größer als die Bytes, die er trägt, also planen Sie Ihre Speicher- und Übertragungsgrößen mit diesem Puffer im Sinn. Und ein Verhalten, das es wert ist, es zu kennen, bevor es Sie beißt: Wenn Sie einen String dekodieren und dann das Ergebnis neu kodieren, ist der neue String nicht garantiert identisch mit dem Original, weil Weißraum verschwindet und Padding normalisiert wird. Vergleichen Sie dekodierte Bytes, wenn Sie Werte vergleichen müssen, nicht den kodierten Text.
Den Zeichensatz wählen, bevor Sie kodieren
Weil der erste Schritt des Text-Kodierens "String zu Bytes" ist, entscheidet der Zeichensatz, den Sie wählen, was der Empfänger sieht, wenn er dekodiert. Visual-Basic-Strings sind innerhalb der Runtime UTF-16, aber die Bytes, die Sie aussenden, sollten dazu passen, was die andere Seite zu lesen erwartet, und das Menü an Möglichkeiten ist kurz:
Encoding.UTF8: Die richtige Vorgabe für Web, APIs und alles Moderne. Es macht einen kompletten Hin-und-Rück-Weg mit jedem Unicode-Zeichen, das die Sprache tragen kann.Encoding.Unicode: UTF-16 Little-Endian. Eine vernünftige Wahl, wenn beide Enden der Leitung .NET-Programme sind, die ausdrücklich UTF-16 vereinbart haben, und nichts weiter.Encoding.ASCII: Nur 7 Bit, und es ersetzt still und leise alles andere durch ein Fragezeichen. "Café" als ASCII zu kodieren gibt Ihnen die Bytes für "Caf?", und genau das, Fragezeichen inklusive, wird zurückdekodiert.Encoding.Default: Auf .NET Framework war das die ANSI-Zeichenseite der Maschine, auf .NET (Core) aber immer UTF-8, egal welche Locale. Meiden Sie es auch hier für austauschbare Daten - benennen Sie die Kodierung ausdrücklich, meist UTF-8.
Imports System
Imports System.Text
Module CharsetPacker
Sub Main()
Dim text As String = "Café"
Dim utf8() As Byte = Encoding.UTF8.GetBytes(text)
Dim ascii() As Byte = Encoding.ASCII.GetBytes(text)
Console.WriteLine(System.Convert.ToBase64String(utf8))
' Q2Fmw6k=
Console.WriteLine(System.Convert.ToBase64String(ascii))
' Q2FmPw== (der Akzent wurde zu einem Fragezeichen)
End Sub
End Module
Zwei verschiedene Base64-Strings, ein Wort, und nur eines von beiden übersteht die Reise. Die praktische Regel: Es sei denn, das Protokoll, dem Sie folgen, nennt ein anderes Schema, kodieren Sie Text als UTF-8 und sagen Sie es.
Base64Url: Das Alphabet, das URLs überlebt
Das Standard-Alphabet enthält + und /, und beide Zeichen haben eigene Jobs innerhalb von URLs, also bricht Base64, das auf diesem Alphabet gebaut ist, in dem Moment, in dem es in einen Query-String oder einen Pfad-Abschnitt landet. Die Lösung, standardisiert in Abschnitt 5 von RFC 4648, tauscht die beiden Übeltäter gegen - und _ aus, die URL-sicher sind, und lässt typischerweise das nachträgliche Padding weg, weil die Datenlänge dem Dekodierer bereits sagt, wo die Daten enden. Diese Variante, bekannt als base64url, ist das Alphabet von JWTs, API-Tokens und einer wachsenden Zahl von APIs. .NET 9 fügte eine eigene Klasse hinzu, und sie ist mit einer Meinung gebaut, die es wert ist, sie zu kennen: Sie lässt Padding aus Design-Entscheidung weg:
Imports System.Buffers.Text
Module UrlSafePacker
Sub Main()
Dim data() As Byte = {219, 255, 0, 63, 16}
Dim packed As String = Base64Url.EncodeToString(data)
Console.WriteLine(packed)
' 2_8APxA (Unterstrich, kein Padding am Ende)
End Sub
End Module
Das Beispiel oben ist ein gutes: Die gewählten Bytes bringen eines der Sonderzeichen zum Vorschein - den Unterstrich, wo das Standard-Alphabet einen Schrägstrich hat - so können Sie den Tausch geschehen sehen. Wenn Sie auf einer älteren Runtime sind, ist dasselbe Alphabet zwei Zeichen-Ersetzungen plus ein Trimmen, und Sie bekommen ein drop-in-kompatibles Ergebnis:
Imports System
Module CompatPacker
Function ToUrlSafe(ByVal packed As String) As String
Return packed.Replace("+"c, "-"c).Replace("/"c, "_"c).TrimEnd("="c)
End Function
End Module
Auf .NET Framework 4.6.2 oder neuer gibt Ihnen das Microsoft.Bcl.Memory-Paket stattdessen die echte Base64Url-Klasse. Entweder wie auch immer, achten Sie auf die Padding-Grenze im Sand: Die Base64Url-Ausgabe von .NET hat kein Padding, während einige Bibliotheken in anderen Ökosystemen es hinzufügen (und ein paar strenge Dekodierer darauf bestehen). JWT verlangt zum Beispiel die ungepaddete Form, also ist die .NET-Vorgabe dort genau richtig. Wenn Sie eine Ökosystem-Grenze überschreiten, prüfen Sie die Erwartung der anderen Seite, bevor Sie den String verschiffen.
Dateien packen
Dateien sind der ursprüngliche Anwendungsfall: Wandeln Sie eine Binärdatei in eine Textdatei um, die E-Mail, FTP und Konfigurationssysteme alle fröhlich tragen. In Visual Basic sind die ganze Aufgabe drei Aufrufe, einer liest und einer schreibt:
Imports System.IO
Module FilePacker
Sub Main()
Dim bytes() As Byte = File.ReadAllBytes("photo.png")
Dim packed As String = System.Convert.ToBase64String(bytes)
File.WriteAllText("photo.b64", packed)
End Sub
End Module
Halten Sie das Größen-Verhältnis in der Tasche: Ein 10-Megabyte-Foto wird zu einer Textdatei von etwa 13,4 Megabytes. Der Vorgang ist auf moderner Hardware schnell (mehr dazu unten), also ist die Kosten fast immer Speicher und Bandbreite, nicht CPU, was die übliche Rechnung für eine 33-Prozent-Steuer ist. Wenn die Datei nur neben dem Text leben wird, der sie referenziert, ist dieses Muster vollkommen in Ordnung; wenn die Datei groß und langlebig ist, fragen Sie, ob der Kanal die Textform überhaupt braucht.
Bilder: Data-URIs von Hand bauen
Das Data-URI-Schema (RFC 2397) bettet Datei-Inhalte direkt in eine URL ein: data:, der Medientyp, der wörtliche Marker ;base64, ein Komma und die kodierten Bytes. Browser benutzen sie, um kleine Bilder und Schriften inline zu setzen. WPF kann einen Data-URI nicht direkt konsumieren - BitmapImage hat keinen Handler für das data:-Schema - also ist der idiomatische Zug, das Präfix abzuschneiden und die Bytes an einen MemoryStream zu geben. Das Bauen des URI in Visual Basic ist eine String-Konkatenation, und das Konsumieren ist ein kleiner Init-Block:
Imports System.IO
Imports System.Windows.Media.Imaging
Module DataUriPacker
Sub Main()
Dim bytes() As Byte = File.ReadAllBytes("logo.png")
Dim dataUri As String = "data:image/png;base64," & System.Convert.ToBase64String(bytes)
Dim image As New BitmapImage()
image.BeginInit()
image.StreamSource = New MemoryStream(System.Convert.FromBase64String(dataUri.Substring(dataUri.IndexOf(","c) + 1)))
image.EndInit()
' image kann jetzt einer Image-Steuerung zugewiesen werden
End Sub
End Module
Der RFC selbst warnt, dass Data-URIs nur für kurze Werte nützlich sind, und HTML-Dokumente verhängen ihre eigenen Längen-Limits für Attribute, also ist der sinnvolle Bereich Icons, Avatare, Thumbnails und winzige Hintergrundmuster. Der Medientyp muss zu den Bytes passen, die Sie tatsächlich kodiert haben, weil nichts downstream ihn aus dem Inhalt neu ableiten wird.
HTTP: Auth-Header und JSON-Payloads
Auf dem Draht sind die zwei Orte, an denen Sie von Hand kodieren, der HTTP-Basic-Auth-Header und JSON-Felder, die Binärdaten oder vor-kodierte Daten tragen. Basic-Auth ist das sichtbarste: Der Header ist das Wort Basic, ein Leerzeichen und das Base64 von username:password, verbunden mit einem Doppelpunkt. Das Bauen ist ein Kodier-Aufruf:
Imports System
Imports System.Text
Module AuthPacker
Function MakeBasicHeader(ByVal user As String, ByVal password As String) As String
Dim raw() As Byte = Encoding.UTF8.GetBytes(user & ":" & password)
Return "Basic " & System.Convert.ToBase64String(raw)
End Function
End Module
Der JSON-Fall ist ebenso Routine. Wenn eine API ein Bild oder ein Zertifikat in einem Request-Body will, kodieren Sie die Bytes und legen Sie den String in den Payload, und System.Text.Json (im Karton seit .NET Core 3.0) erledigt die Serialisierung drumherum:
Imports System.Text.Json
Module ApiPacker
Function WidgetPayload(ByVal name As String, ByVal imageBytes() As Byte) As String
Dim payload = New With {
.name = name,
.image = System.Convert.ToBase64String(imageBytes)
}
Return JsonSerializer.Serialize(payload)
End Function
End Module
Zwei Haus-Regeln: Senden Sie Zugangsdaten nur über HTTPS, denn über nacktes HTTP ist das Base64 ein Kostüm, kein Schloss, und loggen Sie nie den rohen Auth-Header oder die Zugangsdaten, zu denen er dekodiert.
E-Mail-Anhänge und MIME-Umwicklung
E-Mail ist der Ort, an dem Base64 seinen Lebensunterhalt verdient hat. SMTP wurde für 7-Bit-ASCII gebaut, also muss ein binärer Anhang zu Text werden, bevor er fliegen kann, und der MIME-Standard (RFC 2045) traf die Wahl: Base64, umgewickelt auf 76 Zeichen pro Zeile, deklariert mit einem Content-Transfer-Encoding: base64-Header. Wenn Sie mit den System.Net.Mail-Klassen arbeiten, ist das ganze Ritual zwei Zeilen Setup, denn die Mail-Bibliothek erledigt das Umwickeln für Sie zum Senden:
Imports System.IO
Imports System.Net.Mail
Imports System.Net.Mime
Module MailPacker
Sub Main()
Using message As New MailMessage("me@example.com", "you@example.com")
message.Subject = "Quarterly report"
message.Body = "Please find the report attached."
Using stream As New FileStream("report.bin", FileMode.Open, FileAccess.Read)
Dim attachment As New Attachment(stream, "report.bin")
attachment.TransferEncoding = TransferEncoding.Base64
message.Attachments.Add(attachment)
End Using
End Using
End Sub
End Module
Sie müssen die umwickelte Form nur selbst produzieren, mit Base64FormattingOptions.InsertLineBreaks, wenn Sie rohen MIME-Text von Hand schreiben: eine Mailer-Testfixture, ein Legacy-Gateway oder ein Werkzeug, das .eml-Dateien ausspuckt. Die 76-Zeichen-Regel ist keine Stil-Vorliebe; einige Empfangssysteme kürzen längere Zeilen, und deshalb hat sich das Limit im Standard seit Jahrzehnten gehalten.
Kodierte Werte speichern: Datenbanken, Config-Dateien und Env-Vars
Nur-Text-Speicher fragt ständig nach Base64: eine Datenbank-Spalte, die als Text typisiert ist, ein XML-Konfigurationswert, eine Umgebungsvariable. Sie kodieren die Bytes, speichern den String und dekodieren ihn auf dem Weg hinaus. Die Kodier-Seite ist immer derselbe Einzeiler, aber die Speicher-Seite hat Limits, die die Größen-Steuer greifbar machen. Eine normale VARCHAR-Spalte in SQL Server hört bei 8.000 Zeichen auf (eine NVARCHAR-Spalte hört bei der Hälfte auf, 4.000 Zeichen, denn jedes Unicode-Zeichen kostet zwei Bytes) - 8.000 Zeichen sind Raum für etwa 6.000 Bytes Binäres, bevor der 33-Prozent-Überhang Sie drüber drückt, und darüber greifen Sie zu den MAX-Typen oder, ehrlicher gesagt, zu einer echten binären Spalte. Auf Windows ist eine einzelne benutzerdefinierte Umgebungsvariable auf 32.767 Zeichen gedeckelt (und auf XP-Ära-Systemen war der gesamte Umgebungsblock ebenfalls auf diese Größe gedeckelt), also hat "den ganzen Lizenz-Blob in einer Env-Var aufbewahren" eine harte Decke:
Imports System
Module EnvPacker
Sub Main()
Dim blob() As Byte = {1, 2, 3, 4, 5}
Dim packed As String = System.Convert.ToBase64String(blob)
Environment.SetEnvironmentVariable("APP_BLOB", packed)
Console.WriteLine(packed)
' AQIDBAU=
End Sub
End Module
Konfigurationsdateien folgen derselben Form, mit dem Wert, der in XML- oder JSON-Text lebt, und dem Dekodieren, das in Ihrem Startup-Code passiert. Eine Legacy-Notiz für die Unternehmens-Ecke: WCF und XML-Datenverträge serialisieren ein Byte-Array als den base64Binary-XML-Schema-Typ, also speichert ein großer Bestand älterer .NET-Dienste Binäres genau so, und der Wert, den Sie in diesem XML finden, ist normales ToBase64String-Output.
JWTs: Die kompakte Form bauen
Ein JSON Web Token in der kompakten Form ist drei punktgetrennte Stücke base64url: der Header, der Payload und eine Signatur. Die ersten zwei sind klares JSON, und das dritte ist ein kryptografischer Beweis, dass ein Inhaber des richtigen Schlüssels dieses Token gebaut hat. Das Bauen der nicht signierten Form von Hand ist zwei Kodierungen und ein String-Verschmelzen, aber ein echtes JWT braucht den Signatur-Schritt, und ein kleines HMAC-SHA256-Beispiel macht die ganze Sache greifbar:
Imports System
Imports System.Buffers.Text
Imports System.Security.Cryptography
Imports System.Text
Module JwtPacker
Function BuildHs256Jwt(ByVal headerJson As String, ByVal payloadJson As String, ByVal secret() As Byte) As String
Dim header As String = Base64Url.EncodeToString(Encoding.UTF8.GetBytes(headerJson))
Dim body As String = Base64Url.EncodeToString(Encoding.UTF8.GetBytes(payloadJson))
Dim signingInput As String = header & "." & body
Using hmac As New HMACSHA256(secret)
Dim signature() As Byte = hmac.ComputeHash(Encoding.UTF8.GetBytes(signingInput))
Return signingInput & "." & Base64Url.EncodeToString(signature)
End Using
End Function
End Module
Führen Sie es mit dem Header {"alg":"HS256","typ":"JWT"} und einem Payload Ihrer Wahl aus, und das Ergebnis ist ein echtes kompaktes JWT: nirgends Padding, URL-sichere Zeichen in allen drei Teilen. Beachten Sie, dass die Signatur auch base64url ist, weil das gesamte Token eine URL oder einen HTTP-Header überleben muss. Für Produktionssysteme bauen, signieren und verifiziert das System.IdentityModel.Tokens.Jwt-Paket (die IdentityModel-Suite vom Microsoft-Entra-Team) diese Tokens für Sie, und das ist die Ebene, auf der Schlüssel-Verwaltung, Algorithmus-Pinning und Ablauf-Prüfungen hingehören. Von Hand basteln ist für das Verständnis und für kleine Tools in Ordnung; für alles, was Zugriff hütet, lassen Sie die Bibliothek das Gewicht tragen.
Fallen: Wo VB-Kodierer rutschen
Die Fallen hier sind ein Mix aus Sprach-Gewohnheiten und Ausgabe-Formungs-Überraschungen, und die meisten kosten eine Debugging-Sitzung statt eines Absturzes:
- Byte versus Byte(). Der Kodierer will ein Array. In Visual Basic ist ein einzelnes Byte
Byteund ein ArrayByte(), und der Unterschied ist ein Paar Klammern. UnterOption Strict Onist eine falsche Vermutung ein Compile-Fehler; ohne es können Sie stattdessen eine Runtime-Überraschung bekommen. Lassen Sie die Strenge an und die Klammern sichtbar. - Die Encoding.Default-Falle, umgekehrt. Die Story von der Locale-Divergenz ist eine .NET-Framework-Sache: Auf modernem .NET ist
Defaultimmer UTF-8, also kodiert derselbe String auf jeder Maschine dieselbe Weise. Für alles, was Maschinen überschreitet, benennen Sie die Kodierung ausdrücklich, meist UTF-8 - der Rat gilt in beiden Fällen. - CRLF findet einen Weg herein.
InsertLineBreaksist wunderbar für MIME und furchtbar für URLs, JSON und Datenbank-Textspalten, wo es einen Wagenrücksetzer und einen Zeilenumbruch einsetzt, die niemand bestellt hat. Benutzen Sie es nur, wenn der Konsument umwickelte Zeilen erwartet, und wenn Sie im Zweifel sind, benutzen Sie die VorgabeNone. - Padding-Missmatches an der Grenze. Die
Base64Urlvon .NET gibt kein Padding aus, während einige Bibliotheken in anderen Ökosystemen es hinzufügen (und ein paar strenge Dekodierer verlangen es). Wenn Ihr kodierter Wert ein Ökosystem überschreitet, bestätigen Sie die Erwartung der anderen Seite, bevor Sie den String verschiffen; JWT will die ungepaddete Form, die die .NET-Vorgabe ist. - Rundgänge sind keine Identität. Dekodieren Sie einen umwickelten, gepaddeten String und kodieren Sie ihn neu, und Sie bekommen eine saubere Einzelzeile mit frischem Padding, nicht den Original-Text. Wenn Ihre Logik kodierte Werte auf Gleichheit vergleicht, vergleichen Sie stattdessen die dekodierten Bytes.
- Die Größen-Decke ist real. Die Formel für die Ausgabelänge, vier Zeichen pro drei Bytes aufgerundet, überläuft eine 32-Bit-Zählung bei rund 1,5 Gigabyte Eingabe, und der Kodierer antwortet mit einer
OutOfMemoryExceptionstatt eines Teil-Strings. Für Eingaben in der Nähe dieser Größenordnung streamen Sie stattdessen (unten). - Die Span-Mauer. Die span-basierten Kodierer sind aus VB an der Aufrufstelle aufrufbar: Legen Sie Ihre
Byte()- oderChar()-Arrays direkt hinein, und der Compiler wandelt sie um. Aber Sie können keine Variable, kein Feld und keinen Parameter vom TypSpanoderReadOnlySpandeklarieren; der Compiler verweigert es mit "Types with embedded references are not supported in this version of your compiler". Das VB-Idiom ist, die Span-APIs mit normalen Arrays aufzurufen und nie einen Span zu speichern. - BitConverter ist nicht Base64.
BitConverter.ToString(bytes)rendert Hex mit Gedankenstrichen zwischen den Paaren, also ist es eine verlockende falsche Antwort, die4D-61-6Eproduziert, wo das andere SystemTWFuerwartet. Für Base64 ist die KlasseSystem.Convert, jedes Mal.
Tempo und Größe: Performance-Notizen
Der Ruf von Base64 als "langsamer Text-Codec" überlebt den Kontakt mit der modernen Runtime nicht. Der Kodierer in .NET läuft hardware-vektorierte Code, wenn die Maschine ihn unterstützt, mit speziellen Schnellpfaden für die AVX-512-, AVX2- und SSE-Befehlssätze, und der AVX-512-Pfad verschlingt 48 Bytes pro Schritt. Für gewöhnliche Payloads ist der klassische ToBase64String-Aufruf schnell genug, dass der Algorithmus selten der Flaschenhals ist; die Kosten, die Sie spüren, sind die 33-Prozent-Größen-Steuer und, für heiße Pfade, die Zwischen-Allozierungen. Wenn Sie Millionen kleiner Werte kodieren, sind die span-basierten APIs die Verfeinerung: TryToBase64Chars schreibt in einen Zeichen-Span, den Sie kontrollieren, und meldet Erfolg mit einem Booleschen Wert, und System.Buffers.Text.Base64 geht noch weiter, kodiert direkt in UTF-8-Puffer, die Sie allozieren, und dehnt Daten sogar In-Place aus:
Imports System
Imports System.Buffers
Imports System.Buffers.Text
Imports System.Text
Module BufferPacker
Sub Main()
Dim data() As Byte = {1, 2, 3, 4, 5}
Dim textLength As Integer = Base64.GetMaxEncodedToUtf8Length(data.Length)
Dim buffer(textLength) As Byte
Dim written As Integer
Dim consumed As Integer
Dim status As OperationStatus = Base64.EncodeToUtf8(data, buffer, consumed, written)
Dim packed As String = Encoding.ASCII.GetString(buffer, 0, written)
Console.WriteLine(packed)
' AQIDBAU=
End Sub
End Module
Das Muster, das man beachten sollte, ist, dass Sie den Puffer mit dem Helfer bemessen, in ihn kodieren und nur das benutzte Präfix in einen String umwandeln, was die Zwischenfläche so klein hält, wie sie sein kann. Und für Dateien, die groß genug sind, um Strings unangenehm zu machen, hält das Streaming-Paar den Speicher flach: Der ToBase64Transform-Transform, eingewickelt in einen CryptoStream, liest Ihre Eingabe in Chunks und schreibt kodierten Text heraus, so dass eine zwei-Gigabyte-Datei nie in einem Stück zu einem 2,7-Gigabyte-String werden muss:
Imports System.IO
Imports System.Security.Cryptography
Module StreamPacker
Sub EncodeFile(ByVal inputPath As String, ByVal packedPath As String)
Using inputStream As New FileStream(inputPath, FileMode.Open, FileAccess.Read)
Using packedStream As New CryptoStream(New FileStream(packedPath, FileMode.Create), New ToBase64Transform(), CryptoStreamMode.Write)
Dim buffer(65535) As Byte
While True
Dim read As Integer = inputStream.Read(buffer, 0, buffer.Length)
If read = 0 Then Exit While
packedStream.Write(buffer, 0, read)
End While
End Using
End Using
End Sub
End Module
Eine Vorbemerkung: Die .NET-11-Bibliotheken in der Vorschau fügen den vorhandenen Base64-Typen neue Bequemlichkeits- und Span-Overloads hinzu, also, wenn Ihr Projekt Vorschau-Updates mitverfolgen kann, wächst die Werkzeugkiste weiter; wenn es nicht kann, ist alles oben auf jedem unterstützten Release stabil.
Kurze Geschichte: Von MSXML zu Spans
Lange vor .NET entlehnten Visual-Basic-Programme, die Base64 brauchten, es der COM-Welt. Der klassische VB6- und VBA-Trick (die Makro-Sprache, die bis heute in Excel und Office läuft) benutzte stattdessen ein XML-DOM-Element: Der MSXML-Parser lässt einen Knoten seinen DataType als bin.base64 deklarieren, also gibt Ihnen das Schreiben Ihrer Bytes in die nodeTypedValue des Knotens und das Zurücklesen seiner text-Eigenschaft den kodierten String, während das DOM die eigentliche Base64-Mathematik macht (die eigene Charset-Eigenschaft des ADO-Stream-Objekts versteht nur echte Zeichensatz-Namen wie "utf-8" oder "iso-8859-1", aber kein "base64", und spielt daher keine Rolle in der Umwandlung selbst). Es war clever, es war überall, und es ist der Grund, warum "base64 VBA" Jahrzehnte später noch Suchmaschinen zum Leuchten bringt. Die Ära endete 2002, als die erste .NET-Version der Sprache, Visual Basic 7.0, der neuen Common Language Runtime beitrat, und das .NET Framework System.Convert mit ToBase64String aus der Dose brachte. Ab .NET Framework 1.1 im Jahr 2003 konnte jedes VB-Programm Base64 mit einem Aufruf kodieren und ohne zu registrierende Komponenten.
Die modernen Kapitel sind kurz. 2018 fügte .NET Core 2.1 die allozierungsarme TryToBase64Chars-Methode und die niedrigstufige span-basierte System.Buffers.Text.Base64-Klasse hinzu. 2024 standardisierte .NET 9 das URL-sichere Alphabet als Base64Url und beendete ein Jahrzehnt handgeschriebener Replace-Aufrufe. Stand 2026 ist .NET 10 - im November 2025 veröffentlicht - das Long-Term-Support-Release, das all dies trägt, und die .NET-11-Bibliotheken in der Vorschau fügen eine neue Generation von Bequemlichkeitsmethoden hinzu, also ist der Kodierer, vom 2003er-Einzeiler bis zur Span-Ära, die Story derselben Klasse, die schneller und präziser wird, nie die eines Neuanfangs.
Schöne Fakten, VB-Edition
InsertLineBreaksreproduziert die MIME-76-Zeichen-Regel exakt, CRLF inklusive, was heißt, dass die Zeilenumbrüche, die Ihr Kodierer 2026 schreibt, byte für byte die gleiche Form haben wie die, die ein E-Mail-Standard in den 1990ern definiert hat.- Der
IsNot-Operator, hinzugefügt mit Visual Basic 2005, wurde einmal als Gegenstand eines Microsoft-Patentantrags zur Nachricht. Sehr wenige Sprach-Operatoren können diese Auszeichnung für sich beanspruchen. - Das erste Visual Basic kam 1991 heraus, bevor das World Wide Web existierte. Bis das Data-URI-Schema 1998 erschien, hatte Base64 E-Mail-Anhänge schon fünf Jahre lang getragen, und VB war drei Jahre davor zu einer 32-Bit-Sprache herangewachsen, mit Visual Basic 4 im Jahr 1995.
- Auf Hardware mit AVX-512 verarbeitet der Runtime-Kodierer 48 Bytes pro Vektor-Schritt, was der Unterschied zwischen einem Tabellen-Lookup im Museum und einem Fließband in einer Fabrik ist.
- Der
My-Namespace, Visual Basics berühmte Zucker-Schicht aus dem Jahr 2005, brauchte nie einen Base64-Helfer hinzuzufügen.System.Convertwar immer einen Namespace-Import entfernt, ein seltener Fall, in dem die VB-Runtime nichts zu einer Story hinzufügte, die das Framework schon erzählte.
Die Kehrseite
Dieser Artikel hat die Kodier-Seite von Base64 in Visual Basic abgedeckt: die Werkzeugkiste, die Ausgabe-Formungs-Entscheidungen, das URL-sichere Alphabet und die Anwendungsfälle von Dateien bis JWTs. Die umgekehrte Richtung, einen eingehenden String zu nehmen und ihn zurück in die Bytes zu verwandeln, die er versteckt, hat ihr eigenes Verhaltens-Spektrum, ihre Verzeihungs-Regeln und ihre Fallen, und sie wird im ausführlichen Begleit-Artikel zum Dekodieren auf der Schwestern-Site in voller Tiefe behandelt. Der Link dazu sitzt direkt unter dieser Zeile, und das Werkzeug auf der Startseite bleibt der schnellste Weg, um einen kleinen Payload manuell zu kodieren.
Zuletzt aktualisiert: 2026-09-08
Verwandter Artikel: Base64-Dekodierung in Visual Basic: Ein vollständiger Leitfaden