Wie kann man ein Base 64 encoding ohne die Base64 Methode umsetzen?

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());