Dark ITSec

Base 64

Seit der Einführung von Base64 hat sich der Algorithmus sehr starken Einsatz im Web gefunden. Sehr bekannt ist die Implementierung im Einsatz bei verschlüsseltem versenden der Files als Anhang über Multipurpose Internet Mail Extensions or MIME, das hat sich weit verbreitet in HTTP wie wie auch SMPT und anderen Protokollen.

Zu viel über MIME und die Spezifikationen wollte ich hier nicht schreiben also fahren wir weiter fort.
für alle die sich zu MIME mehr wissen wollen (RFC 2045)


HTTP

Eines der bekanntesten einsätze von Base64-Verschlüsselung wird/wurde oft bei den Web-Server-Implementierungen eingesetzt, um eine HTTP Based Basic Authentication durchzuführen.
Wenn der Server bestimmte Ordner auf dem Server durch Passwort schützen will, hat er die Möglichkeit der Based-Basic Authentifizierung.Der Benutzer der auf den Inhalt der Seite oder des Ordners zugreifen will wird zur eingabe eines PAssworten und benutzernamens aufgefordert und dies wird mit Hilfe von Base64 Verschlüsselt übertragen.
Das ganze ist nicht so Kompliziert wie ihr später sehen werdet, also gibt es auch andere "bessere" verfahren als das, z.B. hashverfahren MD5

 

Base-64

Base64 verwenden einen einfachen US-Zeichensatz von  65-Buchstaben (US-ASCII), also 6-Bit pro Zeichen.
Ein Beispiel ‘m’ hat den Wert in Base64 38. Wie kommt man auf die Werte der einzelnen Buchstaben? Man erstellt sich eine einfache Tabelle mit allen werten und Zuweisungen, die wird nach einem Beispiel später vorgestellt.

 

Beispiel
Und jetzt zur schnellen Einführung einfach ein kleines Beispiel.
Sagen wir mal das wir den Text: ‘mne’ haben. Als erstes müssen wir den Text in Dezimalzahlen umwandel.

 "m" hat den wert 109

 "n"  hat den wert 110

 "e"  hat den wert 101
 

Die Werte hintereinander ausgeschrieben 109 110 101 von Dezimal in binär sehen sie so aus:

01101101   01101110   01100101

 

Diese 3 8Bit-Bytes machen einen 24Bit Stream aus.

011011010110111001100101

 

Den 24Bit Stream teilen wir in 6Bit bereiche auf.

011011  010110  111001  100101

 

Wenn wir jetzt die werte der 6Bit von binär in dezimal umwandeln dann sieht das ganze so aus:

27 22 57 37

 

Jetzt die werte von Dezimal wieder in Base 64 Char-Werte umwandeln (würde ein C-Programmierer sagen)
dann sehe das ganze so aus:

27 = b

22 = w

57 = 5

37 = l

 

also aus "mne" wird dann einfach "bw5l". in der folgenden Tabelle können sie die werte noch mal genauer nachvollziehen.

Hier ist eine Tabelle für Base64 ABC
Tabelle 1: Base64 ABC

Wert Encoding

Wert Encoding

Wert Encoding

Wert Encoding

0        A

17         R

34         i

51      z

1        B

18         S

35         j

52      0

2        C

19         T

36         k

53      1

3        D

20         U

37         l

54      2

4        E

21         V

38        m

55      3

5        F

22         W

39         n

56     4

6        G

23         X

40         o

 57     5

7        H

24         Y

41         p

58     6

8         I

25         Z

42         q

59     7

9        J

26         a

 43          r

60     8

10       K

27         b

44         s

61     9

11       L

28         c

45         t

62     +

12       M

29         d

46         u

63      /

13       N

30         e

47         v

(pad) =

14       O

31         f

48        w

 

15       P

32         g

49         x

 

16       Q

33         h

50         y

 

 

Entschlüsseln
Zum Decodieren (Entschlüsseln obwohl kein wirklicher Schlüssel verwendet wird) in Base64 String einfach rückwärts alles durchlaufen.

 

1) Buchstaben in Base64 Dezimalwerte.

2) Dezimalwerte in Binärwerte.

3) Pack die 6Bits zu einem großen Stream von Bits zusammen.

4) Splitte den String in 8-Bit Gruppen (starte von rechts nach Rechts nach Links).

