RSA Problem

M

MeinerEiner_80

Hi zusammen,
ich grübel jetzt schon seit Tagen an einem Problem mit der RSA Verschlüsselung.
Im Netz gibt es zwar genug beispiele dazu.. allerdings reichen diese nicht für meine zwecke..
Ich hab hier eine Schlüsselgroesse von 2048 Bytes gewählt.. das heißt die blockgroesse kann maximal 256 Bytes betragen....

Mein problem an der sache ist nun, die texte die ich verschlüsseln muss, sind groesser als 256 bytes..
eigentlich kein problem, wenn man die nachricht in 256 byte päckchen aufteilt..
nur irgendwie klappt das nicht bei mir..

hier in meinem beispiel wird die nachricht in 2 päckchen aufgeteilt.. 256 und 245 bytes..

wenn ich die nachricht verschlüssele und dann wieder entschlüssele wird nur das erste päckchen korrekt entschlüsselt.. im kleineren steht müll drin...

zu debugzwecken hatte ich in der verschlüsselungsmethode den verschlüsselten text gleich wieder entschlüsselt.. und das hat wunderbar gekappt.. das müsste ja bedeuten, der fehler liegt in der entschlüsselungsmethode..
das was ich entdeckt habe ist, das wenn 245 bytes verschlüsselt werden, das verschlüsselte päckchen 256 bytes gross ist.. und wenn es wieder entschlüsselt wird, es ebenso 256 bytes gross ist.. das ist ein fehler.. aber wie er zustande kommt.. ist mir ein rätsel..
vorallem daher, weil wenn ich eine EINZELNE nachricht < 256 bytes verschlüsseln lassen, d.h. insgesamt nur ein päckchen habe.. klappt das merkwürdigerweise wunderbar...
Das ganze wirkt für mich eher, als würde ich auf ein falsches array element zugreifen..
wahrscheinlich seh ich einfach den wald vor lauter bäumen net mehr, da ich ja schon so lang da dranhock..
vielleicht kann mir jemand von euch weiterhelfen?

