Date: Mon, 6 Dec 1999 08:16:23 -0500 (EST)
From: support@redtenbacher.de
Subject: Automat. Ver-/Entschluesselung von E-Mail, Teil IIIc
Sehr geehrte "signatur"-Abonnenten,
im 3. Schritt des Implementierungsleitfadens für Programmierer
einer automatischen Ver-/Entschlüsselung/Signatur von E-Mail geht
es nun um die genauen Vorgänge, die im Fall einer
verschlüsselten/signierten Eingangsmail ablaufen sollten, um
maximale Interoperabilität mit den existierenden
OpenPGP-kompatiblen Programmen und -Plugins sicherzustellen.
Schritt 3: Abwicklung von Signatur/Entschlüsselung bei
Eingangsmails: Formate, Algorithmen
Um maximale Interoperabilität sicherzustellen, sollte unser
Entschlüsselungs-Modul sowohl mit verschlüsselten (+ggf.
signierten) Mails als auch mit unverschlüsselten, aber signierten
Klartext-Mails, jeweils in ein- und mehrteiliger Form und in den
Formaten "OpenPGP" (RFC 2440) oder "PGP-MIME" (RFC 2015)
zurechtkommen, d.h. all diese Formate automatisch erkennen und
entschlüsseln (bzw. die Signatur verifizieren).
Dann wird alles, was von irgendeiner existierenden PGP-Version,
einem PGP-Plugin oder einem OpenPGP-kompatiblen Produkt erzeugt
wird, richtig erkannt und automatisch entschlüsselt.
Dieser hohe Anspruch ist gar nicht so schwierig umzusetzen, wenn
man richtig herangeht.
Die relevanten Datenformate sind in 3 Internet-Standards
beschrieben:
RFC 2440: "OpenPGP Message Format"
(siehe unter "http://www.ietf.org/rfc/rfc2440.txt")
RFC 2045: "MIME Part 1: Format of Internet Message Bodies"
(siehe unter "http://www.ietf.org/rfc/rfc2045.txt")
RFC 2015: "MIME Security with Pretty Good Privacy (PGP)"
(siehe unter "http://www.ietf.org/rfc/rfc2015.txt")
Die von "KT-MAIL/Krypto" gewählte Vorgehensweise werde ich
wieder, wie in Teil IIIb, nachfolgend in Pseudo-Code näher
beschreiben.
Entschlüsselungroutine von KT-MAIL/Krypto:
Im Fall von KT-MAIL wird die Entschlüsselungsroutine unmittelbar
vor der internen Postverteilung aufgerufen, d.h. zu einem
Zeitpunkt, an dem die Internet-Transportkodierung einer
Eingangsmail (MIME, UUENCODE oder BinHex) bereits entfernt ist.
Falls dies bei Ihrem Mail-System anders ist, müssen Sie daher
ggf. zuerst eine Dekodierung aus dem Internet-Transportformat
vornehmen. Wer dafür noch kein geeignetes Programm hat, kann die
Algorithmen für einen Dekoder, der die Internet-Formate "MIME
Quoted Printable", "MIME Base64", "UUENCODE", "BinHex" und das
Microsoft-spezifische MS-TNEF-Format automatisch erkennt und
dekodiert, dem Programm MAILIN entnehmen, das Sie als Quellcode des
Hauptmoduls (MAILIN.MOD) sowie als kompilierte EXE-Datei (MAILIN.EXE)
unter "http://www.redtenbacher.de/signatur/mailutil.zip" in einem
ZIP-Archiv (MAILUTIL.ZIP) finden.
Anschließend können Sie die Vorgehensweise des Krypto-Moduls von
KT-MAIL verwenden:
"Subject:"-Header der Eingangsmail suchen und daraus die
Zeichenfolgen "!V!", "!S!", "!VS!" und "!SV!" in jeder
Schreibweise groß/klein löschen; anschließend alle
Message-Zeilen löschen, die den Text
"=====*DER*PGP-NACHRICHT=====" (mit "*" als Jokerzeichen)
enthalten.
[Hinweis: Dieser Schritt verhindert, daß jemand von außen eine
Mail schickt, die die Verschlüsselungs-/Signaturmarkierungen
von "KT-MAIL/Krypto" simuliert, um einem Nutzer des Programms
eine scheinbar korrekt signierte Mail eines anderen
unterzujubeln. Falls Sie für die internen Markierungen für
Verschlüsselung/Signatur andere Markierungen als
"KT-MAIL/Krypto" verwenden, sind die Löschbefehle natürlich
entsprechend anzupassen.]
EndZeile := (Zeilennr. der Leerzeile, die die Header-Zeilen der
Eingangsmail vom eigentlichen Mailinhalt trennt);
Sprungmarke "NextInBlock":
AnfZeile := (niedrigste Zeilennummer größer als 'EndZeile',
deren Text entweder mit "-----BEGIN PGP MESSAGE-----" oder mit
"-----BEGIN PGP SIGNED MESSAGE-----" anfängt);
IF (keine [weitere] solche Zeile gefunden)
THEN
GOTO DoneInMail
END;
Entschlüsseln := (Zeile Nr. 'AnfZeile' enthält kein "SIGNED");
[Hinweis: Eine signierte Klartext-Mail beginnt mit "BEGIN PGP
SIGNED MESSAGE", eine verschlüsselte (+ggf. signierte) Mail
hingegen mit "BEGIN PGP MESSAGE".]
EndZeile := (Nr. der letzten Zeile der verschlüsselten oder
signierten Mail [bei signierten Klartext-Mails ist das die
Zeile "-----END PGP SIGNATURE-----", bei verschlüsselten Mails
die Zeile "-----END PGP MESSAGE-----"]);
IF (keine solche Zeile gefunden)
THEN
GOTO NextInBlock
END;
Textblock von 'AnfZeile' bis 'EndZeile' (inkl. dieser beiden
Zeilen mit "BEGIN/END PGP ...") in ein eigenes Fenster kopieren
und als Datei M.SRC speichern, dann evtl. vorhandene Dateien
M.DST und M.CMT löschen;
[Hinweis: Die Dateinamen "m.src" (Message Source), "m.dst"
(Message Destination) und "m.cmt" (Message Comment) sind hier
willkürlich gewählt. Man kann also für diese 3 Temporärdateien
auch 3 andere, feste Dateinamen wählen, die immer wieder
überschrieben werden.]
Mantra := "";
IF (Entschlüsseln="FALSE")
THEN
GOTO DecryptVerify
END;
Programmaufruf: "pgpscan m.src/K";
[Hinweis: Eine verschlüsselte OpenPGP-Datei enthält die KeyIDs
der Empfängerschlüssel in den PGP-Daten der Mail versteckt.
Da wir möglicherweise auf unserem System mehrere private
Schlüssel haben, aber nur den Paßworttext für genau 1 dieser
Schlüssel an PGP übergeben können, müssen wir vorab
herausfinden, für welche(n) Empfänger die Eingangsmail
verschlüsselt ist.
Zum Auslesen dieser Empfängerschlüssel dient das Programm
PGPSCAN, das mit dem Dateinamen der zu prüfenden Datei
aufgerufen wird. (Der Aufruf ohne Option "/K" analysiert und
listet alle PGP-Pakete der Datei, der Programmaufruf mit "/K"
für "Nur Key-IDs extrahieren" liest lediglich die Key-IDs der
Empfängerschlüssel aus und schreibt sie in die Datei
PGPSCAN.KEY.)
Das Programm PGPSCAN finden Sie als Quellcode des Hauptmoduls
(PGPSCAN.MOD) sowie als kompilierte EXE-Datei (PGPSCAN.EXE) im
ZIP-Archiv MAILUTIL.ZIP unter
"http://www.redtenbacher.de/signatur/mailutil.zip".]
IF (Datei PGPSCAN.KEY existiert nicht oder hat 0 Bytes Größe)
THEN
Entschlüsseln := FALSE;
GOTO DecryptVerify
END;
[Hinweis: Signierte Klartext-Mails haben wir vorab
ausgesondert. Diese können daher an dieser Code-Stelle nicht
auftreten. Es könnte sich aber immer noch um eine signierte
Binärdatei handeln, die äußerlich genau wie eine verschlüsselte
Datei aussieht, aber in den PGP-Daten keinen Empfängerschlüssel
enthält. Solche PGP-Mails ohne Empfängerschlüssel sind daran zu
erkennen, daß das Programm PGPSCAN eine Datei PGPSCAN.KEY mit
0 Bytes Größe erzeugt. (Ist die PGP-Datei fehlerhaft, so fehlt
hingegen die Datei PGPSCAN.KEY gänzlich.)]
Lade die Datei PGPSCAN.KEY, gehe ihre Zeilen der Reihe nach durch
und vergleiche diese KeyIDs mit den KeyIDs, die im Schritt 2
(Initialisierung des Krypto-Moduls) in den Variablen
'PGPKeyzzzzzzzz' gespeichert wurden:
IF (keine passende Variable gefunden)
THEN
GOTO NextInBlock
END;
[Wenn wir auf unserem Schlüsselbund keinen passenden
Empfängerschlüssel haben, können wir diesen PGP-Block der
Eingangsmail auch nicht automatisch entschlüsseln und
lassen ihn daher unverändert - denn es könnte ja sein, daß der
Endbenutzer noch einen lokalen PGP-Schlüsselring für
supergeheime Nachrichten hat, die auch vor dem
Mailserver-Administrator geheim gehalten werden sollen und
daher manuell beim Endbenutzer entschlüsselt werden.]
Mantra := (Paßworttext des zum Empfängerschlüssels gehörenden
Signaturschlüssels);
[Hinweis: Dem Wert der passenden Variablen 'PGPKeyzzzzzzzz'
kann die KeyID "xxxxxxxx" des zugehörigen Signaturschlüssels,
und dann dem Wert der entsprechenden Variablen 'PGPPWxxxxxxxx'
(vgl. Schritt 2, Initialisierung des Krypto-Moduls) wiederum
der Paßworttext zum Empfängerschlüssel entnommen werden.
Falls Ihre Entwicklungsumgebung keine dynamisch generierten
Variablennamen unterstützt, läßt sich die benötigte
Funktionalität alternativ auch über POINTER auf den jeweils
zugehörigen Paßworttext realisieren.]
Sprungmarke "DecryptVerify":
[Hinweis: Hier erfolgt die eigentliche Entschlüsselung
(Mantra<>"") bzw. Signaturprüfung (Mantra="").]
IF (Mantra="")
THEN
Programmaufruf der Art:
'pgp -v m.src -o m.dst +batchmode >m.cmt'
ELSE
Programmaufruf der Art:
'pgp -v m.src -o m.dst +batchmode -z"Mantra" >m.cmt'
END;
[Hinweis: Die Programmaufrufe sind für PGP 5.0 (DOS) angegeben
und sind bei Verwendung anderer PGP-Versionen oder des "Gnu
Privacy Guard" entsprechend anzupassen. Außerdem setzen die
obigen Programmaufrufe voraus, daß in der Datei PGP.CFG die
beiden Zeilen "OutputInformationFD=1" und "OutputWarningFD=1"
stehen, damit Ausgabekommentare und Warnungen von PGP in die
Datei "m.cmt" (Message Comment) geschrieben werden.]
IF (Datei M.DST existiert nicht oder hat 0 Bytes Größe)
THEN
GOTO NextInBlock
END;
[Hinweis: Wenn beim Entschlüsseln irgend etwas schiefgeht
(keine Ergebnisdatei), lassen wir diesen PGP-Block
unverändert. Normalerweise sollte dieser Fall allerdings
nur auftreten, wenn der Mailserver-Administrator den
Paßworttext für den Empfängerschlüssel falsch
eingegeben hat.]
DatName := (Dateiname des PGP-Blocks, sofern in der Eingangsmail
enthalten [z.B. über einen "Content-Type:"-Eintrag
mit Parameter "name=..." oder einen
"Content-Disposition:"-Eintrag mit Parameter
"filename=...", der vom Programm MAILIN.EXE oberhalb
des PGP-Blocks eingetragen wird], sonst leer);
IF ('DatName' endet auf ".asc")
THEN
Endung ".asc" aus Variable 'DatName' entfernen
END;
DatTyp := (Typ der Datei M.DST [Text/Binär]);
[Hinweis: Die Typbestimmung kann z.B. mit dem Programm FILETYPE
erfolgen, das Sie als Quellcode des Hauptmoduls (FILETYPE.MOD)
sowie als kompilierte EXE-Datei (FILETYPE.EXE) unter
"http://www.redtenbacher.de/signatur/mailutil.zip" finden.
Dieses Programm prüft die angegebene Datei und klassifiziert
5 Typen:
A = Textdatei mit 7-Bit-ASCII-Zeichen
L = Textdatei mit 8-Bit-Zeichen innerhalb von Latin1
T = Textdatei mit 8-Bit-Zeichen außerhalb von Latin1
M = Komforttext-Makro o.ä. (enthält CHR$(0)-Zeichen)
B = Binärdatei
Der gefundene Typ wird als Datei FILETYPE.LST (mit 1 Byte
Größe) geschrieben. In unserem Fall brauchen wir keine so
detaillierte Klassifizierung, daher würde der Ablauf der
Typbestimmung etwa so aussehen:
Programmaufruf der Art: "filetype m.dst";
Datei FILETYPE.LST laden;
IF (1. Zeichen ist "M" oder "B")
THEN DatTyp := "Binär"
ELSE DatTyp := "Text"
END; ]
IF (DatTyp="Text")
THEN
1. Zeile der Datei M.DST laden;
IF (dort steht "MIME-Version: ...")
THEN
DatTyp := "PGP-MIME"
END;
END;
[Hinweis: Wir hatten uns vorgenommen, auch die PGP-MIME-
Erweiterungen gemäß RFC 2015 in Eingangsmails zu unterstützen.
Dazu brauchen wir bei unserer Vorgehensweise lediglich nach dem
Entschlüsseln zu prüfen, ob das Ergebnis wiederum eine
MIME-Datei ist, und wenn ja, diese noch einmal über das
Programm MAILIN dekodieren.]
IF (DatTyp="PGP-MIME")
THEN
Programmaufruf der folgenden Art: "mailin m.dst"
ELSIF (DatTyp="Binär")
THEN
IF (DatName="")
THEN
DatName := "binmail.000"
[Hinweis: Dadurch wird sichergestellt, daß wir einen
gültigen Dateinamen für die Binäranlage haben]
END;
Programmaufruf der Art "mailout m.dst/B<DatName>";
Programmaufruf der Art "mailin m.dst" (mit anschließendem
Umbenennen der Ergebnisdatei MAIL.MSG in M.DST);
[Hinweis: KT-MAIL leitet Binärdateien aus Sicherheitsgründen
_nicht_ direkt zum Endbenutzer weiter (mit Ausnahme von
DOC-Dateien, die aber vorher zu RTF konvertiert werden);
statt dessen landen Binärdateien in einem
"Quarantäne"-Verzeichnis, und der Endbenutzer bekommt nur
einen entsprechenden Hinweis auf die Binärdatei in seiner
Mail. Dieser Hinweis wird vom Programm MAILIN erzeugt, das
auch die Verwaltung der Dateinamen der Binäranlagen erledigt.
Daher ruft der Krypto-Modul im Fall von entschlüsselten
Binärdateien einfach den Kodierer MAILOUT (mit der Option zum
Erzeugen einer "MIME Base64"-Kodierung) und gleich danach den
Dekodierer MAILIN auf. Anschließend ist die Datei M.DST nur
noch eine Textdatei, die einen Verweis auf die
Original-Binäranlage im Quarantäne-Verzeichnis enthält.
Das Programm MAILOUT finden Sie als Quellcode des Hauptmoduls
(MAILOUT.MOD) sowie als kompilierte EXE-Datei (MAILOUT.EXE)
unter "http://www.redtenbacher.de/signatur/mailutil.zip".
Sollen bei Ihrem Mail-System die Binärdateien direkt zum
Endbenutzer durchgeleitet werden, sind die Konverteraufrufe
entsprechend zu modifizieren: Virenscanner aufrufen; falls
Datei okay ist, dann den Konverter MAILOUT aufrufen; den
Aufruf von MAILIN weglassen und statt dessen bei der
Sprungmarke "DoneInMail" (siehe unten) im Fall von
mehrteiligen MIME-Mails die MIME-Header-Zeilen passend
modifizieren - denn das Programm MAILOUT produziert
einteilige MIME-Dateien.]
END;
Lade die Datei M.CMT (mit den PGP-Kommentaren zur Dekodierung
bzw. Prüfung der Signatur);
IF (Entschlüsseln="TRUE")
THEN
Füge davor eine Zeile folgender Art ein:
"=====STATUS DER PGP-NACHRICHT====="
ELSE
Füge davor eine Zeile folgender Art ein:
"=====STATUS DER SIGNIERTEN PGP-NACHRICHT====="
END;
Schreibe die ergänzte Datei M.CMT zurück;
Lade die Datei M.DST (mit dem entschlüsselten Textinhalt des
PGP-Blocks);
IF (Entschlüsseln="TRUE")
THEN
Füge davor eine Zeile folgender Art ein:
"=====ANFANG DER PGP-NACHRICHT====="
und ans Ende eine Zeile wie:
"=====ENDE DER PGP-NACHRICHT====="
ELSE
Füge davor eine Zeile folgender Art ein:
"=====ANFANG DER SIGNIERTEN PGP-NACHRICHT====="
und ans Ende eine Zeile wie:
"=====ENDE DER SIGNIERTEN PGP-NACHRICHT====="
END;
Schreibe die ergänzte Datei M.DST zurück;
Kehre zum Fenster mit der Original-Eingangsmail zurück;
Lösche daraus die Zeilen von "AnfZeile" bis "EndZeile" sowie
alles davor bis zum letzten Blocktrenner;
[Hinweis: Die Details der Zeilen vor dem PGP-Block hängen hier
von Ihrem Dekodierer ab. Bei MAILIN steht unmittelbar vor
"AnfZeile" der zu löschende Trenner, und im Fall einer
PGP-MIME-Datei kann davor noch ein leerer Blockteil stehen, der
ebenfalls gelöscht werden sollte.]
Füge statt des gelöschten PGP-Blocks in die Eingangsmail den
Inhalt der Datei M.CMT und dahinter den Inhalt der Datei M.DST
ein;
EndZeile := (Zeilennr., auf der anschließend die letzte Zeile der
eingefügten Datei M.DST steht);
GOTO NextInBlock;
Sprungmarke "DoneInMail":
Alle Fenster bis auf dasjenige mit der Eingangsmail schließen;
IF (Eingangsmail enthält jetzt eine Zeile mit
"=====ANFANG DER PGP-NACHRICHT=====")
THEN
Füge ans Ende des "Subject:"-Headers den Hinweis "!V!" an
[Hinweis: Der Zusatz "!V!" garantiert, daß eine Antwortmail auf
diese verschlüsselte Eingangsmail standardmäßig ebenfalls
verschlüsselt wird - siehe Teil I, "Die Sicht des
Endanwenders".]
END;
Schleuse die Ergebnisdatei ins normale Mail-System zur Zustellung
an den Empfänger im Haus ein [siehe Teil IIIa, "Einfügen einer
Dateischnittstelle in ein bestehendes Mail-System"].
ENDE der Entschlüsselungroutine von KT-MAIL/Krypto.
[Hinweis: Im Fall von KT-MAIL wird die Entschlüsselungsroutine
automatisch für jede Eingangsmail einzeln aufgerufen. Bei
anderen Mail-Systemen ist daher der obige Ablauf ggf. um eine
Schleife über alle wartenden Eingangsmails zu ergänzen.]
Damit ist der Schritt 3 des Leitfadens für Programmierer
abgeschlossen. Im 4. (und letzten) Abschnitt behandeln wir dann
den Ablauf bei der Abwicklung von Signatur/Verschlüsselung von
Ausgangsmails.
- Wolfgang Redtenbacher
"signatur"-Moderator
[Zurück zur Hauptseite des
Verschlüsselungsprojekts]