Verschlüsselungsprogramm nur schwer kontrollierbar bzw. buggy auf manchen Systemen

Don83

Bekanntes Mitglied
Hallo,

ich habe vor einer Weile anhand verschiedener Quellen eine Java-Hybridverschlüsselung erstellt. Es hat sich herausgestellt, dass das ganze nicht ganz optimal funktioniert. Grundsätzlich! Es funktioniert!
Jedoch, wenn die Daten zu groß werden dauert es ewig. Ich würde hier gerne printmeldungen einbauen bei denen man sieht wie weit die Verschlüsselung fortgeschritten ist. Also sowas wie... [Zeit] xxx Zeilen verarbeitet, damit man weis wo man ist, während das Programm durchrattert.

Ehrlich gesagt habe ich keine Ahnung ob das beim jetzigen Code überhaupt möglich ist, da die Datei ja nicht Zeilenweise eingelesen wird.

Zudem -> Bei mir funktioniert die Software, auf einem anderem System funktioniert sie zwar auch, aber eben nur auf extrem kleinen Daten. Bei größeren Daten bricht sie einfach ohne Fehlermeldung ab und erzeugt eine extrem kleine Datei. Das schlimme wie gesagt, dass nicht mal ein Fehler geworfen wird. Über das System kann ich leider keine Aussagen machen, ich denke allerdings dass es ein relativ alter und Rechenschwacher Rechner ist.

Meine zwei Probleme also:
1. Ich würde gerne durch Printmeldungen vom Programm über den momentanen Fortschritt auf dem laufenden gehalten werden.
2. Hat jemand eine Ahnung warum das Programm teilweise einfach ohne Fehlermeldung vorgaukelt es wäre fertig und abbricht?

Hier einmal der Programmcode:
Java:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.util.logging.Logger;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;

public class Encrypt{
	/**
	 * Transforms all bytes from the input stream with a crypt alorithm and
	 * sends the transformed bytes to the output stream.
	 * 
	 * @param in
	 *            input stream
	 * @param out
	 *            output stream
	 * @param cipher
	 *            crypt alorithm used
	 */
	public static void crypt(InputStream in, OutputStream out, Cipher cipher)
			throws IOException, GeneralSecurityException {
		
		int blockSize = cipher.getBlockSize();
		//System.out.println(blockSize);
		int outputSize = cipher.getOutputSize(blockSize);
		byte[] input = new byte[blockSize];
		byte[] output = new byte[outputSize];
		int inLength = 0;
		boolean finished = false;
		
		
		while (!finished) {
			inLength = in.read(input);
			if (inLength == blockSize) {
				int outLength = cipher.update(input, 0, blockSize, output);
				out.write(output, 0, outLength);
			} else {
				finished = true;
			}
		}

		if (inLength > 0)
			output = cipher.doFinal(input, 0, inLength);
		else
			output = cipher.doFinal();

		out.write(output);
	}

	/**
	 * Encrypt a byte array with AES using the public RSA key.
	 * 
	 * @param publicKeyFile
	 *            name of the public key
	 * @param plainText
	 *            name of the input file
	 * @param outputFile
	 *            name of the output file
	 */
	public static void encrypt(String publicKeyFile, String inputFile,
			String outputFile) {
		try {
			KeyGenerator keygen = KeyGenerator.getInstance("AES");
			SecureRandom random = new SecureRandom();
			
			keygen.init(random);
			SecretKey key = keygen.generateKey();

			// Wrap with public key
			ObjectInputStream keyIn = new ObjectInputStream(
					new FileInputStream(publicKeyFile));
			Key publicKey = (Key) keyIn.readObject();
			keyIn.close();

			Cipher cipher = Cipher.getInstance("RSA");
			cipher.init(Cipher.WRAP_MODE, publicKey);
			byte[] wrappedKey = cipher.wrap(key);
			DataOutputStream out = new DataOutputStream(new FileOutputStream(
					outputFile));
			out.writeInt(wrappedKey.length);
			out.write(wrappedKey);

			InputStream in = new FileInputStream(inputFile);
			cipher = Cipher.getInstance("AES");
			cipher.init(Cipher.ENCRYPT_MODE, key);
			crypt(in, out, cipher);
			in.close();
			out.close();
		} catch (IOException e) {
		} catch (GeneralSecurityException e) {
		} catch (ClassNotFoundException e) {
		}
	}


	public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
		ConfigReader conf = new ConfigReader();
		String public_Key = conf.getPublickey();
		ObjectInputStream keyIn = new ObjectInputStream(new FileInputStream(
				public_Key));
		keyIn.close();

		String pid = conf.getStdoutput();
		String pid_a = conf.getStdcrypt();
		System.out.println("This process may take some time...");
		encrypt(public_Key, pid, pid_a);
		System.out.println("Encryption completed.");
	}
}