Code:
class Security {
	private KeyPair keyPair;
	private RSAPublicKey publicKey;
	private RSAPrivateKey privateKey;
	private final int RSAKeySize = 2048;
	private final int RSABlockSize = 256;
	public Security(){
	String text = "hallo.. würde das gerne mal verschlüsseln .. bin gespannt ob das klappt.. soo nun reichts.. text ist gross genug";
		
		text =text+text+text;
		byte[] buffer = text.getBytes();
		byte[] encrypt;
		byte[] decrypt;
		generateRSA();
		
		System.out.println(new String(buffer));
		System.out.println("----------------------------------");
		encrypt = encodeWithRSA(buffer,publicKey,RSABlockSize);
		decrypt = decodeWithRSA(encrypt,privateKey,RSABlockSize);
		System.out.println("----------------------------------");
		System.out.println(new String(decrypt));
		
	}
	
	
	byte[] encodeWithRSA(byte[] text,RSAPublicKey key, int blockSize){
		int len;
		if(text.length%blockSize==0){
			len = (text.length/blockSize);
		}
		else{
			len = (text.length/blockSize) +1;
		}
		byte [][]byteArrays = new byte[len][];
		int remain = text.length-blockSize;
		int counter =0;
		int counter2 =0;
		while(remain >=0){
			byte[] buffer = new byte[blockSize];
			for(int i=0; i< blockSize; i++){
				buffer[i] = text[counter];
				counter++;
			}
			byteArrays[counter2]= buffer;
			counter2++;
			remain = text.length-blockSize-counter;
		}
		if(remain!=0){
			remain = blockSize+remain;
			byte[] buffer = new byte[remain];
			for(int i=0; i< remain; i++){
				buffer[i] = text[counter];
				counter++;
			}
			
			byteArrays[counter2]= buffer;
			
		}
		BigInteger cipherText;
		BigInteger message;
		for(int i =0; i< len;i++){
			message = new BigInteger(byteArrays[i]);
			cipherText= message.modPow(key.getPublicExponent(),key.getModulus());
			byteArrays[i] = cipherText.toByteArray();
		}
		
		byte[] buffer = new byte[len*blockSize];
		counter =0;
		for(int i=0; i<byteArrays.length;i++){
			for(int j=0; j < byteArrays[i].length;j++){
				buffer[counter] = byteArrays[i][j];
				counter++;
			}
		}
		return buffer;
	}
	
	
	
	
	byte[] decodeWithRSA(byte[] text,RSAPrivateKey key,int blockSize){
		int	len = (text.length/blockSize);
		byte [][]byteArrays = new byte[len][];
		int counter =0;
		byte[] buffer;
		for(int j=0; j < len;j++){
			buffer = new byte[blockSize];
			for(int i=0; i< blockSize; i++){
				buffer[i] = text[j*len+i];
			}
			byteArrays[j]= buffer;
			
		}
		BigInteger cipherText;
		BigInteger message;
		counter =0;
		for(int i =0; i< byteArrays.length;i++){
			message = new BigInteger(byteArrays[i]);
			cipherText= message.modPow(key.getPrivateExponent(),key.getModulus());
			byteArrays[i] = cipherText.toByteArray();
			counter+=byteArrays[i].length;
		}
		
		
		buffer = new byte[counter];
		int counter2 =0;
		for(int i=0; i<byteArrays.length;i++){
			
			for(int j=0; j < byteArrays[i].length;j++){
				buffer[counter2] = byteArrays[i][j];
				counter2++;
			}
		}
		return buffer;
	}
 
Hallo,

deine Verschlüsselungsmethoden scheinen nur komplette Blöcke zu verschlüsseln. In diesem Fall musst du selbst dafür sorgen, dass deine zu verschlüsselden Textblöcke immer voll, also 256 Byte gross sind.
Ich habe das schonmal programmiert, indem ich mir im letzten byte des Blockes die grösse des Blockes merke. Nach dem entschlüsseln, kann man das Array einfach wieder abschneiden.

Verwende System.arraycopy() das ist besser als die Schleife.

Grüsse TrueSun
 
Hi,
das ist leider nicht die Lösung..
Die Idee, nur Arrays mit der Grösse von 256 Bytes zu verschlüsseln, ist mir nämlich auch schon gekommen.. und hat leider nichts gebracht..
Hätte mich auch ehrlichgesagt sehr gewundert..
denn wie ich ja schon geschrieben habe, wenn ich eine Nachricht kleiner als 256 Bytes verschlüsselt habe, hat das wunderbar geklappt.. nur beim Aufteilen in mehrere ByteArrays gibts Probleme..

Aber danke für den Hinweis auf die arraycopy methode.. damit kann ich meinen Quellcode etwas entschlacken und vielleicht fällt mir dann etwas auf..

*grüssle*
MeinerEiner
 
Also ich weis nun wo der Fehler lag..
irgendwo wo ich die Blöcke aufgeteilt habe, muss ich wohl einen falschen Zugriff gemacht haben..
Ich hab die ganzen Schleifen nun durch das System.arraycopy ersetzt und das hat auf anhieb geklappt.... danke also nochmal für den Tip TrueSun..

Übrigens.. die Blockgrösse muss nicht 256 Bytes betragen.. der Algo kommt auch mit wenigern klar..
 
Hallo,

könntest du mir mal deine korrigierte Security-Klasse zukommen lassen bzw. hier posten? Würde mich sehr freuen.

Gruß,
Jan
 
hi,
da ich jetzt schon mehrere Anfragen bezüglich der Methoden bekommen habe,
hier nochmal für alle..
muss allerdings meine Aussage revidieren, das der Algo auch mit blöcken < 256 zurechtkommt.. wie ich bei meinem derzeitigen Praktikum an der Uni gerade noch rechtzeitig gemerkt habe ;)
Jedenfalls sind nun alle Blöcke gleich gross und an die erste Stelle eines Block wird jeweils gespeichert, um wieviel Bytes er aufgefüllt wurde..

Bitte schön..


