Spion vs. Spion

Wer Daten über andere Leitungen schickt, will verhindern, dass Fremde mithören. Kann man, wie im Internet, nicht für die Sicherheit der Verbindungsstrecke garantieren, helfen Verschlüsselungssysteme, die Daten zu panzern.

In Pocket speichern vorlesen Druckansicht
Lesezeit: 12 Min.
Von
  • Michael Schilli
Inhaltsverzeichnis

Eine auch in kommerziellen Programmen gängige Methode, Daten zu verschlüsseln, ist der XOR-Operator: Er verknüpft einzelne Datenbits so, dass das Ergebnis der Operation 0 ist, falls die entsprechenden Bits der Operanden gleich sind, und 1, falls nicht:

0 xor 0 = 0
1 xor 0 = 1
0 xor 1 = 1
1 xor 1 = 0

Ein Punkt ‘.’ steht zum Beispiel in der ASCII-Tabelle auf Nummer 46, der Buchstabe ‘K’ auf 75 - verknüpft man die Bits beider Darstellungen nach dem XOR-Verfahren, ergibt sich das Zeichen mit der ASCII-Nummer 101, also der Buchstabe ‘e’:

0010 1110    ‘.’  (46)
0100 1011 ’K’ (75)
XOR
0110 0101 ’e’ (101)

Diese Operation lässt sich auch ganz leicht wieder umdrehen: XOR-t man nämlich das Ergebnis ‘e’ mit ’K’, kommt das ursprüngliche Zeichen, der Punkt ‘.’, zum Vorschein. Ein Zeichen im Klartext einer Nachricht kann man folglich mit einem Schlüssel kodieren und hernach mit demselben wieder in Klartext zurückverwandeln. Einen Schlüssel mit nur einem Zeichen zu verwenden, wäre nun allzu trivial, und so ist es üblich, ein Wort (zum Beispiel ‘KEY!’) über den Klartext wie ein Fliesenmuster auszurollen und für jedes Zeichen die XOR-Verknüpfung mit dem Schlüssel zu bestimmen. Listing 1 zeigt die Perl-Implementierung. Die Zeilen 6-8 erzeugen das Schlüsselmuster im Format ‘KEY!KEY!KE...’ und der XOR-Operator ^ in Zeile 11 schließlich verknüpft Klartext und Schlüssel zeichenweise:

... etwas ganz geheimes ...     # Klartext
KEY!KEY!KEY!KEY!KEY!KEY!KEY # Schlüssel
ekw".1.@8e>@%?yF.-<H& *"ekw # Verschlüsselt
Mehr Infos

LISTING 1

xor.pl benutzt den XOR-Operator zur Verschlüsselung.

 1 #!/usr/bin/perl -w
2
3 $KEY = "KEY!";
4 $TEXT = "... etwas ganz geheimes ...";
5
6 $keystring = $KEY x
7 (length($TEXT) / length($KEY) + 1);
8 $keystring = substr($keystring, 0, length($TEXT));
9
10 printf "'%s'\n'%s'\n'%s'\n",
11 $TEXT, $keystring, $TEXT ^ $keystring;

Das Ergebnis besteht aus scheinbar bunt durcheinander gewirbelten Sonderzeichen. Dass diese lesbar sind, darf nicht darüber hinwegtäuschen, dass im XOR-Ergebnis auch undruckbare Zeichen oder sogar Null-Bytes (ASCII-Null) stehen können. Warum aber reicht diese Verschlüsselung nicht aus? Das Verfahren würfelt den Eingangsstring nicht genug durcheinander, aus der Verteilung der im verschlüsselten String auftauchenden Zeichen kann ein geübter Kryptoanalytiker - ohne den geheimen Schlüssel zu kennen! - nicht nur die Schlüssellänge ermitteln, sondern anschließend mit einem Trick sogar die Verschlüsselung rückgängig machen [1]. Besonders deutlich wird der Nachteil des XOR-Verfahrens, wenn man einen String aus lauter Leerzeichen verschlüsselt:

’                           ’    # Klartext
’KEY!KEY!KEY!KEY!KEY!KEY!KEY’ # Schlüssel
’key"key"key"key"key"key"key’ # Verschlüsselt

