Socket publicKey mittels DatagramPacket übertragen

Lord_Aratorn

Aktives Mitglied
Es soll eine Netzwerkkommunikation zwischen mehreren Rechnern über UDP realisiert werden.
Die Kommunikation selber soll verschlüsselt abgehandelt werden (RSA).

Ich habe mir bereits für jeden Rechner ein KeyPair kreiert. Nun muss der PublicKey übers Netzwerkübertragen werden, vom Zielrechner ausgelesen und gespeichert werden um anschließend sämtliche ausgehenden Nachrichten mit Diesem zu verschlüsseln.
Da das Netzwerk über UDP kommunizieren soll, nutze ich DatagramPacket. DatagramPacket.getData() liefert ein byte[] der enthaltenen Daten.
Nun stellt sich die Frage, wie ich einen Key über das Netzwerk übertrage.

Ich habe dafür folgenden Code geschrieben
Code:
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream (bos);
oos.writeObject(publicKey);
oos.close();
System.out.println(bos);
DatagramPacktet p = new DatagramPacket();
p.setData(bos);
//anschließend wird das Packet versendet

Auf der entgegengesetzten Seite muss ich das Paket entpacken, dazu nutze ich folgenden Code
Code:
//Packet ist angekommen. Referenz heizt p
byte[] buffer = p.getData();
ByteArrayInputStream bis = new ByteArrayInputStream(buffer); 
ObjectInputStream ois = new ObjectInputStream(bis); // java.io.StreamCorruptedException: invalid stream header: EFBFBDEF
Key nodeKey = (Key)ois.readObject();

Es fliegt jedoch eine Exception ->"//java.io.StreamCorruptedException: invalid stream header: EFBFBDEF". Ich habe das Netzwerk gesnifft. Das gesendete Packet enthällt den Schlüssel.Jedoch frage ich mich, wie er wieder ausgelesen werden kann.
 
Zuletzt bearbeitet:
S

SlaterB

Gast
> p.setData(bos);
fehlt da noch toBytes() oder so?

mach mal bisschen Fehlereingrenzung:
schau dir doch auf Client-Seite das byte[] an, wie lang, wie lauten die ersten Bits,
kannst du direkt auf das byte[] einen ByteArrayInputStream bis zum ObjectInputStream erfolgreich laufen lassen?

und dann das gleiche auf dem Server, was kommt da für ein byte[] an, wie lang, wie sehen die Bits aus?
entweder es gibt direkt auf dem Client schon eine Exception, oder irgendeinen Unterschied in den Bits,
oder der Server versteht dieselben Bits anders,

ich bezweifle, dass ich in jedem Fall weiter weiß, aber das wäre schon eine Eingrenzung
 

Lord_Aratorn

Aktives Mitglied
> p.setData(bos);
fehlt da noch toBytes() oder so?
nein, das ist so richtig. Das wird implizit gecasted.

Ich habe mir nun mal eine Testclass geschrieben, die wie folgt aussieht:

Code:
public class Bytetest {
	public static void main(String[] args) {
		try {
			byte[] buffer = new byte[1024];
			for (int i = 0; i < buffer.length; i++) {
				buffer[i] = (byte) (Math.random() * 8);
			}
			ByteArrayInputStream bis = new ByteArrayInputStream(buffer);
			ObjectInputStream ois = new ObjectInputStream(fis); //selbe exception hier
			ois.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
Sie wirft mir ebenfalls die selbe Exception. Es scheint so als mache ich etwas falsch, beim erzeugen des OIS.
Muss man muss doch wohl keinen Outputstream erzeugen, bevor man lesen kann, oder?

Eine Vermutung habe ich noch. Kann es sein, dass es am OS liegt? Ich nutze hier ein Ubuntu.
 
Zuletzt bearbeitet:
S

SlaterB

Gast
häh, ein byte[] mit völlig zufälligen Inhalt?
daraus kann man keine Objekte lesen, das ist doch ein irrelevanter Vergleich,

ein ObjectOutputStream schreibt dagegen geordnete Bytes

edit: es gibt auch Java-Tags statt Code-Tags
 

Lord_Aratorn

Aktives Mitglied
häh, ein byte[] mit völlig zufälligen Inhalt?
daraus kann man keine Objekte lesen, das ist doch ein irrelevanter Vergleich,

ein ObjectOutputStream schreibt dagegen geordnete Bytes

edit: es gibt auch Java-Tags statt Code-Tags

Ja, ich weiß, dass ich auß Zufallswerten keine Objekte lesen kann, doch darum geht es auch nicht. Es geht darum, dass ich keinen ByteArrayInputstream in einen OOS stecken kann, ohne das die Exception fliegt. Ist ein byte[] nicht auch ein Objekt?
 

Murray

Top Contributor
Es geht darum, dass ich keinen ByteArrayInputstream in einen OOS stecken kann, ohne das die Exception fliegt. Ist ein byte[] nicht auch ein Objekt?
Natürlich ist ein byte[] auch ein Object- weil in Java alles ein Object ist. Trotzdem kann ObjectInputStream nicht jedes Byte-Array "verstehen"; ein OIS versteht genau solchen Byte-Ströme, die ein ObjectOutputStream geschrieben hat - der wird nämlich zusätzlich zu den Nutzdaten solche Kleinigkeiten wie den Namen der Klasse geschrieben haben
 

Kr0e

Gesperrter Benutzer
Hallo, die Impl vom ObjectInputStream.:

Java:
    protected void readStreamHeader()
	throws IOException, StreamCorruptedException
    {
	short s0 = bin.readShort();
	short s1 = bin.readShort();
	if (s0 != STREAM_MAGIC || s1 != STREAM_VERSION) {
	    throw new StreamCorruptedException(
		String.format("invalid stream header: %04X%04X", s0, s1));
	}
    }

Man kann einen ObjectInputStream ganz leicht überzeugen, dass der Stream ok ist... Ich denk mal das sieht jeder...

Achja, das hier ist uncompilierbar:

Java:
			ByteArrayOutputStream b = new ByteArrayOutputStream();
			DatagramPacket dp = new DatagramPacket(null, 500);
			dp.setData(b);

Die Methode oben wird aufgerufen vom Konstruktor...

ByteBuffer.wrap(buffer).putShort((short)0xaced).putShort((short)5);

Das musst du aufrufen, nachdem du dein byte[] array gefüllt hast und bevor du damit den ByteArrayInputStream fütterst

Genau genommen dürfte dieses Problem aber nicht auftreten, das der ObjectOutputStream genau diese beiden Werte bereits frölich in den ByteArrayOutputStream schreibt... Vorrausgesetzt der ByteArrayOutputStream kritzelt nicht auf iwas darein (Was er glaub ich nicht tut!) dann dürftest du ansich kein Problem haben.

Java:
	public static void main(String[] args) throws Exception {
		ByteArrayOutputStream b = new ByteArrayOutputStream(1024);
		ObjectOutputStream oos = new ObjectOutputStream(b);
		oos.writeObject("Hello!");
		oos.close();

		
		ByteArrayInputStream bis = new ByteArrayInputStream(b.toByteArray());
		ObjectInputStream ois = new ObjectInputStream(bis);
		System.out.println(ois.readObject());
		ois.close();
	}

Hier wird bei mir keine Exception geworfen... Iwas geht vlt. bei der Übertragung flöten...



Gruß,
Chris
 
Zuletzt bearbeitet:

Lord_Aratorn

Aktives Mitglied
Ok, ich denke ich habe die Stelle finden können, an dem das Problem auftritt.

Wie gesagt, verschicke ich den Key (das Objekt) über den UDP-Stream (als Byte).

Wenn nun vor dem Senden und Nachdem Empfangen die Länge des Keys ausgegeben wird, ist diese auch identisch.
Jedoch beinhaltet das Paket, das Den Key enthält noch andere Informationen. Die Daten innerhalb des Packetes sind durch einen "|" getrennt.

Nachdem ich das Paket erhalten habe, erzeuge ich aus den Packetdaten einen String. Auf diesem String einen StringTokenizer mit "I" als Delim. Und laufe dann anschließend die einzelnen Tokens ab. Also auch den Token, in dem der Key steckt. Wenn ich nun allerdings genau auf diesem Token String.getBytes() aufrufe. Erhalte ich ein Byte[] welches länger ist als jenes, das ich zu Beginn in einen String stopfte. Und genau das hindert mich am deserialisieren zum Objekt.

Nun habe ich mir dazu Gedanken gemacht. Ich weiß, dass es eine dumme Idee ist, einen Char als Trennsymbol zu nutzen. Gerade bei verschlüsselten Nachrichten kann nicht sichergestellt werden, dass das Trennsymbol nicht generiert wird. Daher würde sich die alte bewerte Methode eines Längenwertes empfehlen. Oder es werden eine Menge unterschiedliche Pakete erstellt, die jeweils Unterschiedlich serialisiert und deserialisiert werden(Java Network). Dies ist wiederum großer Auffand beim Verwalten und es können sich allerhand Fehler beim serialisieren einschleichen.

Daher nun Meine Frage.
1) wie kann ich meine Urproblem beheben?
2) wie sollte ich die Architektur der Pakete verändern oder anpassen?
 
S

SlaterB

Gast
> erzeuge ich aus den Packetdaten einen String

kannst du die Packetdaten nicht als byte[] erhalten und darin paar Bytes abtrennen? diese Rest kann dann ja zum String werden falls benötigt,
die bytes für den ObjectStream sollten nie zum String werden,

es sei denn kontrolliert, auf Sendeseite hast du ja das byte-Array aus dem ByteArrayOutputStream,
und das kannst du in einem String umwandeln, z.B. mit Ziffern drin passend zu den Bytes "32876ABE23"usw,

ein solcher normal ungefährlicher String kann dann wahrscheinlich ruhig beliebig übertragen werden, zu Bytes im Datagram, am Empfänder wieder String draus usw., da sollte nix kaputt gehen,
beim Empfänger den String dann wieder kontrolliert zu Zahlen parsen und ein passendes byte[] rück-konstruieren,

das einzige was man vermeiden muss, ist, beliebige bytes in einen String umzuwandeln, dann werden die bytes als char interpretiert und String.toBytes() liefert am Ende was anderes, richtig

----

2) wie sollte ich die Architektur der Pakete verändern oder anpassen?