5) Konvertiere die 8Bit Werte in Dezimalwerte

6) Die Dezimalwerte in die Buchstaben der Standard ASCII-Tabelle

 

Kurz ausschnitt aus Perl

use MIME::Base64;

print decode_base64("Eingefügter Text zum decodieren.");

 

# die folgenden sub-routinen sind aus MIME::Base64 herrauskopiert
sub Encode_base64 { 
my $res = "";
my $eol = $_[1];
$eol = "\n" unless defined $eol;
pos($_[0]) = 0;
while ($_[0] =~ /(.{1,45})/gs) {
$res .= substr(pack('u', $1), 1);
chop($res);}
$res =~ tr|` -_|AA-Za-z0-9+/|;
my $padding = (3 - length($_[0]) % 3) % 3;
$res =~ s/.{$padding}$/'=' x $padding/e if $padding;
if (length $eol) {
$res =~ s/(.{1,76})/$1$eol/g;
} $res; }

sub Decode_base64 {
my $str = shift;
my $res = "";
$str =~ tr|A-Za-z0-9+=/||cd;
$str =~ s/=+$//; 
$str =~ tr|A-Za-z0-9+/| -_|;
while ($str =~ /(.{1,60})/gs) {
my $len = chr(32 + length($1)*3/4);
$res .= unpack("u", $len . $1 );
}$res;}
# am ende die 1 - ist wichtig für ein Modul in Perl
1;

 

 

Implementierung in std C für Base 64 encoder/decoder.

#include <appletdefs.h>

#include <iac.h>

#include "base64.h"

 

static char encodingTable [64] = {

 

    'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',   

    'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',   

    'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',   

    'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'

                };

 

static unsigned long gethandlesize (Handle h) {

 

                return (GetHandleSize (h));

                } /*gethandlesize*/

 

 static boolean sethandlesize (Handle h, unsigned long newsize) {

                 SetHandleSize (h, newsize);

                return (MemError () == noErr);

                } /*sethandlesize*/

 

 static unsigned char gethandlechar (Handle h, unsigned long ix) {

 

                return ((*h) [ix]);

                } /*gethandlechar*/

 

 static void sethandlechar (Handle h, unsigned long ix, unsigned char ch) {

 

                (*h) [ix] = ch;

                } /*sethandlechar*/

 

 static boolean encodeHandle (Handle htext, Handle h64, short linelength) {

 

                /*

                encode the handle. some funny stuff about linelength -- it only makes

                sense to make it a multiple of 4. if it's not a multiple of 4, we make it

                so (by only checking it every 4 characters. 

                further, if it's 0, we don't add any line breaks at all.

                */

 

                unsigned long ixtext;

                unsigned long lentext;

                unsigned long origsize;

                long ctremaining;

                unsigned char ch;

                unsigned char inbuf [3], outbuf [4];

                short i;

                short charsonline = 0, ctcopy;

                ixtext = 0;

                lentext = gethandlesize (htext);

                while (true) {

 

                                ctremaining = lentext - ixtext;

                                                if (ctremaining <= 0)

                                                break;

                                                               

                                for (i = 0; i < 3; i++) {

                                                                unsigned long ix = ixtext + i;

                                                                if (ix < lentext)

                                                                inbuf [i] = gethandlechar (htext, ix);

                                                else

                                                                inbuf [i] = 0;

                                                } /*for*/

                               

                                outbuf [0] = (inbuf [0] & 0xFC) >> 2;

                                outbuf [1] = ((inbuf [0] & 0x03) << 4) | ((inbuf [1] & 0xF0) >> 4);

                                outbuf [2] = ((inbuf [1] & 0x0F) << 2) | ((inbuf [2] & 0xC0) >> 6);

                                outbuf [3] = inbuf [2] & 0x3F;

                                origsize = gethandlesize (h64);

               

                                if (!sethandlesize (h64, origsize + 4))

                                                return (false);

                               

                                ctcopy = 4;

                                switch (ctremaining) {

                                                case 1:

                                                                ctcopy = 2;

                                                                break;

                               

                                                case 2:

                                                                ctcopy = 3;

                                                                break;

                                                } /*switch*/

 

                                for (i = 0; i < ctcopy; i++)

                                                sethandlechar (h64, origsize + i, encodingTable [outbuf [i]]);

                                for (i = ctcopy; i < 4; i++)

                                                sethandlechar (h64, origsize + i, '=');

                               

                                ixtext += 3;

                                charsonline += 4;

                                if (linelength > 0) { /*DW 4/8/97 -- 0 means no line breaks*/

                                                                if (charsonline >= linelength) {

                                               

                                                                charsonline = 0;

                                                                origsize = gethandlesize (h64);

                                               

                                                                if (!sethandlesize (h64, origsize + 1))

                                                                                return (false);

                                                                sethandlechar (h64, origsize, '\n');

                                                                }

                                                }

                                } /*while*/

                return (true);

                } /*encodeHandle*/

 

 static boolean decodeHandle (Handle h64, Handle htext) {

 

                unsigned long ixtext;

                unsigned long lentext;

                unsigned long origsize;

                unsigned long ctremaining;

                unsigned char ch;

                unsigned char inbuf [3], outbuf [4];

                short i, ixinbuf;

                boolean flignore;

                boolean flendtext = false;

                ixtext = 0;

                lentext = gethandlesize (h64);

                ixinbuf = 0;

                while (true) {

               

                                if (ixtext >= lentext)

                                                break;

                               

                                ch = gethandlechar (h64, ixtext++);

                                flignore = false;

               

                                if ((ch >= 'A') && (ch <= 'Z'))

                                                ch = ch - 'A';

                                else if ((ch >= 'a') && (ch <= 'z'))

                                                ch = ch - 'a' + 26;

                                else if ((ch >= '0') && (ch <= '9'))

                                                ch = ch - '0' + 52;

                                else if (ch == '+')

                                                ch = 62;

                                else if (ch == '=') /*no op -- can't ignore this one*/

                                                flendtext = true;

                                else if (ch == '/')

                                                ch = 63;

                                else

                                                flignore = true;

               

                                if (!flignore) {

               

                                                short ctcharsinbuf = 3;

                                                boolean flbreak = false;

                                                 if (flendtext) {

                                               

                                                                if (ixinbuf == 0)

                                                                                break;

                                                                if ((ixinbuf == 1) || (ixinbuf == 2))

                                                                                ctcharsinbuf = 1;

                                                                else

                                                                                ctcharsinbuf = 2;

                                               

                                                                ixinbuf = 3;

                                               

                                                                flbreak = true;

                                                                }

                                                inbuf [ixinbuf++] = ch;

                                                if (ixinbuf == 4) {

                                                                ixinbuf = 0;

                                                                outbuf [0] = (inbuf [0] << 2) | ((inbuf [1] & 0x30) >> 4);

                                                                outbuf [1] = ((inbuf [1] & 0x0F) << 4) | ((inbuf [2] & 0x3C) >> 2);

                                                                outbuf [2] = ((inbuf [2] & 0x03) << 6) | (inbuf [3] & 0x3F);

                                                                origsize = gethandlesize (htext);

                                               

                                                                if (!sethandlesize (htext, origsize + ctcharsinbuf))

                                                                                return (false);

                                                                for (i = 0; i < ctcharsinbuf; i++)

                                                                                sethandlechar (htext, origsize + i, outbuf [i]);

                                                                }

                                                if (flbreak)

                                                                break;

                                                }

                                } /*while*/

 

                exit:

                return (true);

                } /*decodeHandle*/

 

 

void base64encodeVerb (void) {

                Handle h64, htext;

                short linelength;

 

                if (!IACgettextparam ((OSType) keyDirectObject, &htext))

                                return;

                if (!IACgetshortparam ((OSType) 'line', &linelength))

                                return;

                h64 = NewHandle (0);

                if (!encodeHandle (htext, h64, linelength))

                                goto error;

               

                DisposHandle (htext);

                IACreturntext (h64);

                return;

                error:

 

                IACreturnerror (1, "\perror encoding the Base 64 text");

                } /*base64encodeVerb*/

 

 void base64decodeVerb (void) {

                Handle h64, htext;

                if (!IACgettextparam ((OSType) keyDirectObject, &h64))

                                return;

                htext = NewHandle (0);

                if (!decodeHandle (h64, htext))

                                goto error;

                DisposHandle (h64);

                IACreturntext (htext);

                return;

                error:

                 IACreturnerror (1, "\perror decoding the Base 64 text");

                } /*base64decodeVerb*/