# [Exception] RSA Verschlüsselung.



## Lord_Aratorn (12. Apr 2010)

Hey, ich habe folgenden Code:


```
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import javax.crypto.Cipher;


public class RSACrypt {
	public byte[] decrypt(Key privateKey, byte[] encrypted)
	{
	    try
	    {
	        Cipher cipher = Cipher.getInstance("RSA");
	        cipher.init(Cipher.DECRYPT_MODE, privateKey);
	        cipher.update(encrypted);
	        return cipher.doFinal();
	    }
	    catch (Exception e)
	    {
	    	e.printStackTrace();
	    }
	    return null;
	}
	
	public byte[] encrypt(Key publickey, byte[] inputFile)
	{
	    try
	    {
	        Cipher cipher = Cipher.getInstance("RSA");
	        cipher.init(Cipher.ENCRYPT_MODE, publickey);
	        cipher.update(inputFile);
	        return cipher.doFinal();
	    }
	    catch (Exception e)
	    {
	    	e.printStackTrace();
	    }
	    return null;
	}

	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		KeyPairGenerator pairgen;
		try {
			pairgen = KeyPairGenerator.getInstance("RSA");
	        SecureRandom random = new SecureRandom();
	        pairgen.initialize(512, random);
	        KeyPair keyPair = pairgen.generateKeyPair();
	        
	        Key publicKey = keyPair.getPublic();
	        Key privateKey = keyPair.getPrivate();
	        
//	        System.out.println("pub:"+ publicKey);
//	        System.err.println("priv:"+ privateKey);
	        
	        
	        RSACrypt cryptor = new RSACrypt();
	        byte[] encrypted = cryptor.encrypt(publicKey, "Dude ist so verdammt cool, das sich die bäume bewegen im wind der gezeiten.".getBytes());
		    System.out.println(new String(encrypted));
	        byte[] decrypted = cryptor.decrypt(privateKey, encrypted);
	        System.out.println(new String(decrypted));
	        
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
	}

}
```

Der Code, soll den test-String "Dude ist so verdammt cool, das sich die bäume bewegen im wind der gezeiten." mit RSA verschlüsseln, anschließend wieder entschlüsseln und ausgeben. Jedoch wird folgende Exception geworfen


```
javax.crypto.IllegalBlockSizeException: Data must not be longer than 53 bytes
	at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:338)
	at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:383)
	at javax.crypto.Cipher.doFinal(Cipher.java:1708)
	at test.RSACrypt.encrypt(RSACrypt.java:34)
	at test.RSACrypt.main(RSACrypt.java:63)
Exception in thread "main" java.lang.NullPointerException
	at java.lang.String.<init>(String.java:601)
	at test.RSACrypt.main(RSACrypt.java:64)
```

Wie man ersehen kann ist der String zu lang und es läuft beim doFinal der encryption Methode was fehl.
Der String "horst" wird ohne Probleme ver- und ent-schlüsselt.
Nun muss ich jedoch auch längere Nachrichten (strings) verschlüsseln können.
Vielleicht hat einer von euch nen Plan, wodran es scheitert.


----------



## SlaterB (12. Apr 2010)

Cryptography - Too large data block for RSA1024


----------



## FArt (12. Apr 2010)

rsa encryption java - Google-Suche


----------



## Lord_Aratorn (13. Apr 2010)

Danke für eure Antworten.
Jedoch ist mir dennoch nicht klar, wie ich das Problem beheben kann.
Der erste Link gibt nicht mal irgendwelche Informationen. Nur den Hinweis, das man synchrone und asynchrone verfahren mischen sollte.


----------



## Wortraum (13. Apr 2010)

Der Hinweis soll Dir sagen, daß Du mit dem asymmetrischen Verfahren (RSA) einen geheimen Schlüssel eines symmetrischen Verfahrens (beispielsweise AES) verschlüsseln sollst. Statt also die Daten mit RSA zu verschlüsseln, verschlüsselst Du einen geheimen Schlüssel, mit dem wiederum die Daten verschlüsselt sind. Das ist gängige Praxis und nennt sich _hybride Verschlüsselung_.

Diese hat drei entscheidende Vorteile: die Verschlüsselung ist etwa um den Faktor 1000 schneller; man kann beliebig große Daten verschlüsseln; die Daten müssen nicht für jede Person einzeln mit dessen öffentlichen Schlüssel verschlüsselt werden, sondern nur der geheime Schlüssel.