Code:
/**
	 * <p>Entschluesselt mit dem Privatkey einen uebergebeben ByteBlock.</p>
	 * <p>Der ByteBlock wird dazu in einzelne Paeckchen der Groesse <i> blockSize </i>
	 * aufgeteilt und einzeln entschluesselt.
	 * Zuerst wird aber das erste Byte des eines Paeckchens entfernt, da dieses die Anzahl der Bytes 
	 * enthaelt, die aus dem Decodierten Paeckchen entfernt werden muessen. 
	 * Zur Entschluesselung wird die von der BigInteger-Klasse angebotene Methode
	 * <i>modPow</i> benutzt</p>
	 * Schliesslich werden die einzelnen entschluesselten Bloecke in einem ByteArray 
	 * gespeichert und zurueckgeliefert.
	 * @param cipher zu entschluesselnde ByteArray
	 * @param key der PrivateKey
	 * @param blockSize die maximale Blockgroesse
	 * @return den entschluesselten ByteArray
	 */
	
	public byte[] decodeWithRSA(byte[] cryptedText, RSAPrivateKey privateKey, int blockSize) {
		// Anzahl der am Ende hinzugefuegten Bytes auslesen und das dafuer angefuegte Byte entfernen
		byte fuellBytes = cryptedText[0];
		byte[] temp = cryptedText;
		cryptedText = new byte[temp.length-1];
		System.arraycopy(temp,1,cryptedText,0,temp.length-1);
		byte[] decryptedText = new byte[cryptedText.length];
		int numOfBlocks = (int)cryptedText.length/256;
		if (cryptedText.length%256 > 0) numOfBlocks++;
		byte[] textBlock = new byte[256];
		BigInteger textBlockInteger;
		for (int i = 0; i<numOfBlocks;i++){
			// zu bearbeitenden Block in textBlock schreiben
			for (int j = 0; j < 256; j++) textBlock[j] = cryptedText[i*256 + j]; 
			
			// konvertierung von textBlock in BigInteger zum entschluesseln
			textBlockInteger = new BigInteger(textBlock);
			textBlockInteger.modPow(privateKey.getPrivateExponent(),privateKey.getModulus());
			textBlock = textBlockInteger.toByteArray();
			
			// textBlock in ausgabearray uebertragen
			for (int j = 0; j < 256; j++) decryptedText[i*256 + j] = textBlock[j];
		}
		// Anzahl der aufgefuellten Bytes am ende auslesen und abschneiden
		temp = decryptedText;
		decryptedText = new byte[temp.length-(fuellBytes+128)];
		System.arraycopy(temp,0,decryptedText,0,temp.length-(fuellBytes+128));
		return decryptedText;
	}
	
	/**
	 * <p>Verschluesselt mit dem PublicKey einen uebergebeben ByteBlock.</p>
	 * <p>Der ByteBlock wird dazu in einzelne Paeckchen der Groesse <i> blockSize </i>
	 * aufgeteilt und einzeln verschluesselt.
	 * Zur Verschluesselung wird die von der BigInteger-Klasse angebotene Methode
	 * <i>modPow</i> benutzt</p>
	 * Schliesslich werden die einzelnen verschluesselten Bloecke in einem ByteArray 
	 * gespeichert und zurueckgeliefert.
	 * Als erstes Byte wird zudem noch eingefuegt, um wieviel Bytes der plainText aufegfuellt
	 * wurde.
	 * @param plain der zu verschluesselnde ByteArray
	 * @param key der PublicKey
	 * @param blockSize die maximale Blockgroesse
	 * @return den verschluesselten ByteArray
	 */
	public byte[] encodeWithRSA(byte[] plainText, RSAPublicKey publicKey, int blockSize) {
		// Testen, wie viele Bytes am Ende  aufgefuellt werden.
		byte fuellBytes = (byte)(256 - (plainText.length % 256) + 128);
		byte[] cryptedData;
		if (plainText.length % 256 == 0)
		    cryptedData = new byte[plainText.length];
		else
			cryptedData = new byte[(plainText.length/256 + 1)*256];
		int numOfBlocks = (int)cryptedData.length/256;
		byte[] textBlock = new byte[256];
		byte[] tempTextBlock;
		BigInteger textBlockInteger;
		for (int i = 0; i<numOfBlocks;i++){
			// zu bearbeitenden Block in textBlock kopieren
			for (int j = 0; (j < 256) && (i*256 + j < plainText.length); j++){
				textBlock[j] = plainText[i*256 + j]; 
			}
			// textBlock in einem BigInteger speichern und verschluesseln
			textBlockInteger = new BigInteger(textBlock);
			textBlockInteger.modPow(publicKey.getPublicExponent(),publicKey.getModulus());
			tempTextBlock = textBlockInteger.toByteArray();
			if (tempTextBlock.length > 256) System.err.println("\n\n\nPaeckchen zu gross");
			// textBlock im Ausgabearray speichern
			for (int j = 0; (j < tempTextBlock.length); j++)
				cryptedData[i*256 + j] = tempTextBlock[j];

		}
		// Byte vor Ausgabearray einfuegen, in dem steht, wie viele Bytes angehaengt wurden.
		byte[] temp = cryptedData;
		cryptedData = new byte[temp.length+1];
		System.arraycopy(temp,0,cryptedData,1,temp.length);
		cryptedData[0] = fuellBytes;
		return cryptedData;
	}


*grüssle*
Jörg
 
Zurück