Wie kann man ein Base 64 encoding ohne die Base64 Methode umsetzen?
Hallo, ich habe letztens als Aufgabe, in unserem IT Unterricht die Aufgabe bekommen, eine C# WPF Anwendung zu erstellen, die einen eingegebenen String zu einem Base64 Ergebnis konvertiert.
Uns wurde nur das Layout der Anwendung gegeben und nichts dazu erklärt, wie der eigentliche Prozess dahinter abläuft. Durch Wikipedia habe ich jetzt erfahren, dass dazu ein String in jeweils 8-Bits unterteilt wird, diese dann zu jeweils 6-Bits unterteilt werden, und sollte das Ergebnis nicht durch 6 teilbar sein, dann mit Nullen aufgefüllt wird.
Unser Unterricht ist nicht der Beste und es wird auch nicht viel erklärt, weswegen sich mir folgende Fragen stellen:
- Wie kann man einen String in seine 8 Bit Bestandteile unterteilen?
- Wie kann man die 8-Bit Stücke in 6-Bit Stücke unterteilen?
- Wie kann man dann aus der Base64 Tabelle (Siehe Wikipedia: Base64 – Wikipedia) den dazugehörigen Zeichensatz wieder als String ausgeben?
Ich vermute mal, die Binärwerte werden in einem Array gespeichert, allerdings habe ich den Workflow mit diesen, im Zusammenhang mit WPF Anwendungen noch nicht gelernt.
Auch wenn mir hier vermutlich dumme Fragen aufgekommen sind, hoffe ich, dass mir jemand diese dennoch beantworten kann.
Vielen Dank im Voraus.
1 Antwort
Wie kann man einen String in seine 8 Bit Bestandteile unterteilen?
Mit den verschiedenen Klassen aus System.Text.Encoding.
Beispiel UTF-8:
string message = "Lorem ipsum dolor sit amet";
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(message)
Wie kann man die 8-Bit Stücke in 6-Bit Stücke unterteilen?
Nimm das kleinste gemeinsame Vielfache (kgv) von 8 und 6.
Der Multiplikator m für 8*m=kgv sagt dir dann, wie viele 8 Bit Blöcke wie vielen 6 Bit Blöcken für 6*M=kgv entsprechen.
8*3=24
6*4=24
Also: 3 Blöcke zu je 8 Bit entsprechen 4 Blöcken zu je 6 Bit.
Dann nimmst du deine 3 Blöcke zu je 8 Bit:
aaaaaaaa bbbbbbbb cccccccc
und teilst diese in 4 Blöcke zu je 6 Bit auf:
aaaaaa aabbbb bbbbcc cccccc
Eine Möglichkeit das zu tun besteht darin, mit einer bitweisen Verschiebung nach links die 3 Bytes zu einem Int32-Wert zusammenzufassen und diesen dann mit bitweisen Verschiebungen nach rechts und einem bitweisen UND in 6 Bit Blöcke aufzuteilen.
Wie kann man dann aus der Base64 Tabelle den dazugehörigen Zeichensatz wieder als String ausgeben?
Ganz einfach: 6 Bit ergeben exakt 64 mögliche Kombinationen (von 0 bis 63).
Der Base64-Zeichensatz hat exakt 64 Zeichen, die jeweils eine Position von 0 bis 63 haben.
Nimm also für jeden 6 Bit Block das Zeichen, das an diesem Index steht.
Ich vermute mal, die Binärwerte werden in einem Array gespeichert,
Muss nicht, aber alles andere wäre Mumpitz.
allerdings habe ich den Workflow mit diesen, im Zusammenhang mit WPF Anwendungen noch nicht gelernt.
Das ist exakt der gleiche wie in jeder anderen Art von Anwendung auch...
P.S.: Beispielcode (weitestgehend ungetestet, aber für plausibel befunden ^^):
string message = "Lorem ipsum dolor sit amet";
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(message)
string charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
System.Text.StringBuilder sb = new System.Text.StringBuilder();
int index, block;
for(index = 0; index + 3 < bytes.Length; index += 3){ // die Nachricht in Blöcken von 3 Bytes durchgehen
block = (bytes[index] << 16) | (bytes[index + 1] << 8) | bytes[index + 2]; //die 3 Bytes zu einer Zahl zusammenfügen
sb.Append(charset[(block >> 18 ) & 0x3f]); // aus dem Charset das Zeichen nehmen, dessen Index den ersten 6 Bit entspricht
sb.Append(charset[(block >> 12 ) & 0x3f]); // das gleiche nochmal für die zweiten 6 Bit
sb.Append(charset[(block >> 6 ) & 0x3f]); // usw...
sb.Append(charset[block & 0x3f]); // ...
}
switch(bytes.Length - index){ // diese Differenz kann 0, 1 oder 2 sein. Bei 0 ist kein weiteres Verfahren nötig.
case 2: // zwei Bytes sind noch übrig
block = (bytes[index] << 16) | (bytes[index + 1] << 8); // siehe oben (nur halt mit nur zwei Bytes)
sb.Append(charset[(block >> 18 ) & 0x3f]);
sb.Append(charset[(block >> 12 ) & 0x3f]);
sb.Append(charset[(block >> 6 ) & 0x3f]);
sb.Append('='); // Füllzeichen anhängen
break;
case 1: // ein btye übrig
block = (bytes[index] << 16); // siehe oben (nur halt mit nur einem Byte)
sb.Append(charset[(block >> 18 ) & 0x3f]);
sb.Append(charset[(block >> 12 ) & 0x3f]);
sb.Append('='); // Füllzeichen anhängen
sb.Append('='); // Füllzeichen anhängen
break;
}
System.Console.WriteLine(sb.ToString());