Du mußt bei Dir also noch folgendes machen:
1) Einen geheimen Schlüssel erzeugen, am besten mit AES.
2) Mit diesem Schlüssel verschlüsselst Du die Daten, die Du derzeit mit dem öffentlichen RSA-Schlüssel zu verschlüsseln versuchst.
3) Statt den Daten verschlüsselst Du mit dem öffentlichen RSA-Schlüssel jetzt nur den AES-Schlüssel.

Das klingt erst einmal kompliziert, ist es aber eigentlich gar nicht. Und nur so kann man die Vorteile von asymmetrischen und symmetrischen Verfahren nutzen. Vielleicht brauchst Du das aber gar nicht und Dir reicht nur AES, das geht natürlich auch. Nur so, wie Du es jetzt hast, geht es nicht, weil sich mit RSA nur sehr kleine Datenmengen verschlüsseln lassen (abhängig von der Schlüssellänge).

Noch ein kleiner Hinweis zur Terminologie:
1) Privater Schlüssel: der private Schlüssel bei einem asymmetrischen Verfahren, der geheim bleiben muß.
2) Geheimer Schlüssel: der Schlüssel bei einem symmetrischen Verfahren, den nur die Personen kennen dürfen, die die Daten lesen sollen.

Viel Erfolg beim Rumprobieren!


----------



## Lord_Aratorn (14. Apr 2010)

Wortraum hat gesagt.:


> Vielleicht brauchst Du das aber gar nicht und Dir reicht nur AES, das geht natürlich auch. Nur so, wie Du es jetzt hast, geht es nicht, weil sich mit RSA nur sehr kleine Datenmengen verschlüsseln lassen (abhängig von der Schlüssellänge).



Ah Ok, es ist also abhängig von der Länge des Erzeugten Schlüssels wie viel Byte an Daten verschlüsselt werden können. Dann versuche ich mal einen längeren Schlüssel.

Ich kenne hybride Verschlüsselungsverfahren und auch das wrappen eines Keys. Doch soll für das Projekt an dem ich gerade arbeite, Daten auf dem Netzwerk verschlüsselt werden, und die Vorgabe ist RSA. Warum? Keine Ahnung SSH wäre da wahrscheinlich eine sinnvollere Lösung.


----------



## SlaterB (14. Apr 2010)

längerer Schlüssel hilft nur wenn die Grenze der Daten fast erreicht ist,
aber dein String kann doch statt 60 auch 100 oder 1000 oder 10000 Byte lang sein,
da nützt es nicht, den eh schon langen und komplizierten Schlüssel genauso aufzublähen,

wenn schon dann arbeite in die naheliegende andere Richtung:
zerteile die zu verschlüsselnden Daten in 50 Byte-Blöcke und verschlüssele die einzeln


----------



## Lord_Aratorn (14. Apr 2010)

ja das habe ich mir auch schon überlegt. Doch da die Netzwerkkommunikation über udp abgehalten werden soll, und da udp weder die Reihenfolge noch die Richtigkeit des Inhaltes sicherstellt, muss ich entweder ein Paket mit allen Blöcken verschicken oder mich selbst um die Reihenfolge kümmern. Schließlich muss der Inhalt wieder zusammengesetzt werden.


----------



## SlaterB (14. Apr 2010)

die Methode encrypt gibt wie bisher am Ende ein byte[] zurück, das Aufteilen beim Ver- und Entschlüsseln wird da intern abgewickelt, soweit möglich,
ganz unabhängig von der sonstigen Verwendung


----------



## Lord_Aratorn (14. Apr 2010)

Das ist mir schon klar, doch muss ich ja das byte[], was ich verschlüsseln will, aufteilen. Anschließend jeden Block verschlüsseln und am ende sämtliche Blöcke zusammenfügen zu einem byte[] und dieses zurückgeben. Oder habe ich da was falsch verstanden?


----------



## SlaterB (14. Apr 2010)

hast du nicht und warum 'doch'?, das sage ich doch auch so


----------



## Lord_Aratorn (14. Apr 2010)

dann müssten ja sämtliche verschlüsselte Blöcke die selbe Länge haben, oder?
Welche wäre die denn? Ist die Blocklänge vor der Verschlüsselung genauso groß wie danach?


----------



## SlaterB (14. Apr 2010)

ich kann das nicht sagen, du könntest es problemlos ausprobieren 
notfalls musst du dir ein Protokoll überlegen, die ersten 100 Bytes sind reserviert für Metainformationen,
im ersten Byte steht die Anzahl der Blöcke n (< 100), in den nächsten n Bytes steht die Länge dieser Blöcke, danach kommen die Bytes,
oder ähnliches

