XOR Verschlüsselung Key Datei

Die Umstellung auf BufferedStreams ergab bei mir eine Zeitoptimierung um ca den Faktor 6, was das ganze schon angenehmer macht.

aktueller Code
[spoiler]

public class XORCrypter {
	public enum CrypterMode {
		ENCRYPT,
		DECRYPT;
	}
	
	private File inputFile;
	private File outputFile;
	private File keyFile;
	private CrypterMode mode;
	private List<CrypterListener> listener = new ArrayList<CrypterListener>();
	private boolean running = false;
	
	private XORCrypter(File inputFile, File outputFile, File keyFile, CrypterMode mode) throws IllegalArgumentException {
		this.inputFile = inputFile;
		this.outputFile = outputFile;
		this.keyFile = keyFile;
		this.mode = mode;
		
		if(keyFile.length() - inputFile.length() < 100) {
			throw new IllegalArgumentException("key file needs to be larger than input file");
		}
		
	}
	
	/**
	 * Creates a crypter object to encrypt
	 * 
	 * @param inputFile
	 * @param outputFile
	 * @param keyFile
	 * @throws Exception 
	 */
	public XORCrypter(File inputFile, File outputFile, File keyFile) throws IllegalArgumentException {
		this(inputFile, outputFile, keyFile, CrypterMode.ENCRYPT);
	}
	
	/**
	 * Creates a crypter object to decrypt
	 * 
	 * @param inputFile
	 * @param keyFile
	 * @throws Exception 
	 */
	public XORCrypter(File inputFile, File keyFile) throws IllegalArgumentException {
		this(inputFile, null, keyFile, CrypterMode.DECRYPT);
	}
	
	public void doWork() {
		running = true;
		
		InputStream inputIn = null;
		InputStream keyIn = null;
		OutputStream outputOut = null;
		
		try {
			inputIn = new BufferedInputStream(new FileInputStream(inputFile));
			keyIn = new BufferedInputStream(new FileInputStream(keyFile));
			
			if(mode == CrypterMode.DECRYPT) {
				//read prefix
				
				//get length
				byte[] prefixData = new byte[4];
				inputIn.read(prefixData);
				
				byte[] keyData = new byte[prefixData.length];
				keyIn.read(keyData);
				
				prefixData = crypt(prefixData, keyData);
				int prefixLength = byteArrayToInt(prefixData);
				
				if(prefixLength > 64) {
					//invalid length
					//generate one and lets see what happens
					prefixLength = new Random().nextInt(61) + 4;
				}

				//get prefix data
				prefixData = new byte[prefixLength];
				inputIn.read(prefixData);
				
				keyData = new byte[prefixData.length];
				keyIn.read(keyData);
				
				prefixData = crypt(prefixData, keyData);
				
				String outputFileName = getNextPossibleFileName(new String(prefixData));
				outputFile = new File(outputFileName);
			}
			
			outputOut = new BufferedOutputStream(new FileOutputStream(outputFile));
			
			if(mode == CrypterMode.ENCRYPT) {
				//write prefix
				
				byte[] prefixData = generatePrefix();
				
				byte[] keyData = new byte[prefixData.length];
				keyIn.read(keyData);
				
				prefixData = crypt(prefixData, keyData);
				
				outputOut.write(prefixData);
			}
						
			byte[] dataBuffer = new byte[1024];
			byte[] keyBuffer = new byte[1024];
			int bytesRead = 0;
			
			while(running && (bytesRead = inputIn.read(dataBuffer)) != -1) {
				keyIn.read(keyBuffer);
				
				outputOut.write(crypt(dataBuffer, keyBuffer, bytesRead));
			}
			
			if(running) {
				for(CrypterListener l : listener) {
					l.finished();
				}
			
				running = false;
			}
			else {
				//aborted
				
				for(CrypterListener l : listener) {
					l.failed("process stopped");
				}
			}
			
		} catch (FileNotFoundException e) {
			for(CrypterListener l : listener) {
				l.failed(e.getMessage());
			}
		} catch (IOException e) {
			for(CrypterListener l : listener) {
				l.failed(e.getMessage());
			}
		}
		finally {
			try {
				if(inputIn != null)
					inputIn.close();
				
				if(keyIn != null)
					keyIn.close();
				
				if(outputOut != null)
					outputOut.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
	}
	
	public void addListener(CrypterListener l) {
		listener.add(l);
	}
	
	public void removeListener(CrypterListener l) {
		listener.remove(l);
	}
	
	private byte[] crypt(byte[] data, byte[] key) {
		return crypt(data, key, data.length);
	}
	
	private byte[] crypt(byte[] data, byte[] key, int length) {
		byte[] cryptedData = new byte[length];
		
		for(int i = 0; i < cryptedData.length; i++) {
			cryptedData** = (byte) (data**^key**);
		}
		
		return cryptedData;
	}
	
	public boolean isRunning() {
		return running;
	}
	
	public void stop() {
		running = false;
	}
	
	private byte[] generatePrefix() {
		String fileName = inputFile.getName();
		
		ByteBuffer b = ByteBuffer.allocate(4 + fileName.getBytes().length);
		b.putInt(fileName.getBytes().length);
		b.put(fileName.getBytes());
	
		return b.array();

	}
	
	private int byteArrayToInt(byte[] b) {
	    return   b[3] & 0xFF |
	            (b[2] & 0xFF) << 8 |
	            (b[1] & 0xFF) << 16 |
	            (b[0] & 0xFF) << 24;
	}
	
	private String getNextPossibleFileName(String name) {
		int counter = 0;
		String nameToTest = name;
		
		while(new File(nameToTest).exists()) {
			counter++;
			nameToTest = counter + "_" + name;
		}
		
		return nameToTest;
	}
}

[/spoiler]

Zwecks Verbessungen lass ich mir die Anregungen aus diesem Thread weiter durch den Kopf gehen und gönn mir noch etwas Theorie :slight_smile: