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*/