Add files via upload

This commit is contained in:
blueShard-dev 2020-05-04 21:23:29 +02:00 committed by GitHub
parent 543db53221
commit 134cd4c8c8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 3638 additions and 0 deletions

3
src/META-INF/MANIFEST.MF Normal file
View File

@ -0,0 +1,3 @@
Manifest-Version: 1.0
Main-Class: org.blueshard.cryptogx.Main

View File

@ -0,0 +1,789 @@
package org.blueshard.cryptogx;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox;
import javafx.stage.*;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.xml.stream.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import java.io.*;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import static org.blueshard.cryptogx.Main.*;
/**
* <p>Class for the user configuration / settings</p>
*/
public class Config {
private static double addConfigGUIX, addConfigGUIY;
private static final HashSet<String> protectedConfigNames = new HashSet<>(Arrays.asList("cryptoGX", "config"));
/**
* <p>Shows a GUI where the user can save settings, which can load later</p>
*
* @param rootWindow from which this GUI will get called
* @param userSetting
* @throws IOException
*/
public static void addSettingGUI(Window rootWindow, Map<String, String> userSetting) throws IOException {
Map<String, String> newSettingItems = new HashMap<>();
Stage rootStage = new Stage();
rootStage.initOwner(rootWindow);
Parent addSettingsRoot = FXMLLoader.load(Config.class.getResource("resources/addSettingsGUI.fxml"));
rootStage.initStyle(StageStyle.UNDECORATED);
rootStage.initModality(Modality.WINDOW_MODAL);
rootStage.setResizable(false);
rootStage.setTitle("cryptoGX");
Scene scene = new Scene(addSettingsRoot, 320, 605);
rootStage.setScene(scene);
scene.setOnMouseDragged(event -> {
rootStage.setX(event.getScreenX() + addConfigGUIX);
rootStage.setY(event.getScreenY() + addConfigGUIY);
});
scene.setOnMousePressed(event -> {
addConfigGUIX = scene.getX() - event.getSceneX();
addConfigGUIY = scene.getY() - event.getSceneY();
});
Thread thread = new Thread(() -> {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
Platform.runLater(() -> {
MenuBar menuBar = (MenuBar) addSettingsRoot.lookup("#menuBar");
menuBar.setOnMouseDragged(event -> {
rootStage.setX(event.getScreenX() + addConfigGUIX);
rootStage.setY(event.getScreenY() + addConfigGUIY);
});
menuBar.setOnMousePressed(event -> {
addConfigGUIX = menuBar.getLayoutX() - event.getSceneX();
addConfigGUIY = menuBar.getLayoutY() - event.getSceneY();
});
ImageView closeButton = (ImageView) addSettingsRoot.lookup("#closeButton");
closeButton.setOnMouseClicked(event -> rootStage.close());
TextField settingsNameEntry = (TextField) addSettingsRoot.lookup("#settingsNameEntry");
TextField textKeyEntry = (TextField) addSettingsRoot.lookup("#textKeyEntry");
textKeyEntry.setText(userSetting.get("textKey"));
TextField textSaltEntry = (TextField) addSettingsRoot.lookup("#textSaltEntry");
textSaltEntry.setText(userSetting.get("textSalt"));
ComboBox textAlgorithmBox = (ComboBox) addSettingsRoot.lookup("#textAlgorithmComboBox");
textAlgorithmBox.setItems(FXCollections.observableArrayList(textAlgorithms));
textAlgorithmBox.setValue(userSetting.get("textAlgorithm"));
TextField fileEnDecryptKeyEntry = (TextField) addSettingsRoot.lookup("#fileEnDecryptKeyEntry");
fileEnDecryptKeyEntry.setText(userSetting.get("fileEnDecryptKey"));
TextField fileEnDecryptSaltEntry = (TextField) addSettingsRoot.lookup("#fileEnDecryptSaltEntry");
fileEnDecryptSaltEntry.setText(userSetting.get("fileEnDecryptSalt"));
ComboBox fileEnDecryptAlgorithmBox = (ComboBox) addSettingsRoot.lookup("#fileEnDecryptAlgorithmComboBox");
fileEnDecryptAlgorithmBox.setItems(FXCollections.observableArrayList(fileEnDecryptAlgorithms));
fileEnDecryptAlgorithmBox.setValue(userSetting.get("fileEnDecryptAlgorithm"));
TextField fileDeleteIterationEntry = (TextField) addSettingsRoot.lookup("#fileDeleteIterationsEntry");
fileDeleteIterationEntry.setText(userSetting.get("fileDeleteIterations"));
fileDeleteIterationEntry.textProperty().addListener((observable, oldValue, newValue) -> {
if (!newValue.matches("[0-9]*")) {
fileDeleteIterationEntry.setText(oldValue);
}
});
TextField fileOutputPathEntry = (TextField) addSettingsRoot.lookup("#fileOutputPathEntry");
fileOutputPathEntry.setText(userSetting.get("fileOutputPath"));
CheckBox removeFromFileBoxCheckBox = (CheckBox) addSettingsRoot.lookup("#removeFromFileBoxCheckBox");
removeFromFileBoxCheckBox.setSelected(Boolean.parseBoolean(userSetting.get("removeFromFileBox")));
CheckBox limitNumberOfThreadsCheckBox = (CheckBox) addSettingsRoot.lookup("#limitNumberOfThreadsCheckBox");
limitNumberOfThreadsCheckBox.setSelected(Boolean.parseBoolean(userSetting.get("limitNumberOfThreads")));
PasswordField hiddenPasswordEntry = (PasswordField) addSettingsRoot.lookup("#hiddenPasswordEntry");
TextField showedPasswordEntry = (TextField) addSettingsRoot.lookup("#showedPasswordEntry");
CheckBox showPassword = (CheckBox) addSettingsRoot.lookup("#showPassword");
showPassword.setOnAction(event -> {
if (showPassword.isSelected()) {
showedPasswordEntry.setText(hiddenPasswordEntry.getText());
showedPasswordEntry.setVisible(true);
hiddenPasswordEntry.setVisible(false);
} else {
hiddenPasswordEntry.setText(showedPasswordEntry.getText());
hiddenPasswordEntry.setVisible(true);
showedPasswordEntry.setVisible(false);
}
});
CheckBox encryptSettings = (CheckBox) addSettingsRoot.lookup("#encryptSettings");
encryptSettings.setOnAction(event -> {
if (encryptSettings.isSelected()) {
hiddenPasswordEntry.setDisable(false);
showedPasswordEntry.setDisable(false);
showPassword.setDisable(false);
} else {
hiddenPasswordEntry.setDisable(true);
showedPasswordEntry.setDisable(true);
showPassword.setDisable(true);
}
});
Button saveButton = (Button) addSettingsRoot.lookup("#saveButton");
saveButton.setOnAction(event -> {
if (settingsNameEntry.getText().trim().isEmpty()) {
warningAlert("Add a name for the setting");
} else if (protectedConfigNames.contains(settingsNameEntry.getText())) {
warningAlert("Please choose another name for this setting");
} else if (encryptSettings.isSelected()){
try {
EnDecrypt.AES encrypt;
if (!hiddenPasswordEntry.isDisabled()) {
encrypt = new EnDecrypt.AES(hiddenPasswordEntry.getText(), new byte[16]);
newSettingItems.put("encryptHash", encrypt.encrypt(hiddenPasswordEntry.getText()));
} else {
encrypt = new EnDecrypt.AES(showedPasswordEntry.getText(), new byte[16]);
newSettingItems.put("encryptHash", encrypt.encrypt(showedPasswordEntry.getText()));
}
newSettingItems.put("textKey", encrypt.encrypt(textKeyEntry.getText()));
newSettingItems.put("textSalt", encrypt.encrypt(textSaltEntry.getText()));
newSettingItems.put("textAlgorithm", encrypt.encrypt(textAlgorithmBox.getSelectionModel().getSelectedItem().toString()));
newSettingItems.put("fileEnDecryptKey", encrypt.encrypt(fileEnDecryptKeyEntry.getText()));
newSettingItems.put("fileEnDecryptSalt", encrypt.encrypt(fileEnDecryptSaltEntry.getText()));
newSettingItems.put("fileEnDecryptAlgorithm", encrypt.encrypt(fileEnDecryptAlgorithmBox.getSelectionModel().getSelectedItem().toString()));
newSettingItems.put("fileDeleteIterations", encrypt.encrypt(fileDeleteIterationEntry.getText()));
newSettingItems.put("fileOutputPath", encrypt.encrypt(fileOutputPathEntry.getText()));
newSettingItems.put("removeFromFileBox", encrypt.encrypt(String.valueOf(removeFromFileBoxCheckBox.isSelected())));
newSettingItems.put("limitNumberOfThreads", encrypt.encrypt(String.valueOf(limitNumberOfThreadsCheckBox.isSelected())));
addSetting(settingsNameEntry.getText(), newSettingItems);
rootStage.close();
} catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | InvalidKeySpecException e) {
e.printStackTrace();
}
} else {
newSettingItems.put("encryptHash", "");
newSettingItems.put("textKey", textKeyEntry.getText());
newSettingItems.put("textSalt", textSaltEntry.getText());
newSettingItems.put("textAlgorithm", textAlgorithmBox.getSelectionModel().getSelectedItem().toString());
newSettingItems.put("fileEnDecryptKey", fileEnDecryptKeyEntry.getText());
newSettingItems.put("fileEnDecryptSalt", fileEnDecryptSaltEntry.getText());
newSettingItems.put("fileEnDecryptAlgorithm", fileEnDecryptAlgorithmBox.getSelectionModel().getSelectedItem().toString());
newSettingItems.put("fileDeleteIterations", fileDeleteIterationEntry.getText());
newSettingItems.put("fileOutputPath", fileOutputPathEntry.getText());
newSettingItems.put("removeFromFileBox", String.valueOf(removeFromFileBoxCheckBox.isSelected()));
newSettingItems.put("limitNumberOfThreads", String.valueOf(limitNumberOfThreadsCheckBox.isSelected()));
addSetting(settingsNameEntry.getText(), newSettingItems);
rootStage.close();
}
});
});
});
thread.start();
rootStage.showAndWait();
}
/**
* <p>Shows a GUI where the user can export settings to a extra file</p>
*
* @param rootWindow from which this GUI will get called
* @throws IOException
*/
public static void exportSettingsGUI(Window rootWindow) throws IOException {
Stage rootStage = new Stage();
rootStage.initOwner(rootWindow);
Parent exportSettingsRoot = FXMLLoader.load(Config.class.getResource("resources/exportSettingsGUI.fxml"));
rootStage.initStyle(StageStyle.UNDECORATED);
rootStage.initModality(Modality.WINDOW_MODAL);
rootStage.setResizable(false);
rootStage.setTitle("cryptoGX");
Scene scene = new Scene(exportSettingsRoot, 254, 253);
rootStage.setScene(scene);
scene.setOnMouseDragged(event -> {
rootStage.setX(event.getScreenX() + addConfigGUIX);
rootStage.setY(event.getScreenY() + addConfigGUIY);
});
scene.setOnMousePressed(event -> {
addConfigGUIX = scene.getX() - event.getSceneX();
addConfigGUIY = scene.getY() - event.getSceneY();
});
Thread thread = new Thread(() -> {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
MenuBar menuBar = (MenuBar) exportSettingsRoot.lookup("#menuBar");
menuBar.setOnMouseDragged(event -> {
rootStage.setX(event.getScreenX() + addConfigGUIX);
rootStage.setY(event.getScreenY() + addConfigGUIY);
});
menuBar.setOnMousePressed(event -> {
addConfigGUIX = menuBar.getLayoutX() - event.getSceneX();
addConfigGUIY = menuBar.getLayoutY() - event.getSceneY();
});
ImageView closeButton = (ImageView) exportSettingsRoot.lookup("#closeButton");
closeButton.setOnMouseClicked(event -> rootStage.close());
VBox settingsBox = (VBox) exportSettingsRoot.lookup("#settingsBox");
Platform.runLater(() -> readUserSettings().keySet().forEach(s -> {
CheckBox newCheckBox = new CheckBox();
newCheckBox.setText(s);
settingsBox.getChildren().add(newCheckBox);
}));
Button exportButton = (Button) exportSettingsRoot.lookup("#exportButton");
exportButton.setOnAction(event -> {
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Export settings");
fileChooser.setInitialFileName("settings.config");
fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("Config files", "*.config", "*.xml"),
new FileChooser.ExtensionFilter("All files", "*.*"));
File file = fileChooser.showSaveDialog(exportSettingsRoot.getScene().getWindow());
if (file != null) {
TreeMap<String, Map<String, String>> writeInfos = new TreeMap<>();
TreeMap<String, Map<String, String>> settings = readUserSettings();
for (int i=0; i<settingsBox.getChildren().size(); i++) {
CheckBox checkBox = (CheckBox) settingsBox.getChildren().get(i);
if (checkBox.isSelected()) {
String checkBoxText = checkBox.getText();
writeInfos.put(checkBoxText, settings.get(checkBoxText));
}
}
if (!file.getAbsolutePath().contains(".")) {
file = new File(file.getAbsolutePath() + ".config");
}
writeConfig(file, writeInfos);
}
});
});
thread.start();
rootStage.showAndWait();
}
/**
* <p>Shows a GUI where the user can load saved settings</p>
*
* @param rootWindow from which this GUI will get called
* @return the settings that the user has chosen
* @throws IOException
*/
public static TreeMap<String, Map<String, String>> loadSettingsGUI(Window rootWindow) throws IOException {
Button[] outerLoadButton = new Button[1];
HashMap<String, String> setting = new HashMap<>();
TreeMap<String, Map<String, String>> settingItems = readUserSettings();
TreeMap<String, Map<String, String>> returnItems = new TreeMap<>();
Stage rootStage = new Stage();
rootStage.initOwner(rootWindow);
AnchorPane loadSettingsRoot = FXMLLoader.load(Config.class.getResource("resources/loadSettingsGUI.fxml"));
rootStage.initStyle(StageStyle.UNDECORATED);
rootStage.initModality(Modality.WINDOW_MODAL);
rootStage.setResizable(false);
rootStage.setTitle("cryptoGX");
rootStage.getIcons().add(new Image(Config.class.getResource("resources/cryptoGX.png").toExternalForm()));
Scene scene = new Scene(loadSettingsRoot, 242, 235);
scene.setOnMouseDragged(event -> {
rootStage.setX(event.getScreenX() + addConfigGUIX);
rootStage.setY(event.getScreenY() + addConfigGUIY);
});
scene.setOnMousePressed(event -> {
addConfigGUIX = scene.getX() - event.getSceneX();
addConfigGUIY = scene.getY() - event.getSceneY();
});
scene.setOnKeyReleased(event -> {
if (event.getCode() == KeyCode.ENTER) {
outerLoadButton[0].fire();
}
});
Thread thread = new Thread(() -> {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
Platform.runLater(() -> {
MenuBar menuBar = (MenuBar) loadSettingsRoot.lookup("#menuBar");
menuBar.setOnMouseDragged(event -> {
rootStage.setX(event.getScreenX() + addConfigGUIX);
rootStage.setY(event.getScreenY() + addConfigGUIY);
});
menuBar.setOnMousePressed(event -> {
addConfigGUIX = menuBar.getLayoutX() - event.getSceneX();
addConfigGUIY = menuBar.getLayoutY() - event.getSceneY();
});
ImageView closeButton = (ImageView) loadSettingsRoot.lookup("#closeButton");
if (settingItems.isEmpty()) {
rootStage.close();
}
closeButton.setOnMouseClicked(event -> {
setting.put("encryptHash", configDefaultEncryptHash);
setting.put("textKey", configDefaultTextKey);
setting.put("textSalt", configDefaultTextSalt);
setting.put("textAlgorithm", configDefaultTextAlgorithm);
setting.put("fileEnDecryptKey", configDefaultFileEnDecryptKey);
setting.put("fileEnDecryptSalt", configDefaultFileEnDecryptSalt);
setting.put("fileEnDecryptAlgorithm", configDefaultFileEnDecryptAlgorithm);
setting.put("fileDeleteIterations", String.valueOf(configDefaultFileDeleteIterations));
setting.put("fileOutputPath", configDefaultFileOutputPath);
setting.put("removeFromFileBox", String.valueOf(configDefaultRemoveFileFromFileBox));
setting.put("limitNumberOfThreads", String.valueOf(configDefaultLimitNumberOfThreads));
returnItems.put("default", setting);
rootStage.close();
});
PasswordField keyHideEntry = (PasswordField) loadSettingsRoot.lookup("#passwordEntryHide");
TextField keyShowEntry = (TextField) loadSettingsRoot.lookup("#passwordEntryShow");
CheckBox showPassword = (CheckBox) loadSettingsRoot.lookup("#showPassword");
showPassword.setOnAction(event -> {
if (showPassword.isSelected()) {
keyShowEntry.setText(keyHideEntry.getText());
keyShowEntry.setVisible(true);
keyHideEntry.setVisible(false);
} else {
keyHideEntry.setText(keyShowEntry.getText());
keyHideEntry.setVisible(true);
keyShowEntry.setVisible(false);
}
});
ComboBox settingsBox = (ComboBox) loadSettingsRoot.lookup("#settingsBox");
settingsBox.setItems(FXCollections.observableArrayList(settingItems.keySet()));
settingsBox.setValue(settingItems.firstKey());
if (settingItems.firstEntry().getValue().get("encryptHash").trim().isEmpty()) {
keyHideEntry.clear();
keyHideEntry.setDisable(true);
keyShowEntry.setDisable(true);
showPassword.setDisable(true);
}
settingsBox.setOnAction(event -> {
try {
if (settingItems.get(settingsBox.getSelectionModel().getSelectedItem().toString()).get("encryptHash").trim().isEmpty()) {
keyHideEntry.clear();
keyHideEntry.setDisable(true);
keyShowEntry.clear();
keyShowEntry.setDisable(true);
showPassword.setDisable(true);
} else {
keyHideEntry.clear();
keyHideEntry.setDisable(false);
keyShowEntry.clear();
keyShowEntry.setDisable(false);
showPassword.setDisable(false);
}
} catch (NullPointerException e) {
//get called when delete button is pressed
}
});
Button loadButton = (Button) loadSettingsRoot.lookup("#loadButton");
loadButton.setOnAction(event -> {
String settingName = settingsBox.getSelectionModel().getSelectedItem().toString();
Map<String, String> selectedSetting = settingItems.get(settingName);
if (keyHideEntry.isDisabled() && showPassword.isDisabled() && showPassword.isDisabled()) {
setting.put("encryptHash", "");
setting.put("textKey", selectedSetting.get("textKey"));
setting.put("textSalt", selectedSetting.get("textSalt"));
setting.put("textAlgorithm", selectedSetting.get("textAlgorithm"));
setting.put("fileEnDecryptKey", selectedSetting.get("fileEnDecryptKey"));
setting.put("fileEnDecryptSalt", selectedSetting.get("fileEnDecryptSalt"));
setting.put("fileEnDecryptAlgorithm", selectedSetting.get("fileEnDecryptAlgorithm"));
setting.put("fileDeleteIterations", selectedSetting.get("fileDeleteIterations"));
setting.put("fileOutputPath", selectedSetting.get("fileOutputPath"));
setting.put("removeFromFileBox", selectedSetting.get("removeFromFileBox"));
setting.put("limitNumberOfThreads", selectedSetting.get("limitNumberOfThreads"));
returnItems.put(settingsBox.getSelectionModel().getSelectedItem().toString(), setting);
rootStage.close();
} else {
EnDecrypt.AES decryptSetting;
if (keyHideEntry.isVisible()) {
decryptSetting = new EnDecrypt.AES(keyHideEntry.getText(), new byte[16]);
} else {
decryptSetting = new EnDecrypt.AES(keyShowEntry.getText(), new byte[16]);
}
try {
if (keyHideEntry.isVisible() && !decryptSetting.encrypt(keyHideEntry.getText()).equals(settingItems.get(settingsBox.getSelectionModel().getSelectedItem().toString()).get("encryptHash").trim())) {
warningAlert("Wrong key is given");
} else if (keyShowEntry.isVisible() && !decryptSetting.encrypt(keyShowEntry.getText()).equals(settingItems.get(settingsBox.getSelectionModel().getSelectedItem().toString()).get("encryptHash").trim())) {
warningAlert("Wrong key is given");
} else {
Map<String, String> selectedEncryptedSetting = settingItems.get(settingName);
setting.put("textKey", decryptSetting.decrypt(selectedEncryptedSetting.get("textKey")));
setting.put("textSalt", decryptSetting.decrypt(selectedEncryptedSetting.get("textSalt")));
setting.put("textAlgorithm", decryptSetting.decrypt(selectedEncryptedSetting.get("textAlgorithm")));
setting.put("fileEnDecryptKey", decryptSetting.decrypt(selectedEncryptedSetting.get("fileEnDecryptKey")));
setting.put("fileEnDecryptSalt", decryptSetting.decrypt(selectedEncryptedSetting.get("fileEnDecryptSalt")));
setting.put("fileEnDecryptAlgorithm", decryptSetting.decrypt(selectedEncryptedSetting.get("fileEnDecryptAlgorithm")));
setting.put("fileDeleteIterations", String.valueOf(Integer.parseInt(decryptSetting.decrypt(selectedEncryptedSetting.get("fileDeleteIterations")))));
setting.put("fileOutputPath", decryptSetting.decrypt(selectedEncryptedSetting.get("fileOutputPath")));
setting.put("removeFromFileBox", decryptSetting.decrypt(selectedEncryptedSetting.get("removeFromFileBox")));
setting.put("limitNumberOfThreads", decryptSetting.decrypt(selectedEncryptedSetting.get("limitNumberOfThreads")));
returnItems.put(settingsBox.getSelectionModel().getSelectedItem().toString(), setting);
rootStage.close();
}
} catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | InvalidKeySpecException e) {
e.printStackTrace();
warningAlert("Wrong key is given");
}
}
});
outerLoadButton[0] = loadButton;
Button deleteButton = (Button) loadSettingsRoot.lookup("#deleteButton");
deleteButton.setOnAction(event -> {
AtomicReference<Double> deleteQuestionX = new AtomicReference<>((double) 0);
AtomicReference<Double> deleteQuestionY = new AtomicReference<>((double) 0);
Alert deleteQuestion = new Alert(Alert.AlertType.CONFIRMATION, "Delete " + settingsBox.getSelectionModel().getSelectedItem().toString() + "?", ButtonType.OK, ButtonType.CANCEL);
deleteQuestion.initStyle(StageStyle.UNDECORATED);
deleteQuestion.setTitle("Confirmation");
((Stage) deleteQuestion.getDialogPane().getScene().getWindow()).getIcons().add(new Image(Config.class.getResource("resources/cryptoGX.png").toExternalForm()));
Scene window = deleteQuestion.getDialogPane().getScene();
window.setOnMouseDragged(dragEvent -> {
deleteQuestion.setX(dragEvent.getScreenX() + deleteQuestionX.get());
deleteQuestion.setY(dragEvent.getScreenY() + deleteQuestionY.get());
});
window.setOnMousePressed(pressEvent -> {
deleteQuestionX.set(window.getX() - pressEvent.getSceneX());
deleteQuestionY.set(window.getY() - pressEvent.getSceneY());
});
Optional<ButtonType> result = deleteQuestion.showAndWait();
if (result.get() == ButtonType.OK) {
deleteUserSetting(settingsBox.getSelectionModel().getSelectedItem().toString());
settingItems.clear();
settingItems.putAll(readUserSettings());
if (settingItems.size() == 0) {
for (int i=0; i<100; i++) {
if (config.isFile()) {
if (config.delete()) {
isConfig = false;
rootStage.close();
break;
}
}
}
rootStage.close();
return;
}
settingsBox.setItems(FXCollections.observableArrayList(settingItems.keySet()));
settingsBox.setValue(settingItems.firstKey());
}
});
});
});
thread.start();
rootStage.setScene(scene);
rootStage.showAndWait();
return returnItems;
}
/**
* <p>Shows a GUI where the user can save the current settings</p>
*
* @param settingName name of the new setting
* @param userSetting the current settings
*/
public static void addSetting(String settingName, Map<String, String> userSetting) {
TreeMap<String, Map<String, String>> newConfig = new TreeMap<>(readUserSettings());
newConfig.put(settingName, userSetting);
writeConfig(newConfig);
}
/**
* <p>Shows a GUI where the user can save the current settings</p>
*
* @param settingName name of the new setting
* @param userSetting the current settings
* @param encryptPassword to encrypt the settings
*/
public static void addSetting(String settingName, Map<String, String> userSetting, String encryptPassword) {
TreeMap<String, Map<String, String>> newConfig = new TreeMap<>(readUserSettings());
newConfig.put(settingName, userSetting);
writeConfig(newConfig, Collections.singletonMap(settingName, encryptPassword));
}
/**
* <p>Deletes a saved setting</p>
*
* @param name of the setting
* @return if the setting could be found
*/
public static boolean deleteUserSetting(String name) {
TreeMap<String, Map<String, String>> newSetting = new TreeMap<>();
TreeMap<String, Map<String, String>> oldSetting = readUserSettings();
boolean found = false;
for (Map.Entry<String, Map<String, String>> entry: oldSetting.entrySet()) {
if (!entry.getKey().equals(name)) {
newSetting.put(entry.getKey(), entry.getValue());
} else {
found = true;
}
}
writeConfig(newSetting);
return found;
}
public static TreeMap<String, Map<String, String>> readUserSettings() {
return readUserSettings(config);
}
/**
* @see Config#readUserSettings(String)
*/
public static TreeMap<String, Map<String, String>> readUserSettings(File file) {
TreeMap<String, Map<String, String>> rootInfos = new TreeMap<>();
try {
XMLInputFactory xmlInputFactory = XMLInputFactory.newFactory();
XMLStreamReader xmlStreamReader;
try {
xmlStreamReader = xmlInputFactory.createXMLStreamReader(new FileInputStream(file));
} catch (FileNotFoundException e) {
return rootInfos;
}
HashMap<String, String> infos = new HashMap<>();
String infoName = null;
StringBuilder infoCharacters = new StringBuilder();
String rootName = null;
while (xmlStreamReader.hasNext()) {
int eventType = xmlStreamReader.next();
switch (eventType) {
case XMLStreamReader.START_ELEMENT:
String startTag = xmlStreamReader.getLocalName().trim();
if (startTag != null) {
if (protectedConfigNames.contains(startTag)) {
continue;
} else if (rootName == null) {
rootName = startTag;
} else {
infoName = startTag;
}
}
break;
case XMLStreamReader.CHARACTERS:
if (infoName != null) {
if (!xmlStreamReader.getText().trim().equals("")) {
infoCharacters.append(xmlStreamReader.getText());
}
}
break;
case XMLStreamReader.END_ELEMENT:
String endTag = xmlStreamReader.getLocalName().trim();
if (endTag != null) {
if (protectedConfigNames.contains(endTag)) {
continue;
} else if (endTag.equals(rootName)) {
rootInfos.put(rootName, infos);
rootName = null;
infos = new HashMap<>();
infoCharacters = new StringBuilder();
} else {
infos.put(infoName, infoCharacters.toString());
infoName = null;
infoCharacters = new StringBuilder();
}
}
break;
}
}
xmlStreamReader.close();
} catch (XMLStreamException e) {
e.printStackTrace();
}
System.out.println(rootInfos);
return rootInfos;
}
/**
* <p>Shows a GUI where the user can choose and load saved settings </p>
*
* @param filename of the file with the settings
* @return the setting that the user has chosen
*/
public static TreeMap<String, Map<String, String>> readUserSettings(String filename) {
return readUserSettings(new File(filename));
}
/**
* <p>Writes settings (could be more than one) to the pre-defined config file</p>
*
* @see Config#writeConfig(File, TreeMap, Map)
*/
public static void writeConfig(TreeMap<String, Map<String, String>> userSettings) {
writeConfig(config, userSettings, null);
}
/**
* <p>Writes settings (could be more than one) to the pre-defined config file</p>
*
* @see Config#writeConfig(File, TreeMap, Map)
*/
public static void writeConfig(TreeMap<String, Map<String, String>> userSettings, Map<String, String> encryptedSettings) {
writeConfig(config, userSettings, encryptedSettings);
}
/**
* <p>Writes settings (could be more than one) to the pre-defined config file</p>
*
* @see Config#writeConfig(String, TreeMap, Map)
*/
public static void writeConfig(String filename, TreeMap<String, Map<String, String>> userSettings) {
writeConfig(filename, userSettings, null);
}
/**
* <p>Writes settings (could be more than one) to the pre-defined config file</p>
*
* @see Config#writeConfig(File, TreeMap, Map)
*/
public static void writeConfig(File file, TreeMap<String, Map<String, String>> userSettings) {
writeConfig(file, userSettings, null);
}
/**
* <p>Writes settings (could be more than one) to a file</p>
*
* @see Config#writeConfig(String, TreeMap, Map)
*/
public static void writeConfig(String filename, TreeMap<String, Map<String, String>> userSettings, Map<String, String> encryptedSettings) {
writeConfig(new File(filename), userSettings, encryptedSettings);
}
/**
* <p>Writes settings (could be more than one) to a file</p>
*
* @param file where the settings should be written in
* @param userSettings of the user
* @param encryptedSettings says which settings from {@param userSettings} should be encrypted with a password
*/
public static void writeConfig(File file, TreeMap<String, Map<String, String>> userSettings, Map<String, String> encryptedSettings) {
EnDecrypt.AES encryptSetting;
StringWriter stringWriter = new StringWriter();
if (encryptedSettings == null) {
encryptedSettings = new HashMap<>();
}
try {
XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newInstance();
XMLStreamWriter xmlStreamWriter = xmlOutputFactory.createXMLStreamWriter(stringWriter);
xmlStreamWriter.writeStartDocument();
xmlStreamWriter.writeStartElement("cryptoGX");
for (Map.Entry<String, Map<String, String>> settingElement: userSettings.entrySet()) {
xmlStreamWriter.writeStartElement(settingElement.getKey());
if (encryptedSettings.containsKey(settingElement.getKey())) {
encryptSetting = new EnDecrypt.AES(settingElement.getKey(), new byte[16]);
for (Map.Entry<String, String> entry: settingElement.getValue().entrySet()) {
xmlStreamWriter.writeStartElement(entry.getKey());
xmlStreamWriter.writeCharacters(encryptSetting.encrypt(entry.getValue()));
xmlStreamWriter.writeEndElement();
}
} else {
for (Map.Entry<String, String> entry: settingElement.getValue().entrySet()) {
xmlStreamWriter.writeStartElement(entry.getKey());
xmlStreamWriter.writeCharacters(entry.getValue());
xmlStreamWriter.writeEndElement();
}
}
xmlStreamWriter.writeEndElement();
}
xmlStreamWriter.writeEndElement();
xmlStreamWriter.writeEndDocument();
//prettify
Source xmlInput = new StreamSource(new StringReader(stringWriter.toString()));
StringWriter prettifyStringWriter = new StringWriter();
StreamResult xmlOutput = new StreamResult(prettifyStringWriter);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
transformerFactory.setAttribute("indent-number", 2);
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.transform(xmlInput, xmlOutput);
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file));
for (String s: prettifyStringWriter.getBuffer().toString().split(System.lineSeparator())) {
bufferedWriter.write(s);
bufferedWriter.newLine();
}
bufferedWriter.close();
} catch (XMLStreamException | IOException | NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | InvalidKeySpecException | TransformerException e) {
e.printStackTrace();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,531 @@
package org.blueshard.cryptogx;
import javax.crypto.*;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.util.Arrays;
import java.util.Base64;
public class EnDecrypt {
public static class AES extends Thread {
private int iterations = 1000;
private int keyLength = 256;
private final String key;
private final byte[] salt;
public AES(String key, byte[] salt) {
this.key = key;
this.salt = salt;
}
public AES(String key, byte[] salt, int iterations) {
this.key = key;
this.salt = salt;
this.iterations = iterations;
}
public AES(String key, byte[] salt, int iterations, int keyLength) {
this.key = key;
this.salt = salt;
this.iterations = iterations;
this.keyLength = keyLength;
}
/**
* <p>Creates a secret key from given (plain text) key and salt</p>
*
* @param key from which a secret key should be created
* @param salt from which a secret key should be created
* @return the secret key
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
*/
public byte[] createSecretKey(String key, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException {
KeySpec keySpec = new PBEKeySpec(key.toCharArray(), salt, this.iterations, keyLength);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
return factory.generateSecret(keySpec).getEncoded();
}
/**
* <p>Writes {@param inputStream} to {@param outputStream}</p>
*
* @param inputStream from which is written
* @param outputStream to which is written
* @param buffer
* @throws IOException
*/
public static void writeLineByLine(InputStream inputStream, OutputStream outputStream, byte[] buffer) throws IOException {
int numOfBytesRead;
while ((numOfBytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, numOfBytesRead);
}
outputStream.close();
inputStream.close();
}
/**
* <p>Encrypts a file randomly line by line</p>
*
* @see EnDecrypt.AES#encryptRandomLineByLine(InputStream, OutputStream, byte[])
*/
public static void encryptFileRandomLineByLine(File inputFile, File outputFile, byte[] buffer) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException, InvalidAlgorithmParameterException {
encryptRandomLineByLine(new FileInputStream(inputFile), new FileOutputStream(outputFile), buffer);
}
/**
* <p>Encrypts a {@link InputStream} randomly line by line</p>
*
* @param inputStream that should be encrypted
* @param outputStream to which the encrypted {@param inputStream} should be written to
* @param buffer
* @throws NoSuchAlgorithmException
* @throws NoSuchPaddingException
* @throws InvalidKeyException
* @throws IOException
* @throws InvalidAlgorithmParameterException
*/
public static void encryptRandomLineByLine(InputStream inputStream, OutputStream outputStream, byte[] buffer) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException, InvalidAlgorithmParameterException {
KeyGenerator randomKey = KeyGenerator.getInstance("AES");
Key secretKey = new SecretKeySpec(randomKey.generateKey().getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
CipherInputStream cipherInputStream = new CipherInputStream(inputStream, cipher);
writeLineByLine(cipherInputStream, outputStream, buffer);
}
/**
* <p>En- / decrypts the {@param inputFile}</p>
*
* @param cipherMode says if the file should be en- or decrypted
* @param inputFile that should be en- / decrypted
* @param outputFile to which the en- / decrypted {@param inputFile} should be written to
* @throws InvalidKeySpecException
* @throws NoSuchAlgorithmException
* @throws NoSuchPaddingException
* @throws InvalidKeyException
* @throws IOException
* @throws BadPaddingException
* @throws IllegalBlockSizeException
*/
public void enDecryptFileAllInOne(int cipherMode, File inputFile, File outputFile) throws InvalidKeySpecException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException, BadPaddingException, IllegalBlockSizeException {
Key secretKey = new SecretKeySpec(createSecretKey(key, salt), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(cipherMode, secretKey);
FileInputStream inputStream = new FileInputStream(inputFile);
byte[] inputBytes = new byte[(int) inputFile.length()];
inputStream.read(inputBytes);
byte[] outputBytes = cipher.doFinal(inputBytes);
FileOutputStream outputStream = new FileOutputStream(outputFile);
outputStream.write(outputBytes);
inputStream.close();
outputStream.close();
}
/**
* <p>En- / decrypts the {@param inputBytes}</p>
*
* @param cipherMode says if the file should be en- or decrypted
* @param inputBytes that should be en- / decrypted
* @param outputStream to which the en- / decrypted {@param inputFile} should be written to
* @throws InvalidKeySpecException
* @throws NoSuchAlgorithmException
* @throws NoSuchPaddingException
* @throws InvalidKeyException
* @throws IOException
* @throws BadPaddingException
* @throws IllegalBlockSizeException
*/
public void enDecryptFileAllInOne(int cipherMode, byte[] inputBytes, OutputStream outputStream) throws InvalidKeySpecException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException, BadPaddingException, IllegalBlockSizeException {
Key secretKey = new SecretKeySpec(createSecretKey(key, salt), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(cipherMode, secretKey);
byte[] outputBytes = cipher.doFinal(inputBytes);
outputStream.write(outputBytes);
outputStream.close();
}
/**
* <p>En- / decrypts the {@param inputFile}</p>
*
* @param cipherMode says if the file should be en- or decrypted
* @param inputFile that should be en- / decrypted
* @param outputFile to which the en- / decrypted {@param inputFile} should be written to
* @param buffer
* @throws InvalidKeySpecException
* @throws NoSuchAlgorithmException
* @throws NoSuchPaddingException
* @throws InvalidKeyException
* @throws IOException
* @throws InvalidAlgorithmParameterException
*/
public void enDecryptLineByLine(int cipherMode, File inputFile, File outputFile, byte[] buffer) throws InvalidKeySpecException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException, InvalidAlgorithmParameterException {
Key secretKey = new SecretKeySpec(createSecretKey(key, salt), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(cipherMode, secretKey);
FileInputStream fileInputStream = new FileInputStream(inputFile);
FileOutputStream fileOutputStream = new FileOutputStream(outputFile);
if (cipherMode == Cipher.ENCRYPT_MODE) {
CipherInputStream cipherInputStream = new CipherInputStream(fileInputStream, cipher);
writeLineByLine(cipherInputStream, fileOutputStream, buffer);
} else if (cipherMode == Cipher.DECRYPT_MODE) {
CipherOutputStream cipherOutputStream = new CipherOutputStream(fileOutputStream, cipher);
writeLineByLine(fileInputStream, cipherOutputStream, buffer);
}
}
/**
* <p>En- / decrypts the {@param inputStream}</p>
*
* @param cipherMode says if the file should be en- or decrypted
* @param inputStream that should be en- / decrypted
* @param outputStream to which the en- / decrypted {@param inputFile} should be written to
* @param buffer
* @throws InvalidKeySpecException
* @throws NoSuchAlgorithmException
* @throws NoSuchPaddingException
* @throws InvalidKeyException
* @throws IOException
* @throws InvalidAlgorithmParameterException
*/
public void enDecryptLineByLine(int cipherMode, InputStream inputStream, OutputStream outputStream, byte[] buffer) throws InvalidKeySpecException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException, InvalidAlgorithmParameterException {
Key secretKey = new SecretKeySpec(createSecretKey(key, salt), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(cipherMode, secretKey);
if (cipherMode == Cipher.ENCRYPT_MODE) {
CipherInputStream cipherInputStream = new CipherInputStream(inputStream, cipher);
writeLineByLine(cipherInputStream, outputStream, buffer);
} else if (cipherMode == Cipher.DECRYPT_MODE) {
CipherOutputStream cipherOutputStream = new CipherOutputStream(outputStream, cipher);
writeLineByLine(inputStream, cipherOutputStream, buffer);
}
}
/**
* <p>Encrypt {@param bytes} randomly</p>
*
* @see EnDecrypt.AES#encryptRandom(byte[])
*/
public static String encryptRandom(String string) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
return encryptRandom(string.getBytes(StandardCharsets.UTF_8));
}
/**
* <p>Encrypt {@param bytes} randomly</p>
*
* @param bytes that should be encrypted
* @return the encrypted {@param bytes} as {@link String}
* @throws NoSuchPaddingException
* @throws NoSuchAlgorithmException
* @throws InvalidKeyException
* @throws BadPaddingException
* @throws IllegalBlockSizeException
*/
public static String encryptRandom(byte[] bytes) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
KeyGenerator randomKey = KeyGenerator.getInstance("AES");
Key secretKey = new SecretKeySpec(randomKey.generateKey().getEncoded(), "AES");
Cipher encryptRandomCipher = Cipher.getInstance("AES");
encryptRandomCipher.init(Cipher.ENCRYPT_MODE, secretKey);
return Base64.getEncoder().encodeToString(encryptRandomCipher.doFinal(bytes));
}
/**
* <p>Encrypts a file randomly at once</p>
*
* @see EnDecrypt.AES#encryptFileRandomAllInOne(File, File)
*/
public static void encryptFileRandomAllInOne(String inputFilename, String outputFilename) throws NoSuchPaddingException, NoSuchAlgorithmException, IOException, BadPaddingException, IllegalBlockSizeException, InvalidKeyException {
encryptFileRandomAllInOne(new File(inputFilename), new File(outputFilename));
}
/**
* <p>Encrypts a file randomly at once</p>
*
* @param inputFile that should be encrypted
* @param outputFile to which the encrypted file should be written to
* @throws NoSuchAlgorithmException
* @throws NoSuchPaddingException
* @throws InvalidKeyException
* @throws IOException
* @throws BadPaddingException
* @throws IllegalBlockSizeException
*/
public static void encryptFileRandomAllInOne(File inputFile, File outputFile) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException, BadPaddingException, IllegalBlockSizeException {
KeyGenerator randomKey = KeyGenerator.getInstance("AES");
Key secretKey = new SecretKeySpec(randomKey.generateKey().getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
FileInputStream inputStream = new FileInputStream(inputFile);
byte[] inputBytes = new byte[(int) inputFile.length()];
inputStream.read(inputBytes);
byte[] outputBytes = cipher.doFinal(inputBytes);
FileOutputStream outputStream = new FileOutputStream(outputFile);
outputStream.write(outputBytes);
inputStream.close();
outputStream.close();
}
/**
* <p>Encrypts {@param inputFilename} randomly line by line and write it to {@param outputFilename}</p>
*
* @see EnDecrypt.AES#encryptRandomLineByLine(InputStream, OutputStream, byte[])
*/
public static void encryptFileRandomLineByLine(String inputFilename, String outputFilename) throws InvalidKeyException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, NoSuchPaddingException, IOException {
encryptRandomLineByLine(new FileInputStream(inputFilename), new FileOutputStream(outputFilename), new byte[64]);
}
/**
* <p>Encrypts {@param inputFilename} randomly line by line and write it to {@param outputFilename}</p>
*
* @see EnDecrypt.AES#encryptRandomLineByLine(InputStream, OutputStream, byte[])
*/
public static void encryptFileRandomLineByLine(String inputFilename, String outputFilename, byte[] buffer) throws InvalidKeyException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, NoSuchPaddingException, IOException {
encryptRandomLineByLine(new FileInputStream(inputFilename), new FileOutputStream(outputFilename), buffer);
}
/**
* <p>Decrypt encrypted {@param encryptedString}</p>
*
* @see EnDecrypt.AES#decrypt(byte[])
*/
public String decrypt(String encryptedString) throws BadPaddingException, IllegalBlockSizeException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException {
Key secretKey = new SecretKeySpec(createSecretKey(key, salt), "AES");
Cipher decryptCipher = Cipher.getInstance("AES");
decryptCipher.init(Cipher.DECRYPT_MODE, secretKey);
return new String(decryptCipher.doFinal(Base64.getDecoder().decode(encryptedString)), StandardCharsets.UTF_8);
}
/**
* <p>Decrypt encrypted {@param bytes}</p>
*
* @param bytes that should be decrypted
* @return decrypted bytes
* @throws BadPaddingException
* @throws IllegalBlockSizeException
* @throws NoSuchPaddingException
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
* @throws InvalidKeyException
*/
public byte[] decrypt(byte[] bytes) throws BadPaddingException, IllegalBlockSizeException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException {
return decrypt(Arrays.toString(bytes)).getBytes(StandardCharsets.UTF_8);
}
/**
* <p>Encrypt {@param bytes}</p>
*
* @see EnDecrypt.AES#encrypt(byte[])
*/
public String encrypt(String string) throws BadPaddingException, IllegalBlockSizeException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException {
return Base64.getEncoder().encodeToString(encrypt(string.getBytes(StandardCharsets.UTF_8)));
}
/**
* <p>Encrypt {@param bytes}</p>
*
* @param bytes that should be encrypted
* @return encrypted bytes
* @throws BadPaddingException
* @throws IllegalBlockSizeException
* @throws NoSuchPaddingException
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
* @throws InvalidKeyException
*/
public byte[] encrypt(byte[] bytes) throws BadPaddingException, IllegalBlockSizeException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException {
Key secretKey = new SecretKeySpec(createSecretKey(key, salt), "AES");
Cipher encryptCipher = Cipher.getInstance("AES");
encryptCipher.init(Cipher.ENCRYPT_MODE, secretKey);
return encryptCipher.doFinal(bytes);
}
/**
* <p>Decrypt encrypted {@param inputFilename} to {@param outputFilename} at once</p>
*
* @param inputFilename that should be decrypted
* @param outputFilename to which the decrypted content should be written to
* @throws NoSuchPaddingException
* @throws NoSuchAlgorithmException
* @throws IOException
* @throws BadPaddingException
* @throws IllegalBlockSizeException
* @throws InvalidKeyException
* @throws InvalidKeySpecException
*/
public void decryptFileAllInOne(String inputFilename, String outputFilename) throws NoSuchPaddingException, NoSuchAlgorithmException, IOException, BadPaddingException, IllegalBlockSizeException, InvalidKeyException, InvalidKeySpecException {
enDecryptFileAllInOne(Cipher.DECRYPT_MODE, new File(inputFilename), new File(outputFilename));
}
/**
* <p>Decrypt encrypted {@param inputBytes} to {@param outputStream} at once</p>
*
* @param inputBytes that should be decrypted
* @param outputStream to which the decrypted content should be written to
* @throws NoSuchPaddingException
* @throws NoSuchAlgorithmException
* @throws IOException
* @throws BadPaddingException
* @throws IllegalBlockSizeException
* @throws InvalidKeyException
* @throws InvalidKeySpecException
*/
public void decryptFileAllInOne(byte[] inputBytes, OutputStream outputStream) throws NoSuchPaddingException, NoSuchAlgorithmException, IOException, BadPaddingException, IllegalBlockSizeException, InvalidKeyException, InvalidKeySpecException {
enDecryptFileAllInOne(Cipher.DECRYPT_MODE, inputBytes, outputStream);
}
/**
* <p>Decrypt encrypted {@param inputFilename} to {@param outputFilename} line by line</p>
*
* @see EnDecrypt.AES#decryptFileLineByLine(InputStream, OutputStream, byte[])
*/
public void decryptFileLineByLine(String inputFilename, String outputFilename) throws NoSuchPaddingException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IOException, InvalidKeyException, InvalidKeySpecException {
enDecryptLineByLine(Cipher.DECRYPT_MODE, new File(inputFilename), new File(outputFilename), new byte[64]);
}
/**
* <p>Decrypt encrypted {@param inputStream} to {@param outputStream} line by line</p>
*
* @see EnDecrypt.AES#decryptFileLineByLine(InputStream, OutputStream, byte[])
*/
public void decryptFileLineByLine(InputStream inputStream, OutputStream outputStream) throws NoSuchPaddingException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IOException, InvalidKeyException, InvalidKeySpecException {
enDecryptLineByLine(Cipher.DECRYPT_MODE, inputStream, outputStream, new byte[64]);
}
/**
* <p>Decrypt encrypted {@param inputFilename} to {@param outputFilename} line by line</p>
*
* @see EnDecrypt.AES#decryptFileLineByLine(InputStream, OutputStream, byte[])
*/
public void decryptFileLineByLine(String inputFilename, String outputFilename, byte[] buffer) throws NoSuchPaddingException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IOException, InvalidKeyException, InvalidKeySpecException {
enDecryptLineByLine(Cipher.DECRYPT_MODE, new File(inputFilename), new File(outputFilename), buffer);
}
/**
* <p>Decrypt encrypted {@param inputStream} to {@param outputStream} line by line</p>
*
* @param inputStream that should be decrypted
* @param outputStream to which the decrypted content should be written to
* @param buffer
* @throws NoSuchPaddingException
* @throws InvalidAlgorithmParameterException
* @throws NoSuchAlgorithmException
* @throws IOException
* @throws InvalidKeyException
* @throws InvalidKeySpecException
*/
public void decryptFileLineByLine(InputStream inputStream, OutputStream outputStream, byte[] buffer) throws NoSuchPaddingException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IOException, InvalidKeyException, InvalidKeySpecException {
enDecryptLineByLine(Cipher.DECRYPT_MODE, inputStream, outputStream, buffer);
}
/**
* <p>DEncrypt {@param inputFilename} to {@param outputFilename} at once</p>
*
* @param inputFilename that should be encrypt
* @param outputFilename to which the encrypted content should be written to
* @throws NoSuchPaddingException
* @throws NoSuchAlgorithmException
* @throws IOException
* @throws BadPaddingException
* @throws IllegalBlockSizeException
* @throws InvalidKeyException
* @throws InvalidKeySpecException
*/
public void encryptFileAllInOne(String inputFilename, String outputFilename) throws NoSuchPaddingException, NoSuchAlgorithmException, IOException, BadPaddingException, IllegalBlockSizeException, InvalidKeyException, InvalidKeySpecException {
enDecryptFileAllInOne(Cipher.ENCRYPT_MODE, new File(inputFilename), new File(outputFilename));
}
/**
* <p>Encrypt {@param inputBytes} to {@param outputStream} at once</p>
*
* @param inputBytes that should be encrypted
* @param outputStream to which the encrypted content should be written to
* @throws NoSuchPaddingException
* @throws NoSuchAlgorithmException
* @throws IOException
* @throws BadPaddingException
* @throws IllegalBlockSizeException
* @throws InvalidKeyException
* @throws InvalidKeySpecException
*/
public void encryptFileAllInOne(byte[] inputBytes, OutputStream outputStream) throws NoSuchPaddingException, NoSuchAlgorithmException, IOException, BadPaddingException, IllegalBlockSizeException, InvalidKeyException, InvalidKeySpecException {
enDecryptFileAllInOne(Cipher.ENCRYPT_MODE, inputBytes, outputStream);
}
/**
* <p>Encrypt {@param inputFilename} to {@param outputFilename} line by line</p>
*
* @see EnDecrypt.AES#encryptFileLineByLine(InputStream, OutputStream, byte[])
*/
public void encryptFileLineByLine(String inputFilename, String outputFilename) throws NoSuchPaddingException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IOException, InvalidKeyException, InvalidKeySpecException {
enDecryptLineByLine(Cipher.ENCRYPT_MODE, new File(inputFilename), new File(outputFilename), new byte[64]);
}
/**
* <p>Encrypt {@param inputStream} to {@param outputStream} line by line</p>
*
* @see EnDecrypt.AES#encryptFileLineByLine(InputStream, OutputStream, byte[])
*/
public void encryptFileLineByLine(InputStream inputStream, OutputStream outputStream) throws NoSuchPaddingException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IOException, InvalidKeyException, InvalidKeySpecException {
enDecryptLineByLine(Cipher.ENCRYPT_MODE, inputStream, outputStream, new byte[64]);
}
/**
* <p>Encrypt {@param inputFilename} to {@param outputFilename} line by line</p>
*
* @see EnDecrypt.AES#encryptFileLineByLine(InputStream, OutputStream, byte[])
*/
public void encryptFileLineByLine(String inputFilename, String outputFilename, byte[] buffer) throws NoSuchPaddingException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IOException, InvalidKeyException, InvalidKeySpecException {
enDecryptLineByLine(Cipher.ENCRYPT_MODE, new File(inputFilename), new File(outputFilename), buffer);
}
/**
* <p>Encrypt {@param inputStream} to {@param outputStream} line by line</p>
*
* @param inputStream that should be encrypted
* @param outputStream to which the encrypted {@param inputStream} should be written to
* @param buffer
* @throws NoSuchPaddingException
* @throws InvalidAlgorithmParameterException
* @throws NoSuchAlgorithmException
* @throws IOException
* @throws InvalidKeyException
* @throws InvalidKeySpecException
*/
public void encryptFileLineByLine(InputStream inputStream, OutputStream outputStream, byte[] buffer) throws NoSuchPaddingException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IOException, InvalidKeyException, InvalidKeySpecException {
enDecryptLineByLine(Cipher.ENCRYPT_MODE, inputStream, outputStream, buffer);
}
}
}

View File

@ -0,0 +1,269 @@
/**
*
* @author blueShard
* @version 1.11.0
*/
package org.blueshard.cryptogx;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.swing.*;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
public class Main extends Application {
protected static final int NON_PORTABLE = 414729643;
protected static final int PORTABLE = 245714766;
protected static final int TYPE = PORTABLE;
protected final static String configDefaultName = "";
protected final static String configDefaultEncryptHash = "";
protected final static String configDefaultTextKey = "";
protected final static String configDefaultTextSalt = "";
protected final static String configDefaultTextAlgorithm = "AES";
protected final static String configDefaultFileEnDecryptKey = "";
protected final static String configDefaultFileEnDecryptSalt = "";
protected final static String configDefaultFileEnDecryptAlgorithm = "AES";
protected final static int configDefaultFileDeleteIterations = 5;
protected final static String configDefaultFileOutputPath = "";
protected final static boolean configDefaultRemoveFileFromFileBox = false;
protected final static boolean configDefaultLimitNumberOfThreads = true;
protected static ArrayList<String> textAlgorithms = new ArrayList<>();
protected static ArrayList<String> fileEnDecryptAlgorithms = new ArrayList<>();
private static Stage mainStage;
private double rootWindowX, rootWindowY;
protected static File config;
protected static boolean isConfig;
/**
* <p>Start the GUI</p>
*
* @param primaryStage of the GUI
* @throws IOException if issues with loading 'mainGUI.fxml'
*/
@Override
public void start(Stage primaryStage) throws IOException {
Thread.setDefaultUncaughtExceptionHandler(Main::exceptionAlert);
mainStage = primaryStage;
Parent root = FXMLLoader.load(getClass().getResource("resources/mainGUI.fxml"));
primaryStage.initStyle(StageStyle.UNDECORATED);
primaryStage.setResizable(false);
primaryStage.setTitle("cryptoGX");
primaryStage.getIcons().add(new Image(getClass().getResource("resources/cryptoGX.png").toExternalForm()));
Scene scene = new Scene(root, 900, 470);
scene.setOnMouseDragged(event -> {
primaryStage.setX(event.getScreenX() + rootWindowX);
primaryStage.setY(event.getScreenY() + rootWindowY);
});
scene.setOnMousePressed(event -> {
rootWindowX = scene.getX() - event.getSceneX();
rootWindowY = scene.getY() - event.getSceneY();
});
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* <p>Enter method for the application.
* Can also be used to en- / decrypt text and files or secure delete files without starting GUI</p>
*
* @param args from the command line
* @return status
* @throws BadPaddingException
* @throws NoSuchAlgorithmException if wrong algorithm is given (command line)
* @throws IllegalBlockSizeException if wrong size for key is given (command line)
* @throws NoSuchPaddingException
* @throws InvalidKeyException if invalid key is given (command line)
* @throws InvalidKeySpecException
* @throws IOException if files cannot be en- / decrypted or deleted correctly (command line)
* @throws InvalidAlgorithmParameterException if wrong algorithm parameters are given (command line)
*/
public static void main(String[] args) throws BadPaddingException, NoSuchAlgorithmException, IllegalBlockSizeException, NoSuchPaddingException, InvalidKeyException, InvalidKeySpecException, IOException, InvalidAlgorithmParameterException {
if (Main.TYPE == Main.NON_PORTABLE) {
if (System.getProperty("os.name").toLowerCase().startsWith("windows")) {
config = new File("C:\\Users\\" + System.getProperty("user.name") + "\\AppData\\Roaming\\cryptoGX\\cryptoGX.config");
} else {
config = new File("cryptoGX.config");
}
} else {
config = new File("cryptoGX.config");
}
isConfig = config.isFile();
if (args.length == 0) {
String version = Runtime.class.getPackage().getImplementationVersion();
if (version.startsWith("1.")) {
if (Integer.parseInt(version.substring(2, 3)) < 8) {
System.out.println("1");
JOptionPane.showMessageDialog(null, "Please use java 1.8.0_240 to java 10.*", "ERROR", JOptionPane.ERROR_MESSAGE);
} else if (Integer.parseInt(version.substring(6, 9)) < 240) {
JOptionPane.showMessageDialog(null, "Please use java 1.8.0_240 to java 10.*", "ERROR", JOptionPane.ERROR_MESSAGE);
}
} else if (Integer.parseInt(version.substring(0, 2)) > 10) {
JOptionPane.showMessageDialog(null, "Please use java 1.8.0_240 to java 10.*", "ERROR", JOptionPane.ERROR_MESSAGE);
} else {
JOptionPane.showMessageDialog(null, "Please use java 1.8.0_240 to java 10.*", "ERROR", JOptionPane.ERROR_MESSAGE);
}
launch(args);
} else {
args[0] = args[0].replace("-", "");
if (args[0].toLowerCase().equals("help") || args[0].toUpperCase().equals("H")) {
System.out.println("Usage AES: \n\n" +
" Text en- / decryption\n" +
" encrypt: <cryptoGX jar file> AES <key> <salt> encrypt <string>\n" +
" decrypt: <cryptoGX jar file> AES <key> <salt> decrypt <encrypted string>\n\n" +
" File en- / decryption\n" +
" encrypt: <cryptoGX jar file> AES <key> <salt> encrypt <path of file to encrypt> <encrypted file dest>\n" +
" decrypt: <cryptoGX jar file> AES <key> <salt> decrypt <encrypted file path> <decrypted file dest>\n\n" +
"File secure delete: <iterations> <path of file to delete>");
} else if (args[0].toLowerCase().equals("delete")) {
if (args.length > 3) {
System.err.println("To many arguments were given, expected 3");
} else if (args.length < 3) {
System.err.println("To few arguments were given, expected 3");
}
try {
SecureDelete.deleteFileLineByLine(args[2], Integer.parseInt(args[1]));
} catch (NumberFormatException e) {
System.err.println(args[1] + " must be a number\n Error: " + e.getMessage());
}
} else if (args[0].toLowerCase().equals("aes")) {
if (args.length < 4) {
System.err.println("To few arguments were given");
System.exit(1);
}
EnDecrypt.AES aes;
if (args[2].isEmpty()) {
aes = new EnDecrypt.AES(args[1], new byte[16]);
} else {
aes = new EnDecrypt.AES(args[1], args[2].getBytes(StandardCharsets.UTF_8));
}
String type = args[3].toLowerCase();
if (type.equals("encrypt")) {
System.out.println(aes.encrypt(args[4]));
} else if (type.equals("decrypt")) {
System.out.println(aes.decrypt(args[4]));
} else if (type.equals("fileencrypt") || type.equals("encryptfile")) {
aes.encryptFileLineByLine(args[4], args[5]);
} else if (type.equals("filedecrypt") ||type.equals("decryptfile")) {
aes.decryptFileLineByLine(args[4], args[5]);
}
}
}
System.exit(0);
}
/**
* <p>"Catch" all uncatched exceptions and opens an alert window</p>
*
* @param thread which called this method
* @param throwable of the thread which called the method
*/
private static void exceptionAlert(Thread thread, Throwable throwable) {
throwable.printStackTrace();
AtomicReference<Double> exceptionAlertX = new AtomicReference<>(Screen.getPrimary().getBounds().getMaxX() / 2);
AtomicReference<Double> exceptionAlertY = new AtomicReference<>(Screen.getPrimary().getBounds().getMaxY() / 2);
Alert enDecryptError = new Alert(Alert.AlertType.ERROR, "Error: " + throwable, ButtonType.OK);
enDecryptError.initStyle(StageStyle.UNDECORATED);
enDecryptError.setTitle("Error");
((Stage) enDecryptError.getDialogPane().getScene().getWindow()).getIcons().add(new Image(Main.class.getResource("resources/cryptoGX.png").toExternalForm()));
Scene window = enDecryptError.getDialogPane().getScene();
window.setOnMouseDragged(dragEvent -> {
enDecryptError.setX(dragEvent.getScreenX() + exceptionAlertX.get());
enDecryptError.setY(dragEvent.getScreenY() + exceptionAlertY.get());
});
window.setOnMousePressed(pressEvent -> {
exceptionAlertX.set(window.getX() - pressEvent.getSceneX());
exceptionAlertY.set(window.getY() - pressEvent.getSceneY());
});
enDecryptError.show();
}
/**
* <p>Shows an error alert window</p>
*
* @param message which will the alert show
* @param error which will show after the message
*/
protected static void errorAlert(String message, String error) {
AtomicReference<Double> alertX = new AtomicReference<>(Screen.getPrimary().getBounds().getMaxX() / 2);
AtomicReference<Double> alertY = new AtomicReference<>(Screen.getPrimary().getBounds().getMaxY() / 2);
Alert enDecryptError = new Alert(Alert.AlertType.ERROR, message +
"\nError: " + error, ButtonType.OK);
enDecryptError.initStyle(StageStyle.UNDECORATED);
enDecryptError.setTitle("Error");
((Stage) enDecryptError.getDialogPane().getScene().getWindow()).getIcons().add(new Image(Main.class.getResource("resources/cryptoGX.png").toExternalForm()));
Scene window = enDecryptError.getDialogPane().getScene();
window.setOnMouseDragged(dragEvent -> {
enDecryptError.setX(dragEvent.getScreenX() + alertX.get());
enDecryptError.setY(dragEvent.getScreenY() + alertY.get());
});
window.setOnMousePressed(pressEvent -> {
alertX.set(window.getX() - pressEvent.getSceneX());
alertY.set(window.getY() - pressEvent.getSceneY());
});
enDecryptError.show();
}
/**
* <p>Shows an warning alert window</p>
*
* @param message that the alert window will show
*/
protected static void warningAlert(String message) {
AtomicReference<Double> alertX = new AtomicReference<>(Screen.getPrimary().getBounds().getMaxX() / 2);
AtomicReference<Double> alertY = new AtomicReference<>(Screen.getPrimary().getBounds().getMaxY() / 2);
Alert enDecryptError = new Alert(Alert.AlertType.WARNING, message, ButtonType.OK);
enDecryptError.initStyle(StageStyle.UNDECORATED);
enDecryptError.setTitle("Error");
((Stage) enDecryptError.getDialogPane().getScene().getWindow()).getIcons().add(new Image(Main.class.getResource("resources/cryptoGX.png").toExternalForm()));
Scene window = enDecryptError.getDialogPane().getScene();
window.setOnMouseDragged(dragEvent -> {
enDecryptError.setX(dragEvent.getScreenX() + alertX.get());
enDecryptError.setY(dragEvent.getScreenY() + alertY.get());
});
window.setOnMousePressed(pressEvent -> {
alertX.set(window.getX() - pressEvent.getSceneX());
alertY.set(window.getY() - pressEvent.getSceneY());
});
enDecryptError.show();
}
}

View File

@ -0,0 +1,196 @@
package org.blueshard.cryptogx;
import java.io.*;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Random;
public class SecureDelete {
/**
* <p>Overwrites the file {@param iterations} times at once with random bytes an delete it</p>
*
* @see SecureDelete#deleteFileAllInOne(File, int)
*/
public static boolean deleteFileAllInOne(String filename, int iterations) throws IOException, NoSuchAlgorithmException {
return deleteFileAllInOne(new File(filename), iterations);
}
/**
* <p>Overwrites the file {@param iterations} times at once with random bytes and delete it</p>
*
* @param file that should be deleted
* @param iterations how many times the file should be overwritten before it gets deleted
* @return if the file could be deleted
* @throws IOException
* @throws NoSuchAlgorithmException
*/
public static boolean deleteFileAllInOne(File file, int iterations) throws IOException, NoSuchAlgorithmException {
long fileLength = file.length() + 1 ;
for (int i=0; i<iterations; i++) {
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file));
if (fileLength > 1000000000) {
int numOfByteArrays = (int) Math.ceil((double) fileLength / 1000000000);
for (int len=0; len<numOfByteArrays; len++) {
int newMaxFileSize = (int) fileLength / numOfByteArrays;
int newMinFileSize = 0;
byte[] randomBytes = new byte[new Random().nextInt(newMaxFileSize - newMinFileSize) + newMinFileSize];
SecureRandom.getInstanceStrong().nextBytes(randomBytes);
bufferedOutputStream.write(randomBytes);
}
} else {
byte[] randomBytes = new byte[new Random().nextInt((int) fileLength)];
SecureRandom.getInstanceStrong().nextBytes(randomBytes);
bufferedOutputStream.write(randomBytes);
}
bufferedOutputStream.flush();
bufferedOutputStream.close();
}
return file.delete();
}
/**
* <p>Overwrites the file {@param iterations} times at once with random bytes (minimal size {@param minFileSize}; maximal size {@param maxFileSize}) and delete it</p>
*
* @see SecureDelete#deleteFileAllInOne(String, int, long, long)
*/
public static boolean deleteFileAllInOne(String filename, int iterations, long minFileSize, long maxFileSize) throws IOException, NoSuchAlgorithmException {
return deleteFileAllInOne(new File(filename), iterations, minFileSize, maxFileSize);
}
/**
* <p>Overwrites the file {@param iterations} times at once with random bytes (minimal size {@param minFileSize}; maximal size {@param maxFileSize}) and delete it</p>
*
* @param file that should be deleted
* @param iterations how many times the file should be overwritten before it gets deleted
* @param minFileSize is the minimal file size for every {@param iterations}
* @param maxFileSize is the maximal file size for every {@param iterations}
* @return if the file could be deleted
* @throws IOException
* @throws NoSuchAlgorithmException
*/
public static boolean deleteFileAllInOne(File file, int iterations, long minFileSize, long maxFileSize) throws IOException, NoSuchAlgorithmException {
for (int i = 0; i < iterations; i++) {
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file));
if (maxFileSize > 1000000000) {
int numOfByteArrays = (int) Math.ceil((double) maxFileSize / 1000000000);
for (int len = 0; len < numOfByteArrays; len++) {
int newMaxFileSize = (int) maxFileSize / numOfByteArrays;
int newMinFileSize = 0;
if (minFileSize != 0) {
newMinFileSize = (int) minFileSize / numOfByteArrays;
}
byte[] randomBytes = new byte[new Random().nextInt(newMaxFileSize - newMinFileSize) + newMinFileSize];
SecureRandom.getInstanceStrong().nextBytes(randomBytes);
bufferedOutputStream.write(randomBytes);
}
} else {
byte[] randomBytes = new byte[new Random().nextInt((int) maxFileSize - (int) minFileSize) + (int) minFileSize];
SecureRandom.getInstanceStrong().nextBytes(randomBytes);
bufferedOutputStream.write(randomBytes);
}
bufferedOutputStream.flush();
bufferedOutputStream.close();
}
return file.delete();
}
/**
* <p>Overwrites the file {@param iterations} times line by line with random bytes and delete it</p>
*
* @see SecureDelete#deleteFileLineByLine(File, int)
*/
public static boolean deleteFileLineByLine(String filename, int iterations) throws NoSuchAlgorithmException, IOException {
return deleteFileLineByLine(new File(filename), iterations);
}
/**
* <p>Overwrites the file {@param iterations} times line by line with random bytes and delete it</p>
*
* @param file that should be deleted
* @param iterations how many times the file should be overwritten before it gets deleted
* @return if the file could be deleted
* @throws IOException
* @throws NoSuchAlgorithmException
*/
public static boolean deleteFileLineByLine(File file, int iterations) throws NoSuchAlgorithmException, IOException {
long fileLength = file.length() + 1 ;
for (int i=0; i<iterations; i++) {
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file));
if (fileLength > 1000000000) {
int numOfByteArrays = (int) Math.ceil((double) fileLength / 1000000000);
for (int len=0; len<numOfByteArrays; len++) {
int newMaxFileSize = (int) fileLength / numOfByteArrays;
int newMinFileSize = 0;
byte[] randomBytes = new byte[new Random().nextInt(newMaxFileSize - newMinFileSize) + newMinFileSize];
SecureRandom.getInstanceStrong().nextBytes(randomBytes);
for (byte b: randomBytes) {
bufferedOutputStream.write(b);
}
}
} else {
byte[] randomBytes = new byte[new Random().nextInt((int) fileLength)];
SecureRandom.getInstanceStrong().nextBytes(randomBytes);
for (byte b : randomBytes) {
bufferedOutputStream.write(b);
}
}
bufferedOutputStream.flush();
bufferedOutputStream.close();
}
return file.delete();
}
/**
* <p>Overwrites the file {@param iterations} times line by line with random bytes (minimal size {@param minFileSize}; maximal size {@param maxFileSize}) and delete it</p>
*/
public static boolean deleteFileLineByLine(String filename, int iterations, long minFileSize, long maxFileSize) throws NoSuchAlgorithmException, IOException {
return deleteFileLineByLine(new File(filename), iterations, minFileSize, maxFileSize);
}
/**
* <p>Overwrites the file {@param iterations} times line by line with random bytes (minimal size {@param minFileSize}; maximal size {@param maxFileSize}) and delete it</p>
*
* @param file that should be deleted
* @param iterations how many times the file should be overwritten before it gets deleted
* @param minFileSize is the minimal file size for every {@param iterations}
* @param maxFileSize is the maximal file size for every {@param iterations}
* @return if the file could be deleted
* @throws IOException
* @throws NoSuchAlgorithmException
*/
public static boolean deleteFileLineByLine(File file, int iterations, long minFileSize, long maxFileSize) throws NoSuchAlgorithmException, IOException {
for (int i=0; i<iterations; i++) {
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file));
if (maxFileSize > 1000000000) {
int numOfByteArrays = (int) Math.ceil((double) maxFileSize / 1000000000);
for (int len=0; len<numOfByteArrays; len++) {
int newMaxFileSize = (int) maxFileSize / numOfByteArrays;
int newMinFileSize = 0;
if (minFileSize != 0) {
newMinFileSize = (int) minFileSize / numOfByteArrays;
}
byte[] randomBytes = new byte[new Random().nextInt(newMaxFileSize - newMinFileSize) + newMinFileSize];
SecureRandom.getInstanceStrong().nextBytes(randomBytes);
for (byte b: randomBytes) {
bufferedOutputStream.write(b);
}
}
} else {
byte[] randomBytes = new byte[new Random().nextInt((int) maxFileSize - (int) minFileSize) + (int) minFileSize];
SecureRandom.getInstanceStrong().nextBytes(randomBytes);
for (byte b : randomBytes) {
bufferedOutputStream.write(b);
}
}
bufferedOutputStream.flush();
bufferedOutputStream.close();
}
return file.delete();
}
}

