# Verschlüsselte Strings über Netzwerk verschicken



## Guest (12. Jan 2009)

Hallo zusammen,
ich bin gerade dabei mit Java und Verschlüsselungen herumzuspielen.
Nun habe ich mir ein Programm geschrieben, welches einen String via publicKey verschlüsselt und verschickt. Der Empfänger hat den dazugehörigen privateKey und soll den String wieder entschlüsseln.
Soweit so gut.
Als erstes habe ich ein KeyPair erstellt und private- sowie publicKey gespeichert. Den publicKey habe ich im Netzwerk auf meinen zweiten PC kopiert.

Vielleicht erstmal den Code, damit ihr es euch anschauen könnt ^^

Auf der Sender-Seite:

```
public class Main {
	public static void main(String[] args) throws Exception{
		Encrypter en = new Encrypter();
		Writer wr = new Writer();
		
		String data = "test";
		byte[] encData = en.encrypt(data);
		wr.write(encData);
	}
}

----------------------------------------------------------------------------------------
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class Writer {

	public void write(byte[] data) {
		try {
			// eine Nachricht wird an den Server geschickt
			InetAddress ia = InetAddress.getByName("192.168.2.5");
			DatagramPacket packet = new DatagramPacket(data, data.length, ia,
					4711);
			DatagramSocket dgSock = new DatagramSocket();
			dgSock.send(packet);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

---------------------------------------------------------------------------------------------
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.security.PublicKey;

import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;


public class Encrypter {

	File publicKeyFile;
	PublicKey publicKey;
	Cipher cipher;
	
	public Encrypter(){
		try{
			publicKeyFile = new File("public.key");
			publicKey = readPublicKey(publicKeyFile);
			cipher = Cipher.getInstance("RSA");
		}
		catch(Exception e){
			e.printStackTrace();
		}
	}
		
	public byte[] encrypt(String data){
		try{
		      cipher.init(Cipher.ENCRYPT_MODE, publicKey);
	              ByteArrayOutputStream baosEncryptedData = new ByteArrayOutputStream();
	              CipherOutputStream cos = new CipherOutputStream(baosEncryptedData,cipher);
	              cos.write(data.getBytes("UTF-8"));
	              cos.flush();
	              cos.close();
	              return baosEncryptedData.toByteArray();	
		}
		
		catch(Exception e){
			e.printStackTrace();
		}
		return null;
	}
	
	private PublicKey readPublicKey(File file) throws Exception {
                ObjectInputStream objectInputStream = new ObjectInputStream(
                new FileInputStream(file));
                PublicKey publicKey = (PublicKey) objectInputStream.readObject();
                objectInputStream.close();
                return publicKey;
    }
}
```

und auf der Empfängerseite:

```
public class MainListener {
	public static void main(String[] args) {
		Decrypter d = new Decrypter();
		Listener l = new Listener(d);
		l.run();
	}
}
---------------------------------------------------------------------------

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.security.InvalidKeyException;
import java.security.PrivateKey;
import java.security.PublicKey;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;

public class Decrypter {

	File privateKeyFile;
	PrivateKey privateKey;
	Cipher cipher;

	private PrivateKey readPrivateKey(File file) throws Exception {
		ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(file));
		PrivateKey privateKey = (PrivateKey)objectInputStream.readObject();
		objectInputStream.close();
		return privateKey;
	}

	// Methode zum entschlüsseln einer verschlüsselten Nachricht
	String decrypt(byte[] encryptedData){
		try{
		     privateKeyFile = new File("private.key");
		     privateKey = readPrivateKey(privateKeyFile);
		     cipher = Cipher.getInstance("RSA");
		     cipher.init(Cipher.DECRYPT_MODE, privateKey);
		     CipherInputStream cis = new CipherInputStream(new ByteArrayInputStream(encryptedData), cipher);
		     ByteArrayOutputStream baosDecryptedData = new ByteArrayOutputStream();
		     byte[] buffer = new byte[8192];
		     int len = 0;
		     while ((len = cis.read(buffer)) > 0) {
		          baosDecryptedData.write(buffer, 0, len);
		     }
		baosDecryptedData.flush();
		cis.close();
		return new String(baosDecryptedData.toByteArray(), "UTF-8");
	        }catch(Exception e){
		     e.printStackTrace();
	 	     return new String("FAIL");
	        }
	}
}
---------------------------------------------------------------------------
import java.net.DatagramPacket;
import java.net.DatagramSocket;


public class Listener {

	Decrypter d;
	
	public Listener(Decrypter d){
		this.d = d;
	}
	
	public void run(){
		try {
			DatagramSocket client = new DatagramSocket(4711);
			
			while (true) {
				DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);
                               // Es wird auf eintreffende Nachrichten/Pakete gewartet
				client.receive(packet);
				System.out.println("recieved");
				byte[] data = packet.getData();
				String encData = new String(data, 0, packet.getLength());
				String decData = d.decrypt(data);
			}
	}catch(Exception e){
		e.printStackTrace();
	}
}
}
```