Und noch der Code zum erstellen der Schlüssel

Java:
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;

public class KeyGen {
	/** The key size. */
	private static final int KEYSIZE = 2048;
	/**
	 * Generate a RSA pair key (public.key, private.key) and stores it in files.
	 * 
	 * @param privateKeyFileName
	 *            name of the private key
	 * @param publicKeyFileName
	 *            name of the public key
	 */
	public static void generateKey(String privateKeyFileName,
			String publicKeyFileName) {
		try {
			KeyPairGenerator pairgen = KeyPairGenerator.getInstance("RSA");
			SecureRandom random = new SecureRandom();
			pairgen.initialize(KEYSIZE, random);
			KeyPair keyPair = pairgen.generateKeyPair();
			ObjectOutputStream out = new ObjectOutputStream(
					new FileOutputStream(publicKeyFileName));
			out.writeObject(keyPair.getPublic());
			out.close();
			out = new ObjectOutputStream(new FileOutputStream(
					privateKeyFileName));
			out.writeObject(keyPair.getPrivate());
			out.close();
		} catch (IOException e) {
		} catch (GeneralSecurityException e) {
		}
	}

	public static void main(String[] args) {
		ConfigReader conf = new ConfigReader();
		String privateKeyFileName = conf.getSecretkey();
		String publicKeyFileName = conf.getPublickey();
		generateKey(privateKeyFileName, publicKeyFileName);
		System.out.println("Schlüsselpaar wurde erzeugt!");
	}
}
 
Zuletzt bearbeitet:

anti-held

Bekanntes Mitglied
wie wäre es mit:

Java:
        int counter = 1;
        while (!finished) {
            inLength = in.read(input);
            if (inLength == blockSize) {
                int outLength = cipher.update(input, 0, blockSize, output);
                out.write(output, 0, outLength);
                System.out.println(String.format("%d bytes written", counter++));
            } else {
                finished = true;
            }
        }
 
Zuletzt bearbeitet:

Don83

Bekanntes Mitglied
Hey,

danke erstmal für den Vorschlag. Ehrlich gesagt kenne ich die Form dieses Syso ausdrucks nicht. Wird bei mir auch als Fehler angezeigt, wenn ich das so übertrage. Aber die Idee verstehe ich natürlich. Wäre es hier dann aber auch möglich, dass man sagt xx Bytes von insgesamt xx written? So dass man also weis, man ist jetzt bei z.B. 5% progress? Kann ich irgendwie die Größe des kompletten Inputs ermitteln?
 

anti-held

Bekanntes Mitglied
sry...
hatte mich verschrieben und es nicht getestet!

hier der Code der funktionieren sollte!

Java:
        System.out.println(String.format("%d percent written", new Double(100 * (double)counter++ / (double)blockSize ).intValue()));
 
Zuletzt bearbeitet:

Don83

Bekanntes Mitglied
Hiho,

also, funktioniert leider nicht ganz so :D.

Hier mal ein kurzer Auszug aus den Printmeldungen:
Java:
175950 percent written
175956 percent written
175962 percent written
175968 percent written
175975 percent written
175981 percent written
175987 percent written
175993 percent written
176000 percent written
Ich denke das Problem liegt darin, dass blockSize nicht die byteGröße des inputs ist sondern lediglich ein Wert von 16(!?). Habe mir das gerade ausprinten lassen.
 

Don83

Bekanntes Mitglied
Hi,
habe nun das richtige kommando gefunden um die Größe des inputstreams zumindest abzuschätzen.
Mit in.available() gehts.

Das ganze sieht dann bei mir im Moment so aus:
Java:
int insize = in.available();
// ....
// ....
System.out.println( new Double(100 * (double)counter++ / insize )+ "% abgeschlossen!");
 

MR_UNIX

Bekanntes Mitglied
Hallo,

die Methode available() kann eigentlich nicht tun, was du willst. Befragte hierzu JavaDoc:
Code:
int	available()
Returns an estimate of the number of bytes that can be read (or skipped over) from this input stream without blocking by the next invocation of a method for this input stream.

Augenmerkt liegt hier auf "estimate", zu Deutsch "geschätzt, ungefähr" und "from this input stream without blocking".
Sprich: nur die Menge wird angezeigt, bis der InputStream wieder blocken würde um neue Daten aus dem File zu ziehen. Hoffe, du versteht wie ich das meine...
 

Don83

Bekanntes Mitglied
Ok, dass es nur ein Schätzwert ist hatte ich verstanden, aber das mit dem Blocking war/ist mir noch nicht so ganz klar. Aber ich weis auch nicht zu 100% wie so ein InputStream funktioniert. Werde mir das gleich mal anlesen. Danke für den Hinweis!
 

Ähnliche Java Themen

Neue Themen


Oben