View File

@ -0,0 +1,21 @@
package org.blueshard.cryptogx;
public class Utils {
/**
* <p>Checks if any character in {@param characters} appears in {@param string}</p>
*
* @param characters that should be searched in {@param string}
* @param string that should be searched for the characters
* @return if any character in {@param characters} appears in {@param string}
*/
public static boolean hasAnyCharacter(CharSequence characters, String string) {
for (char c: characters.toString().toCharArray()) {
if (string.indexOf(c) != -1) {
return true;
}
}
return false;
}
}

View File

@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Accordion?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.PasswordField?>
<?import javafx.scene.control.Separator?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.TitledPane?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Text?>
<AnchorPane fx:id="rootWindow" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="605.0" prefWidth="320.0" style="-fx-border-color: black;" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children>
<MenuBar fx:id="menuBar" prefHeight="25.0" prefWidth="320.0" style="-fx-border-color: black;" />
<ImageView fx:id="closeButton" fitHeight="25.0" fitWidth="25.0" layoutX="295.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@close.png" />
</image>
</ImageView>
<Text fx:id="saveSettingsText" layoutX="125.0" layoutY="46.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Save settings" />
<Text fx:id="nameOfSettingText" layoutX="77.0" layoutY="86.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Name of the new configuration" />
<TextField fx:id="settingsNameEntry" layoutX="27.0" layoutY="101.0" prefHeight="25.0" prefWidth="264.0" />
<Accordion fx:id="rootAccordion" layoutX="10.0" layoutY="150.0" prefHeight="280.0" prefWidth="300.0">
<panes>
<TitledPane fx:id="textEnDecryptRoot" animated="false" text="Text en - / decrypt">
<content>
<AnchorPane fx:id="textEnDecryptPane" minHeight="0.0" minWidth="0.0" prefWidth="200.0">
<children>
<Text fx:id="textKeyText" layoutX="10.0" layoutY="40.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Key" />
<TextField fx:id="textKeyEntry" layoutX="85.0" layoutY="23.0" prefHeight="25.0" prefWidth="175.0" />
<Text fx:id="textSaltText" layoutX="10.0" layoutY="90.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Salt" />
<TextField fx:id="textSaltEntry" layoutX="85.0" layoutY="73.0" prefHeight="25.0" prefWidth="175.0" />
<Text fx:id="textAlgorithmText" layoutX="10.0" layoutY="140.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Algorithm" />
<ComboBox fx:id="textAlgorithmComboBox" layoutX="85.0" layoutY="123.0" prefHeight="25.0" prefWidth="175.0" />
</children>
</AnchorPane>
</content>
</TitledPane>
<TitledPane fx:id="fileEnDecryptRoot" animated="false" text="File en- / decrypt">
<content>
<AnchorPane fx:id="fileEnDecryptPane" minHeight="0.0" minWidth="0.0" prefWidth="200.0">
<children>
<Text fx:id="fileEnDecryptKeyText" layoutX="10.0" layoutY="40.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Key" />
<TextField fx:id="fileEnDecryptKeyEntry" layoutX="85.0" layoutY="23.0" prefHeight="25.0" prefWidth="175.0" />
<Text fx:id="fileEnDecryptSaltText" layoutX="10.0" layoutY="90.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Salt" />
<TextField fx:id="fileEnDecryptSaltEntry" layoutX="85.0" layoutY="73.0" prefHeight="25.0" prefWidth="175.0" />
<Text fx:id="fileEnDecryptAlgorithmText" layoutX="10.0" layoutY="140.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Algorithm" />
<ComboBox fx:id="fileEnDecryptAlgorithmComboBox" layoutX="85.0" layoutY="123.0" prefHeight="25.0" prefWidth="175.0" />
</children>
</AnchorPane>
</content>
</TitledPane>
<TitledPane fx:id="fileDeleteRoot" animated="false" text="Secure delete files">
<content>
<AnchorPane fx:id="fileDeletePane" minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<Text fx:id="fileDeleteIterationsText" layoutX="14.0" layoutY="94.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Iterations" />
<TextField fx:id="fileDeleteIterationsEntry" layoutX="85.0" layoutY="77.0" prefHeight="25.0" prefWidth="175.0" />
</children>
</AnchorPane>
</content>
</TitledPane>
<TitledPane fx:id="settingsRoot" animated="false" text="Settings">
<content>
<AnchorPane fx:id="settingsPane" minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<Text fx:id="fileOutputPathText" layoutX="10.0" layoutY="27.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Default file output path" />
<TextField fx:id="fileOutputPathEntry" layoutX="10.0" layoutY="41.0" prefHeight="25.0" prefWidth="280.0" />
<Button fx:id="fileOutputPathButton" layoutX="85.0" layoutY="78.0" mnemonicParsing="false" text="Change output path" />
<CheckBox fx:id="removeFromFileBoxCheckBox" layoutX="10.0" layoutY="121.0" mnemonicParsing="false" text="Remove files from filebox after en- / decryption" />
<CheckBox fx:id="limitNumberOfThreadsCheckBox" layoutX="10.0" layoutY="151.0" mnemonicParsing="false" text="Limit number of threads" />
</children>
</AnchorPane>
</content>
</TitledPane>
</panes>
</Accordion>
<CheckBox fx:id="encryptSettings" layoutX="10.0" layoutY="447.0" mnemonicParsing="false" text="Encrypt settings" />
<Separator fx:id="separator1" layoutX="10.0" layoutY="474.0" prefWidth="300.0" />
<PasswordField fx:id="hiddenPasswordEntry" disable="true" layoutX="10.0" layoutY="490.0" prefHeight="25.0" prefWidth="300.0" promptText="Password" />
<TextField fx:id="showedPasswordEntry" disable="true" layoutX="10.0" layoutY="490.0" prefHeight="25.0" prefWidth="300.0" promptText="Password" visible="false" />
<CheckBox fx:id="showPassword" disable="true" layoutX="10.0" layoutY="525.0" mnemonicParsing="false" text="Show password" />
<Separator fx:id="separator2" layoutX="10.0" layoutY="551.0" prefWidth="300.0" />
<Button fx:id="saveButton" layoutX="131.0" layoutY="564.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="56.0" text="Save" />
</children>
</AnchorPane>

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Text?>
<AnchorPane fx:id="mainWindow" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="253.0" prefWidth="254.0" style="-fx-border-color: black;" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children>
<MenuBar fx:id="menuBar" prefHeight="25.0" prefWidth="254.0" style="-fx-border-color: black;" />
<ImageView fx:id="closeButton" fitHeight="25.0" fitWidth="25.0" layoutX="228.0" layoutY="1.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@close.png" />
</image>
</ImageView>
<Text fx:id="exportSettingsText" layoutX="88.0" layoutY="48.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Export settings" />
<ScrollPane layoutX="7.0" layoutY="64.0" prefHeight="120.0" prefWidth="240.0">
<content>
<VBox fx:id="settingsBox" prefHeight="118.0" prefWidth="238.0" />
</content>
</ScrollPane>
<Button fx:id="exportButton" layoutX="98.0" layoutY="203.0" mnemonicParsing="false" text="Export..." />
</children>
</AnchorPane>

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<AnchorPane fx:id="rootWindow" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="235.0" prefWidth="242.0" style="-fx-border-color: black;" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children>
<MenuBar fx:id="menuBar" prefHeight="25.0" prefWidth="242.0" style="-fx-border-color: black;" />
<ImageView fx:id="closeButton" fitHeight="25.0" fitWidth="25.0" layoutX="217.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@close.png" />
</image>
</ImageView>
<Text fx:id="loadSettingsText" layoutX="86.0" layoutY="50.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Load settings" />
<ComboBox fx:id="settingsBox" layoutX="24.0" layoutY="72.0" prefHeight="25.0" prefWidth="194.0" />
<Text fx:id="passwordText" layoutX="14.0" layoutY="136.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Password" />
<PasswordField fx:id="passwordEntryHide" layoutX="79.0" layoutY="119.0" />
<TextField fx:id="passwordEntryShow" layoutX="79.0" layoutY="119.0" visible="false" />
<CheckBox fx:id="showPassword" layoutX="14.0" layoutY="154.0" mnemonicParsing="false" text="Show password" />
<Separator fx:id="separator1" layoutX="16.0" layoutY="181.0" prefHeight="0.0" prefWidth="211.0" />
<Button fx:id="loadButton" layoutX="29.0" layoutY="193.0" mnemonicParsing="false" text="Load" />
<Button fx:id="deleteButton" layoutX="162.0" layoutY="193.0" mnemonicParsing="false" text="Delete" />
</children>
</AnchorPane>

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