sende evtl. wirklich nur ein byte[] für die Nutzdaten, gar nix anderes zusätzlich,
auch was du in einer separaten Schicht weitere Information hinzufügst, ruhig wieder mit einem neuen ObjectOutputstream,
es dürfte kein Problem sein, ein beliebiges byte[] erneut zu serialisieren, ist Aufwand, aber korrekt
 
Zuletzt bearbeitet von einem Moderator:
Ähnliche Java Themen
  Titel Forum Antworten Datum
A TCP multiClientServer mit socket mittels ObjectOutputStream Netzwerkprogrammierung 12
windl AirPlay mittels Java Netzwerkprogrammierung 0
vandread Zugriff auf Soziales Netzwerk mittels Java? Netzwerkprogrammierung 4
M HTTP HTTPS-Verbindung mittels Java und Javascript Netzwerkprogrammierung 2
C SingleSignOn auf Client mittels Windows Credentials Netzwerkprogrammierung 11
M Dateiupload mittels HttpClient Netzwerkprogrammierung 3
S SSH-Connection - Auto-Vervollständigung mittels TAB Netzwerkprogrammierung 4
R Sicherheit bei entferntem Methodenaufruf mittels RMI Netzwerkprogrammierung 4
M Bestimmung der Netzwerkklasse mittels IP-Adresse Netzwerkprogrammierung 3
P Textdateien aus Oracle-DB mittels Java auslesen und öffnen Netzwerkprogrammierung 7
S Mittels Java XML abfragen und nicht die Ausgabe-HTML-Datei Netzwerkprogrammierung 5
J Antwort eines Soaprequests parsen mittels org.apache.soap Netzwerkprogrammierung 2
R Mittels BufferedReader Objekte lesen? Netzwerkprogrammierung 5
I http:GET mittels Socket liefert selsame Zeichenfolgen. Netzwerkprogrammierung 4
D txt Datei auslesen mittels URL Netzwerkprogrammierung 7
thE_29 Host mittels IP bekommen? Netzwerkprogrammierung 7
J Größe von DatagramPacket Netzwerkprogrammierung 3
J DatagramPacket --- getData() Netzwerkprogrammierung 10
C Frage zur Klasse DatagramPacket Netzwerkprogrammierung 2
C DatagramPacket korrupt? Netzwerkprogrammierung 2
B UDP / DatagramPacket Netzwerkprogrammierung 5

Ähnliche Java Themen


Oben