So, übertragen tut er schon mal schön. Also ich bekomme als Empfänger den verschlüsselten String mit


```
String encData = new String(data, 0, packet.getLength());
```
 richtig angezeigt. Wenn ich jedoch die empfangenen Daten an den Decrypter übergebe, damit er diese wieder entschlüsselt gibt es nur einen leeren String als Rückgabe.

Ich habe mir mal den "byte[] data" angeguckt. Er hat meistens eine Länge von 128 (genau so wie der String eine Länge von 128 Zeichen hat,wenn ich ihn aus den Datenbytes erstelle. Angezeigt werden jedoch immer weniger).
Die Länge des vom Versende verschickten Strings liegt meist um die 120 Zeichen.

Ich denke also, dass der Byte-Array nicht die korrekte Größe annimmt sondern die größe der nächsten 2er-Potenz.
Kann das sein? Oder hat irgendwer eine Idee, wo der Fehler sonst liegen kann?
Ich würde mich sehr freuen, wenn ihr mir trotz des umfangreichen Quelltexts und Problem, helfen könnten.
Vielen Dank schon mal im Voraus


----------



## dayaftereh (12. Jan 2009)

Warum nutzt du nicht:

1.BufferedWriter
2.BufferedReader

Warum machst du es dir so schwer mit eine DatagramSocket????


----------



## Guest (12. Jan 2009)

bufferdreader/writer arbeitet doch verbindungsorientiert, oder?
muss da nicht die ganze zeit über eine verbindung zwischen den beiden teilnehmern hergestellt sein?
korrigiere mich bitte, wenn dem nicht so ist.

weil genau das möchte ich nicht. ich will verbindungslos programmieren.


----------



## dayaftereh (12. Jan 2009)

Ah ok, das wuste ich nicht^^


----------



## SlaterB (12. Jan 2009)

ich würde an deiner Stelle ein Byte mit Wert 42 senden, dann 2, 5, 20, 100, 120, 128
und jeweils genau schauen, was beim Empfänger ankommt,

dann kannst du dir vielleicht manuell die passenden Bytes rausscheiden, sofern da was nicht stimmt,
zumindest solange, bis hier wer was besseres vorschlägt


----------



## Ebenius (12. Jan 2009)

Ad hoc: Muss es im Decryptor nicht so heißen?: 
	
	
	
	





```
while ((len = cis.read(buffer)) > -1) {
```

Ebenius


----------



## Guest (12. Jan 2009)

ne, leider nicht.
wenn ich auf einem pc erst den string verschlüssel und dann wieder entschlüssel funktioniert es ja.
kann irgendwas am Cipher falsch sein??? Aber ich wüsste nicht was


----------



## HoaX (12. Jan 2009)

ebenius, wennschon dann != -1 ...


lass dir doch mal ausgeben welche bytes du versendest und welche du empfängst. evtl wird dein gesendeter string in zwei paketen übertragen und somit tritt ein fehler auf wenn versuchst zu dekodieren


----------



## dayaftereh (12. Jan 2009)

Haben beide Rechner die Gleich Java version????


----------



## Ebenius (13. Jan 2009)

HoaX hat gesagt.:
			
		

> ebenius, wennschon dann != -1



Warum denn das?


----------



## HoaX (13. Jan 2009)

Ebenius hat gesagt.:
			
		

> HoaX hat gesagt.:
> 
> 
> 
> ...



weils so in der apidoc steht. -1 wenn das ende erreicht ist. und es gibt ja noch zahlen kleiner als -1. was diese bedeuten ist nicht allgemein definiert, hängt also von der entsprechenden implementation ab. darum besser angewöhnen auf != -1 zu prüfen und ggf. einen fehler zu schmeißen wenn < -1


----------



## Ebenius (13. Jan 2009)

Ahja. :-/


----------



## Guest (13. Jan 2009)

