Alexander und Oleg: Die Methoden readHistory und writeHistory funktionieren nun. Baut diese in das GUI ein. Als nächstes brauchen wir eine Schlüsselverwaltung für jedes offene MessageWindow. Dies soll mit Hilfe der Klasse Key bzw. KeyList realisiert werden. Ein neues Objekt vom Typ Key kann man mit den Konstruktoren
Key(int id, String key); Key(int id, String key, long timestamp, boolean selected);initialisieren. Bei dem ersten Konstruktor wird der timestamp auf die aktuelle Zeit und die Variable selected auf true gesetzt. Das Feld String key enthält den Schlüssel, der z.B. per createKey() erzeugt werden kann. Die Schlüssel werden in Dateien verwaltet. Dazu stehen folgende Methoden aus der Klasse CryptFile zur Verfügung:
// liest alle abgespeicherten Schlüssel aus der Schlüsseldatei KeyList readKeys(String verfahren, int buddyid); // schreibt einen neuen Schlüssel in die Schlüsseldatei boolean writeKey(String verfahren, int buddyid, Key schluessel); // liest den aktuell selektierten Schlüssel aus der Datei aus Key getKey(String verfahren, int buddyid); // setzt Schlüssel mit der id -keyid- als den aktuellen Schlüssel boolean setSelectedKey(String verfahren, int buddid, int keyid);Die Klasse KeyList benötigen wir erst einmal nicht, sondern wir arbeiten direkt mit der Klasse Key. Mit getKey erhät man den aktuellen Schlüssel. Sind noch keine Schlüssel für das ausgewählte Verfahren und den Buddy gespeichert, so ist der Rückgabewert null! Mit dem so erhaltenen Schlüsselobjekt kann man nun verschlüsseln. Mit k.getKey() erhält man den Schlüsselstring (den man dann per stringToKey() im CryptSystem verankert).
Wird ein neuer Schlüssel erzeugt, kann man diesen mit der Methode writeKey in die Schlüsseldatei schreiben.
Natürlich müssen erzeugte Schlüssel an den Buddy gesendet werden. Sprecht euch mit der Netzwerkgruppe ab, wie das genau funktioniert. Vielleicht schafft ihr es bis nächste Woche, die Schlüsselübermittlung zu implementieren. Einkommende Schlüssel müssen per writeKey-Methode gespeichert werden.
Die Konfiguration zu jedem Buddy kann man übrigens mittlerweile auch speichern/auslesen, und zwar mit den Methoden
Buddy readBuddy(int); boolean writeBuddy(Buddy);So kann man sich merken, welches Verfahren man zuletzt für diesen Buddy gebraucht hat (kann man im Feld String verfahren des Buddy Objektes festhalten).
Oliver und Philipp: Überprüft den Code der Klasse CryptFile auf mögliche Fehler, die auftreten könnten. Z.B. könnten Dateien nicht vorhanden oder deren Inhalt falsch formatiert sein. Überlegt euch, wie man dadrauf im einzelnen reagieren sollte.
Oliver und Philipp: Für jeden Buddy sollte eine Konfiguration gespeichert werden, und zwar in der Datei data/buddies/config($buddid).xml. Diese enthält folgende Informationen:
<?xml version="1.0" encoding="utf-8"?> <BUDDY> <ID>1</ID> <NAME>Peter</NAME> <IP>192.168.0.107</IP> <VERFAHREN>Vigenere</VERFAHREN> </BUDDY>Ein Buddy-Objekt existiert bereits im package crypto.net, auch mit den entsprechenden Variablen für die vier Felder in der XML-Datei. Wir benötigen nun die zwei Methoden
public boolean writeBuddy(Buddy b); public Buddy readBuddy(int id);um die Konfigurationen zu Lesen/Schreiben. Um die XML-Daten auszulesen, müßt ihr die Klasse BuddyParser erweitern. Orientiert euch hierbei an der Klasse MessageParser, um die XML-Datei Tag für Tag auszulesen und das Buddy-Objekt mit den entsprechenden Werten zu füllen.
Alexander und Oleg: Das Lesen/Schreiben der Serverliste soll geändert werden. Anstatt der Methode CryptFile.readServer() soll die Methode CryptFile.readServer1() benutzt werden. Statt eines String-Arrays wird ein Objekt vom Typ "ServerObjectList" zurückgeliefert (ist von ArrayList abgeleitet). Auf die einzelnen Elemente kann man so zugreifen:
ServerObjectList serverlist; ServerObject server; // liest die Serverliste aus serverlist = readServer1(); for (int i = 0; i < serverlist.size(); i++) { // liest das Element mit Index i aus der Liste aus server = (ServerObject) serverlist.get(i); }Mit den Methoden ServerObject.getName() und ServerObject.getIp() kann man dann jeweils den Namen und die IP des Servers herausfinden. In der JComboBox der Klasse NewServer sollen nur die Namen der Server aufgelistet sein. Wenn man mit dem ausgewählten Server eine Verbindung herstellen möchte, muß man dann die IP des zugehörigen ServerObject benutzen.
Das hört sich erst einmal nach einer Menge Arbeit mit geringem Nutzwert an. Jedoch werden wir die History sowie die Schlüssel später auch aus Dateien auslesen und die Ergebnisse in Listen zurückliefern. Schafft euch also über die oben genannte Aufgabe einen Überblick von der Arbeit mit Objekten vom Typ ArrayList.
Oliver und Philipp: Ich habe in der Klasse CryptFile mehrere Methoden geschrieben, die
das Lesen und Schreiben der Schlüssel in XML Format ermöglichen. Diese neuen
Methoden habe ich im Source Code gekennzeichnet. Die Serverdaten haben wir gestern
schon auf XML umgestellt, das funktioniert auch so weit.
Was jetzt noch fehlt, sind XML Dateien für jeden Buddy. Diese sollten im Verzeichnis
data/buddies/
liegen, als Datei history($buddyid).xml. Das Format sollte folgendermaßen aussehen:
<?xml version="1.0" encoding="utf-8"?> <MESSAGE ID="1" TIMESTAMP="1073648666934" SEND="true">Dies ist die erste Nachricht, die ich verschickt habe</MESSAGE> <MESSAGE ID="2" TIMESTAMP="1073648666955" SEND="false">Dies ist die erste Nachricht, die ich erhalten habe.</MESSAGE> <MESSAGE ID="3" TIMESTAMP="1073648666996" SEND="true">Dies ist die zweite Nachricht, die ich verschickt habe.</MESSAGE>Im Moment soll nur die bisherige Nachrichtenkommunikation in dieser Datei gespeichert werden. Diese soll man auslesen können mit Hilfe der Methode
MessageObjectList readHistory(int buddyid);Eine neue Nachricht soll an das Ende der Datei angehängt werden, und zwar per Aufruf der Funktion
boolean writeHistory(int buddyid, MessageObject m);Die Klassen MessageObject, MessageObjectList, MessageObjectParser sowie das Gerüst der zwei Methoden (in der Datei CryptFile.java) habe ich schon geschrieben. Beim Rest der Implementierung könnt ihr euch an die bestehenden Methoden der Klasse CryptFile anlehnen, die ich speziell gekennzeichnet habe, z.B. readKeys und writeKeys.
Alexander und Oleg: Sprecht euch mit der Netzwerkgruppe ab, um die Nachrichtenübermittlung
zwischen zwei Clients korrekt zu implementieren. Wäre schön, wenn das bis
nächste Woche reibungslos funktioniert.
Nächste Woche stellen wir dann im GUI die Methoden um, die den Lese-/Schreibzugriff
auf Dateien regeln (für die Serverliste, Keys, etc.).
Oliver/Philipp: Die Methoden
boolean writeServer(String[] server); String[] readServer(); String readKey(String verfahren, int buddyid);funktionieren soweit. Die Methode
boolean writeKey(String verfahren, int buddyid, String key);muß noch angepasst werden. Falls zum ersten Mal ein Schlüssel für dieses Verfahren und diesen User angelegt wird, speichert man den Schlüssel wie gehabt in "$buddy_id.key". Falls aber schon ein Schlüssel existiert, muß dieser in der Datei "$buddy_id.old" abgelegt werden, um ihn nachher wieder rekonstruieren zu können. Dabei dürfen noch ältere Schlüssel natürlich nicht überschrieben werden. Am besten den zu speichernden Schlüssel ans Dateiende anfügen.
Alexander/Oleg: Falls ein Buddy ausgewählt ist, muß mit Hilfe der Methode readKey(String verfahren, int buddyid) und der Methode CryptSystem.stringToKey(String k) der jeweilige Schlüssel im Objekt "CryptSystem" abgespeichert werden. Falls noch kein Schlüssel für dieses Verfahren und diesen Buddy existiert, soll automatisch ein Zufallsschlüssel erzeugt werden (CryptSystem.createKey()).
Der Schlüsselbutton im Hauptfenster kann in das MessageWindow verlagert werden. Damit soll man dann später die erzeugten Schlüssel seinem Buddy schicken können.
Wenn eine Nachricht verschickt wird, muß diese mindestens folgende Informationen enthalten:
Der letzte Wert wird nach dem Aufrufen der Methode encrypt in der Variable
int attached der Klasse CryptSystem gespeichert.
Die ist momentan noch als protected deklariert,
das muß die Kryptographiegruppe dann noch ändern.
Bzw. getter und setter Methoden definieren.
Je nachdem, wie gut die Versendung von Nachrichten schon funktioniert, könnt ihr euch
überlegen, wie man diese Informationen allesamt verschickt. Am besten mit der
Netzwerkgruppe absprechen.
public String readKey(String verfahren, int buddyId); public boolean writeKey(String verfahren, int buddyId); public String readServer(); public boolean writeServer(String Server);
Die Schlüssel werden in der Datei "data/keys/" + verfahren + "/" + buddyId + ".key" abgelegt.
Die Serverliste speichern wir in der Datei "data/server/serverlist.txt"
Beschreibung der Methoden:
Dabei ist zu beachten, daß man die entsprechenden Verzeichnisse neu anlegen muß,
falls diese noch nicht existieren. Das Überprüfen, ob Verzeichnisse existieren, und
das anlegen neuer Verzeichnisse, bewältigt man mit der Klasse "File" in java.io.
Zum Anlegen, Lesen und Schreiben von Dateien benutzt man die Klasse "FileReader" bzw.
"FileWriter". Wie das genau geht, steht in Kapitel 18 im Javabuch beschrieben.
crypto.stringToKey(String k);im Objekt crypto der Klasse CryptSystem gespeichert. Zusätzlich soll es einen Button geben, der einen randomisierten Schlüssel erzeugt. Das geht mit der Methode
crypto.createKey();Falls ein Buddy ausgewählt ist, sollte automatisch die Methode
readKey(String verfahren, int buddyId);angesprochen werden. Diese wird im Moment von Oliver und Philipp implementiert. Außerdem brauchen wir noch einen Button, der einen erzeugten Schlüssel an einen Buddy schickt.
Bei dem Connection-Dialog sollte man die Möglichkeit haben, einen neuen Server hinzuzufügen, aus mehreren bereits existierenden Servern auszuwählen, und einzelne Server aus der Liste zu streichen. Hierfür legt man am besten eine neue Klasse (z.B. "ServerObject") an, welche Namen und IP des Servers beinhaltet. Diese ganzen Operationen funktionieren natürlich erst, wenn das Lesen und Schreiben auf der Datei "server.txt" klappt.
Je nachdem, wie weit die Client-Client Kommunikation schon ist, könnt ihr außerdem versuchen, die Nachrichtenübermittlung zu implementieren. Bei Fragen wendet euch an Pavel und David.
Die Aufgaben werden auf jeweils 2 Leute verteilt:
// crypto ist das aktuell ausgewählte CryptSystem-Objekt String key = crypto.keyToString(); // in der Variablen key ist nun der Schluessel gespeichert // funktioniert momentan leider nur mit dem Verfahren Caesar... // bis Donnerstag ist die Methode keyToString auch fuer die // anderen Verfahren implementiert
Erweitert das GUI um eine Buddylist. Beim Anklicken eines
Namens (werden zur Zeit noch statisch generiert) soll
ein Dialogfenster geöffnet werden, mit dem man
Nachrichten verschicken kann. Beim Design könnt
ihr euch an ICQ halten.
Im Hauptfenster könnt ihr schon die Kryptographieprotokolle
"Caesar" und "Vigenere" benutzen, um Nachrichten zu ver- und
entschlüsseln.
Dies erreicht man so:
/* im stringarray "verfahren" der klasse "Kryptosystem" sind die * angebotenen verfahren aufgelistet. im moment * funktionieren die verfahren Caesar und vigenere * ... hier wird der schluessel automatisch erzeugt * falls man einen schluessel mitgeben moechte, geht das so: * Kryptosystem k = Kryptosystem.neu("Caesar", "T"); */ Kryptosystem k = Kryptosystem.neu(Kryptosystem.verfahren[0]); /* klartext string */ k.klartext = "abc"; // testoutput System.out.println("Klartext: " + k.klartext); System.out.println("Schluessel: " + k.schluessel); // verschluesseln k.verschluesseln(); System.out.println("Chiffretext: " + k.chiffretext); // entschluesseln k.entschluesseln(); System.out.println("Klartext: " + k.klartext);
Die .java Dateien kann man sich unten herunterladen.
Außerdem könnt ihr euch das Programm CrypTool installieren und dessen Fähigkeiten schon einmal ausprobieren.
Ihr sollt das bereits bestehende GUI folgendermaßen erweitern:
Ich habe extra kein Bild eingefügt, laßt also eurer künstlerischen Freiheit freien Lauf :-)
Die Gruppe Kryptographie wird in 1-2 Wochen die ersten Verschlüsselungsmethoden implementiert haben. Diese werden in etwa so aussehen:
public class Caesar{ /* verschluesselt einen klartext, schluessel ist ein character */ public String verschluesseln(String klartext, String schluessel); /* entschluesselt einen klartext, schluessel ist ein character (string der laenge 1) */ public String entschluesseln(String chiffretext, String schluessel); /* erzeugt einen randomisierten schluessel */ public String schluesselErzeugen(); /* erzeugt den schluessel, der als parameter uebergeben wird */ public String schluesselErzeugen(String schluessel); }
Diese Methoden werden wir nächste Woche in das GUI integrieren, um eine wirkliche Verschlüsselung durchzuführen.
Viel Spass beim Programmieren!
Wir wollen eine einfache Swing Oberfläche erstellen.
Das Fenster soll zwei Eingabefelder und einen Button enthalten.
Im ersten Eingabefeld soll man einen Text eingeben können,
im zweiten nur einen einzelnen Charakter. Bei Betätigung
des Buttons soll eine Funktion aufgerufen werden, die
die Argumente der zwei Textfelder auf der Konsole ausgibt
(per System.out.println).
Am besten auch direkt javadoc-konform alles dokumentieren :)
Wie das geht steht auf der Hauptseite beschrieben.