Fehler beim Lesen von verschlüsselter xml-Datei

Status
Nicht offen für weitere Antworten.

trazzag

Bekanntes Mitglied
Hallo,

ich habe ein Programm geschrieben, welches mit XML-Dateien arbeitet. Nun wollte ich den Inhalt der Dateien mit Cipher verschlüsseln. Beim einlesen dieser verschlüsselten Datein bekomme ich allerdings eine NullPointerException.
Hier meine Methode zum Speichern (und verschlüsseln) der xml-Dateien:
Code:
public void saveXML(String datei, Document document) {
		try {

			Cipher c = Cipher.getInstance("DES");

			/* Schlüssel für die Verschlüsselung setzen */
			String key = "66776688";
			Key k = new SecretKeySpec(key.getBytes(), "DES");

			c.init(Cipher.ENCRYPT_MODE, k);

			/* FileOutputStream zum schreiben der Datei */
			FileOutputStream fos = new FileOutputStream(datei, false);

			/* FileOutputStream über CipherOutputStream verschlüsseln */
			CipherOutputStream cos = new CipherOutputStream(fos, c);

			/*
			 * Schreiben der XML-Datei (für unverschlüsselt: cos durch fos
			 * ersetzen)
			 */
			XMLOutputter out = new XMLOutputter(Format.getPrettyFormat());
			out.output(document, cos);
			
			fos.close();
			cos.close();
		
		} catch (IOException ioe) {
			ioe.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

Und hier der Codeschnipsel, in dem die xml wieder eingelesen wird:
Code:
Cipher c = Cipher.getInstance("DES");

/* Schlüssel für die Entschlüsselung setzen */
String key = "66776688";
Key k = new SecretKeySpec(key.getBytes(), "DES");

c.init(Cipher.DECRYPT_MODE, k);
			
FileInputStream fis = new FileInputStream("config.xml");
			
CipherInputStream cis = new CipherInputStream(fis, c);
			
//document = new SAXBuilder().build(new File("config.xml"));
document = new SAXBuilder().build(cis);

Also, entschlüsselt wird etwas, es scheint nur kein gültiges xml-Dokument mehr rauszukommen.
Hoffe, mir kann hier jemand helfen!
 
Ich konnte den Fehler jetzt schon weiter eingrenzen: Scheinbar werden bei dem Ver- und auch Entschlüsseln der Datei jeweils die letzten paar Bytes einfach weggelassen.
Beispiel: Meine Schlüssellänge ist 8 Byte, die Datei ist 403 Byte groß, dann werden die letzten 3 Byte weggelassen.
Ist die Datei 400 Byte groß, die letzten 8...

Jemand Ideen?
 
vertausch mal beim ersten codeblock zeile 26/27. wenn der cipherstream noch was gepuffert hat und beim close scheiben will, aber der filestream schon zu ist dann könnten da deine daten verloren geht. sonst schauts eigentlich auf den erstenblick ok aus.
 
Hat leider nichts gebracht... Ich vermute mal, es hängt mit der Schlüssellänge zusammen, also: die Anzahl der zu verschlüsselten Bytes muß ein vielfaches der Schlüssellänge sein (und alles darüber hinaus wird abgeschnitten) oder so ähnlich...?!?
 
Hab ich versucht, hilft leider auch nicht...
Werd mir da wohl ne andere Lösung einfallen lassen müssen. Hat vielleicht jemand vorschläge?
 
Also wenn ich deinen Code hier teste, gibt es einen Lesefehler wenn ich die OutputStreams in dieser Reihenfolge schliesse
Code:
fos.close();
cos.close();
waehrend
Code:
cos.close();
fos.close();
oder auch ein einfaches
Code:
cos.close();
einwandfrei funktioniert.
 
fos.close() und cos.close() hatte ich schon auf anraten von HoaX in der Reihenfolge verändert - hat nix gebracht.

Also, die Verschlüsselung läuft ja auch problemlos, solange die Byte-Anzahl, die verschlüsselt werden muß ein vielfaches von 8 ist. Der Rest fällt einfach weg.

Beim Entschlüsseln scheinen einfach Pauschal die letzten 8 Byte weggelassen zu werden...
 
Ich hab das ganz wie gesagt mit deinem geposteten Code getestet und es funktioniert mit beliebigen XML Dokumenten (halt mit dem vertauschten close). Deswegen sollte die Staffelung XMLOutputter -> CipherOutputStream -> FileOutputStream prizipiell funktionieren. Schau mal nach anderen Fehlerursachen.
 
Bin das ganze jetzt ein wenig unschön umgangen: Ich hab mir eine Methode geschrieben, welche eine vorhandene Datei Byte-weise verschlüsselt. Also speicher ich erst unverschlüsselt und rufe dann die Verschlüsselung auf. Unschön, funktioniert aber...

Hier meine funktionierende Klasse zum Ver- und Entschlüsseln von Dateien:

Code:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.Key;
import java.util.ArrayList;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.spec.SecretKeySpec;

public class DeAndEncryption {

	public static void main(String[] args) {
		DeAndEncryption encr = new DeAndEncryption();
		encr.encryptFile("C:\\standard.xml");
		//encr.decryptFile("C:\\Test.xml");
	}

	private void encryptFile(String datei) {
		try {
			/* Quelldatei festlegen */
			FileInputStream fis = new FileInputStream(datei);

			/* Array für die Bytes der Quelldatei initialisieren */
			ArrayList<Integer> iArray = new ArrayList<Integer>();

			/* byte-weises Lesen der Quelldatei */
			int outbyte = fis.read();
			while (outbyte != -1) {
				iArray.add(outbyte);
				outbyte = fis.read();
			}
			
			/* Cipher-Instanz für die Verschlüsselung holen */
			Cipher c = Cipher.getInstance("DES");

			/* Schlüssel für die Verschlüsselung setzen */
			String key = "12312312";
			Key k = new SecretKeySpec(key.getBytes(), "DES");

			/* Verschlüsselung initialisieren */
			c.init(Cipher.ENCRYPT_MODE, k);

			/* OutputStream zum Schreiben der Datei */
			FileOutputStream fos = new FileOutputStream(datei);

			/* OutputStream über CipherOutputStream verschlüsseln */
			CipherOutputStream cos = new CipherOutputStream(fos, c);

			for (int i = 0; i < iArray.size(); i++) {
				cos.write((Integer) iArray.get(i));
			}
			cos.flush();
			cos.close();
			fos.close();

		} catch (IOException ioe) {
			ioe.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void decryptFile(String datei) {
		try {
			/* Quelldatei festlegen */
			FileInputStream fis = new FileInputStream(datei);

			/* Array für die Bytes der Quelldatei initialisieren */
			ArrayList<Integer> iArray = new ArrayList<Integer>();

			/* Cipher-Instanz für die Verschlüsselung holen */
			Cipher c = Cipher.getInstance("DES");

			/* Schlüssel für die Verschlüsselung setzen */
			String key = "12312312";
			Key k = new SecretKeySpec(key.getBytes(), "DES");

			/* Verschlüsselung initialisieren */
			c.init(Cipher.DECRYPT_MODE, k);

			/* InputStream über CipherInputStream entschlüsseln */
			CipherInputStream cis = new CipherInputStream(fis, c);
			
			/* byte-weises Lesen der Quelldatei */
			int outbyte = cis.read();
			while (outbyte != -1) {
				iArray.add(outbyte);
				outbyte = cis.read();
			}

			/* OutputStream zum Schreiben der Datei */
			FileOutputStream fos = new FileOutputStream(datei);

			for (int i = 0; i < iArray.size(); i++) {
				fos.write((Integer) iArray.get(i));
			}
			fos.flush();
			cis.close();

		} catch (IOException ioe) {
			ioe.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

Warum die andere Variante bei mir nicht läuft, verstehe ich aber immernoch nicht so ganz... *kopfkratz*.
 
Damit hatte ich es bei mir getestet, vielleicht hilft es Dir bei der Problemsuche (ein Grossteil davon ist dein Code 🙂 )
Code:
public class SaveLoadDES
{
	
	public static void main(String[] args)
	{
		try
		{
			String originalXmlFileName ="test.xml";
			String cryptFileName ="crypt.bin";
			// read document from file
			Document document = new SAXBuilder().build(originalXmlFileName);
			// write document encrypted to file
			saveXML(cryptFileName, document);
			// read encrypted document from file
			Document document2 = loadXML(cryptFileName);
			System.out.println("result:" + (document2.getContentSize() == document.getContentSize())); // stupid check
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}
	
	public static Document loadXML(String fileName) 
	{
	    try
		{
			Cipher c = Cipher.getInstance("DES");

			/* Schlüssel für die Entschlüsselung setzen */
			String key = "66776688";
			Key k = new SecretKeySpec(key.getBytes(), "DES");

			c.init(Cipher.DECRYPT_MODE, k);

			FileInputStream fis = new FileInputStream(fileName);

			CipherInputStream cis = new CipherInputStream(fis, c);

			Document document = new SAXBuilder().build(cis);
			return document;
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		return null;
	}
	
	public static void saveXML(String datei, Document document)
	{
		try
		{
			Cipher c = Cipher.getInstance("DES");

			/* Schlüssel für die Verschlüsselung setzen */
			String key = "66776688";
			Key k = new SecretKeySpec(key.getBytes(), "DES");

			c.init(Cipher.ENCRYPT_MODE, k);

			/* FileOutputStream zum schreiben der Datei */
			FileOutputStream fos = new FileOutputStream(datei, false);

			/* FileOutputStream über CipherOutputStream verschlüsseln */
			CipherOutputStream cos = new CipherOutputStream(fos, c);

			/*
			 * Schreiben der XML-Datei (für unverschlüsselt: cos durch fos
			 * ersetzen)
			 */
			XMLOutputter out = new XMLOutputter(Format.getPrettyFormat());
			out.output(document, cos);
			cos.close();
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}
}
 
Habe meine Save-XML-Methode heute nochmal überarbeitet (hatte irgendwo nen Zeilendreher). Auf jeden Fall läuft's jetzt...
Danke für die Hilfe!
 
Hallo,

läuft das jetzt sauber bei dir oder auf die umständliche Weise ala:

wenns sauber läuft könntest du hier sagen, wie du den Fehler behoben hast?

Also speicher ich erst unverschlüsselt und rufe dann die Verschlüsselung auf. Unschön, funktioniert aber...
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Zurück
Oben