leider hat bisher nichts genützt.
das mit -1 habe ich geändert, war aber nicht der fehler. hat ja auch so auf nur einem pc funktioniert.
auf dem laptop habe ich java geupdatet, aber hat leider auch nichts genutzt :-(


----------



## Guest (13. Jan 2009)

achso: übrigens werden alle bytes auch korrekt übertragen.
habe mir mal den verschlüsselten string sowohl vor dem verschicken als auch nach dem empfang als String und Byteweise darstellen lassen. Total identisch :-(


----------



## Mentor49 (13. Jan 2009)

Versuch mal folgendes und poste was ausgegeben wird:

```
client.receive(packet);
            System.out.println("Packet-Length: " + packet.getLength());
            byte[] data = packet.getData();
            System.out.println("Data-Length: " + Data.getLength());
            String encData = new String(data);
            System.out.println("AsString (Encodiert): " + encData);
            System.out.println("String (Encodiert) Length: " + encData.Length());
            String decData = d.decrypt(data);
            System.out.println("AsString (Decodiert): " + decData);
            System.out.println("String (Decodiert) Length: " + decData.Length());
```


----------



## Guest (14. Jan 2009)

habe mal das ausgeben lassen was du geschrieben hast.
zusätzlich noch folgendes eingefügt:


```
System.out.print("AsBytes: ");
	             StringBuffer tmp = new StringBuffer();
	             for(int i =0; i<encData.length(); i++){
	            	 System.out.print(((int)encData.charAt(i))+ " ");
	            	 if(((int)encData.charAt(i)) != 0){
//	            		 System.out.print(((int)encData.charAt(i))+ " ");
	     				tmp.append(encData.charAt(i));
	     			}
	     		}
                     //Im BufferedString befinden sich jetzt also nur die Bytes != 0
	             System.out.println();
	             System.out.println("BufferedString: " + tmp.toString());
	             System.out.println("BufferedString Length: " + tmp.toString().length());
	             decData = d.decrypt(tmp.toString().getBytes());
	             System.out.println("BufferedString (Decodiert): " + decData);
	             System.out.println("BufferedString (Decodiert) Length: " + decData.length());
```





> Packet-Length: 128
> Data-Length: 1024
> AsString (Encodiert): "
> c0¶EzQÙÏÈ›je"ãðXÁ>ˆ‚Öb>[*Æ¤ÈÏ*š—fž‚Yœ18/~)Á?|¾5Z~ðR¹ÛH>,ïRK[\ƒ­¶zš±(¾„Ã:tÒ.åP‰·Gè,
> ...



hier mal das, was ich mir von der client seite vor dem verschicken habe ausgeben lassen:

code war folgender:

```
for(int i =0; i<encDataStr.length(); i++){
			System.out.print(((int)encDataStr.charAt(i))+ " ");
			if(((int)encDataStr.charAt(i)) != -1){
				tmp.append(encDataStr.charAt(i));
			}
		}
```




> 34 13 99 48 65533 69 122 7 81 65533 29 65533 539 106 101 34 65533 65533 88 65533 62 65533 65533 65533 98 62 91 30 127 42 420 65533 65533 42 65533 65533 102 65533 65533 89 65533 49 56 47 126 11 41 65533 65533 124 65533 53 90 126 65533 82 65533 65533 72 62 44 65533 82 75 91 31 92 65533 65533 65533 122 65533 65533 40 23 65533 65533 65533 58 116 65533 46 65533 80 65533 65533 71 65533 4 44 13 65533 87 51 70 65533 119 51 65533 65533 32 65533 125 34 17 65533 104 89 65533 71 100 113 65533 334 37 98 31 41 65533 66 118 16 65533 83 14


----------



## Guest (14. Jan 2009)

achso, hier noch der encodierte String auf der Client-Seite vor dem verschicken:


> c0?EzQ???je"??X?>???b>[*???*??f??Y?18/~)??|?5Z~?R??H>,?RK[\???z??(???:t?.?P??G?,
> ?W3F?w3?? ?}"?hY?Gdq??%b)?Bv?S


----------



## Guest (14. Jan 2009)

so, mir ist aufgefallen, dass die beiden char-angaben ja nicht übereinstimmen.
deshalb mal vorher die byte arrays ausgeben lassen. die sind jedoch gleich, bis darauf dass beim server die ungenutzten bytes im array noch auf "0" gesetzt sind. also die bytes von ende der nachricht bis 1024.


----------



## 117 bytes (14. Jan 2009)

Hi, du bist dir im Klaren darüber, dass 117 das Maximum ist, dass RSA verschlüsseln kann. Dann musst du wieder einen neuen Block anfagen. Nimm AES und schick den SECRET_KEY mit deinem PUBLIC_KEY an den Server, der weiß dann wie er die einkommenden Daten behandeln muss. Außerdem ist das um einiges schneller


----------



## Guest (15. Jan 2009)

117 was?
aber klappt ja auf einem pc so wie es ist, das ist ja das komische.
werde es mal versuchen wenn ich zu hause bin


----------