wenn zu kompliziert, dann eben nicht, war nur ein Vorschlag, hab es selber noch nicht gemacht


----------



## Lord_Aratorn (14. Apr 2010)

kompliziert aber logisch.
Will mir nur nicht soviel arbeit machen


----------



## Lord_Aratorn (14. Apr 2010)

Ich habe mal die encryption und die decryption methode umgeschreiben. Und die klasse um instanzvariablen (publickey, privatekey, test) erweitert.
test beinhaltet die selben daten wie der erste verschlüsselte block. Dies ist zum testen, ob die Blöcke vom encrypt denen vom decrypt entsprechen.
Jedoch ist dieses wohl nicht der Fall. Der auskommentierte Code der encrypt-Methode funktioniert, wenn er einkommentiert wird. der Code in der decrypt jedoch nicht.


```
public byte[] decrypt2(Key privateKey,  byte[] encrypted, int blocksize)
	{
	    try
	    {
	    	ByteArrayOutputStream bos = new ByteArrayOutputStream();
//	    	for (int i = 0; i < encrypted.length; i=i+blocksize) {
	    	int i = 0;
		    	byte[] tmp = new byte[blocksize];
		    	System.arraycopy(encrypted, i, tmp, 0, blocksize);
		    	System.out.println("tmp: "+new String(tmp));
		    	System.out.println("test: "+new String(test));
		    	if (new String(test).equals(new String(tmp))) {
					System.out.println("gleich");
				}
		        Cipher cipher = Cipher.getInstance("RSA");
		        cipher.init(Cipher.DECRYPT_MODE, privateKey);
		        tmp = cipher.doFinal(tmp);
		        bos.write(tmp);
		    	System.err.println("länge: "+ tmp.length + "inhalt:" +new String(tmp));
//	    	}
	    	return bos.toByteArray();
	    }
	    catch (Exception e)
	    {
	    	e.printStackTrace();
	    }
	    return null;
	}
	
	public byte[] encrypt(Key publickey, byte[] inputFile, int blocksize)
	{
	    try
	    {
	    	ByteArrayOutputStream bos = new ByteArrayOutputStream();
	    	for (int i = 0; i < inputFile.length; i=i+blocksize) {
	    		byte[] tmp = new byte[blocksize];
	    	
	    		if (tmp.length < inputFile.length- i){
	    			System.arraycopy(inputFile, i, tmp, 0, tmp.length);
	    		}else{
	    			for (int j = 0; j < inputFile.length-i; j++) {
						tmp[j] = inputFile[i+j];
					}
	    		}
	    		Cipher cipher = Cipher.getInstance("RSA");
	    		cipher.init(Cipher.ENCRYPT_MODE, publickey);
	    		tmp = cipher.doFinal(tmp);
//		    		cipher.init(Cipher.DECRYPT_MODE, privateKey);
//			        tmp = cipher.doFinal(tmp);
//			        System.out.println("dc: "+new String(tmp));
	    		if(i == 0)
	    			this.test = tmp;
	    		bos.write(tmp);
	    		System.err.println("länge: "+ tmp.length + "inhalt:" +new String(tmp));
	    	}
	    	
	        return bos.toByteArray();
	    }
	    catch (Exception e)
	    {
	    	e.printStackTrace();
	    }
	    return null;
	}
```


----------



## FArt (14. Apr 2010)

Funktioniert nicht bedeuetet Exception oder der Vergleich schlägt fehl? Wenn zweiteres, ist es dann wirklich die Entschlüsselung, die fehlschlägt? Wenn ersteres, was sind das für Fehler?
Eines verstehe ich nicht: über meine gepostete Google-Suche findet man sehr schnell funktionierenden Beispielcode. Warum nimmst du den nicht als Startpunkt her? Oft gibt es auch praktische Kommentare dazu, z.B. welche Fehler oft gemacht werden und wie man dem begegnet...

Beispiel für einen Kommentar, der zu deinen Postings hier passen könnte:


> Thanks a lot!
> It was very usefull for me. I had a problem encryting long bytes arrays, this article solved my problens; which were that I didn’t have a copyBytes() method to pass full byte arrays. How ever I tryed to encript a byte array which was not full complete and then , when I tryed to decript it I had exceptions with block size padding and similar.


----------



## Lord_Aratorn (5. Mai 2010)

Blockverschlüsselung hat geholfen!


----------

