Press "Enter" to skip to content

Base64 und andere Kodierungen mit C#

Im Rahmen einer Softwareerweiterung für die österreichische Registrierkassensicherheitsverordnung (was für ein Wort!) benötigte ich verschiedene Kodierungen und Dekodierungen.

Eine Anforderung lautet z. B. den Umsatzzähler verschlüsseln und als Base64 kodierten Wert in eine Zeichenkette einfügen.
Das lässt sich noch einfach mit der integrierten Convert-Funktion bewerkstelligen.

Dann muss man die ganze Zeichenkette für den Signaturvorgang in eine Base64 JWS-Representation umwandeln (hier wird die Base64 Url safe Kodierung ohne  Padding verwendet).
Dazu gibt es in .Net HttpServerUtility.UrlEncode bzw. WebUtility.UrlEncode.
Hm, das ist keine Web- und auch keine Webserveranwendung, wozu also diese DLLs einbinden.
In 2 Jahren frage ich mich, wofür zum Teufel ich HttpServerUtility brauche…..
Außerdem weiß ich nicht genau, was die Methoden wirklich machen (dazu ein interessanter Artikel).
Also doch besser mit ein paar kleinen Hilfsmethoden.

Wenn diese ganze Zeichenkette wieder dekodiert werden muss um sie dann als Base32 Reprästentation ausgeben zu können, die zu dekodierenden Zeichenketten auch noch auf Korrektheit überprüfen will, wird das ganze schnell unübersichtlich (war diese Zeichenkette jetzt Base64 oder Base64 Jws oder vielleicht nur Base64 Url safe?).

Und verständlicher und lesbarer wird der Code schon gar nicht!

Und was ist mit Methoden, die einen Base64 kodierten String erwarten?
Die Signatur sieht dann in etwa so aus:

string ConvertBase64JwsToBase32(string base64JwsEncodedString)

die dazu passende Prüfmethode (hoffentlich vergisst man nicht, die aufzurufen, aber dafür gibts ja dann Unit-Tests):

bool IsBase64JwsStringValid(string base64JwsEncodedString)

Dabei gibt es in C# (und nicht nur in C#) so schöne Konzepte wie Klassen und Kapselung.
Warum wird eine Base64-kodierte Zeichenkette nicht so dargestellt:

Base64String base64 = new Base64String(„5HjRCx+XIz4=“);

Dann ist die Instanz vom Typ Base64String, jede Methode an der dieser Typ übergeben wird kann davon ausgehen, dass sie einen gültigen und vor allem einen korrekten Base64String übergeben bekommt. Keine neuerliche Validierung ist mehr notwendig.
Die Base64String-Klasse ist verantwortlich für die Validierung und wirft eine Exception bei einem nicht validen String.

Die neue Methodensignatur sähe dann so aus:

Base32String ConvertBase64ToBase32(Base64String base64String)

die dazu passende Prüfmethode:

(oh, die brauche ich ja nicht mehr, das hat ja die Base64String-Klasse bereits übernommen)

Auch die Convert-Methode liefert gleich einen korrekten Typ Base32String zurück.

Bei näherer Betrachtung fällt auf, dass die beiden Klassen Base32String und Base64String eine Gemeinsamkeit haben:
Beide Klassen haben nämlich die gleiche Bytefolge als Kodierungsbasis, lediglich die String-Repräsentation ist unterschiedlich.

Diese Gemeinsamkeit können wir jetzt nutzen um eine Basisklasse mit einem Bytearray zu erstellen, von denen die konkreten Klassen dann ableiten (z. B. eine BaseNString-Klasse).

Mit dem passenden Konstruktor

public Base32String(BaseNString baseNString)

sieht die Konvertierung dann so aus:

var base32String = new Base32String(new Base64String(„5HjRCx+XIz4=“));

Ich brauche also keine eigene Convert-Methode mehr, die Konvertierung übernimmt ebenfalls die von BaseN abgeleitete Klasse.

Das Ganze habe ich etwas verfeinert, in eine eigenständige Bibliothek verfrachtet und auf GitHub und NuGet hochgeladen.

Eine Konvertierung eines Base64-kodierten Strings in einen Base32-kodierten String sieht mit dieser Bibliothek so aus:

var result = "Zm9vYg==".AsBase64().ToBase32().ToString();

Die Bibliothek unterstützt die Frameworks .Net Core (netstandard1.0) und .Net40+

Viel Spass beim Kodieren und Dekodieren!