Jan-Peter Klein 2 miesięcy temu
rodzic
commit
e1cc61037e

+ 3 - 5
src/main/java/org/cryptomator/common/RecoverUtil.java

@@ -57,9 +57,7 @@ public class RecoverUtil {
 
 	public static CryptorProvider.Scheme detectCipherCombo(byte[] masterkey, Path pathToVault) {
 		try (Stream<Path> paths = Files.walk(pathToVault.resolve(DATA_DIR_NAME))) {
-			Path c9rFile = paths.filter(path -> path.toString().endsWith(".c9r"))
-					.findFirst()
-					.orElseThrow(() -> new IllegalStateException("No .c9r file found. The vault might not exist or the provided masterkey does not match."));
+			Path c9rFile = paths.filter(path -> path.toString().endsWith(".c9r")).findFirst().orElseThrow(() -> new IllegalStateException("No .c9r file found. The vault might not exist or the provided masterkey does not match."));
 			CryptorProvider.Scheme scheme = determineScheme(c9rFile, masterkey);
 			if (scheme == null) {
 				throw new IllegalArgumentException("Invalid masterkey: Decryption failed.");
@@ -197,7 +195,7 @@ public class RecoverUtil {
 		}
 	}
 
-	public static Task<Void> createResetPasswordTask(ResourceBundle resourceBundle,Stage owner, RecoveryKeyFactory recoveryKeyFactory, Vault vault, StringProperty recoveryKey, NewPasswordController newPasswordController, Stage window, FxApplicationWindows appWindows, Dialogs dialogs) {
+	public static Task<Void> createResetPasswordTask(ResourceBundle resourceBundle, Stage owner, RecoveryKeyFactory recoveryKeyFactory, Vault vault, StringProperty recoveryKey, NewPasswordController newPasswordController, Stage window, FxApplicationWindows appWindows, Dialogs dialogs) {
 
 		Task<Void> task = new ResetPasswordTask(recoveryKeyFactory, vault, recoveryKey, newPasswordController);
 
@@ -277,7 +275,7 @@ public class RecoverUtil {
 		var wrapper = new VaultConfigCache(vaultSettings);
 		Vault vault = vaultComponentFactory.create(vaultSettings, wrapper, VAULT_CONFIG_MISSING, null).vault();
 
-		// Spezialbehandlung für Windows + Dropbox + WinFsp
+		//due to https://github.com/cryptomator/cryptomator/issues/2880#issuecomment-1680313498
 		var nameOfWinfspLocalMounter = "org.cryptomator.frontend.fuse.mount.WinFspMountProvider";
 		if (SystemUtils.IS_OS_WINDOWS && vaultSettings.path.get().toString().contains("Dropbox") && mountServices.stream().anyMatch(s -> s.getClass().getName().equals(nameOfWinfspLocalMounter))) {
 			vaultSettings.mountService.setValue(nameOfWinfspLocalMounter);

+ 23 - 28
src/main/java/org/cryptomator/common/vaults/VaultListManager.java

@@ -8,18 +8,6 @@
  *******************************************************************************/
 package org.cryptomator.common.vaults;
 
-import org.apache.commons.lang3.SystemUtils;
-import org.cryptomator.common.RecoverUtil;
-import org.cryptomator.common.settings.Settings;
-import org.cryptomator.common.settings.VaultSettings;
-import org.cryptomator.cryptofs.CryptoFileSystemProvider;
-import org.cryptomator.cryptofs.DirStructure;
-import org.cryptomator.cryptofs.migration.Migrators;
-import org.cryptomator.integrations.mount.MountService;
-import org.cryptomator.ui.keyloading.KeyLoadingStrategy;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import javax.inject.Inject;
 import javax.inject.Singleton;
 import javafx.collections.ObservableList;
@@ -38,7 +26,18 @@ import static org.cryptomator.common.Constants.VAULTCONFIG_FILENAME;
 import static org.cryptomator.common.vaults.VaultState.Value.ERROR;
 import static org.cryptomator.common.vaults.VaultState.Value.LOCKED;
 import static org.cryptomator.common.vaults.VaultState.Value.MASTERKEY_MISSING;
-import static org.cryptomator.common.vaults.VaultState.Value.VAULT_CONFIG_MISSING;
+
+import org.apache.commons.lang3.SystemUtils;
+import org.cryptomator.common.RecoverUtil;
+import org.cryptomator.common.settings.Settings;
+import org.cryptomator.common.settings.VaultSettings;
+import org.cryptomator.cryptofs.CryptoFileSystemProvider;
+import org.cryptomator.cryptofs.DirStructure;
+import org.cryptomator.cryptofs.migration.Migrators;
+import org.cryptomator.integrations.mount.MountService;
+import org.cryptomator.ui.keyloading.KeyLoadingStrategy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 @Singleton
 public class VaultListManager {
@@ -137,13 +136,13 @@ public class VaultListManager {
 			} catch (NoSuchFileException e) {
 				LOG.warn("Vault config file not found.");
 			}
-			var vaultState = determineVaultState(vaultSettings.path.get(),vaultSettings);
+			var vaultState = determineVaultState(vaultSettings.path.get(), vaultSettings);
 			if (vaultState == LOCKED) { //for legacy reasons: pre v8 vault do not have a config, but they are in the NEEDS_MIGRATION state
 				wrapper.reloadConfig();
 			}
 			return vaultComponentFactory.create(vaultSettings, wrapper, vaultState, null).vault();
 		} catch (IOException e) {
-			LOG.warn("Failed to determine vault state for " + vaultSettings.path.get(), e);
+			LOG.warn("Failed to determine vault state for {}", vaultSettings.path.get(), e);
 			return vaultComponentFactory.create(vaultSettings, wrapper, ERROR, e).vault();
 		}
 	}
@@ -154,10 +153,10 @@ public class VaultListManager {
 		return switch (previousState) {
 			case LOCKED, NEEDS_MIGRATION, MISSING, VAULT_CONFIG_MISSING, MASTERKEY_MISSING -> {
 				try {
-					var determinedState = determineVaultState(vault.getPath(),vault.getVaultSettings());
-					if(determinedState == MASTERKEY_MISSING){
+					var determinedState = determineVaultState(vault.getPath(), vault.getVaultSettings());
+					if (determinedState == MASTERKEY_MISSING) {
 						var vaultScheme = vault.getVaultConfigCache().getUnchecked().getKeyId().getScheme();
-						if(KeyLoadingStrategy.isHubVault(vaultScheme)){
+						if (KeyLoadingStrategy.isHubVault(vaultScheme)) {
 							determinedState = LOCKED;
 						}
 					}
@@ -167,7 +166,7 @@ public class VaultListManager {
 					state.set(determinedState);
 					yield determinedState;
 				} catch (IOException e) {
-					LOG.warn("Failed to determine vault state for " + vault.getPath(), e);
+					LOG.warn("Failed to determine vault state for {}", vault.getPath(), e);
 					state.set(ERROR);
 					vault.setLastKnownException(e);
 					yield ERROR;
@@ -179,7 +178,7 @@ public class VaultListManager {
 					state.set(determinedState);
 					yield determinedState;
 				} catch (IOException e) {
-					LOG.warn("Failed to redetermine vault state for " + vault.getPath(), e);
+					LOG.warn("Failed to redetermine vault state for {}", vault.getPath(), e);
 					vault.setLastKnownException(e);
 					yield ERROR;
 				}
@@ -196,12 +195,9 @@ public class VaultListManager {
 			return VaultState.Value.MISSING;
 		}
 
-		boolean vaultConfigRestored = Files.notExists(pathToVaultConfig) &&
-				RecoverUtil.restoreBackupIfAvailable(pathToVaultConfig, VaultState.Value.VAULT_CONFIG_MISSING);
+		boolean vaultConfigRestored = Files.notExists(pathToVaultConfig) && RecoverUtil.restoreBackupIfAvailable(pathToVaultConfig, VaultState.Value.VAULT_CONFIG_MISSING);
 
-		boolean masterkeyRestored = Files.notExists(pathToMasterkey) &&
-				KeyLoadingStrategy.isMasterkeyFileVault(vaultSettings.lastKnownKeyLoader.get()) &&
-				RecoverUtil.restoreBackupIfAvailable(pathToMasterkey, VaultState.Value.MASTERKEY_MISSING);
+		boolean masterkeyRestored = Files.notExists(pathToMasterkey) && KeyLoadingStrategy.isMasterkeyFileVault(vaultSettings.lastKnownKeyLoader.get()) && RecoverUtil.restoreBackupIfAvailable(pathToMasterkey, VaultState.Value.MASTERKEY_MISSING);
 
 		if (vaultConfigRestored || masterkeyRestored) {
 			return LOCKED;
@@ -211,15 +207,14 @@ public class VaultListManager {
 			return VaultState.Value.VAULT_CONFIG_MISSING;
 		}
 
-		if (Files.notExists(pathToMasterkey) &&
-				KeyLoadingStrategy.isMasterkeyFileVault(vaultSettings.lastKnownKeyLoader.get())) {
+		if (Files.notExists(pathToMasterkey) && KeyLoadingStrategy.isMasterkeyFileVault(vaultSettings.lastKnownKeyLoader.get())) {
 			return VaultState.Value.MASTERKEY_MISSING;
 		}
 
 		return checkDirStructure(pathToVault);
 	}
 
-	private static VaultState.Value checkDirStructure(Path pathToVault) throws IOException{
+	private static VaultState.Value checkDirStructure(Path pathToVault) throws IOException {
 		return switch (CryptoFileSystemProvider.checkDirStructureForVault(pathToVault, VAULTCONFIG_FILENAME, MASTERKEY_FILENAME)) {
 			case VAULT -> VaultState.Value.LOCKED;
 			case UNRELATED -> VaultState.Value.MISSING;

+ 6 - 0
src/main/java/org/cryptomator/common/vaults/VaultState.java

@@ -25,8 +25,14 @@ public class VaultState extends ObservableValueBase<VaultState.Value> implements
 		 */
 		MISSING,
 
+		/**
+		 * No vault config found at the provided path
+		 */
 		VAULT_CONFIG_MISSING,
 
+		/**
+		 * No masterkey found at the provided path
+		 */
 		MASTERKEY_MISSING,
 
 		/**

+ 1 - 2
src/main/java/org/cryptomator/ui/convertvault/ConvertVaultModule.java

@@ -21,7 +21,6 @@ import org.cryptomator.ui.recoverykey.RecoveryKeyValidateController;
 
 import javax.inject.Named;
 import javax.inject.Provider;
-import javafx.beans.property.ObjectProperty;
 import javafx.beans.property.SimpleObjectProperty;
 import javafx.beans.property.SimpleStringProperty;
 import javafx.beans.property.StringProperty;
@@ -123,7 +122,7 @@ abstract class ConvertVaultModule {
 	@IntoMap
 	@FxControllerKey(RecoveryKeyValidateController.class)
 	static FxController bindRecoveryKeyValidateController(@ConvertVaultWindow Vault vault, @ConvertVaultWindow VaultConfig.UnverifiedVaultConfig vaultConfig, @ConvertVaultWindow StringProperty recoveryKey, RecoveryKeyFactory recoveryKeyFactory) {
-		return new RecoveryKeyValidateController(vault, vaultConfig, recoveryKey, recoveryKeyFactory, new SimpleObjectProperty<>(RecoverUtil.Type.CONVERT_VAULT),null,null);
+		return new RecoveryKeyValidateController(vault, vaultConfig, recoveryKey, recoveryKeyFactory, new SimpleObjectProperty<>(RecoverUtil.Type.CONVERT_VAULT), null, null);
 	}
 
 }

+ 1 - 3
src/main/java/org/cryptomator/ui/mainwindow/VaultDetailController.java

@@ -52,9 +52,7 @@ public class VaultDetailController implements FxController {
 				case LOCKED -> FontAwesome5Icon.LOCK;
 				case PROCESSING -> FontAwesome5Icon.SPINNER;
 				case UNLOCKED -> FontAwesome5Icon.LOCK_OPEN;
-				case NEEDS_MIGRATION, MISSING, ERROR -> FontAwesome5Icon.EXCLAMATION_TRIANGLE;
-				case VAULT_CONFIG_MISSING -> FontAwesome5Icon.COGS;
-				case MASTERKEY_MISSING -> FontAwesome5Icon.KEY;
+				case NEEDS_MIGRATION, MISSING, VAULT_CONFIG_MISSING, MASTERKEY_MISSING, ERROR -> FontAwesome5Icon.EXCLAMATION_TRIANGLE;
 			};
 		} else {
 			return FontAwesome5Icon.EXCLAMATION_TRIANGLE;

+ 1 - 3
src/main/java/org/cryptomator/ui/mainwindow/VaultListCellController.java

@@ -55,9 +55,7 @@ public class VaultListCellController implements FxController {
 				case LOCKED -> FontAwesome5Icon.LOCK;
 				case PROCESSING -> FontAwesome5Icon.SPINNER;
 				case UNLOCKED -> FontAwesome5Icon.LOCK_OPEN;
-				case NEEDS_MIGRATION, MISSING, ERROR -> FontAwesome5Icon.EXCLAMATION_TRIANGLE;
-				case VAULT_CONFIG_MISSING -> FontAwesome5Icon.COGS;
-				case MASTERKEY_MISSING -> FontAwesome5Icon.KEY;
+				case NEEDS_MIGRATION, MISSING, VAULT_CONFIG_MISSING, MASTERKEY_MISSING, ERROR -> FontAwesome5Icon.EXCLAMATION_TRIANGLE;
 			};
 		} else {
 			return FontAwesome5Icon.EXCLAMATION_TRIANGLE;

+ 2 - 2
src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyComponent.java

@@ -53,8 +53,8 @@ public interface RecoveryKeyComponent {
 	@Subcomponent.Factory
 	interface Factory {
 
-		RecoveryKeyComponent create(@BindsInstance @RecoveryKeyWindow Vault vault,
-									@BindsInstance @Named("keyRecoveryOwner") Stage owner,
+		RecoveryKeyComponent create(@BindsInstance @RecoveryKeyWindow Vault vault, //
+									@BindsInstance @Named("keyRecoveryOwner") Stage owner, //
 									@BindsInstance @Named("recoverType") ObjectProperty<RecoverUtil.Type> recoverType);
 	}
 

+ 7 - 7
src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyExpertSettingsController.java

@@ -1,12 +1,5 @@
 package org.cryptomator.ui.recoverykey;
 
-import dagger.Lazy;
-import org.cryptomator.ui.addvaultwizard.CreateNewVaultExpertSettingsController;
-import org.cryptomator.ui.common.FxController;
-import org.cryptomator.ui.common.FxmlFile;
-import org.cryptomator.ui.common.FxmlScene;
-import org.cryptomator.ui.controls.NumericTextField;
-
 import javax.inject.Inject;
 import javax.inject.Named;
 import javafx.application.Application;
@@ -18,6 +11,13 @@ import javafx.scene.Scene;
 import javafx.scene.control.CheckBox;
 import javafx.stage.Stage;
 
+import dagger.Lazy;
+import org.cryptomator.ui.addvaultwizard.CreateNewVaultExpertSettingsController;
+import org.cryptomator.ui.common.FxController;
+import org.cryptomator.ui.common.FxmlFile;
+import org.cryptomator.ui.common.FxmlScene;
+import org.cryptomator.ui.controls.NumericTextField;
+
 @RecoveryKeyScoped
 public class RecoveryKeyExpertSettingsController implements FxController {
 

+ 9 - 16
src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyIsHubVaultController.java

@@ -1,43 +1,36 @@
 package org.cryptomator.ui.recoverykey;
 
-import dagger.Lazy;
-import org.cryptomator.common.RecoverUtil;
-import org.cryptomator.ui.common.FxController;
-import org.cryptomator.ui.common.FxmlFile;
-import org.cryptomator.ui.common.FxmlScene;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import javax.inject.Inject;
 import javax.inject.Named;
-import javafx.beans.property.IntegerProperty;
 import javafx.beans.property.ObjectProperty;
 import javafx.fxml.FXML;
 import javafx.scene.Scene;
 import javafx.stage.Stage;
 import java.util.ResourceBundle;
 
+import dagger.Lazy;
+import org.cryptomator.common.RecoverUtil;
+import org.cryptomator.ui.common.FxController;
+import org.cryptomator.ui.common.FxmlFile;
+import org.cryptomator.ui.common.FxmlScene;
+
 @RecoveryKeyScoped
 public class RecoveryKeyIsHubVaultController implements FxController {
 
-	private static final Logger LOG = LoggerFactory.getLogger(RecoveryKeyIsHubVaultController.class);
-
 	private final Stage window;
 	private final Lazy<Scene> recoverykeyRecoverScene;
 	private final ObjectProperty<RecoverUtil.Type> recoverType;
-	private final ResourceBundle resourceBundle;
 
 	@Inject
-	public RecoveryKeyIsHubVaultController(@RecoveryKeyWindow Stage window,
-										   @FxmlScene(FxmlFile.RECOVERYKEY_RECOVER) Lazy<Scene> recoverykeyRecoverScene,
-										   @Named("recoverType") ObjectProperty<RecoverUtil.Type> recoverType,
+	public RecoveryKeyIsHubVaultController(@RecoveryKeyWindow Stage window, //
+										   @FxmlScene(FxmlFile.RECOVERYKEY_RECOVER) Lazy<Scene> recoverykeyRecoverScene, //
+										   @Named("recoverType") ObjectProperty<RecoverUtil.Type> recoverType, //
 										   ResourceBundle resourceBundle) {
 		this.window = window;
 		window.setTitle(resourceBundle.getString("recoveryKey.recoverVaultConfig.title"));
 
 		this.recoverykeyRecoverScene = recoverykeyRecoverScene;
 		this.recoverType = recoverType;
-		this.resourceBundle = resourceBundle;
 	}
 
 	@FXML

+ 2 - 4
src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyRecoverController.java

@@ -12,7 +12,6 @@ import javafx.beans.property.ObjectProperty;
 import javafx.fxml.FXML;
 import javafx.scene.Scene;
 import javafx.stage.Stage;
-import java.util.Optional;
 import java.util.ResourceBundle;
 
 @RecoveryKeyScoped
@@ -28,8 +27,7 @@ public class RecoveryKeyRecoverController implements FxController {
 	public RecoveryKeyRecoverController(@RecoveryKeyWindow Stage window, //
 										@FxmlScene(FxmlFile.RECOVERYKEY_RESET_PASSWORD) Lazy<Scene> resetPasswordScene, //
 										@FxmlScene(FxmlFile.RECOVERYKEY_EXPERT_SETTINGS) Lazy<Scene> expertSettingsScene, //
-										ResourceBundle resourceBundle,
-										@Named("recoverType") ObjectProperty<RecoverUtil.Type> recoverType) {
+										ResourceBundle resourceBundle, @Named("recoverType") ObjectProperty<RecoverUtil.Type> recoverType) {
 		this.window = window;
 
 		this.nextScene = switch (recoverType.get()) {
@@ -45,7 +43,7 @@ public class RecoveryKeyRecoverController implements FxController {
 				window.setTitle(resourceBundle.getString("recoveryKey.recover.title"));
 				yield resetPasswordScene;
 			}
-			case SHOW_KEY-> {
+			case SHOW_KEY -> {
 				window.setTitle(resourceBundle.getString("recoveryKey.display.title"));
 				yield resetPasswordScene;
 			}

+ 28 - 42
src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyResetPasswordController.java

@@ -1,23 +1,5 @@
 package org.cryptomator.ui.recoverykey;
 
-import dagger.Lazy;
-import org.cryptomator.common.RecoverUtil;
-import org.cryptomator.common.vaults.Vault;
-import org.cryptomator.common.vaults.VaultListManager;
-import org.cryptomator.cryptolib.api.CryptoException;
-import org.cryptomator.cryptolib.api.CryptorProvider;
-import org.cryptomator.cryptolib.api.Masterkey;
-import org.cryptomator.cryptolib.common.MasterkeyFileAccess;
-import org.cryptomator.ui.changepassword.NewPasswordController;
-import org.cryptomator.ui.common.FxController;
-import org.cryptomator.ui.common.FxmlFile;
-import org.cryptomator.ui.common.FxmlScene;
-import org.cryptomator.ui.dialogs.Dialogs;
-import org.cryptomator.ui.dialogs.SimpleDialog;
-import org.cryptomator.ui.fxapp.FxApplicationWindows;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import javax.inject.Inject;
 import javax.inject.Named;
 import javafx.beans.property.IntegerProperty;
@@ -36,6 +18,23 @@ import java.util.concurrent.ExecutorService;
 
 import static org.cryptomator.common.Constants.MASTERKEY_FILENAME;
 
+import dagger.Lazy;
+import org.cryptomator.common.RecoverUtil;
+import org.cryptomator.common.vaults.Vault;
+import org.cryptomator.common.vaults.VaultListManager;
+import org.cryptomator.cryptolib.api.CryptoException;
+import org.cryptomator.cryptolib.api.CryptorProvider;
+import org.cryptomator.cryptolib.api.Masterkey;
+import org.cryptomator.cryptolib.common.MasterkeyFileAccess;
+import org.cryptomator.ui.changepassword.NewPasswordController;
+import org.cryptomator.ui.common.FxController;
+import org.cryptomator.ui.common.FxmlFile;
+import org.cryptomator.ui.common.FxmlScene;
+import org.cryptomator.ui.dialogs.Dialogs;
+import org.cryptomator.ui.fxapp.FxApplicationWindows;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 @RecoveryKeyScoped
 public class RecoveryKeyResetPasswordController implements FxController {
 
@@ -65,17 +64,14 @@ public class RecoveryKeyResetPasswordController implements FxController {
 											  @RecoveryKeyWindow Vault vault, //
 											  RecoveryKeyFactory recoveryKeyFactory, //
 											  ExecutorService executor, //
-											  @Named("keyRecoveryOwner") Stage owner,
-											  @RecoveryKeyWindow StringProperty recoveryKey, //
+											  @Named("keyRecoveryOwner") Stage owner, @RecoveryKeyWindow StringProperty recoveryKey, //
 											  @FxmlScene(FxmlFile.RECOVERYKEY_EXPERT_SETTINGS) Lazy<Scene> recoverExpertSettingsScene, //
 											  FxApplicationWindows appWindows, //
 											  MasterkeyFileAccess masterkeyFileAccess, //
 											  VaultListManager vaultListManager, //
 											  @Named("shorteningThreshold") IntegerProperty shorteningThreshold, //
-											  @Named("recoverType") ObjectProperty<RecoverUtil.Type> recoverType,
-											  @Named("cipherCombo") ObjectProperty<CryptorProvider.Scheme> cipherCombo,//
-											  ResourceBundle resourceBundle,
-											  Dialogs dialogs) {
+											  @Named("recoverType") ObjectProperty<RecoverUtil.Type> recoverType, @Named("cipherCombo") ObjectProperty<CryptorProvider.Scheme> cipherCombo,//
+											  ResourceBundle resourceBundle, Dialogs dialogs) {
 		this.window = window;
 		this.vault = vault;
 		this.recoveryKeyFactory = recoveryKeyFactory;
@@ -104,10 +100,9 @@ public class RecoveryKeyResetPasswordController implements FxController {
 
 	@FXML
 	public void close() {
-		if(recoverType.getValue().equals(RecoverUtil.Type.RESTORE_MASTERKEY)){
+		if (recoverType.getValue().equals(RecoverUtil.Type.RESTORE_MASTERKEY)) {
 			window.close();
-		}
-		else {
+		} else {
 			window.setScene(recoverExpertSettingsScene.get());
 		}
 	}
@@ -121,33 +116,24 @@ public class RecoveryKeyResetPasswordController implements FxController {
 				Path masterkeyFilePath = recoveryPath.resolve(MASTERKEY_FILENAME);
 
 				try (Masterkey masterkey = RecoverUtil.loadMasterkey(masterkeyFileAccess, masterkeyFilePath, newPasswordController.passwordField.getCharacters())) {
-					RecoverUtil.initializeCryptoFileSystem(recoveryPath,masterkey,shorteningThreshold,cipherCombo.get());
+					RecoverUtil.initializeCryptoFileSystem(recoveryPath, masterkey, shorteningThreshold, cipherCombo.get());
 				}
 
 				RecoverUtil.moveRecoveredFiles(recoveryPath, vault.getPath());
 				RecoverUtil.deleteRecoveryDirectory(recoveryPath);
 				RecoverUtil.addVaultToList(vaultListManager, vault.getPath());
 
-				dialogs.prepareRecoverPasswordSuccess(window, owner, resourceBundle)
-						.setTitleKey("recoveryKey.recoverVaultConfig.title")
-						.setMessageKey("recoveryKey.recover.resetVaultConfigSuccess.message")
-						.build().showAndWait();
-				window.close(); // Erst jetzt das Fenster schließen
+				dialogs.prepareRecoverPasswordSuccess(window, owner, resourceBundle).setTitleKey("recoveryKey.recoverVaultConfig.title").setMessageKey("recoveryKey.recover.resetVaultConfigSuccess.message").build().showAndWait();
+				window.close();
 
 			} catch (IOException | CryptoException e) {
 				LOG.error("Recovery process failed", e);
 			}
 		} else {
 			Task<Void> task = RecoverUtil.createResetPasswordTask( //
-					resourceBundle,
-					owner,
-					recoveryKeyFactory, //
-					vault, //
-					recoveryKey, //
-					newPasswordController, //
-					window, //
-					appWindows,
-					dialogs);
+					resourceBundle, owner, recoveryKeyFactory, //
+					vault, recoveryKey, newPasswordController, //
+					window, appWindows, dialogs);
 			executor.submit(task);
 		}
 	}

+ 21 - 12
src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyValidateController.java

@@ -134,24 +134,33 @@ public class RecoveryKeyValidateController implements FxController {
 	}
 
 	private void validateRecoveryKey() {
-		AtomicBoolean illegalArgumentExceptionOccurred = new AtomicBoolean(false);
-		boolean valid = switch (recoverType.get()) {
+		switch (recoverType.get()) {
 			case RESTORE_VAULT_CONFIG -> {
+				AtomicBoolean illegalArgumentExceptionOccurred = new AtomicBoolean(false);
 				var combo = RecoverUtil.validateRecoveryKeyAndGetCombo(
 						recoveryKeyFactory, vault, recoveryKey, masterkeyFileAccess, illegalArgumentExceptionOccurred);
 				combo.ifPresent(cipherCombo::set);
-				yield combo.isPresent();
+				if (illegalArgumentExceptionOccurred.get()) {
+					recoveryKeyState.set(RecoveryKeyState.INVALID);
+				} else if (combo.isPresent()) {
+					recoveryKeyState.set(RecoveryKeyState.CORRECT);
+				} else {
+					recoveryKeyState.set(RecoveryKeyState.WRONG);
+				}
+			}
+			case RESTORE_MASTERKEY, RESET_PASSWORD, SHOW_KEY, CONVERT_VAULT -> {
+				isWrongKey = false;
+				boolean valid = recoveryKeyFactory.validateRecoveryKey(recoveryKey.get(),
+						unverifiedVaultConfig != null ? this::checkKeyAgainstVaultConfig : null);
+				if (valid) {
+					recoveryKeyState.set(RecoveryKeyState.CORRECT);
+				} else if (isWrongKey) { //set via side effect in checkKeyAgainstVaultConfig()
+					recoveryKeyState.set(RecoveryKeyState.WRONG);
+				} else {
+					recoveryKeyState.set(RecoveryKeyState.INVALID);
+				}
 			}
-			case RESTORE_MASTERKEY, RESET_PASSWORD, SHOW_KEY, CONVERT_VAULT ->
-					recoveryKeyFactory.validateRecoveryKey(recoveryKey.get(),
-							unverifiedVaultConfig != null ? this::checkKeyAgainstVaultConfig : null);
-		};
-
-		if (valid) {
-			recoveryKeyState.set(RecoveryKeyState.CORRECT);
-			return;
 		}
-		recoveryKeyState.set(illegalArgumentExceptionOccurred.get() ? RecoveryKeyState.INVALID : RecoveryKeyState.WRONG);
 	}
 
 	/* Getter/Setter */

+ 1 - 9
src/main/java/org/cryptomator/ui/vaultoptions/MasterkeyOptionsController.java

@@ -7,8 +7,6 @@ import org.cryptomator.ui.changepassword.ChangePasswordComponent;
 import org.cryptomator.ui.common.FxController;
 import org.cryptomator.ui.forgetpassword.ForgetPasswordComponent;
 import org.cryptomator.ui.recoverykey.RecoveryKeyComponent;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import javax.inject.Inject;
 import javafx.beans.property.ObjectProperty;
@@ -17,13 +15,10 @@ import javafx.beans.property.SimpleObjectProperty;
 import javafx.beans.value.ObservableValue;
 import javafx.fxml.FXML;
 import javafx.stage.Stage;
-import java.util.ResourceBundle;
 
 @VaultOptionsScoped
 public class MasterkeyOptionsController implements FxController {
 
-	private static final Logger LOG = LoggerFactory.getLogger(MasterkeyOptionsController.class);
-
 	private final Vault vault;
 	private final Stage window;
 	private final ChangePasswordComponent.Builder changePasswordWindow;
@@ -31,19 +26,16 @@ public class MasterkeyOptionsController implements FxController {
 	private final ForgetPasswordComponent.Builder forgetPasswordWindow;
 	private final KeychainManager keychain;
 	private final ObservableValue<Boolean> passwordSaved;
-	private final ResourceBundle resourceBundle;
 
 
 	@Inject
-	MasterkeyOptionsController(@VaultOptionsWindow Vault vault, @VaultOptionsWindow Stage window, ChangePasswordComponent.Builder changePasswordWindow, RecoveryKeyComponent.Factory recoveryKeyWindow, ForgetPasswordComponent.Builder forgetPasswordWindow, KeychainManager keychain, //
-							   ResourceBundle resourceBundle) {
+	MasterkeyOptionsController(@VaultOptionsWindow Vault vault, @VaultOptionsWindow Stage window, ChangePasswordComponent.Builder changePasswordWindow, RecoveryKeyComponent.Factory recoveryKeyWindow, ForgetPasswordComponent.Builder forgetPasswordWindow, KeychainManager keychain) {
 		this.vault = vault;
 		this.window = window;
 		this.changePasswordWindow = changePasswordWindow;
 		this.recoveryKeyWindow = recoveryKeyWindow;
 		this.forgetPasswordWindow = forgetPasswordWindow;
 		this.keychain = keychain;
-		this.resourceBundle = resourceBundle;
 		if (keychain.isSupported() && !keychain.isLocked()) {
 			this.passwordSaved = keychain.getPassphraseStoredProperty(vault.getId()).orElse(false);
 		} else {

+ 2 - 2
src/main/resources/fxml/addvault_existing.fxml

@@ -3,11 +3,11 @@
 <?import javafx.geometry.Insets?>
 <?import javafx.scene.control.Button?>
 <?import javafx.scene.control.ButtonBar?>
+<?import javafx.scene.control.CheckBox?>
 <?import javafx.scene.control.Label?>
 <?import javafx.scene.image.ImageView?>
 <?import javafx.scene.layout.Region?>
 <?import javafx.scene.layout.VBox?>
-<?import javafx.scene.control.CheckBox?>
 <VBox xmlns:fx="http://javafx.com/fxml"
 	  xmlns="http://javafx.com/javafx"
 	  fx:controller="org.cryptomator.ui.addvaultwizard.ChooseExistingVaultController"
@@ -29,7 +29,7 @@
 		<Region VBox.vgrow="ALWAYS"/>
 		<ButtonBar buttonMinWidth="120" buttonOrder="+CX">
 			<buttons>
-				<Button text="%addvaultwizard.existing.restore" ButtonBar.buttonData="NEXT_FORWARD" onAction="#restoreVaultConfigWithRecoveryKey" visible="${controller.restoreButtonVisible}" />
+				<Button text="%addvaultwizard.existing.restore" ButtonBar.buttonData="NEXT_FORWARD" onAction="#restoreVaultConfigWithRecoveryKey" visible="${controller.restoreButtonVisible}"/>
 				<Button text="%addvaultwizard.existing.chooseBtn" ButtonBar.buttonData="NEXT_FORWARD" onAction="#chooseFileAndNext" defaultButton="true"/>
 			</buttons>
 		</ButtonBar>

+ 2 - 2
src/main/resources/fxml/recoverykey_expert_settings.fxml

@@ -1,7 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
-<?import org.cryptomator.ui.controls.FontAwesome5IconView?>
-<?import org.cryptomator.ui.controls.NumericTextField?>
 <?import javafx.geometry.Insets?>
 <?import javafx.scene.control.Button?>
 <?import javafx.scene.control.ButtonBar?>
@@ -15,6 +13,8 @@
 <?import javafx.scene.layout.StackPane?>
 <?import javafx.scene.layout.VBox?>
 <?import javafx.scene.shape.Circle?>
+<?import org.cryptomator.ui.controls.FontAwesome5IconView?>
+<?import org.cryptomator.ui.controls.NumericTextField?>
 <HBox xmlns:fx="http://javafx.com/fxml"
 	  xmlns="http://javafx.com/javafx"
 	  fx:controller="org.cryptomator.ui.recoverykey.RecoveryKeyExpertSettingsController"

+ 4 - 4
src/main/resources/fxml/recoverykey_is_hub_vault.fxml

@@ -3,12 +3,12 @@
 <?import javafx.geometry.Insets?>
 <?import javafx.scene.control.Button?>
 <?import javafx.scene.control.ButtonBar?>
-<?import javafx.scene.layout.Region?>
-<?import javafx.scene.layout.HBox?>
-<?import javafx.scene.layout.VBox?>
 <?import javafx.scene.control.Label?>
-<?import javafx.scene.layout.StackPane?>
 <?import javafx.scene.Group?>
+<?import javafx.scene.layout.HBox?>
+<?import javafx.scene.layout.Region?>
+<?import javafx.scene.layout.StackPane?>
+<?import javafx.scene.layout.VBox?>
 <?import javafx.scene.shape.Circle?>
 <?import org.cryptomator.ui.controls.FontAwesome5IconView?>
 <HBox xmlns:fx="http://javafx.com/fxml"