View File

@ -0,0 +1,103 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.control.RadioMenuItem?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.control.Separator?>
<?import javafx.scene.control.SeparatorMenuItem?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Text?>
<AnchorPane fx:id="rootWindow" prefHeight="470.0" prefWidth="900.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.blueshard.cryptogx.Controller">
<children>
<MenuBar fx:id="menubar" prefHeight="25.0" prefWidth="900.0">
<menus>
<Menu fx:id="fileMenu" mnemonicParsing="false" text="File">
<items>
<MenuItem fx:id="fileMenuClose" mnemonicParsing="false" onAction="#closeApplication" text="Exit" />
</items>
</Menu>
<Menu fx:id="settingsMenu" mnemonicParsing="false" text="Settings">
<items>
<MenuItem fx:id="setDefaultOutputPath" mnemonicParsing="false" text="Set default file en- / decryption output path..." />
<RadioMenuItem fx:id="removeFileFromFileBox" mnemonicParsing="false" text="Remove files from filebox after en- / decryption" />
<RadioMenuItem fx:id="limitNumberOfThreads" mnemonicParsing="false" selected="true" text="Limit number of threads" />
<SeparatorMenuItem fx:id="settingsSeparator1" mnemonicParsing="false" />
<MenuItem fx:id="saveSettings" mnemonicParsing="false" text="Save settings..." />
<MenuItem fx:id="loadSettings" disable="true" mnemonicParsing="false" text="Load settings..." />
<MenuItem fx:id="exportSettings" disable="true" mnemonicParsing="false" text="Export settings..." />
<MenuItem fx:id="importSettings" mnemonicParsing="false" text="Import settings..." />
</items></Menu>
<Menu fx:id="helpMenu" mnemonicParsing="false" text="Help" />
</menus>
</MenuBar>
<ImageView fx:id="minimizeWindow" fitHeight="25.0" fitWidth="25.0" layoutX="850.0" onMouseClicked="#minimizeApplication" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@minimize.png" />
</image></ImageView>
<ImageView fx:id="closeWindow" fitHeight="25.0" fitWidth="25.0" layoutX="875.0" onMouseClicked="#closeApplication" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@close.png" />
</image></ImageView>
<Text fx:id="textText" layoutX="103.0" layoutY="50.0" strokeType="OUTSIDE" strokeWidth="0.0" text="En- / decrypt Text" />
<TextField fx:id="textKeyEntry" layoutX="76.0" layoutY="64.0" onKeyTyped="#keyTypedTooltip" onMouseExited="#mouseExitEntryTooltip" onMouseMoved="#mouseOverEntryTooltip" promptText="Key" />
<TextArea fx:id="textDecryptedEntry" layoutX="7.0" layoutY="107.0" onKeyTyped="#keyTypedTooltip" prefHeight="105.0" prefWidth="286.0" promptText="Decrypted Text" />
<TextArea fx:id="textEncryptedEntry" layoutX="7.0" layoutY="222.0" onKeyTyped="#keyTypedTooltip" prefHeight="105.0" prefWidth="286.0" promptText="Encrypted Text" />
<Button fx:id="textEncryptButton" layoutX="47.0" layoutY="339.0" mnemonicParsing="false" onAction="#textEncryptButton" text="Encrypt" />
<ImageView fx:id="textLoadingImage" fitHeight="40.0" fitWidth="40.0" layoutX="131.0" layoutY="332.0" pickOnBounds="true" preserveRatio="true" />
<Button fx:id="textDecryptButton" layoutX="199.0" layoutY="340.0" mnemonicParsing="false" onAction="#textDecryptButton" text="Decrypt" />
<Separator fx:id="textSeparator1" layoutX="7.0" layoutY="379.0" prefHeight="8.0" prefWidth="109.0" />
<Text fx:id="textAdvanced" layoutX="124.0" layoutY="386.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Advanced" wrappingWidth="53.701171875" />
<Separator fx:id="textSeparator2" layoutX="187.0" layoutY="379.0" prefHeight="8.0" prefWidth="109.0" />
<Text fx:id="textAlgorithm" layoutX="194.0" layoutY="409.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Algorithm" />
<TextField fx:id="textSaltEntry" layoutX="14.0" layoutY="419.0" onKeyTyped="#keyTypedTooltip" onMouseExited="#mouseExitEntryTooltip" onMouseMoved="#mouseOverEntryTooltip" prefHeight="25.0" prefWidth="136.0" promptText="Salt" />
<ComboBox fx:id="textAlgorithmBox" layoutX="156.0" layoutY="419.0" prefHeight="25.0" prefWidth="136.0" />
<Separator fx:id="midSeparator1" layoutX="300.0" layoutY="35.0" orientation="VERTICAL" prefHeight="424.0" prefWidth="0.0" />
<Text fx:id="fileEnDecryptText" layoutX="403.0" layoutY="50.0" strokeType="OUTSIDE" strokeWidth="0.0" text="En- / decrypt Files" />
<TextField fx:id="fileEnDecryptKeyEntry" layoutX="376.0" layoutY="64.0" onKeyTyped="#keyTypedTooltip" onMouseExited="#mouseExitEntryTooltip" onMouseMoved="#mouseOverEntryTooltip" promptText="Key" />
<Button fx:id="fileEnDecryptFilesButton" layoutX="408.0" layoutY="97.0" mnemonicParsing="false" onAction="#fileEnDecryptChoose" text="Choose files..." />
<ScrollPane fx:id="fileEnDecryptInputScroll" hbarPolicy="NEVER" layoutX="309.0" layoutY="130.0" onKeyPressed="#onFileEnDecryptPaste" prefHeight="107.0" prefWidth="286.0">
<content>
<VBox fx:id="fileEnDecryptInputFiles" onDragDropped="#onFileEnDecryptDragNDrop" onDragOver="#onFileEnDecryptDragOver" prefHeight="105.0" prefWidth="282.0" />
</content>
</ScrollPane>
<Text fx:id="fileEncryptOutputFileText" layoutX="310.0" layoutY="261.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Encrypted File" />
<TextField fx:id="fileEncryptOutputFile" editable="false" layoutX="390.0" layoutY="244.0" onKeyTyped="#keyTypedTooltip" onMouseExited="#mouseExitEntryTooltip" onMouseMoved="#mouseOverEntryTooltip" prefHeight="25.0" prefWidth="201.0" />
<Text fx:id="fileDecryptOutputFileText" layoutX="310.0" layoutY="290.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Decrypted File" />
<TextField fx:id="fileDecryptOutputFile" editable="false" layoutX="390.0" layoutY="273.0" onKeyTyped="#keyTypedTooltip" onMouseExited="#mouseExitEntryTooltip" onMouseMoved="#mouseOverEntryTooltip" prefHeight="25.0" prefWidth="201.0" />
<Button fx:id="fileEncrypt" layoutX="347.0" layoutY="313.0" mnemonicParsing="false" onAction="#fileEncryptButton" text="Encrypt" />
<ImageView fx:id="fileEnDecryptLoadingImage" fitHeight="40.0" fitWidth="40.0" layoutX="432.0" layoutY="306.0" pickOnBounds="true" preserveRatio="true" />
<Button fx:id="fileDecrypt" layoutX="499.0" layoutY="313.0" mnemonicParsing="false" onAction="#fileDecryptButton" text="Decrypt" />
<Button fx:id="fileEnDecryptStop" layoutX="426.0" layoutY="346.0" mnemonicParsing="false" onAction="#fileEnDecryptCancelButton" text="Cancel" />
<Separator fx:id="fileEnDecryptSeparator1" layoutX="309.0" layoutY="379.0" prefHeight="8.0" prefWidth="109.0" />
<Text fx:id="fileEnDecryptAdvanced" layoutX="426.0" layoutY="386.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Advanced" wrappingWidth="53.701171875" />
<Separator fx:id="fileEnDecryptSeparator2" layoutX="485.0" layoutY="379.0" prefHeight="8.0" prefWidth="109.0" />
<Text fx:id="fileEnDecryptAlgorithm" layoutX="494.0" layoutY="409.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Algorithm" />
<TextField fx:id="fileEnDecryptSaltEntry" layoutX="311.0" layoutY="419.0" onKeyTyped="#keyTypedTooltip" onMouseExited="#mouseExitEntryTooltip" onMouseMoved="#mouseOverEntryTooltip" prefHeight="25.0" prefWidth="136.0" promptText="Salt" />
<ComboBox fx:id="fileEnDecryptAlgorithmBox" layoutX="455.0" layoutY="419.0" prefHeight="25.0" prefWidth="136.0" />
<Separator fx:id="midSeparator2" layoutX="600.0" layoutY="35.0" orientation="VERTICAL" prefHeight="424.0" prefWidth="0.0" />
<Text fx:id="fileDeleteText" layoutX="703.0" layoutY="50.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Secure delete files" />
<Button fx:id="fileEnDecryptFilesButton1" layoutX="708.0" layoutY="64.0" mnemonicParsing="false" onAction="#fileDeleteChoose" text="Choose files..." />
<ScrollPane fx:id="fileDeleteInputScroll" hbarPolicy="NEVER" layoutX="608.0" layoutY="96.0" prefHeight="228.0" prefWidth="285.0">
<content>
<VBox fx:id="fileDeleteInputFiles" onDragDropped="#onFileDeleteDragNDrop" onDragOver="#onFileDeleteDragOver" prefHeight="226.0" prefWidth="282.0" />
</content>
</ScrollPane>
<Button fx:id="fileDeleteButton" layoutX="647.0" layoutY="339.0" mnemonicParsing="false" onAction="#fileDelete" text="Delete" />
<ImageView fx:id="fileDeleteLoadingImage" fitHeight="40.0" fitWidth="40.0" layoutX="729.0" layoutY="332.0" pickOnBounds="true" preserveRatio="true" />
<Button fx:id="fileDeleteStop" layoutX="799.0" layoutY="339.0" mnemonicParsing="false" onAction="#fileDeleteCancelButton" text="Cancel" />
<Separator fx:id="fileDeleteSeparator1" layoutX="610.0" layoutY="379.0" prefHeight="8.0" prefWidth="109.0" />
<Text fx:id="fileDeleteAdvanced" layoutX="725.0" layoutY="386.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Advanced" wrappingWidth="53.015625" />
<Separator fx:id="fileDeleteSeparator2" layoutX="781.0" layoutY="379.0" prefHeight="8.0" prefWidth="109.0" />
<TextField fx:id="fileDeleteIterationsEntry" layoutX="684.0" layoutY="419.0" onKeyTyped="#keyTypedTooltip" onMouseExited="#mouseExitEntryTooltip" onMouseMoved="#mouseOverEntryTooltip" prefHeight="25.0" prefWidth="136.0" promptText="Iterations" text="5" />
</children>
</AnchorPane>

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB