diff --git a/eu.steffo.cleaver.iml b/eu.steffo.cleaver.iml index 5770e2e..971f913 100644 --- a/eu.steffo.cleaver.iml +++ b/eu.steffo.cleaver.iml @@ -6,6 +6,7 @@ + diff --git a/examples/loremipsum.txt.c1 b/examples/loremipsum.txt.c1 deleted file mode 100644 index a55d884..0000000 Binary files a/examples/loremipsum.txt.c1 and /dev/null differ diff --git a/examples/loremipsum.txt.c2 b/examples/loremipsum.txt.c2 deleted file mode 100644 index 1fcb998..0000000 Binary files a/examples/loremipsum.txt.c2 and /dev/null differ diff --git a/examples/loremipsum.txt.c3 b/examples/loremipsum.txt.c3 deleted file mode 100644 index 64e357b..0000000 Binary files a/examples/loremipsum.txt.c3 and /dev/null differ diff --git a/examples/loremipsum.txt.c4 b/examples/loremipsum.txt.c4 deleted file mode 100644 index b2669ac..0000000 Binary files a/examples/loremipsum.txt.c4 and /dev/null differ diff --git a/examples/loremipsum.txt.c5 b/examples/loremipsum.txt.c5 deleted file mode 100644 index 1601410..0000000 Binary files a/examples/loremipsum.txt.c5 and /dev/null differ diff --git a/examples/loremipsum.txt.c6 b/examples/loremipsum.txt.c6 deleted file mode 100644 index 8b3e07c..0000000 Binary files a/examples/loremipsum.txt.c6 and /dev/null differ diff --git a/examples/loremipsum.txt.c7 b/examples/loremipsum.txt.c7 deleted file mode 100644 index 38c3caf..0000000 Binary files a/examples/loremipsum.txt.c7 and /dev/null differ diff --git a/examples/loremipsum.txt.c8 b/examples/loremipsum.txt.c8 deleted file mode 100644 index 2b0582b..0000000 Binary files a/examples/loremipsum.txt.c8 and /dev/null differ diff --git a/examples/loremipsum.txt.c9 b/examples/loremipsum.txt.c9 deleted file mode 100644 index 33e43a2..0000000 Binary files a/examples/loremipsum.txt.c9 and /dev/null differ diff --git a/examples/loremipsum.txt.chp b/examples/loremipsum.txt.chp deleted file mode 100644 index 4816b80..0000000 --- a/examples/loremipsum.txt.chp +++ /dev/null @@ -1 +0,0 @@ -loremipsum.txt \ No newline at end of file diff --git a/src/eu/steffo/cleaver/gui/CleaverFrame.java b/src/eu/steffo/cleaver/gui/CleaverFrame.java index 144091b..b15ec90 100644 --- a/src/eu/steffo/cleaver/gui/CleaverFrame.java +++ b/src/eu/steffo/cleaver/gui/CleaverFrame.java @@ -109,7 +109,7 @@ public class CleaverFrame extends JFrame { @Override public void actionPerformed(ActionEvent e) { for(Job job : jobs) { - if(job.getProgress() instanceof NotStartedProgress) + if(job.getState() == Thread.State.NEW) { job.start(); } diff --git a/src/eu/steffo/cleaver/logic/ChopJob.java b/src/eu/steffo/cleaver/logic/ChopJob.java index 444337e..3d5efcd 100644 --- a/src/eu/steffo/cleaver/logic/ChopJob.java +++ b/src/eu/steffo/cleaver/logic/ChopJob.java @@ -98,7 +98,7 @@ public class ChopJob extends Job { outputStream = new SplitFileOutputStream(file.getAbsolutePath(), splitConfig.getPartSize()); } else { - outputStream = new FileOutputStream(String.format("%s.c00", file.getAbsolutePath())); + outputStream = new FileOutputStream(String.format("%s.c0", file.getAbsolutePath())); } if(compressConfig != null) { @@ -160,6 +160,7 @@ public class ChopJob extends Job { this.setProgress(new FinishedProgress()); } catch (Throwable e) { + e.printStackTrace(); this.setProgress(new ErrorProgress(e)); } } diff --git a/src/eu/steffo/cleaver/logic/StitchJob.java b/src/eu/steffo/cleaver/logic/StitchJob.java index eaa3334..c95623a 100644 --- a/src/eu/steffo/cleaver/logic/StitchJob.java +++ b/src/eu/steffo/cleaver/logic/StitchJob.java @@ -193,7 +193,7 @@ public class StitchJob extends Job { inputStream = new SplitFileInputStream(resultFile.getPath(), splitConfig.getPartSize()); } else { - inputStream = new FileInputStream(String.format("%s.c00", resultFile.getAbsolutePath())); + inputStream = new FileInputStream(String.format("%s.c0", resultFile.getAbsolutePath())); } if (compressConfig != null) { @@ -201,7 +201,7 @@ public class StitchJob extends Job { } if (cryptConfig != null) { - inputStream = new CryptInputStream(inputStream); + inputStream = new CryptInputStream(inputStream, cryptConfig.getKey()); } //Pipe everything to the output @@ -220,6 +220,7 @@ public class StitchJob extends Job { this.setProgress(new FinishedProgress()); } catch (Throwable e) { + e.printStackTrace(); this.setProgress(new ErrorProgress(e)); } } diff --git a/src/eu/steffo/cleaver/logic/crypt/CryptInputStream.java b/src/eu/steffo/cleaver/logic/crypt/CryptInputStream.java index 0995979..9049393 100644 --- a/src/eu/steffo/cleaver/logic/crypt/CryptInputStream.java +++ b/src/eu/steffo/cleaver/logic/crypt/CryptInputStream.java @@ -1,14 +1,112 @@ package eu.steffo.cleaver.logic.crypt; import javax.crypto.Cipher; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.SecretKeySpec; import java.io.FilterInputStream; +import java.io.IOException; import java.io.InputStream; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.KeySpec; public class CryptInputStream extends FilterInputStream { + private Cipher cipher; - public CryptInputStream(InputStream in) { - super(in); + /** + * @return The algorithm used for the encryption. + */ + public String getAlgorithm() { + return "AES"; } - //TODO: This doesn't do anything... yet. + /** + * @return The mode of operation used for the encryption. + */ + public String getModeOfOperation() { + return "CFB8"; + } + + /** + * @return The padding used for the encryption. + */ + public String getPadding() { + return "PKCS5Padding"; + } + + /** + * @return The secret key algorithm used in the generation of the final key. + */ + public String getKeyAlgorithm() { + return "PBKDF2WithHmacSHA1"; + } + + /** + * @return The full transformation string as required by {@link Cipher#getInstance(String)}. + */ + public String getTransformationString() { + return String.format("%s/%s/%s", getAlgorithm(), getModeOfOperation(), getPadding()); + } + + + public CryptInputStream(InputStream in, String key) throws InvalidKeyException { + super(in); + + //Setup the cipher object + try { + cipher = Cipher.getInstance(getTransformationString()); + } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { + //Should never happen, as it's predefined + e.printStackTrace(); + return; + } + + //Create the salt + byte[] salt = new byte[8]; + SecureRandom secureRandom = new SecureRandom(); + secureRandom.nextBytes(salt); + + //Create the KeySpec + //Using the recommended 65536 as iteration count + KeySpec spec = new PBEKeySpec(key.toCharArray(), salt, 65536, 256); + + SecretKeyFactory factory; + try { + factory = SecretKeyFactory.getInstance(getKeyAlgorithm()); + } catch (NoSuchAlgorithmException e) { + //Should never happen, as it's predefined + e.printStackTrace(); + return; + } + + //Create the pbkdf secret key + SecretKey pbkdf; + try { + pbkdf = factory.generateSecret(spec); + } catch (InvalidKeySpecException e) { + //Should never happen, as it's predefined + e.printStackTrace(); + return; + } + + //"Convert" the secret key to a AES secret key + SecretKey aes = new SecretKeySpec(pbkdf.getEncoded(), getAlgorithm()); + + //Init the cipher instance + cipher.init(Cipher.DECRYPT_MODE, aes); + } + + @Override + public int read() throws IOException { + int encryptedInt = super.read(); + byte[] encryptedByte = new byte[1]; + encryptedByte[0] = (byte)encryptedInt; + byte[] decryptedByte = cipher.update(encryptedByte); + return decryptedByte[0]; + } } diff --git a/src/eu/steffo/cleaver/logic/crypt/CryptOutputStream.java b/src/eu/steffo/cleaver/logic/crypt/CryptOutputStream.java index a2913e1..ae7eec3 100644 --- a/src/eu/steffo/cleaver/logic/crypt/CryptOutputStream.java +++ b/src/eu/steffo/cleaver/logic/crypt/CryptOutputStream.java @@ -4,68 +4,119 @@ import eu.steffo.cleaver.errors.ProgrammingError; import javax.crypto.Cipher; import javax.crypto.NoSuchPaddingException; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; import java.io.FilterOutputStream; import java.io.IOException; import java.io.OutputStream; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.KeySpec; public class CryptOutputStream extends FilterOutputStream { private Cipher cipher; - private final String algorithm; - private final String modeOfOperation; - private final String padding; - + /** + * @return The algorithm used for the encryption. + */ public String getAlgorithm() { - return algorithm; + return "AES"; } + /** + * @return The mode of operation used for the encryption. + */ public String getModeOfOperation() { - return modeOfOperation; + return "CFB8"; } + /** + * @return The padding used for the encryption. + */ public String getPadding() { - return padding; + return "PKCS5Padding"; } + /** + * @return The secret key algorithm used in the generation of the final key. + */ + public String getKeyAlgorithm() { + return "PBKDF2WithHmacSHA1"; + } + + /** + * @return The full transformation string as required by {@link Cipher#getInstance(String)}. + */ public String getTransformationString() { - return String.format("%s/%s/%s", algorithm, modeOfOperation, padding); + return String.format("%s/%s/%s", getAlgorithm(), getModeOfOperation(), getPadding()); } - public CryptOutputStream(OutputStream out, String key, String algorithm, String modeOfOperation, String padding) throws ProgrammingError { + /** + * Create a new CryptOutputStream with default {@link Cipher} parameters. + * (AES algorithm in operation mode CFB8 with PKCS5 padding) + * + * Does not use this as {@literal try} and {@literal catch} are not supported. + * + * @param out The {@link OutputStream} to connect this {@link FilterOutputStream} to. + * @param key The desired encryption key. + */ + public CryptOutputStream(OutputStream out, String key) throws InvalidKeyException { super(out); - this.algorithm = algorithm; - this.modeOfOperation = modeOfOperation; - this.padding = padding; - //Setup the cipher object try { cipher = Cipher.getInstance(getTransformationString()); - } catch (NoSuchAlgorithmException e) { - // This should never happen. - throw new ProgrammingError("Invalid algor specified in the CryptOutputStream."); - } catch (NoSuchPaddingException e) { - // This should never happen. - throw new ProgrammingError("Invalid padding specified in the CryptOutputStream."); + } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { + //Should never happen, as it's predefined + e.printStackTrace(); + return; } - try { - cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key.getBytes(), this.algorithm)); - } catch (InvalidKeyException e) { - // This should never happen. - throw new ProgrammingError("Invalid key specified in the CryptOutputStream."); - } - } - public CryptOutputStream(OutputStream out, String key) throws ProgrammingError { - this(out, key, "AES", "CBC", "PKCS5Padding"); + //Create the salt + byte[] salt = new byte[8]; + SecureRandom secureRandom = new SecureRandom(); + secureRandom.nextBytes(salt); + + //Create the KeySpec + //Using the recommended 65536 as iteration count + KeySpec spec = new PBEKeySpec(key.toCharArray(), salt, 65536, 256); + + SecretKeyFactory factory; + try { + factory = SecretKeyFactory.getInstance(getKeyAlgorithm()); + } catch (NoSuchAlgorithmException e) { + //Should never happen, as it's predefined + e.printStackTrace(); + return; + } + + //Create the pbkdf secret key + SecretKey pbkdf; + try { + pbkdf = factory.generateSecret(spec); + } catch (InvalidKeySpecException e) { + //Should never happen, as it's predefined + e.printStackTrace(); + return; + } + + //"Convert" the secret key to a AES secret key + SecretKey aes = new SecretKeySpec(pbkdf.getEncoded(), getAlgorithm()); + + //Init the cipher instance + cipher.init(Cipher.ENCRYPT_MODE, aes); } @Override - public void write(int b) throws IOException { - //TODO - super.write(b); + public void write(int decryptedInt) throws IOException { + byte[] decryptedByte = new byte[1]; + decryptedByte[0] = (byte)decryptedInt; + byte[] encryptedByte = cipher.update(decryptedByte); + int encryptedInt = encryptedByte[0]; + super.write(encryptedInt); } }