Hier scheint sogar der geheime Schlüssel im verschlüsselten String durch - dem Codeknacker kommen die Freudentränen. Nein, um auch die härtesten Cracker auszutricksen, müssen schwerere Geschütze her: Erprobte Verfahren wie DES oder IDEA legen die Messlatte höher und verzwirbeln die Daten durch komplizierte Algorithmen zumindest so, dass sich vielleicht der Mann vom Geheimdienst daran versuchen könnte, aber Normalsterbliche zwangsläufig scheitern. DES wurde 1975 in Zusammenarbeit von IBM und dem amerikanischen Geheimdienst als Data Encryption Standard veröffentlicht, und obwohl es viele Spekulationen darüber gibt, inwieweit die sonst sehr geheimnistuerische NSA (National Security Agency) Hintertüren eingebaut habe, um ihren Spionen das Knacken zu erleichtern, gilt das Verfahren immer noch als relativ sicher. Der neuere IDEA (International Data Encryption Algorithm) kam 1990 auf den Markt; für kommerzielle Anwendungen ist eine Lizenz erforderlich. Seine Popularität rührt daher, dass ihn das weit verbreitete Programm PGP (Pretty Good Privacy) verwendet. Die Unix-Funktion crypt(3) hingegen, die Passwörter verschlüsselt, basiert zwar auf einem modifizierten DES-Verfahren, taugt aber überhaupt nicht zum Verschlüsseln längerer Texte.

Auch DES oder IDEA liefern unter Umständen undruckbare Zeichen oder sogar Null-Bytes, sodass man den entstehenden Buchstabensalat am besten als Hex-Zahl oder aber in der Base64-Kodierung ausdruckt, wenn man verschlüsselte Informationen per E-Mail oder Cookie verschickt.

Listing 2 zeigt, wie man mittels des Moduls Crypt::DES (Installation s. Kasten) Verschlüssler-Objekte erzeugt, die 8 Byte lange Schlüssel akzeptieren und dann 8 Byte lange Zeichenketten nach dem DES-Algorithmus kodieren.

Mehr Infos

Installation

Die Crypt-Module, die auf dem CPAN als Crypt-DES-1.0 und Crypt-IDEA-1.0 vorliegen, ließen sich auf dem verwendeten RedHat 5.2 Linux nicht auf Anhieb übersetzen, die Dateien des.h und idea.h verlangten nach

#include <machine/types.h>

was durch

#include <sys/types.h>

ersetzt werden musste, und in idea.c war

#include <machine/endian.h>

in

#include <endian.h>

zu ändern. Dann verlief die übliche Perl-Modul-Installation mit

perl Makefile.PL
make
make install

korrekt. Die übrigen im Text verwendeten Module Crypt::CBC, Digest::MD5, Digest::SHA1 und Digest::HMAC installieren ohne Probleme. In den folgenden Distributionen vom CPAN ist alles Notwendige enthalten:

GARY/Crypt-DES-1.0.tar.gz
GARY/Crypt-IDEA-1.0.tar.gz
LDS/Crypt-CBC-1.20.tar.gz
GAAS/Digest-MD5-2.08.tar.gz
Mehr Infos

LISTING 2

Acht Byte lange Blöcke kodiert des.pl mit dem DES-Verfahren.

 1 #!/usr/bin/perl -w
2
3 use Crypt::DES;
4 use MIME::Base64;
5
6 # 8 Byte Key
7 $key = pack("H16", "e64e2722f9594c3");
8
9 # Neues Verschlüsselungsobjekt
10 $cipher = DES->new($key);
11
12 # Verschlüsseln -- 8 Bytes
13 $ciphertext = $cipher->encrypt("Klartext");
14
15 # Als Hex-Zahl ausgeben
16 print "Cipher: ", encode_base64($ciphertext);
17
18 # Entschlüsseln -- 8 Bytes
19 $cleartext = $cipher->decrypt($ciphertext);
20
21 print "Clear: $cleartext\n";

Einen 8 Byte langen Schlüssel definiert man am lesbarsten mit einer Hex-Zahlenreihe, die die pack-Funktion mit dem Formatkommando H16 als 16 Halb-Bytes einliest (Zeile 7). Der Konstruktor des DES-Objektes erzeugt daraus ein Objekt, das die Methoden encrypt() und decrypt() versteht. Sie akzeptieren 8 Byte lange Skalare und ver- beziehungsweise entschlüsseln den jeweiligen Block. Die zum Teil unleserlichen Zeichen in $ciphertext wandelt die Funktion encode_base64() des MIME::Base64-Moduls in eine druckbare Zeichenfolge. des.pl gibt zunächst die verschlüsselte Folge und anschließend den wieder entschlüsselten Klartext aus:

Cipher: NF25M86G0w4=
Clear: Klartext

8-Byte-Blöcke erweisen sich natürlich schnell als unhandlich, wenn es darum geht, ganze Sätze oder Dateien zu verschlüsseln. Das Modul Crypt::CBC implementiert deswegen einen Chain-Block-Cipher, der Zeichenketten beliebiger Länge verarbeitet und auch handlichere Schlüssel in Stringform entgegennimmt.

Crypt::CBC arbeitet wahlweise mit dem DES- oder dem IDEA-Algorithmus. Wie Listing 3 zeigt, erwartet der Konstruktor new den Schlüssel und den Namen des Verfahrens (derzeit Crypt::DES oder Crypt::IDEA). Das entstehende Cipher-Objekt kennt nicht nur die Methoden encrypt() und decrypt(), die mit zum Teil undruckbaren Darstellungen arbeiten, sondern auch encrypt_hex() und decrypt_hex(), die verschlüsselte Hexzahlen verwenden:

Cipher: b06522dae4d84b63ce75a3776c4930ee
Clear: Der Klartext
Mehr Infos

LISTING 3

cbc.pl kann beliebig lange Texte mit dem DES-Algorithmus verschlüsseln.

 1 #!/usr/bin/perl -w
2
3 use Crypt::CBC;
4
5 # Neuer Block-Cipher, IDEA-Algorithmus
6 $cipher = Crypt::CBC->new("Schlüssel!", "Crypt::IDEA");
7
8 # Verschlüsseln und verhexen
9 $cipherhex = $cipher->encrypt_hex("Der Klartext");
10
11 # Enthexen und entschlüsseln
12 $cleartext = $cipher->decrypt_hex($cipherhex);
13
14 print "Cipher: $cipherhex\n";
15 print "Clear: $cleartext\n";

Der IDEA-Algorithmus benutzt einen 32-Byte-Schlüssel und kodiert ebenfalls 8 Byte lange Blöcke, was das Crypt::CBC-Modul geschickt verbirgt, denn es verarbeitet beliebige Textlängen und der Schlüssel wird, wie auch bei der Chain-Block-Version des DES-Verfahrens, aus dem Ergebnis einer Message-Digest-Funktion auf den Schlüsselstring bestimmt.

Eine kleine Applikation, die ihre Standardeingabe oder den Inhalt von auf der Kommandozeile angegebenen Dateien ver- beziehungsweise entschlüsselt zeigt Listing 4.

Mehr Infos

LISTING 4

Auf der Kommandozeile angegebene Dateien ver- oder entschlüsselt crypt.pl.

 1 #!/usr/bin/perl -w
...
7 use Crypt::CBC;
8 use MIME::Base64;
9
10 $| = 1;
11 $DECRYPT = 0;
12
13 (shift, $DECRYPT = 1) if @ARGV && $ARGV[0] eq "-d";
14 $KEY = shift or usage("No key given");
15
16 $data = join('', <>);
17
18 $cipher = Crypt::CBC->new($KEY, "Crypt::IDEA");
19
20 if($DECRYPT) {
21 print $cipher->decrypt(decode_base64($data));
22 } else {
23 print encode_base64($cipher->encrypt($data));
24 }
25
26 sub usage {
27 print "@_\nusage: $0 [-d] key [file] ...\n";
28 exit 1;
29 }
crypt.pl key data >data.crypt

kodiert den Inhalt der Datei data mit dem Schlüssel key und gibt das Ergebnis Base64-kodiert in die Datei data.crypt aus. Umgekehrt liest

crypt.pl -d key data.crypt

den Datensalat aus data.crypt wieder ein, kehrt die Base64-Kodierung um, entschlüsselt ihn mit dem Schlüssel key, und gibt das Ergebnis aus.

Liegt beim Entschlüsseln wie in

crypt.pl key data | crypt.pl -d otherkey

der falsche Schlüssel vor, ist das Ergebnis ein wüster Haufen von Sonderzeichen.

DES und IDEA sind symmetrische Verfahren - derselbe geheime Schlüssel dient sowohl zum Ver- als auch zum Entschlüsseln. Dies stellt zwei Kommunikationspartner, die einander kodierte Nachrichten zuspielen wollen, vor die Schwierigkeit, vor dem Sendebeginn den Schlüssel auszutauschen. Rauscht er ohne Vorsichtsmaßnahmen durch die Leitung, kann ihn jeder Mithörer aufschnappen und selbst die folgenden Nachrichten entschlüsseln, falls er den Algorithmus kennt, von denen es nur eine Hand voll gibt. Nein, den Schlüssel kann man nur sicher über einen anderen Kanal transportieren - im Notfall muss sich Rambo mit einem kleinen Aktenkoffer durch den Dschungel schlagen.

Asymmetrische Verfahren wie RSA (verwendet vom populären PGP) hingegen arbeiten mit zwei verschiedenen Schlüsseln - einem geheimen und einem öffentlichen. Der geheime verlässt niemals den heimischen Rechner, während den öffentlichen die ganze Welt kennt, denn er steht quasi im Telefonbuch. Die beiden Schlüssel ergeben ein Paar: Was der öffentliche Schlüssel verschleiert, kann nur der private knacken und umgekehrt. Der Sender holt den öffentlichen Schlüssel des Empfängers, verschlüsselt die Nachricht damit und sendet sie über den offenen Kanal. Der öffentliche Schlüssel kann die Nachricht nicht mehr auseinander nehmen, denn das Verfahren ist nicht umkehrbar - und der Algorithmus ist zu robust, als dass man ihn knacken könnte. So kann niemand die Nachricht verstehen - außer dem Empfänger, der sie mit dem privaten Schlüssel mühelos in Klartext wandelt.

Die Vorteile asymmetrischer Verfahren scheinen überwältigend - warum kommen dann überhaupt symmetrische Verschlüsselungen zum Einsatz? Hauptsächlich der Geschwindigkeit wegen, denn DES oder IDEA laufen tausendmal schneller. In der Praxis (wie bei PGP) wird nur der kurze geheime Schlüssel mit einem asymmetrischen Verfahren ausgetauscht. Die Verschlüsselung längerer Dokumente übernimmt anschließend ein symmetrischer Algorithmus. Oft kommt ein Session Key für DES oder IDEA zum Einsatz, den einer der Kommunikationspartner mit einem Zufallsgenerator erzeugt, mit dem Public Key des Gegenüber verschlüsselt und über die Leitung sendet. Der andere entschlüsselt den geheimen symmetrischen Schlüssel mit seinem privaten Schlüssel und schon können beide mit dem Session Key symmetrisch verschlüsselte Dokumente austauschen.

Um die Integrität einer Nachricht zu garantieren, also auszuschließen, dass sie ein Böswilliger verändert, bevor sie beim Empfänger ankommt, kommen Message-Digest-Funktionen zum Einsatz.

Diese Verfahren funktionieren nur in einer Richtung: Sie berechnen aus einem längeren Text eine kurze verzwickte Quersumme. So wie es bei weitem einfacher ist, den Inhalt einer Zahnpastatube auszudrücken, als ihn wieder zurück in die Tube zu befördern, fabrizieren diese Einwegfunktionen aus einem Dokument flott einen Hash-Stempel, aber umgekehrt ist es praktisch ausgeschlossen, daraus ein Dokument zu bauen. Eine brauchbare Hashfunktion zeichnet aus, dass sie selten Konflikte produziert, zwei verschiedene Dokumente werden also kaum denselben Stempel erzeugen. Fügt der Absender der Nachricht den Stempel bei, muss der Empfänger nur den Algorithmus über den Nachrichtentext laufen lassen und das Ergebnis mit dem Stempel vergleichen - sind beide gleich, ist die Nachricht unverändert. Hätte hingegen jemand den Text modifiziert, ergäbe die Message-Digest-Funktion einen völlig anderen Stempel-Wert.

Am bekanntesten sind das MD5- und das SHA1-(Secure-Hash-Algorithm)-Verfahren und für beide gibt es natürlich fertige Perl-Module. Listing 5 bindet Digest::MD5 ein, erzeugt mit new ein neues MD5-Objekt und gibt diesem mit der add()-Methode Datenstücke zu fressen. Ein nachfolgender Aufruf der digest()-Methode liefert den Stempelwert. Dieser liegt in binärem Format vor, in dig_md5.pl sorgt die unpack-Funktion dafür, dass alles ins Hex-Format umgewandelt wird, bevor es zur Ausgabe schreitet:

Digest is bf334438d815fe72cc134737b2eea67b
Mehr Infos

LISTING 5

dig_md5.pl erzeugt aus beliebigen Daten einen MD5-Stempel.

 1 #!/usr/bin/perl -w
2
3 use Digest::MD5;
4
5 $md5 = Digest::MD5->new();
6
7 $md5->add("Erstes Feld");
8 $md5->add("Zweites Feld");
9
10 $digest = $md5->digest();
11
12 print "Digest is ", unpack("H*", $digest), "\n";
Mehr Infos

LISTING 6

hmac.pl berechnet den MD5-Stempel einer Datei in Kombination mit einem Schlüssel.

 1 #!/usr/bin/perl -w
...
8 use Digest::HMAC;
9 use Digest::SHA1;
10 use Digest::MD5;
11
12 $METHOD = shift if @ARGV &&
13 $ARGV[0] =~ /^-(md5|sha1)/;
14 usage("No method defined") unless defined $METHOD;
15 $METHOD = "Digest::" . uc(substr($METHOD, 1));
16
17 $KEY = shift or usage("No key given");
18
19 $hmac = Digest::HMAC->new($KEY, $METHOD);
20 $hmac->add(join('', <>));
21 print $hmac->b64digest, "\n";
22
23 sub usage {
24 print "@_\nusage: $0 -md5|-sha1 key [file] ...\n";
25 exit 1;
26 }

Nun könnte natürlich ein besonders Schlauer die Nachricht verändern und gleich einen neuen Message-Digest-Stempel beifügen. Um das zu verhindern, lassen sich die Einwegfunktionen mit kryptographischen Methoden verbinden - das Ergebnis des Stempels ergibt sich dann aus der Kombination der Textdaten mit einem geheimen Schlüssel.

Das Digest::HMAC-Modul bietet eine solche, nach [2] definierte Schnittstelle an. Das Skript hmac.pl ermittelt wahlweise den MD5- oder den SHA1-Stempel, abhängig von einem gewählten Passwort und von Daten, die mittels einer Datei oder der Standardeingabe hereingereicht werden. Für eine leere Datei data.dat ergibt sich:

hmac.pl -md5 ’Geheim!’ data.dat
> y5qhaO//MZW2Xh9vKb07Fw

hmac.pl -sha1 ’Geheim!’ data.dat
> /3WgoJLa/0WlVcF4mAm9uTyBDz4

Der Konstruktor der Klasse Digest::HMAC nimmt den gewählten Schlüssel und den Namen des verwendeten Moduls für das Einwegverfahren entgegen. Die übrigen Methoden von Digest::HMAC sind die gleichen wie bei Digest::MD5 und Digest::SHA1: digest() liefert den Stempel im Binärformat, hexdigest() als Hexzahl und b64digest() nach dem Base-64-Verfahren kodiert.

Mit einem anderen Passwort lässt sich der Stempel nicht reproduzieren:

hmac.pl -md5 ’Geheim’ data.dat
> VaC7hTt27nvnGHIWn5jVJg

Und auch nach nur geringfügigen Veränderungen im Text, etwa wenn man nur den Buchstaben ‘a’ einfügt, ist der Stempel nicht wiederzuerkennen:

hmac.pl -md5 ’Geheim!’ data1.dat
> 5Dp89Kvf0AFeVzY0/g9Skw

Für die Schlüsselwahl schließlich gelten bei den Kryptographieverfahren die gleichen Regeln wie bei der Auswahl von Passwörtern: Unleserliche Wortkombinationen mit Sonderzeichen treiben Spione in den Wahnsinn.

MICHAEL SCHILLI
arbeitet als Web-Engineer für America Online Inc., Mountain View, Kalifornien. Er ist Autor des 1998 bei Addison-Wesley erschienenen Buches ‘GoTo Perl 5’.

[1] Bruce Schneier; Applied Cryptography; 2nd Edition, (December 1995); John Wiley & Sons; ISBN 0471117099

[2] RFC 2104 zum HMAC-Verfahren (ck)